1 ; --------------------------------------------------------------
2 ; prog100k.4th, compile 100 kbytes, to test speed of compilation
3 ; --------------------------------------------------------------
5 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
6 \ MSP_EXP430FR4133 MSP_EXP430FR2355 CHIPSTICK_FR2433
8 \ MY_MSP430FR5738_1 MY_MSP430FR5738 MY_MSP430FR5948 MY_MSP430FR5948_1
11 \ Copyright (C) <2016> <J.M. THOORENS>
13 \ This program is free software: you can redistribute it and/or modify
14 \ it under the terms of the GNU General Public License as published by
15 \ the Free Software Foundation, either version 3 of the License, or
16 \ (at your option) any later version.
18 \ This program is distributed in the hope that it will be useful,
19 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
20 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 \ GNU General Public License for more details.
23 \ You should have received a copy of the GNU General Public License
24 \ along with this program. If not, see <http://www.gnu.org/licenses/>.
27 \ ===========================================================================
28 \ remember: for good downloading to target, all lines must be ended with CR+LF !
29 \ ===========================================================================
33 \ R4 to R7 must be saved before use and restored after
34 \ scratch registers Y to S are free for use
35 \ under interrupt, IP is free for use
37 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, R7, R6, R5, R4
38 \ example : PUSHM IP,Y
40 \ POPM order : R4, R5, R6, R7, Y, X, W, T, S, IP,TOS,PSP
43 \ FORTH conditionnals: unary{ 0= 0< 0> }, binary{ = < > U< }
45 \ ASSEMBLER conditionnal usage with IF UNTIL WHILE S< S>= U< U>= 0= 0<> 0>=
47 \ ASSEMBLER conditionnal usage with ?JMP ?GOTO S< S>= U< U>= 0= 0<> <0
50 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
51 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
52 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
54 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
55 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
56 \ without usage of an auxiliary 5V to feed the LCD_Vo
57 \ and without potentiometer to adjust the LCD contrast :
58 \ to adjust LCD contrast, just press S1 (-) or S2 (+)
59 \ LCDVo current consumption ~ 500 uA.
61 \ ===================================================================================
62 \ notice : adjust TA0EX0,TB0CTL,TB0EX0 and 20_us to the target frequency if <> 8MHz !
63 \ ===================================================================================
66 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
68 \ GND <-------+---0V0----------> 1 LCD_Vss
69 \ VCC >------ | --3V6-----+----> 2 LCD_Vdd
76 \ TB0.2 >---||--+--^/\/\/v--+----> 3 LCD_Vo (= 0V6 without modulation)
77 \ -------------------------> 4 LCD_RW
78 \ -------------------------> 5 LCD_RW
79 \ -------------------------> 6 LCD_EN
80 \ <------------------------> 11 LCD_DB4
81 \ <------------------------> 12 LCD_DB5
82 \ <------------------------> 13 LCD_DB5
83 \ <------------------------> 14 LCD_DB7
85 \ <----- LCD contrast + <--- Sw1 <--- (finger) :-)
86 \ <----- LCD contrast - <--- Sw2 <--- (finger) :-)
88 \ rc5 <--- OUT IR_Receiver (1 TSOP32236)
95 CODE MAX \ n1 n2 -- n3 signed maximum
103 CODE MIN \ n1 n2 -- n3 signed minimum
111 : U.R \ u n -- display u unsigned in n width (n >= 2)
113 R> OVER - 0 MAX SPACES TYPE
117 CODE 20_US \ n -- n * 20 us
118 BEGIN \ 3 cycles loop + 6~
119 \ MOV #5,W \ 3 MCLK = 1 MHz
120 \ MOV #23,W \ 3 MCLK = 4 MHz
121 MOV #51,W \ 3 MCLK = 8 MHz
122 \ MOV #104,W \ 3 MCLK = 16 MHz
123 \ MOV #158,W \ 3 MCLK = 24 MHz
124 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
134 CODE TOP_LCD \ LCD Sample
135 \ \ if write : %xxxxWWWW --
136 \ \ if read : -- %0000RRRR
137 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
138 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
139 0= IF \ write LCD bits pattern
141 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
142 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
145 THEN \ read LCD bits pattern
148 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
149 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
155 CODE LCD_W \ byte -- write byte to LCD
157 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
158 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
159 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
160 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
161 COLON \ high level word starts here
162 TOP_LCD 2 20_US \ write high nibble first
167 CODE LCD_WrC \ char -- Write Char
168 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
173 CODE LCD_WrF \ func -- Write Fonction
174 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
180 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
185 $02 LCD_WrF 100 20_us
189 \ : LCD_Entry_set $04 OR LCD_WrF ;
191 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
193 \ : LCD_Display_Shift $10 OR LCD_WrF ;
195 \ : LCD_Fn_Set $20 OR LCD_WrF ;
197 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
199 \ : LCD_Goto $80 OR LCD_WrF ;
201 \ CODE LCD_R \ -- byte read byte from LCD
202 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
203 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
204 \ COLON \ starts a FORTH word
205 \ TOP_LCD 2 20_us \ -- %0000HHHH
206 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
207 \ HI2LO \ switch from FORTH to assembler
208 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
209 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
210 \ MOV @RSP+,IP \ restore IP saved by COLON
215 \ CODE LCD_RdS \ -- status Read Status
216 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
221 \ CODE LCD_RdC \ -- char Read Char
222 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
227 \ -------------+------+------+------+------++---+---+---+---+---------+
228 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
229 \ -------------+------+------+------+------++---+---+---+---+---------+
230 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
231 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
232 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
233 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
234 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
235 \ -------------+------+------+------+------++---+---+---+---+---------+
238 \ ******************************\
239 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
240 \ ******************************\
241 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
242 \ ------------------------------\
243 \ define LPM mode for ACCEPT \
244 \ ------------------------------\
245 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
246 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
247 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
248 BIT.B #SW2,&SW2_IN \ test switch S2
249 0= IF \ case of switch S2 pressed
250 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
252 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
255 BIT.B #SW1,&SW1_IN \ test switch S1 input
256 0= IF \ case of Switch S1 pressed
257 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
259 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
263 RETI \ CPU is ON, GIE is OFF
268 \ ------------------------------\
269 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
270 \ ******************************\
271 ASM RC5_INT \ wake up on Px.RC5 change interrupt
272 \ ******************************\
273 \ \ in : SR(9)=old Toggle bit memory (ADD on)
274 \ \ SMclock = 8|16|24 MHz
275 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
276 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
277 \ \ SR(9)=new Toggle bit memory (ADD on)
278 \ ------------------------------\
279 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
280 \ ------------------------------\
281 \ define LPM mode for ACCEPT \
282 \ ------------------------------\
283 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
284 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
285 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
286 \ ------------------------------\
287 \ RC5_FirstStartBitHalfCycle: \
288 \ ------------------------------\
289 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
290 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
291 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
292 MOV #1778,X \ RC5_Period in us
293 MOV #14,W \ count of loop
295 \ ------------------------------\
296 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
297 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
298 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
299 \ RC5_Compute_3/4_Period: \ |
300 RRUM #1,X \ X=1/2 cycle |
304 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
305 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
307 \ ------------------------------\
308 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
309 \ ------------------------------\
310 BIT.B #RC5,&IR_IN \ C_flag = IR bit
311 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
312 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
313 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
314 SUB #1,W \ decrement count loop
315 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
316 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
317 0<> WHILE \ ----> out of loop ----+
318 \ RC5_compute_7/4_Time_out: \ |
319 ADD X,Y \ | out of bound = 7/4 period
320 \ RC5_WaitHalfCycleP1.2_IFG: \ |
322 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
323 0>= IF \ | if cycle time out of bound
324 BIC #$30,&TA0CTL \ | stop timer_A0
325 RETI \ | then quit to do nothing
327 \ ------------------------------\ |
328 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
330 MOV &TA0R,X \ | | get new RC5_period value
331 REPEAT \ ----> loop back --+ |
332 \ ------------------------------\ |
333 \ RC5_SampleEndOf: \ <---------------------+
334 \ ------------------------------\
335 BIC #$30,&TA0CTL \ stop timer_A0
336 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
337 \ ******************************\
338 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
339 \ ******************************\
340 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
341 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
342 XOR IP,X \ (new XOR old) Toggle bit (13)
343 BIT #BIT13,X \ X(13) = New_RC5_command
344 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
346 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
347 \ ******************************\
348 \ RC5_ComputeNewRC5word \
349 \ ******************************\
351 MOV &BASE,2(PSP) \ save variable BASE before use
352 MOV TOS,0(PSP) \ save TOS before use
353 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
354 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
355 \ ******************************\
357 \ ******************************\
358 BIT #$4000,IP \ test /C6 bit in IP
359 0= IF BIS #$40,TOS \ set C6 bit in S
360 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
361 \ ******************************\
362 \ RC5_CommandByteIsDone \ RC5_code --
363 \ ******************************\
365 \ ------------------------------\
366 \ Display IR_RC5 code \
367 \ ------------------------------\
368 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
369 \ ------------------------------\
370 LO2HI \ switch from assembler to FORTH
371 ['] LCD_CLEAR IS CR \ redirects CR
372 ['] LCD_WrC IS EMIT \ redirects EMIT
373 $10 BASE ! \ change BASE to hexadecimal
374 CR ." $" 2 U.R \ print IR_RC5 code
375 ['] (CR) IS CR \ restore CR
376 ['] (EMIT) IS EMIT \ restore EMIT
377 HI2LO \ switch from FORTH to assembler
378 \ ------------------------------\
379 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
380 \ ------------------------------\
381 MOV @PSP+,&BASE \ restore variable BASE
382 RETI \ CPU is ON, GIE is OFF
387 \ ------------------------------\
388 \ TB0CTL = %0000 0010 1001 0100\$3C0
389 \ - - \CNTL Counter lentgh \ 00 = 16 bits
390 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
391 \ -- \ID input divider \ 10 = /4
392 \ -- \MC Mode Control \ 01 = up to TB0CCR0
393 \ - \TBCLR TimerB Clear
396 \ --------------------------------\\
397 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
398 \ -- \CM Capture Mode
403 \ --- \OUTMOD \ 011 = set/reset
409 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
411 \ ------------------------------\
412 \ set TimerB to make 50kHz PWM \
413 \ ------------------------------\
414 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
415 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
416 \ ------------------------------\
417 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
418 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
419 \ ------------------------------\
420 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
421 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
422 \ ------------------------------\
423 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
424 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
425 \ ------------------------------\
426 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
427 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
428 \ ------------------------------\
429 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
430 \ ------------------------------\
431 \ set TimerB to generate PWM for LCD_Vo
432 \ ------------------------------\
433 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
434 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
435 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
436 \ ------------------------------\
437 BIS.B #LCDVo,&LCDVo_DIR \
438 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
439 \ ------------------------------\
440 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
441 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
442 \ ------------------------------\
443 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
444 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
445 \ ------------------------------\
446 \ WDT interval init part \
447 \ ------------------------------\
448 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
449 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
450 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
451 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
452 \ ------------------------------\
454 \ ------------------------------\
455 BIS.B #RC5,&IR_IE \ enable RC5_Int
456 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
457 \ ------------------------------\
458 \ init interrupt vectors
459 \ ------------------------------\
460 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
461 MOV #RC5_INT,&IR_Vec \ init interrupt vector
462 \ ------------------------------\
463 \ define LPM mode for ACCEPT \
464 \ ------------------------------\
465 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
466 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
467 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
469 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
471 \ ------------------------------\
473 \ ------------------------------\
474 $03E8 20_US \ 1- wait 20 ms
475 $03 TOP_LCD \ 2- send DB5=DB4=1
476 $CD 20_US \ 3- wait 4,1 ms
477 $03 TOP_LCD \ 4- send again DB5=DB4=1
478 $5 20_US \ 5- wait 0,1 ms
479 $03 TOP_LCD \ 6- send again again DB5=DB4=1
480 $2 20_US \ wait 40 us = LCD cycle
481 $02 TOP_LCD \ 7- send DB5=1 DB4=0
482 $2 20_US \ wait 40 us = LCD cycle
483 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
484 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
485 LCD_Clear \ 10- "LCD_Clear"
486 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
487 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
488 LCD_Clear \ 10- "LCD_Clear"
489 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
490 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
492 ['] (CR) IS CR \ ' (CR) is CR
493 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
495 ." RC5toLCD is running. Type STOP to quit"
496 \ NOECHO \ uncomment to run this app without terminal connexion
497 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
498 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
502 : STOP \ stops multitasking, must to be used before downloading app
503 ['] (WARM) IS WARM \ remove START app from FORTH init process
504 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
512 CODE MAX \ n1 n2 -- n3 signed maximum
520 CODE MIN \ n1 n2 -- n3 signed minimum
528 : U.R \ u n -- display u unsigned in n width (n >= 2)
530 R> OVER - 0 MAX SPACES TYPE
534 CODE 20_US \ n -- n * 20 us
535 BEGIN \ 3 cycles loop + 6~
536 \ MOV #5,W \ 3 MCLK = 1 MHz
537 \ MOV #23,W \ 3 MCLK = 4 MHz
538 MOV #51,W \ 3 MCLK = 8 MHz
539 \ MOV #104,W \ 3 MCLK = 16 MHz
540 \ MOV #158,W \ 3 MCLK = 24 MHz
541 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
551 CODE TOP_LCD \ LCD Sample
552 \ \ if write : %xxxxWWWW --
553 \ \ if read : -- %0000RRRR
554 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
555 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
556 0= IF \ write LCD bits pattern
558 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
559 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
562 THEN \ read LCD bits pattern
565 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
566 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
572 CODE LCD_W \ byte -- write byte to LCD
574 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
575 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
576 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
577 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
578 COLON \ high level word starts here
579 TOP_LCD 2 20_US \ write high nibble first
584 CODE LCD_WrC \ char -- Write Char
585 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
590 CODE LCD_WrF \ func -- Write Fonction
591 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
597 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
602 $02 LCD_WrF 100 20_us
606 \ : LCD_Entry_set $04 OR LCD_WrF ;
608 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
610 \ : LCD_Display_Shift $10 OR LCD_WrF ;
612 \ : LCD_Fn_Set $20 OR LCD_WrF ;
614 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
616 \ : LCD_Goto $80 OR LCD_WrF ;
618 \ CODE LCD_R \ -- byte read byte from LCD
619 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
620 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
621 \ COLON \ starts a FORTH word
622 \ TOP_LCD 2 20_us \ -- %0000HHHH
623 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
624 \ HI2LO \ switch from FORTH to assembler
625 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
626 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
627 \ MOV @RSP+,IP \ restore IP saved by COLON
632 \ CODE LCD_RdS \ -- status Read Status
633 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
638 \ CODE LCD_RdC \ -- char Read Char
639 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
644 \ -------------+------+------+------+------++---+---+---+---+---------+
645 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
646 \ -------------+------+------+------+------++---+---+---+---+---------+
647 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
648 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
649 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
650 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
651 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
652 \ -------------+------+------+------+------++---+---+---+---+---------+
655 \ ******************************\
656 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
657 \ ******************************\
658 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
659 \ ------------------------------\
660 \ define LPM mode for ACCEPT \
661 \ ------------------------------\
662 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
663 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
664 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
665 BIT.B #SW2,&SW2_IN \ test switch S2
666 0= IF \ case of switch S2 pressed
667 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
669 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
672 BIT.B #SW1,&SW1_IN \ test switch S1 input
673 0= IF \ case of Switch S1 pressed
674 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
676 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
680 RETI \ CPU is ON, GIE is OFF
685 \ ------------------------------\
686 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
687 \ ******************************\
688 ASM RC5_INT \ wake up on Px.RC5 change interrupt
689 \ ******************************\
690 \ \ in : SR(9)=old Toggle bit memory (ADD on)
691 \ \ SMclock = 8|16|24 MHz
692 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
693 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
694 \ \ SR(9)=new Toggle bit memory (ADD on)
695 \ ------------------------------\
696 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
697 \ ------------------------------\
698 \ define LPM mode for ACCEPT \
699 \ ------------------------------\
700 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
701 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
702 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
703 \ ------------------------------\
704 \ RC5_FirstStartBitHalfCycle: \
705 \ ------------------------------\
706 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
707 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
708 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
709 MOV #1778,X \ RC5_Period in us
710 MOV #14,W \ count of loop
712 \ ------------------------------\
713 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
714 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
715 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
716 \ RC5_Compute_3/4_Period: \ |
717 RRUM #1,X \ X=1/2 cycle |
721 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
722 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
724 \ ------------------------------\
725 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
726 \ ------------------------------\
727 BIT.B #RC5,&IR_IN \ C_flag = IR bit
728 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
729 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
730 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
731 SUB #1,W \ decrement count loop
732 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
733 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
734 0<> WHILE \ ----> out of loop ----+
735 \ RC5_compute_7/4_Time_out: \ |
736 ADD X,Y \ | out of bound = 7/4 period
737 \ RC5_WaitHalfCycleP1.2_IFG: \ |
739 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
740 0>= IF \ | if cycle time out of bound
741 BIC #$30,&TA0CTL \ | stop timer_A0
742 RETI \ | then quit to do nothing
744 \ ------------------------------\ |
745 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
747 MOV &TA0R,X \ | | get new RC5_period value
748 REPEAT \ ----> loop back --+ |
749 \ ------------------------------\ |
750 \ RC5_SampleEndOf: \ <---------------------+
751 \ ------------------------------\
752 BIC #$30,&TA0CTL \ stop timer_A0
753 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
754 \ ******************************\
755 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
756 \ ******************************\
757 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
758 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
759 XOR IP,X \ (new XOR old) Toggle bit (13)
760 BIT #BIT13,X \ X(13) = New_RC5_command
761 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
763 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
764 \ ******************************\
765 \ RC5_ComputeNewRC5word \
766 \ ******************************\
768 MOV &BASE,2(PSP) \ save variable BASE before use
769 MOV TOS,0(PSP) \ save TOS before use
770 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
771 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
772 \ ******************************\
774 \ ******************************\
775 BIT #$4000,IP \ test /C6 bit in IP
776 0= IF BIS #$40,TOS \ set C6 bit in S
777 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
778 \ ******************************\
779 \ RC5_CommandByteIsDone \ RC5_code --
780 \ ******************************\
782 \ ------------------------------\
783 \ Display IR_RC5 code \
784 \ ------------------------------\
785 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
786 \ ------------------------------\
787 LO2HI \ switch from assembler to FORTH
788 ['] LCD_CLEAR IS CR \ redirects CR
789 ['] LCD_WrC IS EMIT \ redirects EMIT
790 $10 BASE ! \ change BASE to hexadecimal
791 CR ." $" 2 U.R \ print IR_RC5 code
792 ['] (CR) IS CR \ restore CR
793 ['] (EMIT) IS EMIT \ restore EMIT
794 HI2LO \ switch from FORTH to assembler
795 \ ------------------------------\
796 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
797 \ ------------------------------\
798 MOV @PSP+,&BASE \ restore variable BASE
799 RETI \ CPU is ON, GIE is OFF
804 \ ------------------------------\
805 \ TB0CTL = %0000 0010 1001 0100\$3C0
806 \ - - \CNTL Counter lentgh \ 00 = 16 bits
807 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
808 \ -- \ID input divider \ 10 = /4
809 \ -- \MC Mode Control \ 01 = up to TB0CCR0
810 \ - \TBCLR TimerB Clear
813 \ --------------------------------\\
814 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
815 \ -- \CM Capture Mode
820 \ --- \OUTMOD \ 011 = set/reset
826 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
828 \ ------------------------------\
829 \ set TimerB to make 50kHz PWM \
830 \ ------------------------------\
831 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
832 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
833 \ ------------------------------\
834 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
835 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
836 \ ------------------------------\
837 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
838 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
839 \ ------------------------------\
840 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
841 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
842 \ ------------------------------\
843 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
844 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
845 \ ------------------------------\
846 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
847 \ ------------------------------\
848 \ set TimerB to generate PWM for LCD_Vo
849 \ ------------------------------\
850 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
851 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
852 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
853 \ ------------------------------\
854 BIS.B #LCDVo,&LCDVo_DIR \
855 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
856 \ ------------------------------\
857 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
858 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
859 \ ------------------------------\
860 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
861 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
862 \ ------------------------------\
863 \ WDT interval init part \
864 \ ------------------------------\
865 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
866 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
867 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
868 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
869 \ ------------------------------\
871 \ ------------------------------\
872 BIS.B #RC5,&IR_IE \ enable RC5_Int
873 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
874 \ ------------------------------\
875 \ init interrupt vectors
876 \ ------------------------------\
877 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
878 MOV #RC5_INT,&IR_Vec \ init interrupt vector
879 \ ------------------------------\
880 \ define LPM mode for ACCEPT \
881 \ ------------------------------\
882 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
883 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
884 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
886 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
888 \ ------------------------------\
890 \ ------------------------------\
891 $03E8 20_US \ 1- wait 20 ms
892 $03 TOP_LCD \ 2- send DB5=DB4=1
893 $CD 20_US \ 3- wait 4,1 ms
894 $03 TOP_LCD \ 4- send again DB5=DB4=1
895 $5 20_US \ 5- wait 0,1 ms
896 $03 TOP_LCD \ 6- send again again DB5=DB4=1
897 $2 20_US \ wait 40 us = LCD cycle
898 $02 TOP_LCD \ 7- send DB5=1 DB4=0
899 $2 20_US \ wait 40 us = LCD cycle
900 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
901 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
902 LCD_Clear \ 10- "LCD_Clear"
903 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
904 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
905 LCD_Clear \ 10- "LCD_Clear"
906 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
907 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
909 ['] (CR) IS CR \ ' (CR) is CR
910 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
912 ." RC5toLCD is running. Type STOP to quit"
913 \ NOECHO \ uncomment to run this app without terminal connexion
914 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
915 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
919 : STOP \ stops multitasking, must to be used before downloading app
920 ['] (WARM) IS WARM \ remove START app from FORTH init process
921 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
929 CODE MAX \ n1 n2 -- n3 signed maximum
937 CODE MIN \ n1 n2 -- n3 signed minimum
945 : U.R \ u n -- display u unsigned in n width (n >= 2)
947 R> OVER - 0 MAX SPACES TYPE
951 CODE 20_US \ n -- n * 20 us
952 BEGIN \ 3 cycles loop + 6~
953 \ MOV #5,W \ 3 MCLK = 1 MHz
954 \ MOV #23,W \ 3 MCLK = 4 MHz
955 MOV #51,W \ 3 MCLK = 8 MHz
956 \ MOV #104,W \ 3 MCLK = 16 MHz
957 \ MOV #158,W \ 3 MCLK = 24 MHz
958 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
968 CODE TOP_LCD \ LCD Sample
969 \ \ if write : %xxxxWWWW --
970 \ \ if read : -- %0000RRRR
971 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
972 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
973 0= IF \ write LCD bits pattern
975 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
976 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
979 THEN \ read LCD bits pattern
982 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
983 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
989 CODE LCD_W \ byte -- write byte to LCD
991 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
992 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
993 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
994 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
995 COLON \ high level word starts here
996 TOP_LCD 2 20_US \ write high nibble first
1001 CODE LCD_WrC \ char -- Write Char
1002 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1007 CODE LCD_WrF \ func -- Write Fonction
1008 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1014 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1019 $02 LCD_WrF 100 20_us
1023 \ : LCD_Entry_set $04 OR LCD_WrF ;
1025 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1027 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1029 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1031 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1033 \ : LCD_Goto $80 OR LCD_WrF ;
1035 \ CODE LCD_R \ -- byte read byte from LCD
1036 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1037 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1038 \ COLON \ starts a FORTH word
1039 \ TOP_LCD 2 20_us \ -- %0000HHHH
1040 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1041 \ HI2LO \ switch from FORTH to assembler
1042 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1043 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1044 \ MOV @RSP+,IP \ restore IP saved by COLON
1049 \ CODE LCD_RdS \ -- status Read Status
1050 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1055 \ CODE LCD_RdC \ -- char Read Char
1056 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1061 \ -------------+------+------+------+------++---+---+---+---+---------+
1062 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1063 \ -------------+------+------+------+------++---+---+---+---+---------+
1064 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1065 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1066 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1067 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1068 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1069 \ -------------+------+------+------+------++---+---+---+---+---------+
1072 \ ******************************\
1073 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1074 \ ******************************\
1075 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1076 \ ------------------------------\
1077 \ define LPM mode for ACCEPT \
1078 \ ------------------------------\
1079 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1080 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1081 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1082 BIT.B #SW2,&SW2_IN \ test switch S2
1083 0= IF \ case of switch S2 pressed
1084 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1086 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1089 BIT.B #SW1,&SW1_IN \ test switch S1 input
1090 0= IF \ case of Switch S1 pressed
1091 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1093 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1097 RETI \ CPU is ON, GIE is OFF
1102 \ ------------------------------\
1103 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1104 \ ******************************\
1105 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1106 \ ******************************\
1107 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1108 \ \ SMclock = 8|16|24 MHz
1109 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1110 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1111 \ \ SR(9)=new Toggle bit memory (ADD on)
1112 \ ------------------------------\
1113 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1114 \ ------------------------------\
1115 \ define LPM mode for ACCEPT \
1116 \ ------------------------------\
1117 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1118 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1119 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1120 \ ------------------------------\
1121 \ RC5_FirstStartBitHalfCycle: \
1122 \ ------------------------------\
1123 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1124 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1125 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1126 MOV #1778,X \ RC5_Period in us
1127 MOV #14,W \ count of loop
1129 \ ------------------------------\
1130 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1131 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1132 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1133 \ RC5_Compute_3/4_Period: \ |
1134 RRUM #1,X \ X=1/2 cycle |
1138 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1139 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1141 \ ------------------------------\
1142 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1143 \ ------------------------------\
1144 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1145 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1146 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1147 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1148 SUB #1,W \ decrement count loop
1149 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1150 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1151 0<> WHILE \ ----> out of loop ----+
1152 \ RC5_compute_7/4_Time_out: \ |
1153 ADD X,Y \ | out of bound = 7/4 period
1154 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1156 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1157 0>= IF \ | if cycle time out of bound
1158 BIC #$30,&TA0CTL \ | stop timer_A0
1159 RETI \ | then quit to do nothing
1161 \ ------------------------------\ |
1162 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1164 MOV &TA0R,X \ | | get new RC5_period value
1165 REPEAT \ ----> loop back --+ |
1166 \ ------------------------------\ |
1167 \ RC5_SampleEndOf: \ <---------------------+
1168 \ ------------------------------\
1169 BIC #$30,&TA0CTL \ stop timer_A0
1170 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
1171 \ ******************************\
1172 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1173 \ ******************************\
1174 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
1175 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
1176 XOR IP,X \ (new XOR old) Toggle bit (13)
1177 BIT #BIT13,X \ X(13) = New_RC5_command
1178 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
1180 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
1181 \ ******************************\
1182 \ RC5_ComputeNewRC5word \
1183 \ ******************************\
1185 MOV &BASE,2(PSP) \ save variable BASE before use
1186 MOV TOS,0(PSP) \ save TOS before use
1187 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
1188 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
1189 \ ******************************\
1190 \ RC5_ComputeC6bit \
1191 \ ******************************\
1192 BIT #$4000,IP \ test /C6 bit in IP
1193 0= IF BIS #$40,TOS \ set C6 bit in S
1194 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
1195 \ ******************************\
1196 \ RC5_CommandByteIsDone \ RC5_code --
1197 \ ******************************\
1199 \ ------------------------------\
1200 \ Display IR_RC5 code \
1201 \ ------------------------------\
1202 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
1203 \ ------------------------------\
1204 LO2HI \ switch from assembler to FORTH
1205 ['] LCD_CLEAR IS CR \ redirects CR
1206 ['] LCD_WrC IS EMIT \ redirects EMIT
1207 $10 BASE ! \ change BASE to hexadecimal
1208 CR ." $" 2 U.R \ print IR_RC5 code
1209 ['] (CR) IS CR \ restore CR
1210 ['] (EMIT) IS EMIT \ restore EMIT
1211 HI2LO \ switch from FORTH to assembler
1212 \ ------------------------------\
1213 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
1214 \ ------------------------------\
1215 MOV @PSP+,&BASE \ restore variable BASE
1216 RETI \ CPU is ON, GIE is OFF
1221 \ ------------------------------\
1222 \ TB0CTL = %0000 0010 1001 0100\$3C0
1223 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1224 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1225 \ -- \ID input divider \ 10 = /4
1226 \ -- \MC Mode Control \ 01 = up to TB0CCR0
1227 \ - \TBCLR TimerB Clear
1230 \ --------------------------------\\
1231 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1232 \ -- \CM Capture Mode
1237 \ --- \OUTMOD \ 011 = set/reset
1243 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
1245 \ ------------------------------\
1246 \ set TimerB to make 50kHz PWM \
1247 \ ------------------------------\
1248 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1249 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
1250 \ ------------------------------\
1251 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1252 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
1253 \ ------------------------------\
1254 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1255 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
1256 \ ------------------------------\
1257 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1258 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
1259 \ ------------------------------\
1260 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1261 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
1262 \ ------------------------------\
1263 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
1264 \ ------------------------------\
1265 \ set TimerB to generate PWM for LCD_Vo
1266 \ ------------------------------\
1267 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
1268 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
1269 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1270 \ ------------------------------\
1271 BIS.B #LCDVo,&LCDVo_DIR \
1272 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
1273 \ ------------------------------\
1274 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1275 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1276 \ ------------------------------\
1277 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1278 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1279 \ ------------------------------\
1280 \ WDT interval init part \
1281 \ ------------------------------\
1282 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
1283 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
1284 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
1285 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
1286 \ ------------------------------\
1288 \ ------------------------------\
1289 BIS.B #RC5,&IR_IE \ enable RC5_Int
1290 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1291 \ ------------------------------\
1292 \ init interrupt vectors
1293 \ ------------------------------\
1294 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
1295 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1296 \ ------------------------------\
1297 \ define LPM mode for ACCEPT \
1298 \ ------------------------------\
1299 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1300 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1301 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1303 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
1305 \ ------------------------------\
1307 \ ------------------------------\
1308 $03E8 20_US \ 1- wait 20 ms
1309 $03 TOP_LCD \ 2- send DB5=DB4=1
1310 $CD 20_US \ 3- wait 4,1 ms
1311 $03 TOP_LCD \ 4- send again DB5=DB4=1
1312 $5 20_US \ 5- wait 0,1 ms
1313 $03 TOP_LCD \ 6- send again again DB5=DB4=1
1314 $2 20_US \ wait 40 us = LCD cycle
1315 $02 TOP_LCD \ 7- send DB5=1 DB4=0
1316 $2 20_US \ wait 40 us = LCD cycle
1317 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1318 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1319 LCD_Clear \ 10- "LCD_Clear"
1320 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1321 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1322 LCD_Clear \ 10- "LCD_Clear"
1323 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1324 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1326 ['] (CR) IS CR \ ' (CR) is CR
1327 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
1329 ." RC5toLCD is running. Type STOP to quit"
1330 \ NOECHO \ uncomment to run this app without terminal connexion
1331 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
1332 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
1336 : STOP \ stops multitasking, must to be used before downloading app
1337 ['] (WARM) IS WARM \ remove START app from FORTH init process
1338 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
1346 CODE MAX \ n1 n2 -- n3 signed maximum
1347 CMP @PSP,TOS \ n2-n1
1348 S< ?GOTO FW1 \ n2<n1
1354 CODE MIN \ n1 n2 -- n3 signed minimum
1355 CMP @PSP,TOS \ n2-n1
1356 S< ?GOTO BW1 \ n2<n1
1362 : U.R \ u n -- display u unsigned in n width (n >= 2)
1364 R> OVER - 0 MAX SPACES TYPE
1368 CODE 20_US \ n -- n * 20 us
1369 BEGIN \ 3 cycles loop + 6~
1370 \ MOV #5,W \ 3 MCLK = 1 MHz
1371 \ MOV #23,W \ 3 MCLK = 4 MHz
1372 MOV #51,W \ 3 MCLK = 8 MHz
1373 \ MOV #104,W \ 3 MCLK = 16 MHz
1374 \ MOV #158,W \ 3 MCLK = 24 MHz
1375 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
1385 CODE TOP_LCD \ LCD Sample
1386 \ \ if write : %xxxxWWWW --
1387 \ \ if read : -- %0000RRRR
1388 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1389 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1390 0= IF \ write LCD bits pattern
1392 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1393 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1396 THEN \ read LCD bits pattern
1399 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1400 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1406 CODE LCD_W \ byte -- write byte to LCD
1408 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
1409 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
1410 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1411 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1412 COLON \ high level word starts here
1413 TOP_LCD 2 20_US \ write high nibble first
1418 CODE LCD_WrC \ char -- Write Char
1419 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1424 CODE LCD_WrF \ func -- Write Fonction
1425 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1431 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1436 $02 LCD_WrF 100 20_us
1440 \ : LCD_Entry_set $04 OR LCD_WrF ;
1442 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1444 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1446 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1448 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1450 \ : LCD_Goto $80 OR LCD_WrF ;
1452 \ CODE LCD_R \ -- byte read byte from LCD
1453 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1454 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1455 \ COLON \ starts a FORTH word
1456 \ TOP_LCD 2 20_us \ -- %0000HHHH
1457 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1458 \ HI2LO \ switch from FORTH to assembler
1459 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1460 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1461 \ MOV @RSP+,IP \ restore IP saved by COLON
1466 \ CODE LCD_RdS \ -- status Read Status
1467 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1472 \ CODE LCD_RdC \ -- char Read Char
1473 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1478 \ -------------+------+------+------+------++---+---+---+---+---------+
1479 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1480 \ -------------+------+------+------+------++---+---+---+---+---------+
1481 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1482 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1483 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1484 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1485 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1486 \ -------------+------+------+------+------++---+---+---+---+---------+
1489 \ ******************************\
1490 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1491 \ ******************************\
1492 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1493 \ ------------------------------\
1494 \ define LPM mode for ACCEPT \
1495 \ ------------------------------\
1496 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1497 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1498 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1499 BIT.B #SW2,&SW2_IN \ test switch S2
1500 0= IF \ case of switch S2 pressed
1501 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1503 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1506 BIT.B #SW1,&SW1_IN \ test switch S1 input
1507 0= IF \ case of Switch S1 pressed
1508 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1510 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1514 RETI \ CPU is ON, GIE is OFF
1519 \ ------------------------------\
1520 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1521 \ ******************************\
1522 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1523 \ ******************************\
1524 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1525 \ \ SMclock = 8|16|24 MHz
1526 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1527 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1528 \ \ SR(9)=new Toggle bit memory (ADD on)
1529 \ ------------------------------\
1530 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1531 \ ------------------------------\
1532 \ define LPM mode for ACCEPT \
1533 \ ------------------------------\
1534 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1535 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1536 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1537 \ ------------------------------\
1538 \ RC5_FirstStartBitHalfCycle: \
1539 \ ------------------------------\
1540 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1541 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1542 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1543 MOV #1778,X \ RC5_Period in us
1544 MOV #14,W \ count of loop
1546 \ ------------------------------\
1547 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1548 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1549 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1550 \ RC5_Compute_3/4_Period: \ |
1551 RRUM #1,X \ X=1/2 cycle |
1555 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1556 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1558 \ ------------------------------\
1559 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1560 \ ------------------------------\
1561 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1562 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1563 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1564 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1565 SUB #1,W \ decrement count loop
1566 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1567 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1568 0<> WHILE \ ----> out of loop ----+
1569 \ RC5_compute_7/4_Time_out: \ |
1570 ADD X,Y \ | out of bound = 7/4 period
1571 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1573 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1574 0>= IF \ | if cycle time out of bound
1575 BIC #$30,&TA0CTL \ | stop timer_A0
1576 RETI \ | then quit to do nothing
1578 \ ------------------------------\ |
1579 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1581 MOV &TA0R,X \ | | get new RC5_period value
1582 REPEAT \ ----> loop back --+ |
1583 \ ------------------------------\ |
1584 \ RC5_SampleEndOf: \ <---------------------+
1585 \ ------------------------------\
1586 BIC #$30,&TA0CTL \ stop timer_A0
1587 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
1588 \ ******************************\
1589 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1590 \ ******************************\
1591 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
1592 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
1593 XOR IP,X \ (new XOR old) Toggle bit (13)
1594 BIT #BIT13,X \ X(13) = New_RC5_command
1595 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
1597 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
1598 \ ******************************\
1599 \ RC5_ComputeNewRC5word \
1600 \ ******************************\
1602 MOV &BASE,2(PSP) \ save variable BASE before use
1603 MOV TOS,0(PSP) \ save TOS before use
1604 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
1605 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
1606 \ ******************************\
1607 \ RC5_ComputeC6bit \
1608 \ ******************************\
1609 BIT #$4000,IP \ test /C6 bit in IP
1610 0= IF BIS #$40,TOS \ set C6 bit in S
1611 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
1612 \ ******************************\
1613 \ RC5_CommandByteIsDone \ RC5_code --
1614 \ ******************************\
1616 \ ------------------------------\
1617 \ Display IR_RC5 code \
1618 \ ------------------------------\
1619 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
1620 \ ------------------------------\
1621 LO2HI \ switch from assembler to FORTH
1622 ['] LCD_CLEAR IS CR \ redirects CR
1623 ['] LCD_WrC IS EMIT \ redirects EMIT
1624 $10 BASE ! \ change BASE to hexadecimal
1625 CR ." $" 2 U.R \ print IR_RC5 code
1626 ['] (CR) IS CR \ restore CR
1627 ['] (EMIT) IS EMIT \ restore EMIT
1628 HI2LO \ switch from FORTH to assembler
1629 \ ------------------------------\
1630 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
1631 \ ------------------------------\
1632 MOV @PSP+,&BASE \ restore variable BASE
1633 RETI \ CPU is ON, GIE is OFF
1638 \ ------------------------------\
1639 \ TB0CTL = %0000 0010 1001 0100\$3C0
1640 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1641 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1642 \ -- \ID input divider \ 10 = /4
1643 \ -- \MC Mode Control \ 01 = up to TB0CCR0
1644 \ - \TBCLR TimerB Clear
1647 \ --------------------------------\\
1648 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1649 \ -- \CM Capture Mode
1654 \ --- \OUTMOD \ 011 = set/reset
1660 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
1662 \ ------------------------------\
1663 \ set TimerB to make 50kHz PWM \
1664 \ ------------------------------\
1665 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1666 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
1667 \ ------------------------------\
1668 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1669 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
1670 \ ------------------------------\
1671 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1672 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
1673 \ ------------------------------\
1674 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1675 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
1676 \ ------------------------------\
1677 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1678 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
1679 \ ------------------------------\
1680 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
1681 \ ------------------------------\
1682 \ set TimerB to generate PWM for LCD_Vo
1683 \ ------------------------------\
1684 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
1685 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
1686 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1687 \ ------------------------------\
1688 BIS.B #LCDVo,&LCDVo_DIR \
1689 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
1690 \ ------------------------------\
1691 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1692 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1693 \ ------------------------------\
1694 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1695 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1696 \ ------------------------------\
1697 \ WDT interval init part \
1698 \ ------------------------------\
1699 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
1700 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
1701 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
1702 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
1703 \ ------------------------------\
1705 \ ------------------------------\
1706 BIS.B #RC5,&IR_IE \ enable RC5_Int
1707 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1708 \ ------------------------------\
1709 \ init interrupt vectors
1710 \ ------------------------------\
1711 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
1712 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1713 \ ------------------------------\
1714 \ define LPM mode for ACCEPT \
1715 \ ------------------------------\
1716 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1717 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1718 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1720 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
1722 \ ------------------------------\
1724 \ ------------------------------\
1725 $03E8 20_US \ 1- wait 20 ms
1726 $03 TOP_LCD \ 2- send DB5=DB4=1
1727 $CD 20_US \ 3- wait 4,1 ms
1728 $03 TOP_LCD \ 4- send again DB5=DB4=1
1729 $5 20_US \ 5- wait 0,1 ms
1730 $03 TOP_LCD \ 6- send again again DB5=DB4=1
1731 $2 20_US \ wait 40 us = LCD cycle
1732 $02 TOP_LCD \ 7- send DB5=1 DB4=0
1733 $2 20_US \ wait 40 us = LCD cycle
1734 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1735 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1736 LCD_Clear \ 10- "LCD_Clear"
1737 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1738 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1739 LCD_Clear \ 10- "LCD_Clear"
1740 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1741 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1743 ['] (CR) IS CR \ ' (CR) is CR
1744 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
1746 ." RC5toLCD is running. Type STOP to quit"
1747 \ NOECHO \ uncomment to run this app without terminal connexion
1748 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
1749 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
1753 : STOP \ stops multitasking, must to be used before downloading app
1754 ['] (WARM) IS WARM \ remove START app from FORTH init process
1755 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
1763 CODE MAX \ n1 n2 -- n3 signed maximum
1764 CMP @PSP,TOS \ n2-n1
1765 S< ?GOTO FW1 \ n2<n1
1771 CODE MIN \ n1 n2 -- n3 signed minimum
1772 CMP @PSP,TOS \ n2-n1
1773 S< ?GOTO BW1 \ n2<n1
1779 : U.R \ u n -- display u unsigned in n width (n >= 2)
1781 R> OVER - 0 MAX SPACES TYPE
1785 CODE 20_US \ n -- n * 20 us
1786 BEGIN \ 3 cycles loop + 6~
1787 \ MOV #5,W \ 3 MCLK = 1 MHz
1788 \ MOV #23,W \ 3 MCLK = 4 MHz
1789 MOV #51,W \ 3 MCLK = 8 MHz
1790 \ MOV #104,W \ 3 MCLK = 16 MHz
1791 \ MOV #158,W \ 3 MCLK = 24 MHz
1792 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
1802 CODE TOP_LCD \ LCD Sample
1803 \ \ if write : %xxxxWWWW --
1804 \ \ if read : -- %0000RRRR
1805 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1806 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1807 0= IF \ write LCD bits pattern
1809 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1810 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1813 THEN \ read LCD bits pattern
1816 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1817 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1823 CODE LCD_W \ byte -- write byte to LCD
1825 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
1826 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
1827 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1828 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1829 COLON \ high level word starts here
1830 TOP_LCD 2 20_US \ write high nibble first
1835 CODE LCD_WrC \ char -- Write Char
1836 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1841 CODE LCD_WrF \ func -- Write Fonction
1842 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1848 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1853 $02 LCD_WrF 100 20_us
1857 \ : LCD_Entry_set $04 OR LCD_WrF ;
1859 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1861 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1863 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1865 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1867 \ : LCD_Goto $80 OR LCD_WrF ;
1869 \ CODE LCD_R \ -- byte read byte from LCD
1870 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1871 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1872 \ COLON \ starts a FORTH word
1873 \ TOP_LCD 2 20_us \ -- %0000HHHH
1874 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1875 \ HI2LO \ switch from FORTH to assembler
1876 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1877 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1878 \ MOV @RSP+,IP \ restore IP saved by COLON
1883 \ CODE LCD_RdS \ -- status Read Status
1884 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1889 \ CODE LCD_RdC \ -- char Read Char
1890 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1895 \ -------------+------+------+------+------++---+---+---+---+---------+
1896 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1897 \ -------------+------+------+------+------++---+---+---+---+---------+
1898 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1899 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1900 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1901 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1902 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1903 \ -------------+------+------+------+------++---+---+---+---+---------+
1906 \ ******************************\
1907 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1908 \ ******************************\
1909 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1910 \ ------------------------------\
1911 \ define LPM mode for ACCEPT \
1912 \ ------------------------------\
1913 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1914 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1915 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1916 BIT.B #SW2,&SW2_IN \ test switch S2
1917 0= IF \ case of switch S2 pressed
1918 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1920 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1923 BIT.B #SW1,&SW1_IN \ test switch S1 input
1924 0= IF \ case of Switch S1 pressed
1925 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1927 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1931 RETI \ CPU is ON, GIE is OFF
1936 \ ------------------------------\
1937 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1938 \ ******************************\
1939 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1940 \ ******************************\
1941 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1942 \ \ SMclock = 8|16|24 MHz
1943 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1944 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1945 \ \ SR(9)=new Toggle bit memory (ADD on)
1946 \ ------------------------------\
1947 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1948 \ ------------------------------\
1949 \ define LPM mode for ACCEPT \
1950 \ ------------------------------\
1951 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1952 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1953 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1954 \ ------------------------------\
1955 \ RC5_FirstStartBitHalfCycle: \
1956 \ ------------------------------\
1957 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1958 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1959 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1960 MOV #1778,X \ RC5_Period in us
1961 MOV #14,W \ count of loop
1963 \ ------------------------------\
1964 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1965 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1966 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1967 \ RC5_Compute_3/4_Period: \ |
1968 RRUM #1,X \ X=1/2 cycle |
1972 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1973 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1975 \ ------------------------------\
1976 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1977 \ ------------------------------\
1978 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1979 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1980 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1981 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1982 SUB #1,W \ decrement count loop
1983 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1984 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1985 0<> WHILE \ ----> out of loop ----+
1986 \ RC5_compute_7/4_Time_out: \ |
1987 ADD X,Y \ | out of bound = 7/4 period
1988 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1990 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1991 0>= IF \ | if cycle time out of bound
1992 BIC #$30,&TA0CTL \ | stop timer_A0
1993 RETI \ | then quit to do nothing
1995 \ ------------------------------\ |
1996 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1998 MOV &TA0R,X \ | | get new RC5_period value
1999 REPEAT \ ----> loop back --+ |
2000 \ ------------------------------\ |
2001 \ RC5_SampleEndOf: \ <---------------------+
2002 \ ------------------------------\
2003 BIC #$30,&TA0CTL \ stop timer_A0
2004 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
2005 \ ******************************\
2006 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2007 \ ******************************\
2008 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
2009 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2010 XOR IP,X \ (new XOR old) Toggle bit (13)
2011 BIT #BIT13,X \ X(13) = New_RC5_command
2012 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2014 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2015 \ ******************************\
2016 \ RC5_ComputeNewRC5word \
2017 \ ******************************\
2019 MOV &BASE,2(PSP) \ save variable BASE before use
2020 MOV TOS,0(PSP) \ save TOS before use
2021 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2022 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2023 \ ******************************\
2024 \ RC5_ComputeC6bit \
2025 \ ******************************\
2026 BIT #$4000,IP \ test /C6 bit in IP
2027 0= IF BIS #$40,TOS \ set C6 bit in S
2028 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2029 \ ******************************\
2030 \ RC5_CommandByteIsDone \ RC5_code --
2031 \ ******************************\
2033 \ ------------------------------\
2034 \ Display IR_RC5 code \
2035 \ ------------------------------\
2036 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2037 \ ------------------------------\
2038 LO2HI \ switch from assembler to FORTH
2039 ['] LCD_CLEAR IS CR \ redirects CR
2040 ['] LCD_WrC IS EMIT \ redirects EMIT
2041 $10 BASE ! \ change BASE to hexadecimal
2042 CR ." $" 2 U.R \ print IR_RC5 code
2043 ['] (CR) IS CR \ restore CR
2044 ['] (EMIT) IS EMIT \ restore EMIT
2045 HI2LO \ switch from FORTH to assembler
2046 \ ------------------------------\
2047 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2048 \ ------------------------------\
2049 MOV @PSP+,&BASE \ restore variable BASE
2050 RETI \ CPU is ON, GIE is OFF
2055 \ ------------------------------\
2056 \ TB0CTL = %0000 0010 1001 0100\$3C0
2057 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2058 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2059 \ -- \ID input divider \ 10 = /4
2060 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2061 \ - \TBCLR TimerB Clear
2064 \ --------------------------------\\
2065 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2066 \ -- \CM Capture Mode
2071 \ --- \OUTMOD \ 011 = set/reset
2077 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2079 \ ------------------------------\
2080 \ set TimerB to make 50kHz PWM \
2081 \ ------------------------------\
2082 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2083 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2084 \ ------------------------------\
2085 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2086 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2087 \ ------------------------------\
2088 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2089 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2090 \ ------------------------------\
2091 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2092 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2093 \ ------------------------------\
2094 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2095 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2096 \ ------------------------------\
2097 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2098 \ ------------------------------\
2099 \ set TimerB to generate PWM for LCD_Vo
2100 \ ------------------------------\
2101 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2102 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2103 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2104 \ ------------------------------\
2105 BIS.B #LCDVo,&LCDVo_DIR \
2106 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2107 \ ------------------------------\
2108 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2109 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2110 \ ------------------------------\
2111 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2112 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2113 \ ------------------------------\
2114 \ WDT interval init part \
2115 \ ------------------------------\
2116 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2117 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2118 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2119 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2120 \ ------------------------------\
2122 \ ------------------------------\
2123 BIS.B #RC5,&IR_IE \ enable RC5_Int
2124 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2125 \ ------------------------------\
2126 \ init interrupt vectors
2127 \ ------------------------------\
2128 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2129 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2130 \ ------------------------------\
2131 \ define LPM mode for ACCEPT \
2132 \ ------------------------------\
2133 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2134 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2135 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2137 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2139 \ ------------------------------\
2141 \ ------------------------------\
2142 $03E8 20_US \ 1- wait 20 ms
2143 $03 TOP_LCD \ 2- send DB5=DB4=1
2144 $CD 20_US \ 3- wait 4,1 ms
2145 $03 TOP_LCD \ 4- send again DB5=DB4=1
2146 $5 20_US \ 5- wait 0,1 ms
2147 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2148 $2 20_US \ wait 40 us = LCD cycle
2149 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2150 $2 20_US \ wait 40 us = LCD cycle
2151 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2152 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2153 LCD_Clear \ 10- "LCD_Clear"
2154 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2155 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2156 LCD_Clear \ 10- "LCD_Clear"
2157 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2158 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2160 ['] (CR) IS CR \ ' (CR) is CR
2161 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2163 ." RC5toLCD is running. Type STOP to quit"
2164 \ NOECHO \ uncomment to run this app without terminal connexion
2165 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
2166 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
2170 : STOP \ stops multitasking, must to be used before downloading app
2171 ['] (WARM) IS WARM \ remove START app from FORTH init process
2172 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
2180 CODE MAX \ n1 n2 -- n3 signed maximum
2181 CMP @PSP,TOS \ n2-n1
2182 S< ?GOTO FW1 \ n2<n1
2188 CODE MIN \ n1 n2 -- n3 signed minimum
2189 CMP @PSP,TOS \ n2-n1
2190 S< ?GOTO BW1 \ n2<n1
2196 : U.R \ u n -- display u unsigned in n width (n >= 2)
2198 R> OVER - 0 MAX SPACES TYPE
2202 CODE 20_US \ n -- n * 20 us
2203 BEGIN \ 3 cycles loop + 6~
2204 \ MOV #5,W \ 3 MCLK = 1 MHz
2205 \ MOV #23,W \ 3 MCLK = 4 MHz
2206 MOV #51,W \ 3 MCLK = 8 MHz
2207 \ MOV #104,W \ 3 MCLK = 16 MHz
2208 \ MOV #158,W \ 3 MCLK = 24 MHz
2209 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
2219 CODE TOP_LCD \ LCD Sample
2220 \ \ if write : %xxxxWWWW --
2221 \ \ if read : -- %0000RRRR
2222 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2223 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2224 0= IF \ write LCD bits pattern
2226 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2227 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2230 THEN \ read LCD bits pattern
2233 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2234 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2240 CODE LCD_W \ byte -- write byte to LCD
2242 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2243 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2244 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2245 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2246 COLON \ high level word starts here
2247 TOP_LCD 2 20_US \ write high nibble first
2252 CODE LCD_WrC \ char -- Write Char
2253 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2258 CODE LCD_WrF \ func -- Write Fonction
2259 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2265 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
2270 $02 LCD_WrF 100 20_us
2274 \ : LCD_Entry_set $04 OR LCD_WrF ;
2276 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
2278 \ : LCD_Display_Shift $10 OR LCD_WrF ;
2280 \ : LCD_Fn_Set $20 OR LCD_WrF ;
2282 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
2284 \ : LCD_Goto $80 OR LCD_WrF ;
2286 \ CODE LCD_R \ -- byte read byte from LCD
2287 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2288 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2289 \ COLON \ starts a FORTH word
2290 \ TOP_LCD 2 20_us \ -- %0000HHHH
2291 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
2292 \ HI2LO \ switch from FORTH to assembler
2293 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
2294 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
2295 \ MOV @RSP+,IP \ restore IP saved by COLON
2300 \ CODE LCD_RdS \ -- status Read Status
2301 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2306 \ CODE LCD_RdC \ -- char Read Char
2307 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2312 \ -------------+------+------+------+------++---+---+---+---+---------+
2313 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
2314 \ -------------+------+------+------+------++---+---+---+---+---------+
2315 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
2316 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
2317 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
2318 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
2319 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
2320 \ -------------+------+------+------+------++---+---+---+---+---------+
2323 \ ******************************\
2324 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2325 \ ******************************\
2326 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
2327 \ ------------------------------\
2328 \ define LPM mode for ACCEPT \
2329 \ ------------------------------\
2330 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2331 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2332 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2333 BIT.B #SW2,&SW2_IN \ test switch S2
2334 0= IF \ case of switch S2 pressed
2335 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
2337 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
2340 BIT.B #SW1,&SW1_IN \ test switch S1 input
2341 0= IF \ case of Switch S1 pressed
2342 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
2344 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
2348 RETI \ CPU is ON, GIE is OFF
2353 \ ------------------------------\
2354 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2355 \ ******************************\
2356 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2357 \ ******************************\
2358 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2359 \ \ SMclock = 8|16|24 MHz
2360 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
2361 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
2362 \ \ SR(9)=new Toggle bit memory (ADD on)
2363 \ ------------------------------\
2364 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
2365 \ ------------------------------\
2366 \ define LPM mode for ACCEPT \
2367 \ ------------------------------\
2368 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2369 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2370 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2371 \ ------------------------------\
2372 \ RC5_FirstStartBitHalfCycle: \
2373 \ ------------------------------\
2374 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
2375 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
2376 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
2377 MOV #1778,X \ RC5_Period in us
2378 MOV #14,W \ count of loop
2380 \ ------------------------------\
2381 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
2382 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
2383 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
2384 \ RC5_Compute_3/4_Period: \ |
2385 RRUM #1,X \ X=1/2 cycle |
2389 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
2390 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
2392 \ ------------------------------\
2393 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
2394 \ ------------------------------\
2395 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2396 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
2397 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2398 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2399 SUB #1,W \ decrement count loop
2400 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
2401 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2402 0<> WHILE \ ----> out of loop ----+
2403 \ RC5_compute_7/4_Time_out: \ |
2404 ADD X,Y \ | out of bound = 7/4 period
2405 \ RC5_WaitHalfCycleP1.2_IFG: \ |
2407 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
2408 0>= IF \ | if cycle time out of bound
2409 BIC #$30,&TA0CTL \ | stop timer_A0
2410 RETI \ | then quit to do nothing
2412 \ ------------------------------\ |
2413 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
2415 MOV &TA0R,X \ | | get new RC5_period value
2416 REPEAT \ ----> loop back --+ |
2417 \ ------------------------------\ |
2418 \ RC5_SampleEndOf: \ <---------------------+
2419 \ ------------------------------\
2420 BIC #$30,&TA0CTL \ stop timer_A0
2421 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
2422 \ ******************************\
2423 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2424 \ ******************************\
2425 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
2426 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2427 XOR IP,X \ (new XOR old) Toggle bit (13)
2428 BIT #BIT13,X \ X(13) = New_RC5_command
2429 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2431 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2432 \ ******************************\
2433 \ RC5_ComputeNewRC5word \
2434 \ ******************************\
2436 MOV &BASE,2(PSP) \ save variable BASE before use
2437 MOV TOS,0(PSP) \ save TOS before use
2438 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2439 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2440 \ ******************************\
2441 \ RC5_ComputeC6bit \
2442 \ ******************************\
2443 BIT #$4000,IP \ test /C6 bit in IP
2444 0= IF BIS #$40,TOS \ set C6 bit in S
2445 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2446 \ ******************************\
2447 \ RC5_CommandByteIsDone \ RC5_code --
2448 \ ******************************\
2450 \ ------------------------------\
2451 \ Display IR_RC5 code \
2452 \ ------------------------------\
2453 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2454 \ ------------------------------\
2455 LO2HI \ switch from assembler to FORTH
2456 ['] LCD_CLEAR IS CR \ redirects CR
2457 ['] LCD_WrC IS EMIT \ redirects EMIT
2458 $10 BASE ! \ change BASE to hexadecimal
2459 CR ." $" 2 U.R \ print IR_RC5 code
2460 ['] (CR) IS CR \ restore CR
2461 ['] (EMIT) IS EMIT \ restore EMIT
2462 HI2LO \ switch from FORTH to assembler
2463 \ ------------------------------\
2464 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2465 \ ------------------------------\
2466 MOV @PSP+,&BASE \ restore variable BASE
2467 RETI \ CPU is ON, GIE is OFF
2472 \ ------------------------------\
2473 \ TB0CTL = %0000 0010 1001 0100\$3C0
2474 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2475 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2476 \ -- \ID input divider \ 10 = /4
2477 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2478 \ - \TBCLR TimerB Clear
2481 \ --------------------------------\\
2482 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2483 \ -- \CM Capture Mode
2488 \ --- \OUTMOD \ 011 = set/reset
2494 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2496 \ ------------------------------\
2497 \ set TimerB to make 50kHz PWM \
2498 \ ------------------------------\
2499 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2500 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2501 \ ------------------------------\
2502 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2503 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2504 \ ------------------------------\
2505 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2506 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2507 \ ------------------------------\
2508 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2509 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2510 \ ------------------------------\
2511 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2512 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2513 \ ------------------------------\
2514 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2515 \ ------------------------------\
2516 \ set TimerB to generate PWM for LCD_Vo
2517 \ ------------------------------\
2518 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2519 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2520 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2521 \ ------------------------------\
2522 BIS.B #LCDVo,&LCDVo_DIR \
2523 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2524 \ ------------------------------\
2525 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2526 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2527 \ ------------------------------\
2528 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2529 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2530 \ ------------------------------\
2531 \ WDT interval init part \
2532 \ ------------------------------\
2533 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2534 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2535 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2536 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2537 \ ------------------------------\
2539 \ ------------------------------\
2540 BIS.B #RC5,&IR_IE \ enable RC5_Int
2541 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2542 \ ------------------------------\
2543 \ init interrupt vectors
2544 \ ------------------------------\
2545 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2546 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2547 \ ------------------------------\
2548 \ define LPM mode for ACCEPT \
2549 \ ------------------------------\
2550 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2551 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2552 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2554 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2556 \ ------------------------------\
2558 \ ------------------------------\
2559 $03E8 20_US \ 1- wait 20 ms
2560 $03 TOP_LCD \ 2- send DB5=DB4=1
2561 $CD 20_US \ 3- wait 4,1 ms
2562 $03 TOP_LCD \ 4- send again DB5=DB4=1
2563 $5 20_US \ 5- wait 0,1 ms
2564 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2565 $2 20_US \ wait 40 us = LCD cycle
2566 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2567 $2 20_US \ wait 40 us = LCD cycle
2568 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2569 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2570 LCD_Clear \ 10- "LCD_Clear"
2571 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2572 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2573 LCD_Clear \ 10- "LCD_Clear"
2574 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2575 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2577 ['] (CR) IS CR \ ' (CR) is CR
2578 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2580 ." RC5toLCD is running. Type STOP to quit"
2581 \ NOECHO \ uncomment to run this app without terminal connexion
2582 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
2583 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
2587 : STOP \ stops multitasking, must to be used before downloading app
2588 ['] (WARM) IS WARM \ remove START app from FORTH init process
2589 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
2597 CODE MAX \ n1 n2 -- n3 signed maximum
2598 CMP @PSP,TOS \ n2-n1
2599 S< ?GOTO FW1 \ n2<n1
2605 CODE MIN \ n1 n2 -- n3 signed minimum
2606 CMP @PSP,TOS \ n2-n1
2607 S< ?GOTO BW1 \ n2<n1
2613 : U.R \ u n -- display u unsigned in n width (n >= 2)
2615 R> OVER - 0 MAX SPACES TYPE
2619 CODE 20_US \ n -- n * 20 us
2620 BEGIN \ 3 cycles loop + 6~
2621 \ MOV #5,W \ 3 MCLK = 1 MHz
2622 \ MOV #23,W \ 3 MCLK = 4 MHz
2623 MOV #51,W \ 3 MCLK = 8 MHz
2624 \ MOV #104,W \ 3 MCLK = 16 MHz
2625 \ MOV #158,W \ 3 MCLK = 24 MHz
2626 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
2636 CODE TOP_LCD \ LCD Sample
2637 \ \ if write : %xxxxWWWW --
2638 \ \ if read : -- %0000RRRR
2639 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2640 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2641 0= IF \ write LCD bits pattern
2643 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2644 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2647 THEN \ read LCD bits pattern
2650 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2651 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2657 CODE LCD_W \ byte -- write byte to LCD
2659 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2660 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2661 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2662 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2663 COLON \ high level word starts here
2664 TOP_LCD 2 20_US \ write high nibble first
2669 CODE LCD_WrC \ char -- Write Char
2670 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2675 CODE LCD_WrF \ func -- Write Fonction
2676 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2682 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
2687 $02 LCD_WrF 100 20_us
2691 \ : LCD_Entry_set $04 OR LCD_WrF ;
2693 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
2695 \ : LCD_Display_Shift $10 OR LCD_WrF ;
2697 \ : LCD_Fn_Set $20 OR LCD_WrF ;
2699 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
2701 \ : LCD_Goto $80 OR LCD_WrF ;
2703 \ CODE LCD_R \ -- byte read byte from LCD
2704 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2705 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2706 \ COLON \ starts a FORTH word
2707 \ TOP_LCD 2 20_us \ -- %0000HHHH
2708 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
2709 \ HI2LO \ switch from FORTH to assembler
2710 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
2711 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
2712 \ MOV @RSP+,IP \ restore IP saved by COLON
2717 \ CODE LCD_RdS \ -- status Read Status
2718 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2723 \ CODE LCD_RdC \ -- char Read Char
2724 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2729 \ -------------+------+------+------+------++---+---+---+---+---------+
2730 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
2731 \ -------------+------+------+------+------++---+---+---+---+---------+
2732 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
2733 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
2734 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
2735 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
2736 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
2737 \ -------------+------+------+------+------++---+---+---+---+---------+
2740 \ ******************************\
2741 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2742 \ ******************************\
2743 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
2744 \ ------------------------------\
2745 \ define LPM mode for ACCEPT \
2746 \ ------------------------------\
2747 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2748 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2749 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2750 BIT.B #SW2,&SW2_IN \ test switch S2
2751 0= IF \ case of switch S2 pressed
2752 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
2754 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
2757 BIT.B #SW1,&SW1_IN \ test switch S1 input
2758 0= IF \ case of Switch S1 pressed
2759 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
2761 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
2765 RETI \ CPU is ON, GIE is OFF
2770 \ ------------------------------\
2771 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2772 \ ******************************\
2773 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2774 \ ******************************\
2775 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2776 \ \ SMclock = 8|16|24 MHz
2777 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
2778 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
2779 \ \ SR(9)=new Toggle bit memory (ADD on)
2780 \ ------------------------------\
2781 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
2782 \ ------------------------------\
2783 \ define LPM mode for ACCEPT \
2784 \ ------------------------------\
2785 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2786 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2787 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2788 \ ------------------------------\
2789 \ RC5_FirstStartBitHalfCycle: \
2790 \ ------------------------------\
2791 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
2792 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
2793 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
2794 MOV #1778,X \ RC5_Period in us
2795 MOV #14,W \ count of loop
2797 \ ------------------------------\
2798 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
2799 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
2800 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
2801 \ RC5_Compute_3/4_Period: \ |
2802 RRUM #1,X \ X=1/2 cycle |
2806 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
2807 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
2809 \ ------------------------------\
2810 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
2811 \ ------------------------------\
2812 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2813 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
2814 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2815 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2816 SUB #1,W \ decrement count loop
2817 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
2818 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2819 0<> WHILE \ ----> out of loop ----+
2820 \ RC5_compute_7/4_Time_out: \ |
2821 ADD X,Y \ | out of bound = 7/4 period
2822 \ RC5_WaitHalfCycleP1.2_IFG: \ |
2824 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
2825 0>= IF \ | if cycle time out of bound
2826 BIC #$30,&TA0CTL \ | stop timer_A0
2827 RETI \ | then quit to do nothing
2829 \ ------------------------------\ |
2830 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
2832 MOV &TA0R,X \ | | get new RC5_period value
2833 REPEAT \ ----> loop back --+ |
2834 \ ------------------------------\ |
2835 \ RC5_SampleEndOf: \ <---------------------+
2836 \ ------------------------------\
2837 BIC #$30,&TA0CTL \ stop timer_A0
2838 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
2839 \ ******************************\
2840 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2841 \ ******************************\
2842 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
2843 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2844 XOR IP,X \ (new XOR old) Toggle bit (13)
2845 BIT #BIT13,X \ X(13) = New_RC5_command
2846 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2848 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2849 \ ******************************\
2850 \ RC5_ComputeNewRC5word \
2851 \ ******************************\
2853 MOV &BASE,2(PSP) \ save variable BASE before use
2854 MOV TOS,0(PSP) \ save TOS before use
2855 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2856 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2857 \ ******************************\
2858 \ RC5_ComputeC6bit \
2859 \ ******************************\
2860 BIT #$4000,IP \ test /C6 bit in IP
2861 0= IF BIS #$40,TOS \ set C6 bit in S
2862 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2863 \ ******************************\
2864 \ RC5_CommandByteIsDone \ RC5_code --
2865 \ ******************************\
2867 \ ------------------------------\
2868 \ Display IR_RC5 code \
2869 \ ------------------------------\
2870 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2871 \ ------------------------------\
2872 LO2HI \ switch from assembler to FORTH
2873 ['] LCD_CLEAR IS CR \ redirects CR
2874 ['] LCD_WrC IS EMIT \ redirects EMIT
2875 $10 BASE ! \ change BASE to hexadecimal
2876 CR ." $" 2 U.R \ print IR_RC5 code
2877 ['] (CR) IS CR \ restore CR
2878 ['] (EMIT) IS EMIT \ restore EMIT
2879 HI2LO \ switch from FORTH to assembler
2880 \ ------------------------------\
2881 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2882 \ ------------------------------\
2883 MOV @PSP+,&BASE \ restore variable BASE
2884 RETI \ CPU is ON, GIE is OFF
2889 \ ------------------------------\
2890 \ TB0CTL = %0000 0010 1001 0100\$3C0
2891 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2892 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2893 \ -- \ID input divider \ 10 = /4
2894 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2895 \ - \TBCLR TimerB Clear
2898 \ --------------------------------\\
2899 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2900 \ -- \CM Capture Mode
2905 \ --- \OUTMOD \ 011 = set/reset
2911 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2913 \ ------------------------------\
2914 \ set TimerB to make 50kHz PWM \
2915 \ ------------------------------\
2916 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2917 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2918 \ ------------------------------\
2919 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2920 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2921 \ ------------------------------\
2922 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2923 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2924 \ ------------------------------\
2925 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2926 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2927 \ ------------------------------\
2928 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2929 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2930 \ ------------------------------\
2931 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2932 \ ------------------------------\
2933 \ set TimerB to generate PWM for LCD_Vo
2934 \ ------------------------------\
2935 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2936 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2937 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2938 \ ------------------------------\
2939 BIS.B #LCDVo,&LCDVo_DIR \
2940 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2941 \ ------------------------------\
2942 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2943 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2944 \ ------------------------------\
2945 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2946 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2947 \ ------------------------------\
2948 \ WDT interval init part \
2949 \ ------------------------------\
2950 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2951 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2952 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2953 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2954 \ ------------------------------\
2956 \ ------------------------------\
2957 BIS.B #RC5,&IR_IE \ enable RC5_Int
2958 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2959 \ ------------------------------\
2960 \ init interrupt vectors
2961 \ ------------------------------\
2962 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2963 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2964 \ ------------------------------\
2965 \ define LPM mode for ACCEPT \
2966 \ ------------------------------\
2967 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2968 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2969 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2971 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2973 \ ------------------------------\
2975 \ ------------------------------\
2976 $03E8 20_US \ 1- wait 20 ms
2977 $03 TOP_LCD \ 2- send DB5=DB4=1
2978 $CD 20_US \ 3- wait 4,1 ms
2979 $03 TOP_LCD \ 4- send again DB5=DB4=1
2980 $5 20_US \ 5- wait 0,1 ms
2981 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2982 $2 20_US \ wait 40 us = LCD cycle
2983 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2984 $2 20_US \ wait 40 us = LCD cycle
2985 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2986 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2987 LCD_Clear \ 10- "LCD_Clear"
2988 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2989 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2990 LCD_Clear \ 10- "LCD_Clear"
2991 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2992 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2994 ['] (CR) IS CR \ ' (CR) is CR
2995 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2997 ." RC5toLCD is running. Type STOP to quit"
2998 \ NOECHO \ uncomment to run this app without terminal connexion
2999 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
3000 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
3004 : STOP \ stops multitasking, must to be used before downloading app
3005 ['] (WARM) IS WARM \ remove START app from FORTH init process
3006 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
3431 CODE MAX \ n1 n2 -- n3 signed maximum
3432 CMP @PSP,TOS \ n2-n1
3433 S< ?GOTO FW1 \ n2<n1
3439 CODE MIN \ n1 n2 -- n3 signed minimum
3440 CMP @PSP,TOS \ n2-n1
3441 S< ?GOTO BW1 \ n2<n1
3447 : U.R \ u n -- display u unsigned in n width (n >= 2)
3449 R> OVER - 0 MAX SPACES TYPE
3453 CODE 20_US \ n -- n * 20 us
3454 BEGIN \ 3 cycles loop + 6~
3455 \ MOV #5,W \ 3 MCLK = 1 MHz
3456 \ MOV #23,W \ 3 MCLK = 4 MHz
3457 MOV #51,W \ 3 MCLK = 8 MHz
3458 \ MOV #104,W \ 3 MCLK = 16 MHz
3459 \ MOV #158,W \ 3 MCLK = 24 MHz
3460 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
3470 CODE TOP_LCD \ LCD Sample
3471 \ \ if write : %xxxxWWWW --
3472 \ \ if read : -- %0000RRRR
3473 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3474 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3475 0= IF \ write LCD bits pattern
3477 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3478 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3481 THEN \ read LCD bits pattern
3484 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3485 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3491 CODE LCD_W \ byte -- write byte to LCD
3493 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3494 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3495 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3496 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3497 COLON \ high level word starts here
3498 TOP_LCD 2 20_US \ write high nibble first
3503 CODE LCD_WrC \ char -- Write Char
3504 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3509 CODE LCD_WrF \ func -- Write Fonction
3510 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3516 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
3521 $02 LCD_WrF 100 20_us
3525 \ : LCD_Entry_set $04 OR LCD_WrF ;
3527 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
3529 \ : LCD_Display_Shift $10 OR LCD_WrF ;
3531 \ : LCD_Fn_Set $20 OR LCD_WrF ;
3533 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
3535 \ : LCD_Goto $80 OR LCD_WrF ;
3537 \ CODE LCD_R \ -- byte read byte from LCD
3538 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3539 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3540 \ COLON \ starts a FORTH word
3541 \ TOP_LCD 2 20_us \ -- %0000HHHH
3542 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3543 \ HI2LO \ switch from FORTH to assembler
3544 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3545 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3546 \ MOV @RSP+,IP \ restore IP saved by COLON
3551 \ CODE LCD_RdS \ -- status Read Status
3552 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3557 \ CODE LCD_RdC \ -- char Read Char
3558 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3563 \ -------------+------+------+------+------++---+---+---+---+---------+
3564 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
3565 \ -------------+------+------+------+------++---+---+---+---+---------+
3566 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
3567 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
3568 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
3569 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
3570 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
3571 \ -------------+------+------+------+------++---+---+---+---+---------+
3574 \ ******************************\
3575 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3576 \ ******************************\
3577 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
3578 \ ------------------------------\
3579 \ define LPM mode for ACCEPT \
3580 \ ------------------------------\
3581 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3582 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3583 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3584 BIT.B #SW2,&SW2_IN \ test switch S2
3585 0= IF \ case of switch S2 pressed
3586 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
3588 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
3591 BIT.B #SW1,&SW1_IN \ test switch S1 input
3592 0= IF \ case of Switch S1 pressed
3593 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
3595 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
3599 RETI \ CPU is ON, GIE is OFF
3604 \ ------------------------------\
3605 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3606 \ ******************************\
3607 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3608 \ ******************************\
3609 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3610 \ \ SMclock = 8|16|24 MHz
3611 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
3612 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
3613 \ \ SR(9)=new Toggle bit memory (ADD on)
3614 \ ------------------------------\
3615 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
3616 \ ------------------------------\
3617 \ define LPM mode for ACCEPT \
3618 \ ------------------------------\
3619 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3620 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3621 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3622 \ ------------------------------\
3623 \ RC5_FirstStartBitHalfCycle: \
3624 \ ------------------------------\
3625 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
3626 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
3627 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
3628 MOV #1778,X \ RC5_Period in us
3629 MOV #14,W \ count of loop
3631 \ ------------------------------\
3632 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
3633 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
3634 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
3635 \ RC5_Compute_3/4_Period: \ |
3636 RRUM #1,X \ X=1/2 cycle |
3640 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
3641 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
3643 \ ------------------------------\
3644 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
3645 \ ------------------------------\
3646 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3647 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
3648 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3649 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3650 SUB #1,W \ decrement count loop
3651 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
3652 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3653 0<> WHILE \ ----> out of loop ----+
3654 \ RC5_compute_7/4_Time_out: \ |
3655 ADD X,Y \ | out of bound = 7/4 period
3656 \ RC5_WaitHalfCycleP1.2_IFG: \ |
3658 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
3659 0>= IF \ | if cycle time out of bound
3660 BIC #$30,&TA0CTL \ | stop timer_A0
3661 RETI \ | then quit to do nothing
3663 \ ------------------------------\ |
3664 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
3666 MOV &TA0R,X \ | | get new RC5_period value
3667 REPEAT \ ----> loop back --+ |
3668 \ ------------------------------\ |
3669 \ RC5_SampleEndOf: \ <---------------------+
3670 \ ------------------------------\
3671 BIC #$30,&TA0CTL \ stop timer_A0
3672 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
3673 \ ******************************\
3674 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3675 \ ******************************\
3676 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
3677 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
3678 XOR IP,X \ (new XOR old) Toggle bit (13)
3679 BIT #BIT13,X \ X(13) = New_RC5_command
3680 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
3682 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
3683 \ ******************************\
3684 \ RC5_ComputeNewRC5word \
3685 \ ******************************\
3687 MOV &BASE,2(PSP) \ save variable BASE before use
3688 MOV TOS,0(PSP) \ save TOS before use
3689 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
3690 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
3691 \ ******************************\
3692 \ RC5_ComputeC6bit \
3693 \ ******************************\
3694 BIT #$4000,IP \ test /C6 bit in IP
3695 0= IF BIS #$40,TOS \ set C6 bit in S
3696 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
3697 \ ******************************\
3698 \ RC5_CommandByteIsDone \ RC5_code --
3699 \ ******************************\
3701 \ ------------------------------\
3702 \ Display IR_RC5 code \
3703 \ ------------------------------\
3704 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
3705 \ ------------------------------\
3706 LO2HI \ switch from assembler to FORTH
3707 ['] LCD_CLEAR IS CR \ redirects CR
3708 ['] LCD_WrC IS EMIT \ redirects EMIT
3709 $10 BASE ! \ change BASE to hexadecimal
3710 CR ." $" 2 U.R \ print IR_RC5 code
3711 ['] (CR) IS CR \ restore CR
3712 ['] (EMIT) IS EMIT \ restore EMIT
3713 HI2LO \ switch from FORTH to assembler
3714 \ ------------------------------\
3715 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
3716 \ ------------------------------\
3717 MOV @PSP+,&BASE \ restore variable BASE
3718 RETI \ CPU is ON, GIE is OFF
3723 \ ------------------------------\
3724 \ TB0CTL = %0000 0010 1001 0100\$3C0
3725 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3726 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3727 \ -- \ID input divider \ 10 = /4
3728 \ -- \MC Mode Control \ 01 = up to TB0CCR0
3729 \ - \TBCLR TimerB Clear
3732 \ --------------------------------\\
3733 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3734 \ -- \CM Capture Mode
3739 \ --- \OUTMOD \ 011 = set/reset
3745 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
3747 \ ------------------------------\
3748 \ set TimerB to make 50kHz PWM \
3749 \ ------------------------------\
3750 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3751 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
3752 \ ------------------------------\
3753 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3754 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
3755 \ ------------------------------\
3756 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3757 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
3758 \ ------------------------------\
3759 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3760 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
3761 \ ------------------------------\
3762 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3763 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
3764 \ ------------------------------\
3765 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
3766 \ ------------------------------\
3767 \ set TimerB to generate PWM for LCD_Vo
3768 \ ------------------------------\
3769 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
3770 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
3771 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3772 \ ------------------------------\
3773 BIS.B #LCDVo,&LCDVo_DIR \
3774 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
3775 \ ------------------------------\
3776 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3777 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3778 \ ------------------------------\
3779 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3780 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3781 \ ------------------------------\
3782 \ WDT interval init part \
3783 \ ------------------------------\
3784 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
3785 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
3786 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
3787 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
3788 \ ------------------------------\
3790 \ ------------------------------\
3791 BIS.B #RC5,&IR_IE \ enable RC5_Int
3792 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3793 \ ------------------------------\
3794 \ init interrupt vectors
3795 \ ------------------------------\
3796 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
3797 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3798 \ ------------------------------\
3799 \ define LPM mode for ACCEPT \
3800 \ ------------------------------\
3801 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3802 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3803 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3805 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
3807 \ ------------------------------\
3809 \ ------------------------------\
3810 $03E8 20_US \ 1- wait 20 ms
3811 $03 TOP_LCD \ 2- send DB5=DB4=1
3812 $CD 20_US \ 3- wait 4,1 ms
3813 $03 TOP_LCD \ 4- send again DB5=DB4=1
3814 $5 20_US \ 5- wait 0,1 ms
3815 $03 TOP_LCD \ 6- send again again DB5=DB4=1
3816 $2 20_US \ wait 40 us = LCD cycle
3817 $02 TOP_LCD \ 7- send DB5=1 DB4=0
3818 $2 20_US \ wait 40 us = LCD cycle
3819 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3820 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3821 LCD_Clear \ 10- "LCD_Clear"
3822 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3823 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3824 LCD_Clear \ 10- "LCD_Clear"
3825 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3826 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3828 ['] (CR) IS CR \ ' (CR) is CR
3829 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
3831 ." RC5toLCD is running. Type STOP to quit"
3832 \ NOECHO \ uncomment to run this app without terminal connexion
3833 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
3834 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
3838 : STOP \ stops multitasking, must to be used before downloading app
3839 ['] (WARM) IS WARM \ remove START app from FORTH init process
3840 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
3848 CODE MAX \ n1 n2 -- n3 signed maximum
3849 CMP @PSP,TOS \ n2-n1
3850 S< ?GOTO FW1 \ n2<n1
3856 CODE MIN \ n1 n2 -- n3 signed minimum
3857 CMP @PSP,TOS \ n2-n1
3858 S< ?GOTO BW1 \ n2<n1
3864 : U.R \ u n -- display u unsigned in n width (n >= 2)
3866 R> OVER - 0 MAX SPACES TYPE
3870 CODE 20_US \ n -- n * 20 us
3871 BEGIN \ 3 cycles loop + 6~
3872 \ MOV #5,W \ 3 MCLK = 1 MHz
3873 \ MOV #23,W \ 3 MCLK = 4 MHz
3874 MOV #51,W \ 3 MCLK = 8 MHz
3875 \ MOV #104,W \ 3 MCLK = 16 MHz
3876 \ MOV #158,W \ 3 MCLK = 24 MHz
3877 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
3887 CODE TOP_LCD \ LCD Sample
3888 \ \ if write : %xxxxWWWW --
3889 \ \ if read : -- %0000RRRR
3890 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3891 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3892 0= IF \ write LCD bits pattern
3894 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3895 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3898 THEN \ read LCD bits pattern
3901 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3902 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3908 CODE LCD_W \ byte -- write byte to LCD
3910 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3911 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3912 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3913 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3914 COLON \ high level word starts here
3915 TOP_LCD 2 20_US \ write high nibble first
3920 CODE LCD_WrC \ char -- Write Char
3921 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3926 CODE LCD_WrF \ func -- Write Fonction
3927 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3933 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
3938 $02 LCD_WrF 100 20_us
3942 \ : LCD_Entry_set $04 OR LCD_WrF ;
3944 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
3946 \ : LCD_Display_Shift $10 OR LCD_WrF ;
3948 \ : LCD_Fn_Set $20 OR LCD_WrF ;
3950 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
3952 \ : LCD_Goto $80 OR LCD_WrF ;
3954 \ CODE LCD_R \ -- byte read byte from LCD
3955 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3956 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3957 \ COLON \ starts a FORTH word
3958 \ TOP_LCD 2 20_us \ -- %0000HHHH
3959 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3960 \ HI2LO \ switch from FORTH to assembler
3961 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3962 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3963 \ MOV @RSP+,IP \ restore IP saved by COLON
3968 \ CODE LCD_RdS \ -- status Read Status
3969 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3974 \ CODE LCD_RdC \ -- char Read Char
3975 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3980 \ -------------+------+------+------+------++---+---+---+---+---------+
3981 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
3982 \ -------------+------+------+------+------++---+---+---+---+---------+
3983 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
3984 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
3985 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
3986 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
3987 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
3988 \ -------------+------+------+------+------++---+---+---+---+---------+
3991 \ ******************************\
3992 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3993 \ ******************************\
3994 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
3995 \ ------------------------------\
3996 \ define LPM mode for ACCEPT \
3997 \ ------------------------------\
3998 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3999 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4000 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4001 BIT.B #SW2,&SW2_IN \ test switch S2
4002 0= IF \ case of switch S2 pressed
4003 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
4005 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
4008 BIT.B #SW1,&SW1_IN \ test switch S1 input
4009 0= IF \ case of Switch S1 pressed
4010 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
4012 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
4016 RETI \ CPU is ON, GIE is OFF
4021 \ ------------------------------\
4022 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4023 \ ******************************\
4024 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4025 \ ******************************\
4026 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4027 \ \ SMclock = 8|16|24 MHz
4028 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
4029 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
4030 \ \ SR(9)=new Toggle bit memory (ADD on)
4031 \ ------------------------------\
4032 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
4033 \ ------------------------------\
4034 \ define LPM mode for ACCEPT \
4035 \ ------------------------------\
4036 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4037 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4038 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4039 \ ------------------------------\
4040 \ RC5_FirstStartBitHalfCycle: \
4041 \ ------------------------------\
4042 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
4043 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
4044 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
4045 MOV #1778,X \ RC5_Period in us
4046 MOV #14,W \ count of loop
4048 \ ------------------------------\
4049 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
4050 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
4051 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
4052 \ RC5_Compute_3/4_Period: \ |
4053 RRUM #1,X \ X=1/2 cycle |
4057 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
4058 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
4060 \ ------------------------------\
4061 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
4062 \ ------------------------------\
4063 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4064 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
4065 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4066 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4067 SUB #1,W \ decrement count loop
4068 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
4069 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4070 0<> WHILE \ ----> out of loop ----+
4071 \ RC5_compute_7/4_Time_out: \ |
4072 ADD X,Y \ | out of bound = 7/4 period
4073 \ RC5_WaitHalfCycleP1.2_IFG: \ |
4075 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
4076 0>= IF \ | if cycle time out of bound
4077 BIC #$30,&TA0CTL \ | stop timer_A0
4078 RETI \ | then quit to do nothing
4080 \ ------------------------------\ |
4081 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
4083 MOV &TA0R,X \ | | get new RC5_period value
4084 REPEAT \ ----> loop back --+ |
4085 \ ------------------------------\ |
4086 \ RC5_SampleEndOf: \ <---------------------+
4087 \ ------------------------------\
4088 BIC #$30,&TA0CTL \ stop timer_A0
4089 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
4090 \ ******************************\
4091 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4092 \ ******************************\
4093 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
4094 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
4095 XOR IP,X \ (new XOR old) Toggle bit (13)
4096 BIT #BIT13,X \ X(13) = New_RC5_command
4097 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
4099 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
4100 \ ******************************\
4101 \ RC5_ComputeNewRC5word \
4102 \ ******************************\
4104 MOV &BASE,2(PSP) \ save variable BASE before use
4105 MOV TOS,0(PSP) \ save TOS before use
4106 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
4107 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
4108 \ ******************************\
4109 \ RC5_ComputeC6bit \
4110 \ ******************************\
4111 BIT #$4000,IP \ test /C6 bit in IP
4112 0= IF BIS #$40,TOS \ set C6 bit in S
4113 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
4114 \ ******************************\
4115 \ RC5_CommandByteIsDone \ RC5_code --
4116 \ ******************************\
4118 \ ------------------------------\
4119 \ Display IR_RC5 code \
4120 \ ------------------------------\
4121 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
4122 \ ------------------------------\
4123 LO2HI \ switch from assembler to FORTH
4124 ['] LCD_CLEAR IS CR \ redirects CR
4125 ['] LCD_WrC IS EMIT \ redirects EMIT
4126 $10 BASE ! \ change BASE to hexadecimal
4127 CR ." $" 2 U.R \ print IR_RC5 code
4128 ['] (CR) IS CR \ restore CR
4129 ['] (EMIT) IS EMIT \ restore EMIT
4130 HI2LO \ switch from FORTH to assembler
4131 \ ------------------------------\
4132 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
4133 \ ------------------------------\
4134 MOV @PSP+,&BASE \ restore variable BASE
4135 RETI \ CPU is ON, GIE is OFF
4140 \ ------------------------------\
4141 \ TB0CTL = %0000 0010 1001 0100\$3C0
4142 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4143 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4144 \ -- \ID input divider \ 10 = /4
4145 \ -- \MC Mode Control \ 01 = up to TB0CCR0
4146 \ - \TBCLR TimerB Clear
4149 \ --------------------------------\\
4150 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4151 \ -- \CM Capture Mode
4156 \ --- \OUTMOD \ 011 = set/reset
4162 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
4164 \ ------------------------------\
4165 \ set TimerB to make 50kHz PWM \
4166 \ ------------------------------\
4167 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4168 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
4169 \ ------------------------------\
4170 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4171 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
4172 \ ------------------------------\
4173 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4174 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
4175 \ ------------------------------\
4176 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4177 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
4178 \ ------------------------------\
4179 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4180 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
4181 \ ------------------------------\
4182 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
4183 \ ------------------------------\
4184 \ set TimerB to generate PWM for LCD_Vo
4185 \ ------------------------------\
4186 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
4187 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
4188 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4189 \ ------------------------------\
4190 BIS.B #LCDVo,&LCDVo_DIR \
4191 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
4192 \ ------------------------------\
4193 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4194 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4195 \ ------------------------------\
4196 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4197 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4198 \ ------------------------------\
4199 \ WDT interval init part \
4200 \ ------------------------------\
4201 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
4202 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
4203 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
4204 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
4205 \ ------------------------------\
4207 \ ------------------------------\
4208 BIS.B #RC5,&IR_IE \ enable RC5_Int
4209 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4210 \ ------------------------------\
4211 \ init interrupt vectors
4212 \ ------------------------------\
4213 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
4214 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4215 \ ------------------------------\
4216 \ define LPM mode for ACCEPT \
4217 \ ------------------------------\
4218 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4219 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4220 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4222 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
4224 \ ------------------------------\
4226 \ ------------------------------\
4227 $03E8 20_US \ 1- wait 20 ms
4228 $03 TOP_LCD \ 2- send DB5=DB4=1
4229 $CD 20_US \ 3- wait 4,1 ms
4230 $03 TOP_LCD \ 4- send again DB5=DB4=1
4231 $5 20_US \ 5- wait 0,1 ms
4232 $03 TOP_LCD \ 6- send again again DB5=DB4=1
4233 $2 20_US \ wait 40 us = LCD cycle
4234 $02 TOP_LCD \ 7- send DB5=1 DB4=0
4235 $2 20_US \ wait 40 us = LCD cycle
4236 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4237 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4238 LCD_Clear \ 10- "LCD_Clear"
4239 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4240 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4241 LCD_Clear \ 10- "LCD_Clear"
4242 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4243 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4245 ['] (CR) IS CR \ ' (CR) is CR
4246 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
4248 ." RC5toLCD is running. Type STOP to quit"
4249 \ NOECHO \ uncomment to run this app without terminal connexion
4250 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
4251 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
4255 : STOP \ stops multitasking, must to be used before downloading app
4256 ['] (WARM) IS WARM \ remove START app from FORTH init process
4257 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
4265 CODE MAX \ n1 n2 -- n3 signed maximum
4266 CMP @PSP,TOS \ n2-n1
4267 S< ?GOTO FW1 \ n2<n1
4273 CODE MIN \ n1 n2 -- n3 signed minimum
4274 CMP @PSP,TOS \ n2-n1
4275 S< ?GOTO BW1 \ n2<n1
4281 : U.R \ u n -- display u unsigned in n width (n >= 2)
4283 R> OVER - 0 MAX SPACES TYPE
4287 CODE 20_US \ n -- n * 20 us
4288 BEGIN \ 3 cycles loop + 6~
4289 \ MOV #5,W \ 3 MCLK = 1 MHz
4290 \ MOV #23,W \ 3 MCLK = 4 MHz
4291 MOV #51,W \ 3 MCLK = 8 MHz
4292 \ MOV #104,W \ 3 MCLK = 16 MHz
4293 \ MOV #158,W \ 3 MCLK = 24 MHz
4294 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
4304 CODE TOP_LCD \ LCD Sample
4305 \ \ if write : %xxxxWWWW --
4306 \ \ if read : -- %0000RRRR
4307 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4308 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4309 0= IF \ write LCD bits pattern
4311 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4312 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4315 THEN \ read LCD bits pattern
4318 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4319 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4325 CODE LCD_W \ byte -- write byte to LCD
4327 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
4328 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
4329 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4330 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4331 COLON \ high level word starts here
4332 TOP_LCD 2 20_US \ write high nibble first
4337 CODE LCD_WrC \ char -- Write Char
4338 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4343 CODE LCD_WrF \ func -- Write Fonction
4344 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4350 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
4355 $02 LCD_WrF 100 20_us
4359 \ : LCD_Entry_set $04 OR LCD_WrF ;
4361 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
4363 \ : LCD_Display_Shift $10 OR LCD_WrF ;
4365 \ : LCD_Fn_Set $20 OR LCD_WrF ;
4367 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
4369 \ : LCD_Goto $80 OR LCD_WrF ;
4371 \ CODE LCD_R \ -- byte read byte from LCD
4372 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4373 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4374 \ COLON \ starts a FORTH word
4375 \ TOP_LCD 2 20_us \ -- %0000HHHH
4376 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
4377 \ HI2LO \ switch from FORTH to assembler
4378 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
4379 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
4380 \ MOV @RSP+,IP \ restore IP saved by COLON
4385 \ CODE LCD_RdS \ -- status Read Status
4386 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4391 \ CODE LCD_RdC \ -- char Read Char
4392 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4397 \ -------------+------+------+------+------++---+---+---+---+---------+
4398 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
4399 \ -------------+------+------+------+------++---+---+---+---+---------+
4400 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
4401 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
4402 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
4403 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
4404 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
4405 \ -------------+------+------+------+------++---+---+---+---+---------+
4408 \ ******************************\
4409 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4410 \ ******************************\
4411 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
4412 \ ------------------------------\
4413 \ define LPM mode for ACCEPT \
4414 \ ------------------------------\
4415 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4416 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4417 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4418 BIT.B #SW2,&SW2_IN \ test switch S2
4419 0= IF \ case of switch S2 pressed
4420 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
4422 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
4425 BIT.B #SW1,&SW1_IN \ test switch S1 input
4426 0= IF \ case of Switch S1 pressed
4427 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
4429 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
4433 RETI \ CPU is ON, GIE is OFF
4438 \ ------------------------------\
4439 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4440 \ ******************************\
4441 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4442 \ ******************************\
4443 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4444 \ \ SMclock = 8|16|24 MHz
4445 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
4446 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
4447 \ \ SR(9)=new Toggle bit memory (ADD on)
4448 \ ------------------------------\
4449 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
4450 \ ------------------------------\
4451 \ define LPM mode for ACCEPT \
4452 \ ------------------------------\
4453 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4454 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4455 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4456 \ ------------------------------\
4457 \ RC5_FirstStartBitHalfCycle: \
4458 \ ------------------------------\
4459 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
4460 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
4461 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
4462 MOV #1778,X \ RC5_Period in us
4463 MOV #14,W \ count of loop
4465 \ ------------------------------\
4466 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
4467 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
4468 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
4469 \ RC5_Compute_3/4_Period: \ |
4470 RRUM #1,X \ X=1/2 cycle |
4474 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
4475 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
4477 \ ------------------------------\
4478 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
4479 \ ------------------------------\
4480 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4481 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
4482 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4483 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4484 SUB #1,W \ decrement count loop
4485 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
4486 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4487 0<> WHILE \ ----> out of loop ----+
4488 \ RC5_compute_7/4_Time_out: \ |
4489 ADD X,Y \ | out of bound = 7/4 period
4490 \ RC5_WaitHalfCycleP1.2_IFG: \ |
4492 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
4493 0>= IF \ | if cycle time out of bound
4494 BIC #$30,&TA0CTL \ | stop timer_A0
4495 RETI \ | then quit to do nothing
4497 \ ------------------------------\ |
4498 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
4500 MOV &TA0R,X \ | | get new RC5_period value
4501 REPEAT \ ----> loop back --+ |
4502 \ ------------------------------\ |
4503 \ RC5_SampleEndOf: \ <---------------------+
4504 \ ------------------------------\
4505 BIC #$30,&TA0CTL \ stop timer_A0
4506 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
4507 \ ******************************\
4508 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4509 \ ******************************\
4510 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
4511 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
4512 XOR IP,X \ (new XOR old) Toggle bit (13)
4513 BIT #BIT13,X \ X(13) = New_RC5_command
4514 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
4516 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
4517 \ ******************************\
4518 \ RC5_ComputeNewRC5word \
4519 \ ******************************\
4521 MOV &BASE,2(PSP) \ save variable BASE before use
4522 MOV TOS,0(PSP) \ save TOS before use
4523 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
4524 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
4525 \ ******************************\
4526 \ RC5_ComputeC6bit \
4527 \ ******************************\
4528 BIT #$4000,IP \ test /C6 bit in IP
4529 0= IF BIS #$40,TOS \ set C6 bit in S
4530 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
4531 \ ******************************\
4532 \ RC5_CommandByteIsDone \ RC5_code --
4533 \ ******************************\
4535 \ ------------------------------\
4536 \ Display IR_RC5 code \
4537 \ ------------------------------\
4538 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
4539 \ ------------------------------\
4540 LO2HI \ switch from assembler to FORTH
4541 ['] LCD_CLEAR IS CR \ redirects CR
4542 ['] LCD_WrC IS EMIT \ redirects EMIT
4543 $10 BASE ! \ change BASE to hexadecimal
4544 CR ." $" 2 U.R \ print IR_RC5 code
4545 ['] (CR) IS CR \ restore CR
4546 ['] (EMIT) IS EMIT \ restore EMIT
4547 HI2LO \ switch from FORTH to assembler
4548 \ ------------------------------\
4549 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
4550 \ ------------------------------\
4551 MOV @PSP+,&BASE \ restore variable BASE
4552 RETI \ CPU is ON, GIE is OFF
4557 \ ------------------------------\
4558 \ TB0CTL = %0000 0010 1001 0100\$3C0
4559 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4560 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4561 \ -- \ID input divider \ 10 = /4
4562 \ -- \MC Mode Control \ 01 = up to TB0CCR0
4563 \ - \TBCLR TimerB Clear
4566 \ --------------------------------\\
4567 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4568 \ -- \CM Capture Mode
4573 \ --- \OUTMOD \ 011 = set/reset
4579 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
4581 \ ------------------------------\
4582 \ set TimerB to make 50kHz PWM \
4583 \ ------------------------------\
4584 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4585 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
4586 \ ------------------------------\
4587 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4588 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
4589 \ ------------------------------\
4590 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4591 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
4592 \ ------------------------------\
4593 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4594 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
4595 \ ------------------------------\
4596 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4597 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
4598 \ ------------------------------\
4599 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
4600 \ ------------------------------\
4601 \ set TimerB to generate PWM for LCD_Vo
4602 \ ------------------------------\
4603 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
4604 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
4605 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4606 \ ------------------------------\
4607 BIS.B #LCDVo,&LCDVo_DIR \
4608 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
4609 \ ------------------------------\
4610 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4611 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4612 \ ------------------------------\
4613 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4614 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4615 \ ------------------------------\
4616 \ WDT interval init part \
4617 \ ------------------------------\
4618 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
4619 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
4620 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
4621 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
4622 \ ------------------------------\
4624 \ ------------------------------\
4625 BIS.B #RC5,&IR_IE \ enable RC5_Int
4626 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4627 \ ------------------------------\
4628 \ init interrupt vectors
4629 \ ------------------------------\
4630 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
4631 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4632 \ ------------------------------\
4633 \ define LPM mode for ACCEPT \
4634 \ ------------------------------\
4635 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4636 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4637 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4639 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
4641 \ ------------------------------\
4643 \ ------------------------------\
4644 $03E8 20_US \ 1- wait 20 ms
4645 $03 TOP_LCD \ 2- send DB5=DB4=1
4646 $CD 20_US \ 3- wait 4,1 ms
4647 $03 TOP_LCD \ 4- send again DB5=DB4=1
4648 $5 20_US \ 5- wait 0,1 ms
4649 $03 TOP_LCD \ 6- send again again DB5=DB4=1
4650 $2 20_US \ wait 40 us = LCD cycle
4651 $02 TOP_LCD \ 7- send DB5=1 DB4=0
4652 $2 20_US \ wait 40 us = LCD cycle
4653 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4654 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4655 LCD_Clear \ 10- "LCD_Clear"
4656 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4657 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4658 LCD_Clear \ 10- "LCD_Clear"
4659 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4660 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4662 ['] (CR) IS CR \ ' (CR) is CR
4663 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
4665 ." RC5toLCD is running. Type STOP to quit"
4666 \ NOECHO \ uncomment to run this app without terminal connexion
4667 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
4668 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
4672 : STOP \ stops multitasking, must to be used before downloading app
4673 ['] (WARM) IS WARM \ remove START app from FORTH init process
4674 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
4682 CODE MAX \ n1 n2 -- n3 signed maximum
4683 CMP @PSP,TOS \ n2-n1
4684 S< ?GOTO FW1 \ n2<n1
4690 CODE MIN \ n1 n2 -- n3 signed minimum
4691 CMP @PSP,TOS \ n2-n1
4692 S< ?GOTO BW1 \ n2<n1
4698 : U.R \ u n -- display u unsigned in n width (n >= 2)
4700 R> OVER - 0 MAX SPACES TYPE
4704 CODE 20_US \ n -- n * 20 us
4705 BEGIN \ 3 cycles loop + 6~
4706 \ MOV #5,W \ 3 MCLK = 1 MHz
4707 \ MOV #23,W \ 3 MCLK = 4 MHz
4708 MOV #51,W \ 3 MCLK = 8 MHz
4709 \ MOV #104,W \ 3 MCLK = 16 MHz
4710 \ MOV #158,W \ 3 MCLK = 24 MHz
4711 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
4721 CODE TOP_LCD \ LCD Sample
4722 \ \ if write : %xxxxWWWW --
4723 \ \ if read : -- %0000RRRR
4724 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4725 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4726 0= IF \ write LCD bits pattern
4728 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4729 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4732 THEN \ read LCD bits pattern
4735 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4736 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4742 CODE LCD_W \ byte -- write byte to LCD
4744 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
4745 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
4746 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4747 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4748 COLON \ high level word starts here
4749 TOP_LCD 2 20_US \ write high nibble first
4754 CODE LCD_WrC \ char -- Write Char
4755 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4760 CODE LCD_WrF \ func -- Write Fonction
4761 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4767 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
4772 $02 LCD_WrF 100 20_us
4776 \ : LCD_Entry_set $04 OR LCD_WrF ;
4778 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
4780 \ : LCD_Display_Shift $10 OR LCD_WrF ;
4782 \ : LCD_Fn_Set $20 OR LCD_WrF ;
4784 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
4786 \ : LCD_Goto $80 OR LCD_WrF ;
4788 \ CODE LCD_R \ -- byte read byte from LCD
4789 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4790 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4791 \ COLON \ starts a FORTH word
4792 \ TOP_LCD 2 20_us \ -- %0000HHHH
4793 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
4794 \ HI2LO \ switch from FORTH to assembler
4795 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
4796 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
4797 \ MOV @RSP+,IP \ restore IP saved by COLON
4802 \ CODE LCD_RdS \ -- status Read Status
4803 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4808 \ CODE LCD_RdC \ -- char Read Char
4809 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4814 \ -------------+------+------+------+------++---+---+---+---+---------+
4815 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
4816 \ -------------+------+------+------+------++---+---+---+---+---------+
4817 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
4818 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
4819 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
4820 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
4821 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
4822 \ -------------+------+------+------+------++---+---+---+---+---------+
4825 \ ******************************\
4826 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4827 \ ******************************\
4828 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
4829 \ ------------------------------\
4830 \ define LPM mode for ACCEPT \
4831 \ ------------------------------\
4832 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4833 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4834 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4835 BIT.B #SW2,&SW2_IN \ test switch S2
4836 0= IF \ case of switch S2 pressed
4837 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
4839 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
4842 BIT.B #SW1,&SW1_IN \ test switch S1 input
4843 0= IF \ case of Switch S1 pressed
4844 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
4846 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
4850 RETI \ CPU is ON, GIE is OFF
4855 \ ------------------------------\
4856 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4857 \ ******************************\
4858 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4859 \ ******************************\
4860 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4861 \ \ SMclock = 8|16|24 MHz
4862 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
4863 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
4864 \ \ SR(9)=new Toggle bit memory (ADD on)
4865 \ ------------------------------\
4866 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
4867 \ ------------------------------\
4868 \ define LPM mode for ACCEPT \
4869 \ ------------------------------\
4870 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4871 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4872 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4873 \ ------------------------------\
4874 \ RC5_FirstStartBitHalfCycle: \
4875 \ ------------------------------\
4876 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
4877 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
4878 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
4879 MOV #1778,X \ RC5_Period in us
4880 MOV #14,W \ count of loop
4882 \ ------------------------------\
4883 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
4884 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
4885 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
4886 \ RC5_Compute_3/4_Period: \ |
4887 RRUM #1,X \ X=1/2 cycle |
4891 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
4892 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
4894 \ ------------------------------\
4895 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
4896 \ ------------------------------\
4897 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4898 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
4899 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4900 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4901 SUB #1,W \ decrement count loop
4902 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
4903 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4904 0<> WHILE \ ----> out of loop ----+
4905 \ RC5_compute_7/4_Time_out: \ |
4906 ADD X,Y \ | out of bound = 7/4 period
4907 \ RC5_WaitHalfCycleP1.2_IFG: \ |
4909 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
4910 0>= IF \ | if cycle time out of bound
4911 BIC #$30,&TA0CTL \ | stop timer_A0
4912 RETI \ | then quit to do nothing
4914 \ ------------------------------\ |
4915 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
4917 MOV &TA0R,X \ | | get new RC5_period value
4918 REPEAT \ ----> loop back --+ |
4919 \ ------------------------------\ |
4920 \ RC5_SampleEndOf: \ <---------------------+
4921 \ ------------------------------\
4922 BIC #$30,&TA0CTL \ stop timer_A0
4923 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
4924 \ ******************************\
4925 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4926 \ ******************************\
4927 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
4928 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
4929 XOR IP,X \ (new XOR old) Toggle bit (13)
4930 BIT #BIT13,X \ X(13) = New_RC5_command
4931 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
4933 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
4934 \ ******************************\
4935 \ RC5_ComputeNewRC5word \
4936 \ ******************************\
4938 MOV &BASE,2(PSP) \ save variable BASE before use
4939 MOV TOS,0(PSP) \ save TOS before use
4940 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
4941 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
4942 \ ******************************\
4943 \ RC5_ComputeC6bit \
4944 \ ******************************\
4945 BIT #$4000,IP \ test /C6 bit in IP
4946 0= IF BIS #$40,TOS \ set C6 bit in S
4947 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
4948 \ ******************************\
4949 \ RC5_CommandByteIsDone \ RC5_code --
4950 \ ******************************\
4952 \ ------------------------------\
4953 \ Display IR_RC5 code \
4954 \ ------------------------------\
4955 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
4956 \ ------------------------------\
4957 LO2HI \ switch from assembler to FORTH
4958 ['] LCD_CLEAR IS CR \ redirects CR
4959 ['] LCD_WrC IS EMIT \ redirects EMIT
4960 $10 BASE ! \ change BASE to hexadecimal
4961 CR ." $" 2 U.R \ print IR_RC5 code
4962 ['] (CR) IS CR \ restore CR
4963 ['] (EMIT) IS EMIT \ restore EMIT
4964 HI2LO \ switch from FORTH to assembler
4965 \ ------------------------------\
4966 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
4967 \ ------------------------------\
4968 MOV @PSP+,&BASE \ restore variable BASE
4969 RETI \ CPU is ON, GIE is OFF
4974 \ ------------------------------\
4975 \ TB0CTL = %0000 0010 1001 0100\$3C0
4976 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4977 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4978 \ -- \ID input divider \ 10 = /4
4979 \ -- \MC Mode Control \ 01 = up to TB0CCR0
4980 \ - \TBCLR TimerB Clear
4983 \ --------------------------------\\
4984 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4985 \ -- \CM Capture Mode
4990 \ --- \OUTMOD \ 011 = set/reset
4996 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
4998 \ ------------------------------\
4999 \ set TimerB to make 50kHz PWM \
5000 \ ------------------------------\
5001 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5002 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
5003 \ ------------------------------\
5004 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5005 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
5006 \ ------------------------------\
5007 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5008 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
5009 \ ------------------------------\
5010 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5011 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
5012 \ ------------------------------\
5013 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5014 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
5015 \ ------------------------------\
5016 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
5017 \ ------------------------------\
5018 \ set TimerB to generate PWM for LCD_Vo
5019 \ ------------------------------\
5020 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
5021 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
5022 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5023 \ ------------------------------\
5024 BIS.B #LCDVo,&LCDVo_DIR \
5025 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
5026 \ ------------------------------\
5027 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5028 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5029 \ ------------------------------\
5030 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5031 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5032 \ ------------------------------\
5033 \ WDT interval init part \
5034 \ ------------------------------\
5035 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
5036 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
5037 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
5038 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
5039 \ ------------------------------\
5041 \ ------------------------------\
5042 BIS.B #RC5,&IR_IE \ enable RC5_Int
5043 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5044 \ ------------------------------\
5045 \ init interrupt vectors
5046 \ ------------------------------\
5047 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
5048 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5049 \ ------------------------------\
5050 \ define LPM mode for ACCEPT \
5051 \ ------------------------------\
5052 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5053 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5054 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5056 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
5058 \ ------------------------------\
5060 \ ------------------------------\
5061 $03E8 20_US \ 1- wait 20 ms
5062 $03 TOP_LCD \ 2- send DB5=DB4=1
5063 $CD 20_US \ 3- wait 4,1 ms
5064 $03 TOP_LCD \ 4- send again DB5=DB4=1
5065 $5 20_US \ 5- wait 0,1 ms
5066 $03 TOP_LCD \ 6- send again again DB5=DB4=1
5067 $2 20_US \ wait 40 us = LCD cycle
5068 $02 TOP_LCD \ 7- send DB5=1 DB4=0
5069 $2 20_US \ wait 40 us = LCD cycle
5070 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5071 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5072 LCD_Clear \ 10- "LCD_Clear"
5073 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5074 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5075 LCD_Clear \ 10- "LCD_Clear"
5076 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5077 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5079 ['] (CR) IS CR \ ' (CR) is CR
5080 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
5082 ." RC5toLCD is running. Type STOP to quit"
5083 \ NOECHO \ uncomment to run this app without terminal connexion
5084 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
5085 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
5089 : STOP \ stops multitasking, must to be used before downloading app
5090 ['] (WARM) IS WARM \ remove START app from FORTH init process
5091 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
5099 CODE MAX \ n1 n2 -- n3 signed maximum
5100 CMP @PSP,TOS \ n2-n1
5101 S< ?GOTO FW1 \ n2<n1
5107 CODE MIN \ n1 n2 -- n3 signed minimum
5108 CMP @PSP,TOS \ n2-n1
5109 S< ?GOTO BW1 \ n2<n1
5115 : U.R \ u n -- display u unsigned in n width (n >= 2)
5117 R> OVER - 0 MAX SPACES TYPE
5121 CODE 20_US \ n -- n * 20 us
5122 BEGIN \ 3 cycles loop + 6~
5123 \ MOV #5,W \ 3 MCLK = 1 MHz
5124 \ MOV #23,W \ 3 MCLK = 4 MHz
5125 MOV #51,W \ 3 MCLK = 8 MHz
5126 \ MOV #104,W \ 3 MCLK = 16 MHz
5127 \ MOV #158,W \ 3 MCLK = 24 MHz
5128 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
5138 CODE TOP_LCD \ LCD Sample
5139 \ \ if write : %xxxxWWWW --
5140 \ \ if read : -- %0000RRRR
5141 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5142 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5143 0= IF \ write LCD bits pattern
5145 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5146 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5149 THEN \ read LCD bits pattern
5152 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5153 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5159 CODE LCD_W \ byte -- write byte to LCD
5161 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5162 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5163 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5164 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5165 COLON \ high level word starts here
5166 TOP_LCD 2 20_US \ write high nibble first
5171 CODE LCD_WrC \ char -- Write Char
5172 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5177 CODE LCD_WrF \ func -- Write Fonction
5178 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5184 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
5189 $02 LCD_WrF 100 20_us
5193 \ : LCD_Entry_set $04 OR LCD_WrF ;
5195 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
5197 \ : LCD_Display_Shift $10 OR LCD_WrF ;
5199 \ : LCD_Fn_Set $20 OR LCD_WrF ;
5201 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
5203 \ : LCD_Goto $80 OR LCD_WrF ;
5205 \ CODE LCD_R \ -- byte read byte from LCD
5206 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5207 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5208 \ COLON \ starts a FORTH word
5209 \ TOP_LCD 2 20_us \ -- %0000HHHH
5210 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
5211 \ HI2LO \ switch from FORTH to assembler
5212 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
5213 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
5214 \ MOV @RSP+,IP \ restore IP saved by COLON
5219 \ CODE LCD_RdS \ -- status Read Status
5220 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5225 \ CODE LCD_RdC \ -- char Read Char
5226 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5231 \ -------------+------+------+------+------++---+---+---+---+---------+
5232 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
5233 \ -------------+------+------+------+------++---+---+---+---+---------+
5234 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
5235 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
5236 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
5237 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
5238 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
5239 \ -------------+------+------+------+------++---+---+---+---+---------+
5242 \ ******************************\
5243 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5244 \ ******************************\
5245 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
5246 \ ------------------------------\
5247 \ define LPM mode for ACCEPT \
5248 \ ------------------------------\
5249 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5250 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5251 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5252 BIT.B #SW2,&SW2_IN \ test switch S2
5253 0= IF \ case of switch S2 pressed
5254 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
5256 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
5259 BIT.B #SW1,&SW1_IN \ test switch S1 input
5260 0= IF \ case of Switch S1 pressed
5261 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
5263 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
5267 RETI \ CPU is ON, GIE is OFF
5272 \ ------------------------------\
5273 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5274 \ ******************************\
5275 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5276 \ ******************************\
5277 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5278 \ \ SMclock = 8|16|24 MHz
5279 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
5280 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
5281 \ \ SR(9)=new Toggle bit memory (ADD on)
5282 \ ------------------------------\
5283 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
5284 \ ------------------------------\
5285 \ define LPM mode for ACCEPT \
5286 \ ------------------------------\
5287 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5288 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5289 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5290 \ ------------------------------\
5291 \ RC5_FirstStartBitHalfCycle: \
5292 \ ------------------------------\
5293 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
5294 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
5295 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
5296 MOV #1778,X \ RC5_Period in us
5297 MOV #14,W \ count of loop
5299 \ ------------------------------\
5300 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
5301 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
5302 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
5303 \ RC5_Compute_3/4_Period: \ |
5304 RRUM #1,X \ X=1/2 cycle |
5308 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
5309 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
5311 \ ------------------------------\
5312 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
5313 \ ------------------------------\
5314 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5315 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
5316 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5317 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5318 SUB #1,W \ decrement count loop
5319 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
5320 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5321 0<> WHILE \ ----> out of loop ----+
5322 \ RC5_compute_7/4_Time_out: \ |
5323 ADD X,Y \ | out of bound = 7/4 period
5324 \ RC5_WaitHalfCycleP1.2_IFG: \ |
5326 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
5327 0>= IF \ | if cycle time out of bound
5328 BIC #$30,&TA0CTL \ | stop timer_A0
5329 RETI \ | then quit to do nothing
5331 \ ------------------------------\ |
5332 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
5334 MOV &TA0R,X \ | | get new RC5_period value
5335 REPEAT \ ----> loop back --+ |
5336 \ ------------------------------\ |
5337 \ RC5_SampleEndOf: \ <---------------------+
5338 \ ------------------------------\
5339 BIC #$30,&TA0CTL \ stop timer_A0
5340 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
5341 \ ******************************\
5342 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
5343 \ ******************************\
5344 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
5345 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
5346 XOR IP,X \ (new XOR old) Toggle bit (13)
5347 BIT #BIT13,X \ X(13) = New_RC5_command
5348 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
5350 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
5351 \ ******************************\
5352 \ RC5_ComputeNewRC5word \
5353 \ ******************************\
5355 MOV &BASE,2(PSP) \ save variable BASE before use
5356 MOV TOS,0(PSP) \ save TOS before use
5357 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
5358 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
5359 \ ******************************\
5360 \ RC5_ComputeC6bit \
5361 \ ******************************\
5362 BIT #$4000,IP \ test /C6 bit in IP
5363 0= IF BIS #$40,TOS \ set C6 bit in S
5364 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
5365 \ ******************************\
5366 \ RC5_CommandByteIsDone \ RC5_code --
5367 \ ******************************\
5369 \ ------------------------------\
5370 \ Display IR_RC5 code \
5371 \ ------------------------------\
5372 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
5373 \ ------------------------------\
5374 LO2HI \ switch from assembler to FORTH
5375 ['] LCD_CLEAR IS CR \ redirects CR
5376 ['] LCD_WrC IS EMIT \ redirects EMIT
5377 $10 BASE ! \ change BASE to hexadecimal
5378 CR ." $" 2 U.R \ print IR_RC5 code
5379 ['] (CR) IS CR \ restore CR
5380 ['] (EMIT) IS EMIT \ restore EMIT
5381 HI2LO \ switch from FORTH to assembler
5382 \ ------------------------------\
5383 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
5384 \ ------------------------------\
5385 MOV @PSP+,&BASE \ restore variable BASE
5386 RETI \ CPU is ON, GIE is OFF
5391 \ ------------------------------\
5392 \ TB0CTL = %0000 0010 1001 0100\$3C0
5393 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5394 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5395 \ -- \ID input divider \ 10 = /4
5396 \ -- \MC Mode Control \ 01 = up to TB0CCR0
5397 \ - \TBCLR TimerB Clear
5400 \ --------------------------------\\
5401 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5402 \ -- \CM Capture Mode
5407 \ --- \OUTMOD \ 011 = set/reset
5413 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
5415 \ ------------------------------\
5416 \ set TimerB to make 50kHz PWM \
5417 \ ------------------------------\
5418 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5419 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
5420 \ ------------------------------\
5421 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5422 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
5423 \ ------------------------------\
5424 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5425 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
5426 \ ------------------------------\
5427 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5428 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
5429 \ ------------------------------\
5430 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5431 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
5432 \ ------------------------------\
5433 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
5434 \ ------------------------------\
5435 \ set TimerB to generate PWM for LCD_Vo
5436 \ ------------------------------\
5437 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
5438 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
5439 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5440 \ ------------------------------\
5441 BIS.B #LCDVo,&LCDVo_DIR \
5442 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
5443 \ ------------------------------\
5444 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5445 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5446 \ ------------------------------\
5447 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5448 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5449 \ ------------------------------\
5450 \ WDT interval init part \
5451 \ ------------------------------\
5452 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
5453 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
5454 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
5455 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
5456 \ ------------------------------\
5458 \ ------------------------------\
5459 BIS.B #RC5,&IR_IE \ enable RC5_Int
5460 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5461 \ ------------------------------\
5462 \ init interrupt vectors
5463 \ ------------------------------\
5464 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
5465 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5466 \ ------------------------------\
5467 \ define LPM mode for ACCEPT \
5468 \ ------------------------------\
5469 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5470 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5471 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5473 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
5475 \ ------------------------------\
5477 \ ------------------------------\
5478 $03E8 20_US \ 1- wait 20 ms
5479 $03 TOP_LCD \ 2- send DB5=DB4=1
5480 $CD 20_US \ 3- wait 4,1 ms
5481 $03 TOP_LCD \ 4- send again DB5=DB4=1
5482 $5 20_US \ 5- wait 0,1 ms
5483 $03 TOP_LCD \ 6- send again again DB5=DB4=1
5484 $2 20_US \ wait 40 us = LCD cycle
5485 $02 TOP_LCD \ 7- send DB5=1 DB4=0
5486 $2 20_US \ wait 40 us = LCD cycle
5487 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5488 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5489 LCD_Clear \ 10- "LCD_Clear"
5490 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5491 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5492 LCD_Clear \ 10- "LCD_Clear"
5493 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5494 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5496 ['] (CR) IS CR \ ' (CR) is CR
5497 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
5499 ." RC5toLCD is running. Type STOP to quit"
5500 \ NOECHO \ uncomment to run this app without terminal connexion
5501 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
5502 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
5506 : STOP \ stops multitasking, must to be used before downloading app
5507 ['] (WARM) IS WARM \ remove START app from FORTH init process
5508 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
5516 CODE MAX \ n1 n2 -- n3 signed maximum
5517 CMP @PSP,TOS \ n2-n1
5518 S< ?GOTO FW1 \ n2<n1
5524 CODE MIN \ n1 n2 -- n3 signed minimum
5525 CMP @PSP,TOS \ n2-n1
5526 S< ?GOTO BW1 \ n2<n1
5532 : U.R \ u n -- display u unsigned in n width (n >= 2)
5534 R> OVER - 0 MAX SPACES TYPE
5538 CODE 20_US \ n -- n * 20 us
5539 BEGIN \ 3 cycles loop + 6~
5540 \ MOV #5,W \ 3 MCLK = 1 MHz
5541 \ MOV #23,W \ 3 MCLK = 4 MHz
5542 MOV #51,W \ 3 MCLK = 8 MHz
5543 \ MOV #104,W \ 3 MCLK = 16 MHz
5544 \ MOV #158,W \ 3 MCLK = 24 MHz
5545 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
5555 CODE TOP_LCD \ LCD Sample
5556 \ \ if write : %xxxxWWWW --
5557 \ \ if read : -- %0000RRRR
5558 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5559 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5560 0= IF \ write LCD bits pattern
5562 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5563 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5566 THEN \ read LCD bits pattern
5569 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5570 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5576 CODE LCD_W \ byte -- write byte to LCD
5578 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5579 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5580 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5581 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5582 COLON \ high level word starts here
5583 TOP_LCD 2 20_US \ write high nibble first
5588 CODE LCD_WrC \ char -- Write Char
5589 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5594 CODE LCD_WrF \ func -- Write Fonction
5595 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5601 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
5606 $02 LCD_WrF 100 20_us
5610 \ : LCD_Entry_set $04 OR LCD_WrF ;
5612 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
5614 \ : LCD_Display_Shift $10 OR LCD_WrF ;
5616 \ : LCD_Fn_Set $20 OR LCD_WrF ;
5618 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
5620 \ : LCD_Goto $80 OR LCD_WrF ;
5622 \ CODE LCD_R \ -- byte read byte from LCD
5623 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5624 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5625 \ COLON \ starts a FORTH word
5626 \ TOP_LCD 2 20_us \ -- %0000HHHH
5627 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
5628 \ HI2LO \ switch from FORTH to assembler
5629 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
5630 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
5631 \ MOV @RSP+,IP \ restore IP saved by COLON
5636 \ CODE LCD_RdS \ -- status Read Status
5637 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5642 \ CODE LCD_RdC \ -- char Read Char
5643 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5648 \ -------------+------+------+------+------++---+---+---+---+---------+
5649 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
5650 \ -------------+------+------+------+------++---+---+---+---+---------+
5651 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
5652 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
5653 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
5654 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
5655 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
5656 \ -------------+------+------+------+------++---+---+---+---+---------+
5659 \ ******************************\
5660 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5661 \ ******************************\
5662 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
5663 \ ------------------------------\
5664 \ define LPM mode for ACCEPT \
5665 \ ------------------------------\
5666 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5667 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5668 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5669 BIT.B #SW2,&SW2_IN \ test switch S2
5670 0= IF \ case of switch S2 pressed
5671 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
5673 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
5676 BIT.B #SW1,&SW1_IN \ test switch S1 input
5677 0= IF \ case of Switch S1 pressed
5678 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
5680 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
5684 RETI \ CPU is ON, GIE is OFF
5689 \ ------------------------------\
5690 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5691 \ ******************************\
5692 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5693 \ ******************************\
5694 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5695 \ \ SMclock = 8|16|24 MHz
5696 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
5697 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
5698 \ \ SR(9)=new Toggle bit memory (ADD on)
5699 \ ------------------------------\
5700 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
5701 \ ------------------------------\
5702 \ define LPM mode for ACCEPT \
5703 \ ------------------------------\
5704 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5705 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5706 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5707 \ ------------------------------\
5708 \ RC5_FirstStartBitHalfCycle: \
5709 \ ------------------------------\
5710 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
5711 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
5712 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
5713 MOV #1778,X \ RC5_Period in us
5714 MOV #14,W \ count of loop
5716 \ ------------------------------\
5717 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
5718 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
5719 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
5720 \ RC5_Compute_3/4_Period: \ |
5721 RRUM #1,X \ X=1/2 cycle |
5725 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
5726 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
5728 \ ------------------------------\
5729 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
5730 \ ------------------------------\
5731 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5732 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
5733 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5734 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5735 SUB #1,W \ decrement count loop
5736 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
5737 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5738 0<> WHILE \ ----> out of loop ----+
5739 \ RC5_compute_7/4_Time_out: \ |
5740 ADD X,Y \ | out of bound = 7/4 period
5741 \ RC5_WaitHalfCycleP1.2_IFG: \ |
5743 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
5744 0>= IF \ | if cycle time out of bound
5745 BIC #$30,&TA0CTL \ | stop timer_A0
5746 RETI \ | then quit to do nothing
5748 \ ------------------------------\ |
5749 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
5751 MOV &TA0R,X \ | | get new RC5_period value
5752 REPEAT \ ----> loop back --+ |
5753 \ ------------------------------\ |
5754 \ RC5_SampleEndOf: \ <---------------------+
5755 \ ------------------------------\
5756 BIC #$30,&TA0CTL \ stop timer_A0
5757 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
5758 \ ******************************\
5759 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
5760 \ ******************************\
5761 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
5762 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
5763 XOR IP,X \ (new XOR old) Toggle bit (13)
5764 BIT #BIT13,X \ X(13) = New_RC5_command
5765 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
5767 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
5768 \ ******************************\
5769 \ RC5_ComputeNewRC5word \
5770 \ ******************************\
5772 MOV &BASE,2(PSP) \ save variable BASE before use
5773 MOV TOS,0(PSP) \ save TOS before use
5774 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
5775 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
5776 \ ******************************\
5777 \ RC5_ComputeC6bit \
5778 \ ******************************\
5779 BIT #$4000,IP \ test /C6 bit in IP
5780 0= IF BIS #$40,TOS \ set C6 bit in S
5781 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
5782 \ ******************************\
5783 \ RC5_CommandByteIsDone \ RC5_code --
5784 \ ******************************\
5786 \ ------------------------------\
5787 \ Display IR_RC5 code \
5788 \ ------------------------------\
5789 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
5790 \ ------------------------------\
5791 LO2HI \ switch from assembler to FORTH
5792 ['] LCD_CLEAR IS CR \ redirects CR
5793 ['] LCD_WrC IS EMIT \ redirects EMIT
5794 $10 BASE ! \ change BASE to hexadecimal
5795 CR ." $" 2 U.R \ print IR_RC5 code
5796 ['] (CR) IS CR \ restore CR
5797 ['] (EMIT) IS EMIT \ restore EMIT
5798 HI2LO \ switch from FORTH to assembler
5799 \ ------------------------------\
5800 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
5801 \ ------------------------------\
5802 MOV @PSP+,&BASE \ restore variable BASE
5803 RETI \ CPU is ON, GIE is OFF
5808 \ ------------------------------\
5809 \ TB0CTL = %0000 0010 1001 0100\$3C0
5810 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5811 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5812 \ -- \ID input divider \ 10 = /4
5813 \ -- \MC Mode Control \ 01 = up to TB0CCR0
5814 \ - \TBCLR TimerB Clear
5817 \ --------------------------------\\
5818 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5819 \ -- \CM Capture Mode
5824 \ --- \OUTMOD \ 011 = set/reset
5830 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
5832 \ ------------------------------\
5833 \ set TimerB to make 50kHz PWM \
5834 \ ------------------------------\
5835 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5836 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
5837 \ ------------------------------\
5838 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5839 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
5840 \ ------------------------------\
5841 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5842 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
5843 \ ------------------------------\
5844 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5845 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
5846 \ ------------------------------\
5847 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5848 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
5849 \ ------------------------------\
5850 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
5851 \ ------------------------------\
5852 \ set TimerB to generate PWM for LCD_Vo
5853 \ ------------------------------\
5854 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
5855 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
5856 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5857 \ ------------------------------\
5858 BIS.B #LCDVo,&LCDVo_DIR \
5859 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
5860 \ ------------------------------\
5861 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5862 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5863 \ ------------------------------\
5864 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5865 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5866 \ ------------------------------\
5867 \ WDT interval init part \
5868 \ ------------------------------\
5869 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
5870 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
5871 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
5872 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
5873 \ ------------------------------\
5875 \ ------------------------------\
5876 BIS.B #RC5,&IR_IE \ enable RC5_Int
5877 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5878 \ ------------------------------\
5879 \ init interrupt vectors
5880 \ ------------------------------\
5881 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
5882 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5883 \ ------------------------------\
5884 \ define LPM mode for ACCEPT \
5885 \ ------------------------------\
5886 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5887 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5888 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5890 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
5892 \ ------------------------------\
5894 \ ------------------------------\
5895 $03E8 20_US \ 1- wait 20 ms
5896 $03 TOP_LCD \ 2- send DB5=DB4=1
5897 $CD 20_US \ 3- wait 4,1 ms
5898 $03 TOP_LCD \ 4- send again DB5=DB4=1
5899 $5 20_US \ 5- wait 0,1 ms
5900 $03 TOP_LCD \ 6- send again again DB5=DB4=1
5901 $2 20_US \ wait 40 us = LCD cycle
5902 $02 TOP_LCD \ 7- send DB5=1 DB4=0
5903 $2 20_US \ wait 40 us = LCD cycle
5904 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5905 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5906 LCD_Clear \ 10- "LCD_Clear"
5907 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5908 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5909 LCD_Clear \ 10- "LCD_Clear"
5910 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5911 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5913 ['] (CR) IS CR \ ' (CR) is CR
5914 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
5916 ." RC5toLCD is running. Type STOP to quit"
5917 \ NOECHO \ uncomment to run this app without terminal connexion
5918 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
5919 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
5923 : STOP \ stops multitasking, must to be used before downloading app
5924 ['] (WARM) IS WARM \ remove START app from FORTH init process
5925 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
5933 CODE MAX \ n1 n2 -- n3 signed maximum
5934 CMP @PSP,TOS \ n2-n1
5935 S< ?GOTO FW1 \ n2<n1
5941 CODE MIN \ n1 n2 -- n3 signed minimum
5942 CMP @PSP,TOS \ n2-n1
5943 S< ?GOTO BW1 \ n2<n1
5949 : U.R \ u n -- display u unsigned in n width (n >= 2)
5951 R> OVER - 0 MAX SPACES TYPE
5955 CODE 20_US \ n -- n * 20 us
5956 BEGIN \ 3 cycles loop + 6~
5957 \ MOV #5,W \ 3 MCLK = 1 MHz
5958 \ MOV #23,W \ 3 MCLK = 4 MHz
5959 MOV #51,W \ 3 MCLK = 8 MHz
5960 \ MOV #104,W \ 3 MCLK = 16 MHz
5961 \ MOV #158,W \ 3 MCLK = 24 MHz
5962 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
5972 CODE TOP_LCD \ LCD Sample
5973 \ \ if write : %xxxxWWWW --
5974 \ \ if read : -- %0000RRRR
5975 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5976 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5977 0= IF \ write LCD bits pattern
5979 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5980 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5983 THEN \ read LCD bits pattern
5986 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5987 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5993 CODE LCD_W \ byte -- write byte to LCD
5995 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5996 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5997 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5998 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5999 COLON \ high level word starts here
6000 TOP_LCD 2 20_US \ write high nibble first
6005 CODE LCD_WrC \ char -- Write Char
6006 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6011 CODE LCD_WrF \ func -- Write Fonction
6012 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6018 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
6023 $02 LCD_WrF 100 20_us
6027 \ : LCD_Entry_set $04 OR LCD_WrF ;
6029 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
6031 \ : LCD_Display_Shift $10 OR LCD_WrF ;
6033 \ : LCD_Fn_Set $20 OR LCD_WrF ;
6035 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
6037 \ : LCD_Goto $80 OR LCD_WrF ;
6039 \ CODE LCD_R \ -- byte read byte from LCD
6040 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6041 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6042 \ COLON \ starts a FORTH word
6043 \ TOP_LCD 2 20_us \ -- %0000HHHH
6044 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
6045 \ HI2LO \ switch from FORTH to assembler
6046 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
6047 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
6048 \ MOV @RSP+,IP \ restore IP saved by COLON
6053 \ CODE LCD_RdS \ -- status Read Status
6054 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6059 \ CODE LCD_RdC \ -- char Read Char
6060 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6065 \ -------------+------+------+------+------++---+---+---+---+---------+
6066 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
6067 \ -------------+------+------+------+------++---+---+---+---+---------+
6068 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
6069 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
6070 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
6071 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
6072 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
6073 \ -------------+------+------+------+------++---+---+---+---+---------+
6076 \ ******************************\
6077 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6078 \ ******************************\
6079 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
6080 \ ------------------------------\
6081 \ define LPM mode for ACCEPT \
6082 \ ------------------------------\
6083 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6084 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6085 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6086 BIT.B #SW2,&SW2_IN \ test switch S2
6087 0= IF \ case of switch S2 pressed
6088 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
6090 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
6093 BIT.B #SW1,&SW1_IN \ test switch S1 input
6094 0= IF \ case of Switch S1 pressed
6095 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
6097 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
6101 RETI \ CPU is ON, GIE is OFF
6106 \ ------------------------------\
6107 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6108 \ ******************************\
6109 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6110 \ ******************************\
6111 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6112 \ \ SMclock = 8|16|24 MHz
6113 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
6114 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
6115 \ \ SR(9)=new Toggle bit memory (ADD on)
6116 \ ------------------------------\
6117 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
6118 \ ------------------------------\
6119 \ define LPM mode for ACCEPT \
6120 \ ------------------------------\
6121 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6122 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6123 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6124 \ ------------------------------\
6125 \ RC5_FirstStartBitHalfCycle: \
6126 \ ------------------------------\
6127 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
6128 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
6129 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
6130 MOV #1778,X \ RC5_Period in us
6131 MOV #14,W \ count of loop
6133 \ ------------------------------\
6134 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
6135 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
6136 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
6137 \ RC5_Compute_3/4_Period: \ |
6138 RRUM #1,X \ X=1/2 cycle |
6142 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
6143 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
6145 \ ------------------------------\
6146 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
6147 \ ------------------------------\
6148 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6149 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
6150 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6151 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6152 SUB #1,W \ decrement count loop
6153 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
6154 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6155 0<> WHILE \ ----> out of loop ----+
6156 \ RC5_compute_7/4_Time_out: \ |
6157 ADD X,Y \ | out of bound = 7/4 period
6158 \ RC5_WaitHalfCycleP1.2_IFG: \ |
6160 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
6161 0>= IF \ | if cycle time out of bound
6162 BIC #$30,&TA0CTL \ | stop timer_A0
6163 RETI \ | then quit to do nothing
6165 \ ------------------------------\ |
6166 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
6168 MOV &TA0R,X \ | | get new RC5_period value
6169 REPEAT \ ----> loop back --+ |
6170 \ ------------------------------\ |
6171 \ RC5_SampleEndOf: \ <---------------------+
6172 \ ------------------------------\
6173 BIC #$30,&TA0CTL \ stop timer_A0
6174 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
6175 \ ******************************\
6176 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
6177 \ ******************************\
6178 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
6179 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
6180 XOR IP,X \ (new XOR old) Toggle bit (13)
6181 BIT #BIT13,X \ X(13) = New_RC5_command
6182 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
6184 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
6185 \ ******************************\
6186 \ RC5_ComputeNewRC5word \
6187 \ ******************************\
6189 MOV &BASE,2(PSP) \ save variable BASE before use
6190 MOV TOS,0(PSP) \ save TOS before use
6191 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
6192 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
6193 \ ******************************\
6194 \ RC5_ComputeC6bit \
6195 \ ******************************\
6196 BIT #$4000,IP \ test /C6 bit in IP
6197 0= IF BIS #$40,TOS \ set C6 bit in S
6198 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
6199 \ ******************************\
6200 \ RC5_CommandByteIsDone \ RC5_code --
6201 \ ******************************\
6203 \ ------------------------------\
6204 \ Display IR_RC5 code \
6205 \ ------------------------------\
6206 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
6207 \ ------------------------------\
6208 LO2HI \ switch from assembler to FORTH
6209 ['] LCD_CLEAR IS CR \ redirects CR
6210 ['] LCD_WrC IS EMIT \ redirects EMIT
6211 $10 BASE ! \ change BASE to hexadecimal
6212 CR ." $" 2 U.R \ print IR_RC5 code
6213 ['] (CR) IS CR \ restore CR
6214 ['] (EMIT) IS EMIT \ restore EMIT
6215 HI2LO \ switch from FORTH to assembler
6216 \ ------------------------------\
6217 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
6218 \ ------------------------------\
6219 MOV @PSP+,&BASE \ restore variable BASE
6220 RETI \ CPU is ON, GIE is OFF
6225 \ ------------------------------\
6226 \ TB0CTL = %0000 0010 1001 0100\$3C0
6227 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6228 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6229 \ -- \ID input divider \ 10 = /4
6230 \ -- \MC Mode Control \ 01 = up to TB0CCR0
6231 \ - \TBCLR TimerB Clear
6234 \ --------------------------------\\
6235 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6236 \ -- \CM Capture Mode
6241 \ --- \OUTMOD \ 011 = set/reset
6247 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
6249 \ ------------------------------\
6250 \ set TimerB to make 50kHz PWM \
6251 \ ------------------------------\
6252 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
6253 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
6254 \ ------------------------------\
6255 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
6256 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
6257 \ ------------------------------\
6258 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6259 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
6260 \ ------------------------------\
6261 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6262 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
6263 \ ------------------------------\
6264 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6265 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
6266 \ ------------------------------\
6267 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
6268 \ ------------------------------\
6269 \ set TimerB to generate PWM for LCD_Vo
6270 \ ------------------------------\
6271 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
6272 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
6273 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6274 \ ------------------------------\
6275 BIS.B #LCDVo,&LCDVo_DIR \
6276 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
6277 \ ------------------------------\
6278 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6279 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6280 \ ------------------------------\
6281 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6282 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6283 \ ------------------------------\
6284 \ WDT interval init part \
6285 \ ------------------------------\
6286 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
6287 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
6288 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
6289 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
6290 \ ------------------------------\
6292 \ ------------------------------\
6293 BIS.B #RC5,&IR_IE \ enable RC5_Int
6294 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6295 \ ------------------------------\
6296 \ init interrupt vectors
6297 \ ------------------------------\
6298 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
6299 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6300 \ ------------------------------\
6301 \ define LPM mode for ACCEPT \
6302 \ ------------------------------\
6303 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6304 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6305 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6307 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
6309 \ ------------------------------\
6311 \ ------------------------------\
6312 $03E8 20_US \ 1- wait 20 ms
6313 $03 TOP_LCD \ 2- send DB5=DB4=1
6314 $CD 20_US \ 3- wait 4,1 ms
6315 $03 TOP_LCD \ 4- send again DB5=DB4=1
6316 $5 20_US \ 5- wait 0,1 ms
6317 $03 TOP_LCD \ 6- send again again DB5=DB4=1
6318 $2 20_US \ wait 40 us = LCD cycle
6319 $02 TOP_LCD \ 7- send DB5=1 DB4=0
6320 $2 20_US \ wait 40 us = LCD cycle
6321 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6322 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6323 LCD_Clear \ 10- "LCD_Clear"
6324 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6325 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6326 LCD_Clear \ 10- "LCD_Clear"
6327 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6328 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6330 ['] (CR) IS CR \ ' (CR) is CR
6331 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
6333 ." RC5toLCD is running. Type STOP to quit"
6334 \ NOECHO \ uncomment to run this app without terminal connexion
6335 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
6336 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
6340 : STOP \ stops multitasking, must to be used before downloading app
6341 ['] (WARM) IS WARM \ remove START app from FORTH init process
6342 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
6350 CODE MAX \ n1 n2 -- n3 signed maximum
6351 CMP @PSP,TOS \ n2-n1
6352 S< ?GOTO FW1 \ n2<n1
6358 CODE MIN \ n1 n2 -- n3 signed minimum
6359 CMP @PSP,TOS \ n2-n1
6360 S< ?GOTO BW1 \ n2<n1
6366 : U.R \ u n -- display u unsigned in n width (n >= 2)
6368 R> OVER - 0 MAX SPACES TYPE
6372 CODE 20_US \ n -- n * 20 us
6373 BEGIN \ 3 cycles loop + 6~
6374 \ MOV #5,W \ 3 MCLK = 1 MHz
6375 \ MOV #23,W \ 3 MCLK = 4 MHz
6376 MOV #51,W \ 3 MCLK = 8 MHz
6377 \ MOV #104,W \ 3 MCLK = 16 MHz
6378 \ MOV #158,W \ 3 MCLK = 24 MHz
6379 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
6389 CODE TOP_LCD \ LCD Sample
6390 \ \ if write : %xxxxWWWW --
6391 \ \ if read : -- %0000RRRR
6392 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6393 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6394 0= IF \ write LCD bits pattern
6396 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6397 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6400 THEN \ read LCD bits pattern
6403 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6404 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6410 CODE LCD_W \ byte -- write byte to LCD
6412 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
6413 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
6414 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6415 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6416 COLON \ high level word starts here
6417 TOP_LCD 2 20_US \ write high nibble first
6422 CODE LCD_WrC \ char -- Write Char
6423 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6428 CODE LCD_WrF \ func -- Write Fonction
6429 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6435 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
6440 $02 LCD_WrF 100 20_us
6444 \ : LCD_Entry_set $04 OR LCD_WrF ;
6446 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
6448 \ : LCD_Display_Shift $10 OR LCD_WrF ;
6450 \ : LCD_Fn_Set $20 OR LCD_WrF ;
6452 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
6454 \ : LCD_Goto $80 OR LCD_WrF ;
6456 \ CODE LCD_R \ -- byte read byte from LCD
6457 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6458 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6459 \ COLON \ starts a FORTH word
6460 \ TOP_LCD 2 20_us \ -- %0000HHHH
6461 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
6462 \ HI2LO \ switch from FORTH to assembler
6463 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
6464 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
6465 \ MOV @RSP+,IP \ restore IP saved by COLON
6470 \ CODE LCD_RdS \ -- status Read Status
6471 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6476 \ CODE LCD_RdC \ -- char Read Char
6477 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6482 \ -------------+------+------+------+------++---+---+---+---+---------+
6483 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
6484 \ -------------+------+------+------+------++---+---+---+---+---------+
6485 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
6486 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
6487 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
6488 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
6489 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
6490 \ -------------+------+------+------+------++---+---+---+---+---------+
6493 \ ******************************\
6494 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6495 \ ******************************\
6496 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
6497 \ ------------------------------\
6498 \ define LPM mode for ACCEPT \
6499 \ ------------------------------\
6500 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6501 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6502 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6503 BIT.B #SW2,&SW2_IN \ test switch S2
6504 0= IF \ case of switch S2 pressed
6505 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
6507 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
6510 BIT.B #SW1,&SW1_IN \ test switch S1 input
6511 0= IF \ case of Switch S1 pressed
6512 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
6514 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
6518 RETI \ CPU is ON, GIE is OFF
6523 \ ------------------------------\
6524 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6525 \ ******************************\
6526 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6527 \ ******************************\
6528 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6529 \ \ SMclock = 8|16|24 MHz
6530 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
6531 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
6532 \ \ SR(9)=new Toggle bit memory (ADD on)
6533 \ ------------------------------\
6534 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
6535 \ ------------------------------\
6536 \ define LPM mode for ACCEPT \
6537 \ ------------------------------\
6538 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6539 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6540 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6541 \ ------------------------------\
6542 \ RC5_FirstStartBitHalfCycle: \
6543 \ ------------------------------\
6544 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
6545 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
6546 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
6547 MOV #1778,X \ RC5_Period in us
6548 MOV #14,W \ count of loop
6550 \ ------------------------------\
6551 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
6552 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
6553 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
6554 \ RC5_Compute_3/4_Period: \ |
6555 RRUM #1,X \ X=1/2 cycle |
6559 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
6560 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
6562 \ ------------------------------\
6563 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
6564 \ ------------------------------\
6565 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6566 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
6567 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6568 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6569 SUB #1,W \ decrement count loop
6570 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
6571 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6572 0<> WHILE \ ----> out of loop ----+
6573 \ RC5_compute_7/4_Time_out: \ |
6574 ADD X,Y \ | out of bound = 7/4 period
6575 \ RC5_WaitHalfCycleP1.2_IFG: \ |
6577 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
6578 0>= IF \ | if cycle time out of bound
6579 BIC #$30,&TA0CTL \ | stop timer_A0
6580 RETI \ | then quit to do nothing
6582 \ ------------------------------\ |
6583 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
6585 MOV &TA0R,X \ | | get new RC5_period value
6586 REPEAT \ ----> loop back --+ |
6587 \ ------------------------------\ |
6588 \ RC5_SampleEndOf: \ <---------------------+
6589 \ ------------------------------\
6590 BIC #$30,&TA0CTL \ stop timer_A0
6591 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
6592 \ ******************************\
6593 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
6594 \ ******************************\
6595 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
6596 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
6597 XOR IP,X \ (new XOR old) Toggle bit (13)
6598 BIT #BIT13,X \ X(13) = New_RC5_command
6599 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
6601 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
6602 \ ******************************\
6603 \ RC5_ComputeNewRC5word \
6604 \ ******************************\
6606 MOV &BASE,2(PSP) \ save variable BASE before use
6607 MOV TOS,0(PSP) \ save TOS before use
6608 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
6609 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
6610 \ ******************************\
6611 \ RC5_ComputeC6bit \
6612 \ ******************************\
6613 BIT #$4000,IP \ test /C6 bit in IP
6614 0= IF BIS #$40,TOS \ set C6 bit in S
6615 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
6616 \ ******************************\
6617 \ RC5_CommandByteIsDone \ RC5_code --
6618 \ ******************************\
6620 \ ------------------------------\
6621 \ Display IR_RC5 code \
6622 \ ------------------------------\
6623 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
6624 \ ------------------------------\
6625 LO2HI \ switch from assembler to FORTH
6626 ['] LCD_CLEAR IS CR \ redirects CR
6627 ['] LCD_WrC IS EMIT \ redirects EMIT
6628 $10 BASE ! \ change BASE to hexadecimal
6629 CR ." $" 2 U.R \ print IR_RC5 code
6630 ['] (CR) IS CR \ restore CR
6631 ['] (EMIT) IS EMIT \ restore EMIT
6632 HI2LO \ switch from FORTH to assembler
6633 \ ------------------------------\
6634 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
6635 \ ------------------------------\
6636 MOV @PSP+,&BASE \ restore variable BASE
6637 RETI \ CPU is ON, GIE is OFF
6642 \ ------------------------------\
6643 \ TB0CTL = %0000 0010 1001 0100\$3C0
6644 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6645 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6646 \ -- \ID input divider \ 10 = /4
6647 \ -- \MC Mode Control \ 01 = up to TB0CCR0
6648 \ - \TBCLR TimerB Clear
6651 \ --------------------------------\\
6652 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6653 \ -- \CM Capture Mode
6658 \ --- \OUTMOD \ 011 = set/reset
6664 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
6666 \ ------------------------------\
6667 \ set TimerB to make 50kHz PWM \
6668 \ ------------------------------\
6669 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
6670 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
6671 \ ------------------------------\
6672 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
6673 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
6674 \ ------------------------------\
6675 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6676 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
6677 \ ------------------------------\
6678 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6679 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
6680 \ ------------------------------\
6681 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6682 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
6683 \ ------------------------------\
6684 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
6685 \ ------------------------------\
6686 \ set TimerB to generate PWM for LCD_Vo
6687 \ ------------------------------\
6688 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
6689 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
6690 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6691 \ ------------------------------\
6692 BIS.B #LCDVo,&LCDVo_DIR \
6693 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
6694 \ ------------------------------\
6695 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6696 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6697 \ ------------------------------\
6698 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6699 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6700 \ ------------------------------\
6701 \ WDT interval init part \
6702 \ ------------------------------\
6703 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
6704 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
6705 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
6706 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
6707 \ ------------------------------\
6709 \ ------------------------------\
6710 BIS.B #RC5,&IR_IE \ enable RC5_Int
6711 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6712 \ ------------------------------\
6713 \ init interrupt vectors
6714 \ ------------------------------\
6715 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
6716 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6717 \ ------------------------------\
6718 \ define LPM mode for ACCEPT \
6719 \ ------------------------------\
6720 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6721 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6722 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6724 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
6726 \ ------------------------------\
6728 \ ------------------------------\
6729 $03E8 20_US \ 1- wait 20 ms
6730 $03 TOP_LCD \ 2- send DB5=DB4=1
6731 $CD 20_US \ 3- wait 4,1 ms
6732 $03 TOP_LCD \ 4- send again DB5=DB4=1
6733 $5 20_US \ 5- wait 0,1 ms
6734 $03 TOP_LCD \ 6- send again again DB5=DB4=1
6735 $2 20_US \ wait 40 us = LCD cycle
6736 $02 TOP_LCD \ 7- send DB5=1 DB4=0
6737 $2 20_US \ wait 40 us = LCD cycle
6738 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6739 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6740 LCD_Clear \ 10- "LCD_Clear"
6741 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6742 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6743 LCD_Clear \ 10- "LCD_Clear"
6744 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6745 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6747 ['] (CR) IS CR \ ' (CR) is CR
6748 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
6750 ." RC5toLCD is running. Type STOP to quit"
6751 \ NOECHO \ uncomment to run this app without terminal connexion
6752 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
6753 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
6757 : STOP \ stops multitasking, must to be used before downloading app
6758 ['] (WARM) IS WARM \ remove START app from FORTH init process
6759 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
6767 CODE MAX \ n1 n2 -- n3 signed maximum
6768 CMP @PSP,TOS \ n2-n1
6769 S< ?GOTO FW1 \ n2<n1
6775 CODE MIN \ n1 n2 -- n3 signed minimum
6776 CMP @PSP,TOS \ n2-n1
6777 S< ?GOTO BW1 \ n2<n1
6783 : U.R \ u n -- display u unsigned in n width (n >= 2)
6785 R> OVER - 0 MAX SPACES TYPE
6789 CODE 20_US \ n -- n * 20 us
6790 BEGIN \ 3 cycles loop + 6~
6791 \ MOV #5,W \ 3 MCLK = 1 MHz
6792 \ MOV #23,W \ 3 MCLK = 4 MHz
6793 MOV #51,W \ 3 MCLK = 8 MHz
6794 \ MOV #104,W \ 3 MCLK = 16 MHz
6795 \ MOV #158,W \ 3 MCLK = 24 MHz
6796 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
6806 CODE TOP_LCD \ LCD Sample
6807 \ \ if write : %xxxxWWWW --
6808 \ \ if read : -- %0000RRRR
6809 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6810 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6811 0= IF \ write LCD bits pattern
6813 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6814 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6817 THEN \ read LCD bits pattern
6820 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6821 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6827 CODE LCD_W \ byte -- write byte to LCD
6829 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
6830 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
6831 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6832 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6833 COLON \ high level word starts here
6834 TOP_LCD 2 20_US \ write high nibble first
6839 CODE LCD_WrC \ char -- Write Char
6840 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6845 CODE LCD_WrF \ func -- Write Fonction
6846 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6852 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
6857 $02 LCD_WrF 100 20_us
6861 \ : LCD_Entry_set $04 OR LCD_WrF ;
6863 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
6865 \ : LCD_Display_Shift $10 OR LCD_WrF ;
6867 \ : LCD_Fn_Set $20 OR LCD_WrF ;
6869 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
6871 \ : LCD_Goto $80 OR LCD_WrF ;
6873 \ CODE LCD_R \ -- byte read byte from LCD
6874 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6875 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6876 \ COLON \ starts a FORTH word
6877 \ TOP_LCD 2 20_us \ -- %0000HHHH
6878 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
6879 \ HI2LO \ switch from FORTH to assembler
6880 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
6881 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
6882 \ MOV @RSP+,IP \ restore IP saved by COLON
6887 \ CODE LCD_RdS \ -- status Read Status
6888 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6893 \ CODE LCD_RdC \ -- char Read Char
6894 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6899 \ -------------+------+------+------+------++---+---+---+---+---------+
6900 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
6901 \ -------------+------+------+------+------++---+---+---+---+---------+
6902 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
6903 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
6904 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
6905 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
6906 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
6907 \ -------------+------+------+------+------++---+---+---+---+---------+
6910 \ ******************************\
6911 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6912 \ ******************************\
6913 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
6914 \ ------------------------------\
6915 \ define LPM mode for ACCEPT \
6916 \ ------------------------------\
6917 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6918 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6919 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6920 BIT.B #SW2,&SW2_IN \ test switch S2
6921 0= IF \ case of switch S2 pressed
6922 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
6924 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
6927 BIT.B #SW1,&SW1_IN \ test switch S1 input
6928 0= IF \ case of Switch S1 pressed
6929 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
6931 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
6935 RETI \ CPU is ON, GIE is OFF
6940 \ ------------------------------\
6941 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6942 \ ******************************\
6943 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6944 \ ******************************\
6945 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6946 \ \ SMclock = 8|16|24 MHz
6947 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
6948 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
6949 \ \ SR(9)=new Toggle bit memory (ADD on)
6950 \ ------------------------------\
6951 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
6952 \ ------------------------------\
6953 \ define LPM mode for ACCEPT \
6954 \ ------------------------------\
6955 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6956 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6957 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6958 \ ------------------------------\
6959 \ RC5_FirstStartBitHalfCycle: \
6960 \ ------------------------------\
6961 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
6962 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
6963 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
6964 MOV #1778,X \ RC5_Period in us
6965 MOV #14,W \ count of loop
6967 \ ------------------------------\
6968 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
6969 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
6970 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
6971 \ RC5_Compute_3/4_Period: \ |
6972 RRUM #1,X \ X=1/2 cycle |
6976 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
6977 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
6979 \ ------------------------------\
6980 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
6981 \ ------------------------------\
6982 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6983 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
6984 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6985 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6986 SUB #1,W \ decrement count loop
6987 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
6988 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6989 0<> WHILE \ ----> out of loop ----+
6990 \ RC5_compute_7/4_Time_out: \ |
6991 ADD X,Y \ | out of bound = 7/4 period
6992 \ RC5_WaitHalfCycleP1.2_IFG: \ |
6994 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
6995 0>= IF \ | if cycle time out of bound
6996 BIC #$30,&TA0CTL \ | stop timer_A0
6997 RETI \ | then quit to do nothing
6999 \ ------------------------------\ |
7000 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
7002 MOV &TA0R,X \ | | get new RC5_period value
7003 REPEAT \ ----> loop back --+ |
7004 \ ------------------------------\ |
7005 \ RC5_SampleEndOf: \ <---------------------+
7006 \ ------------------------------\
7007 BIC #$30,&TA0CTL \ stop timer_A0
7008 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
7009 \ ******************************\
7010 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7011 \ ******************************\
7012 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
7013 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
7014 XOR IP,X \ (new XOR old) Toggle bit (13)
7015 BIT #BIT13,X \ X(13) = New_RC5_command
7016 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
7018 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
7019 \ ******************************\
7020 \ RC5_ComputeNewRC5word \
7021 \ ******************************\
7023 MOV &BASE,2(PSP) \ save variable BASE before use
7024 MOV TOS,0(PSP) \ save TOS before use
7025 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
7026 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
7027 \ ******************************\
7028 \ RC5_ComputeC6bit \
7029 \ ******************************\
7030 BIT #$4000,IP \ test /C6 bit in IP
7031 0= IF BIS #$40,TOS \ set C6 bit in S
7032 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
7033 \ ******************************\
7034 \ RC5_CommandByteIsDone \ RC5_code --
7035 \ ******************************\
7037 \ ------------------------------\
7038 \ Display IR_RC5 code \
7039 \ ------------------------------\
7040 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
7041 \ ------------------------------\
7042 LO2HI \ switch from assembler to FORTH
7043 ['] LCD_CLEAR IS CR \ redirects CR
7044 ['] LCD_WrC IS EMIT \ redirects EMIT
7045 $10 BASE ! \ change BASE to hexadecimal
7046 CR ." $" 2 U.R \ print IR_RC5 code
7047 ['] (CR) IS CR \ restore CR
7048 ['] (EMIT) IS EMIT \ restore EMIT
7049 HI2LO \ switch from FORTH to assembler
7050 \ ------------------------------\
7051 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
7052 \ ------------------------------\
7053 MOV @PSP+,&BASE \ restore variable BASE
7054 RETI \ CPU is ON, GIE is OFF
7059 \ ------------------------------\
7060 \ TB0CTL = %0000 0010 1001 0100\$3C0
7061 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7062 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7063 \ -- \ID input divider \ 10 = /4
7064 \ -- \MC Mode Control \ 01 = up to TB0CCR0
7065 \ - \TBCLR TimerB Clear
7068 \ --------------------------------\\
7069 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7070 \ -- \CM Capture Mode
7075 \ --- \OUTMOD \ 011 = set/reset
7081 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
7083 \ ------------------------------\
7084 \ set TimerB to make 50kHz PWM \
7085 \ ------------------------------\
7086 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7087 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
7088 \ ------------------------------\
7089 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7090 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
7091 \ ------------------------------\
7092 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7093 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
7094 \ ------------------------------\
7095 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7096 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
7097 \ ------------------------------\
7098 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7099 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
7100 \ ------------------------------\
7101 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
7102 \ ------------------------------\
7103 \ set TimerB to generate PWM for LCD_Vo
7104 \ ------------------------------\
7105 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
7106 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
7107 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7108 \ ------------------------------\
7109 BIS.B #LCDVo,&LCDVo_DIR \
7110 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
7111 \ ------------------------------\
7112 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7113 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7114 \ ------------------------------\
7115 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7116 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7117 \ ------------------------------\
7118 \ WDT interval init part \
7119 \ ------------------------------\
7120 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
7121 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
7122 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
7123 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
7124 \ ------------------------------\
7126 \ ------------------------------\
7127 BIS.B #RC5,&IR_IE \ enable RC5_Int
7128 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7129 \ ------------------------------\
7130 \ init interrupt vectors
7131 \ ------------------------------\
7132 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
7133 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7134 \ ------------------------------\
7135 \ define LPM mode for ACCEPT \
7136 \ ------------------------------\
7137 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7138 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7139 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7141 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
7143 \ ------------------------------\
7145 \ ------------------------------\
7146 $03E8 20_US \ 1- wait 20 ms
7147 $03 TOP_LCD \ 2- send DB5=DB4=1
7148 $CD 20_US \ 3- wait 4,1 ms
7149 $03 TOP_LCD \ 4- send again DB5=DB4=1
7150 $5 20_US \ 5- wait 0,1 ms
7151 $03 TOP_LCD \ 6- send again again DB5=DB4=1
7152 $2 20_US \ wait 40 us = LCD cycle
7153 $02 TOP_LCD \ 7- send DB5=1 DB4=0
7154 $2 20_US \ wait 40 us = LCD cycle
7155 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7156 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7157 LCD_Clear \ 10- "LCD_Clear"
7158 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7159 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7160 LCD_Clear \ 10- "LCD_Clear"
7161 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7162 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7164 ['] (CR) IS CR \ ' (CR) is CR
7165 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
7167 ." RC5toLCD is running. Type STOP to quit"
7168 \ NOECHO \ uncomment to run this app without terminal connexion
7169 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
7170 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
7174 : STOP \ stops multitasking, must to be used before downloading app
7175 ['] (WARM) IS WARM \ remove START app from FORTH init process
7176 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
7184 CODE MAX \ n1 n2 -- n3 signed maximum
7185 CMP @PSP,TOS \ n2-n1
7186 S< ?GOTO FW1 \ n2<n1
7192 CODE MIN \ n1 n2 -- n3 signed minimum
7193 CMP @PSP,TOS \ n2-n1
7194 S< ?GOTO BW1 \ n2<n1
7200 : U.R \ u n -- display u unsigned in n width (n >= 2)
7202 R> OVER - 0 MAX SPACES TYPE
7206 CODE 20_US \ n -- n * 20 us
7207 BEGIN \ 3 cycles loop + 6~
7208 \ MOV #5,W \ 3 MCLK = 1 MHz
7209 \ MOV #23,W \ 3 MCLK = 4 MHz
7210 MOV #51,W \ 3 MCLK = 8 MHz
7211 \ MOV #104,W \ 3 MCLK = 16 MHz
7212 \ MOV #158,W \ 3 MCLK = 24 MHz
7213 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
7223 CODE TOP_LCD \ LCD Sample
7224 \ \ if write : %xxxxWWWW --
7225 \ \ if read : -- %0000RRRR
7226 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7227 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7228 0= IF \ write LCD bits pattern
7230 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7231 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7234 THEN \ read LCD bits pattern
7237 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7238 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7244 CODE LCD_W \ byte -- write byte to LCD
7246 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
7247 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
7248 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7249 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7250 COLON \ high level word starts here
7251 TOP_LCD 2 20_US \ write high nibble first
7256 CODE LCD_WrC \ char -- Write Char
7257 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7262 CODE LCD_WrF \ func -- Write Fonction
7263 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7269 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
7274 $02 LCD_WrF 100 20_us
7278 \ : LCD_Entry_set $04 OR LCD_WrF ;
7280 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
7282 \ : LCD_Display_Shift $10 OR LCD_WrF ;
7284 \ : LCD_Fn_Set $20 OR LCD_WrF ;
7286 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
7288 \ : LCD_Goto $80 OR LCD_WrF ;
7290 \ CODE LCD_R \ -- byte read byte from LCD
7291 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7292 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7293 \ COLON \ starts a FORTH word
7294 \ TOP_LCD 2 20_us \ -- %0000HHHH
7295 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
7296 \ HI2LO \ switch from FORTH to assembler
7297 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
7298 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
7299 \ MOV @RSP+,IP \ restore IP saved by COLON
7304 \ CODE LCD_RdS \ -- status Read Status
7305 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7310 \ CODE LCD_RdC \ -- char Read Char
7311 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7316 \ -------------+------+------+------+------++---+---+---+---+---------+
7317 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
7318 \ -------------+------+------+------+------++---+---+---+---+---------+
7319 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
7320 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
7321 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
7322 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
7323 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
7324 \ -------------+------+------+------+------++---+---+---+---+---------+
7327 \ ******************************\
7328 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7329 \ ******************************\
7330 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
7331 \ ------------------------------\
7332 \ define LPM mode for ACCEPT \
7333 \ ------------------------------\
7334 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7335 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7336 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7337 BIT.B #SW2,&SW2_IN \ test switch S2
7338 0= IF \ case of switch S2 pressed
7339 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
7341 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
7344 BIT.B #SW1,&SW1_IN \ test switch S1 input
7345 0= IF \ case of Switch S1 pressed
7346 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
7348 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
7352 RETI \ CPU is ON, GIE is OFF
7357 \ ------------------------------\
7358 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7359 \ ******************************\
7360 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7361 \ ******************************\
7362 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7363 \ \ SMclock = 8|16|24 MHz
7364 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
7365 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
7366 \ \ SR(9)=new Toggle bit memory (ADD on)
7367 \ ------------------------------\
7368 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
7369 \ ------------------------------\
7370 \ define LPM mode for ACCEPT \
7371 \ ------------------------------\
7372 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7373 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7374 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7375 \ ------------------------------\
7376 \ RC5_FirstStartBitHalfCycle: \
7377 \ ------------------------------\
7378 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
7379 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
7380 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
7381 MOV #1778,X \ RC5_Period in us
7382 MOV #14,W \ count of loop
7384 \ ------------------------------\
7385 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
7386 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
7387 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
7388 \ RC5_Compute_3/4_Period: \ |
7389 RRUM #1,X \ X=1/2 cycle |
7393 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
7394 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
7396 \ ------------------------------\
7397 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
7398 \ ------------------------------\
7399 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7400 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
7401 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7402 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7403 SUB #1,W \ decrement count loop
7404 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
7405 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7406 0<> WHILE \ ----> out of loop ----+
7407 \ RC5_compute_7/4_Time_out: \ |
7408 ADD X,Y \ | out of bound = 7/4 period
7409 \ RC5_WaitHalfCycleP1.2_IFG: \ |
7411 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
7412 0>= IF \ | if cycle time out of bound
7413 BIC #$30,&TA0CTL \ | stop timer_A0
7414 RETI \ | then quit to do nothing
7416 \ ------------------------------\ |
7417 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
7419 MOV &TA0R,X \ | | get new RC5_period value
7420 REPEAT \ ----> loop back --+ |
7421 \ ------------------------------\ |
7422 \ RC5_SampleEndOf: \ <---------------------+
7423 \ ------------------------------\
7424 BIC #$30,&TA0CTL \ stop timer_A0
7425 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
7426 \ ******************************\
7427 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7428 \ ******************************\
7429 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
7430 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
7431 XOR IP,X \ (new XOR old) Toggle bit (13)
7432 BIT #BIT13,X \ X(13) = New_RC5_command
7433 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
7435 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
7436 \ ******************************\
7437 \ RC5_ComputeNewRC5word \
7438 \ ******************************\
7440 MOV &BASE,2(PSP) \ save variable BASE before use
7441 MOV TOS,0(PSP) \ save TOS before use
7442 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
7443 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
7444 \ ******************************\
7445 \ RC5_ComputeC6bit \
7446 \ ******************************\
7447 BIT #$4000,IP \ test /C6 bit in IP
7448 0= IF BIS #$40,TOS \ set C6 bit in S
7449 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
7450 \ ******************************\
7451 \ RC5_CommandByteIsDone \ RC5_code --
7452 \ ******************************\
7454 \ ------------------------------\
7455 \ Display IR_RC5 code \
7456 \ ------------------------------\
7457 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
7458 \ ------------------------------\
7459 LO2HI \ switch from assembler to FORTH
7460 ['] LCD_CLEAR IS CR \ redirects CR
7461 ['] LCD_WrC IS EMIT \ redirects EMIT
7462 $10 BASE ! \ change BASE to hexadecimal
7463 CR ." $" 2 U.R \ print IR_RC5 code
7464 ['] (CR) IS CR \ restore CR
7465 ['] (EMIT) IS EMIT \ restore EMIT
7466 HI2LO \ switch from FORTH to assembler
7467 \ ------------------------------\
7468 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
7469 \ ------------------------------\
7470 MOV @PSP+,&BASE \ restore variable BASE
7471 RETI \ CPU is ON, GIE is OFF
7476 \ ------------------------------\
7477 \ TB0CTL = %0000 0010 1001 0100\$3C0
7478 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7479 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7480 \ -- \ID input divider \ 10 = /4
7481 \ -- \MC Mode Control \ 01 = up to TB0CCR0
7482 \ - \TBCLR TimerB Clear
7485 \ --------------------------------\\
7486 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7487 \ -- \CM Capture Mode
7492 \ --- \OUTMOD \ 011 = set/reset
7498 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
7500 \ ------------------------------\
7501 \ set TimerB to make 50kHz PWM \
7502 \ ------------------------------\
7503 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7504 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
7505 \ ------------------------------\
7506 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7507 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
7508 \ ------------------------------\
7509 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7510 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
7511 \ ------------------------------\
7512 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7513 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
7514 \ ------------------------------\
7515 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7516 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
7517 \ ------------------------------\
7518 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
7519 \ ------------------------------\
7520 \ set TimerB to generate PWM for LCD_Vo
7521 \ ------------------------------\
7522 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
7523 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
7524 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7525 \ ------------------------------\
7526 BIS.B #LCDVo,&LCDVo_DIR \
7527 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
7528 \ ------------------------------\
7529 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7530 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7531 \ ------------------------------\
7532 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7533 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7534 \ ------------------------------\
7535 \ WDT interval init part \
7536 \ ------------------------------\
7537 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
7538 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
7539 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
7540 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
7541 \ ------------------------------\
7543 \ ------------------------------\
7544 BIS.B #RC5,&IR_IE \ enable RC5_Int
7545 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7546 \ ------------------------------\
7547 \ init interrupt vectors
7548 \ ------------------------------\
7549 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
7550 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7551 \ ------------------------------\
7552 \ define LPM mode for ACCEPT \
7553 \ ------------------------------\
7554 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7555 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7556 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7558 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
7560 \ ------------------------------\
7562 \ ------------------------------\
7563 $03E8 20_US \ 1- wait 20 ms
7564 $03 TOP_LCD \ 2- send DB5=DB4=1
7565 $CD 20_US \ 3- wait 4,1 ms
7566 $03 TOP_LCD \ 4- send again DB5=DB4=1
7567 $5 20_US \ 5- wait 0,1 ms
7568 $03 TOP_LCD \ 6- send again again DB5=DB4=1
7569 $2 20_US \ wait 40 us = LCD cycle
7570 $02 TOP_LCD \ 7- send DB5=1 DB4=0
7571 $2 20_US \ wait 40 us = LCD cycle
7572 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7573 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7574 LCD_Clear \ 10- "LCD_Clear"
7575 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7576 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7577 LCD_Clear \ 10- "LCD_Clear"
7578 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7579 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7581 ['] (CR) IS CR \ ' (CR) is CR
7582 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
7584 ." RC5toLCD is running. Type STOP to quit"
7585 \ NOECHO \ uncomment to run this app without terminal connexion
7586 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
7587 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
7591 : STOP \ stops multitasking, must to be used before downloading app
7592 ['] (WARM) IS WARM \ remove START app from FORTH init process
7593 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
7601 CODE MAX \ n1 n2 -- n3 signed maximum
7602 CMP @PSP,TOS \ n2-n1
7603 S< ?GOTO FW1 \ n2<n1
7609 CODE MIN \ n1 n2 -- n3 signed minimum
7610 CMP @PSP,TOS \ n2-n1
7611 S< ?GOTO BW1 \ n2<n1
7617 : U.R \ u n -- display u unsigned in n width (n >= 2)
7619 R> OVER - 0 MAX SPACES TYPE
7623 CODE 20_US \ n -- n * 20 us
7624 BEGIN \ 3 cycles loop + 6~
7625 \ MOV #5,W \ 3 MCLK = 1 MHz
7626 \ MOV #23,W \ 3 MCLK = 4 MHz
7627 MOV #51,W \ 3 MCLK = 8 MHz
7628 \ MOV #104,W \ 3 MCLK = 16 MHz
7629 \ MOV #158,W \ 3 MCLK = 24 MHz
7630 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
7640 CODE TOP_LCD \ LCD Sample
7641 \ \ if write : %xxxxWWWW --
7642 \ \ if read : -- %0000RRRR
7643 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7644 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7645 0= IF \ write LCD bits pattern
7647 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7648 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7651 THEN \ read LCD bits pattern
7654 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7655 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7661 CODE LCD_W \ byte -- write byte to LCD
7663 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
7664 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
7665 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7666 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7667 COLON \ high level word starts here
7668 TOP_LCD 2 20_US \ write high nibble first
7673 CODE LCD_WrC \ char -- Write Char
7674 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7679 CODE LCD_WrF \ func -- Write Fonction
7680 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7686 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
7691 $02 LCD_WrF 100 20_us
7695 \ : LCD_Entry_set $04 OR LCD_WrF ;
7697 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
7699 \ : LCD_Display_Shift $10 OR LCD_WrF ;
7701 \ : LCD_Fn_Set $20 OR LCD_WrF ;
7703 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
7705 \ : LCD_Goto $80 OR LCD_WrF ;
7707 \ CODE LCD_R \ -- byte read byte from LCD
7708 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7709 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7710 \ COLON \ starts a FORTH word
7711 \ TOP_LCD 2 20_us \ -- %0000HHHH
7712 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
7713 \ HI2LO \ switch from FORTH to assembler
7714 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
7715 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
7716 \ MOV @RSP+,IP \ restore IP saved by COLON
7721 \ CODE LCD_RdS \ -- status Read Status
7722 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7727 \ CODE LCD_RdC \ -- char Read Char
7728 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7733 \ -------------+------+------+------+------++---+---+---+---+---------+
7734 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
7735 \ -------------+------+------+------+------++---+---+---+---+---------+
7736 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
7737 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
7738 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
7739 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
7740 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
7741 \ -------------+------+------+------+------++---+---+---+---+---------+
7744 \ ******************************\
7745 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7746 \ ******************************\
7747 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
7748 \ ------------------------------\
7749 \ define LPM mode for ACCEPT \
7750 \ ------------------------------\
7751 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7752 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7753 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7754 BIT.B #SW2,&SW2_IN \ test switch S2
7755 0= IF \ case of switch S2 pressed
7756 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
7758 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
7761 BIT.B #SW1,&SW1_IN \ test switch S1 input
7762 0= IF \ case of Switch S1 pressed
7763 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
7765 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
7769 RETI \ CPU is ON, GIE is OFF
7774 \ ------------------------------\
7775 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7776 \ ******************************\
7777 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7778 \ ******************************\
7779 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7780 \ \ SMclock = 8|16|24 MHz
7781 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
7782 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
7783 \ \ SR(9)=new Toggle bit memory (ADD on)
7784 \ ------------------------------\
7785 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
7786 \ ------------------------------\
7787 \ define LPM mode for ACCEPT \
7788 \ ------------------------------\
7789 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7790 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7791 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7792 \ ------------------------------\
7793 \ RC5_FirstStartBitHalfCycle: \
7794 \ ------------------------------\
7795 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
7796 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
7797 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
7798 MOV #1778,X \ RC5_Period in us
7799 MOV #14,W \ count of loop
7801 \ ------------------------------\
7802 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
7803 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
7804 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
7805 \ RC5_Compute_3/4_Period: \ |
7806 RRUM #1,X \ X=1/2 cycle |
7810 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
7811 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
7813 \ ------------------------------\
7814 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
7815 \ ------------------------------\
7816 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7817 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
7818 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7819 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7820 SUB #1,W \ decrement count loop
7821 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
7822 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7823 0<> WHILE \ ----> out of loop ----+
7824 \ RC5_compute_7/4_Time_out: \ |
7825 ADD X,Y \ | out of bound = 7/4 period
7826 \ RC5_WaitHalfCycleP1.2_IFG: \ |
7828 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
7829 0>= IF \ | if cycle time out of bound
7830 BIC #$30,&TA0CTL \ | stop timer_A0
7831 RETI \ | then quit to do nothing
7833 \ ------------------------------\ |
7834 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
7836 MOV &TA0R,X \ | | get new RC5_period value
7837 REPEAT \ ----> loop back --+ |
7838 \ ------------------------------\ |
7839 \ RC5_SampleEndOf: \ <---------------------+
7840 \ ------------------------------\
7841 BIC #$30,&TA0CTL \ stop timer_A0
7842 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
7843 \ ******************************\
7844 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7845 \ ******************************\
7846 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
7847 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
7848 XOR IP,X \ (new XOR old) Toggle bit (13)
7849 BIT #BIT13,X \ X(13) = New_RC5_command
7850 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
7852 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
7853 \ ******************************\
7854 \ RC5_ComputeNewRC5word \
7855 \ ******************************\
7857 MOV &BASE,2(PSP) \ save variable BASE before use
7858 MOV TOS,0(PSP) \ save TOS before use
7859 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
7860 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
7861 \ ******************************\
7862 \ RC5_ComputeC6bit \
7863 \ ******************************\
7864 BIT #$4000,IP \ test /C6 bit in IP
7865 0= IF BIS #$40,TOS \ set C6 bit in S
7866 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
7867 \ ******************************\
7868 \ RC5_CommandByteIsDone \ RC5_code --
7869 \ ******************************\
7871 \ ------------------------------\
7872 \ Display IR_RC5 code \
7873 \ ------------------------------\
7874 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
7875 \ ------------------------------\
7876 LO2HI \ switch from assembler to FORTH
7877 ['] LCD_CLEAR IS CR \ redirects CR
7878 ['] LCD_WrC IS EMIT \ redirects EMIT
7879 $10 BASE ! \ change BASE to hexadecimal
7880 CR ." $" 2 U.R \ print IR_RC5 code
7881 ['] (CR) IS CR \ restore CR
7882 ['] (EMIT) IS EMIT \ restore EMIT
7883 HI2LO \ switch from FORTH to assembler
7884 \ ------------------------------\
7885 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
7886 \ ------------------------------\
7887 MOV @PSP+,&BASE \ restore variable BASE
7888 RETI \ CPU is ON, GIE is OFF
7893 \ ------------------------------\
7894 \ TB0CTL = %0000 0010 1001 0100\$3C0
7895 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7896 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7897 \ -- \ID input divider \ 10 = /4
7898 \ -- \MC Mode Control \ 01 = up to TB0CCR0
7899 \ - \TBCLR TimerB Clear
7902 \ --------------------------------\\
7903 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7904 \ -- \CM Capture Mode
7909 \ --- \OUTMOD \ 011 = set/reset
7915 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
7917 \ ------------------------------\
7918 \ set TimerB to make 50kHz PWM \
7919 \ ------------------------------\
7920 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7921 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
7922 \ ------------------------------\
7923 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7924 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
7925 \ ------------------------------\
7926 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7927 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
7928 \ ------------------------------\
7929 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7930 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
7931 \ ------------------------------\
7932 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7933 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
7934 \ ------------------------------\
7935 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
7936 \ ------------------------------\
7937 \ set TimerB to generate PWM for LCD_Vo
7938 \ ------------------------------\
7939 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
7940 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
7941 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7942 \ ------------------------------\
7943 BIS.B #LCDVo,&LCDVo_DIR \
7944 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
7945 \ ------------------------------\
7946 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7947 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7948 \ ------------------------------\
7949 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7950 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7951 \ ------------------------------\
7952 \ WDT interval init part \
7953 \ ------------------------------\
7954 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
7955 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
7956 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
7957 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
7958 \ ------------------------------\
7960 \ ------------------------------\
7961 BIS.B #RC5,&IR_IE \ enable RC5_Int
7962 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7963 \ ------------------------------\
7964 \ init interrupt vectors
7965 \ ------------------------------\
7966 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
7967 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7968 \ ------------------------------\
7969 \ define LPM mode for ACCEPT \
7970 \ ------------------------------\
7971 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7972 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7973 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7975 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
7977 \ ------------------------------\
7979 \ ------------------------------\
7980 $03E8 20_US \ 1- wait 20 ms
7981 $03 TOP_LCD \ 2- send DB5=DB4=1
7982 $CD 20_US \ 3- wait 4,1 ms
7983 $03 TOP_LCD \ 4- send again DB5=DB4=1
7984 $5 20_US \ 5- wait 0,1 ms
7985 $03 TOP_LCD \ 6- send again again DB5=DB4=1
7986 $2 20_US \ wait 40 us = LCD cycle
7987 $02 TOP_LCD \ 7- send DB5=1 DB4=0
7988 $2 20_US \ wait 40 us = LCD cycle
7989 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7990 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7991 LCD_Clear \ 10- "LCD_Clear"
7992 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7993 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7994 LCD_Clear \ 10- "LCD_Clear"
7995 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7996 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7998 ['] (CR) IS CR \ ' (CR) is CR
7999 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
8001 ." RC5toLCD is running. Type STOP to quit"
8002 \ NOECHO \ uncomment to run this app without terminal connexion
8003 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
8004 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
8008 : STOP \ stops multitasking, must to be used before downloading app
8009 ['] (WARM) IS WARM \ remove START app from FORTH init process
8010 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
8018 CODE MAX \ n1 n2 -- n3 signed maximum
8019 CMP @PSP,TOS \ n2-n1
8020 S< ?GOTO FW1 \ n2<n1
8026 CODE MIN \ n1 n2 -- n3 signed minimum
8027 CMP @PSP,TOS \ n2-n1
8028 S< ?GOTO BW1 \ n2<n1
8034 : U.R \ u n -- display u unsigned in n width (n >= 2)
8036 R> OVER - 0 MAX SPACES TYPE
8040 CODE 20_US \ n -- n * 20 us
8041 BEGIN \ 3 cycles loop + 6~
8042 \ MOV #5,W \ 3 MCLK = 1 MHz
8043 \ MOV #23,W \ 3 MCLK = 4 MHz
8044 MOV #51,W \ 3 MCLK = 8 MHz
8045 \ MOV #104,W \ 3 MCLK = 16 MHz
8046 \ MOV #158,W \ 3 MCLK = 24 MHz
8047 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
8057 CODE TOP_LCD \ LCD Sample
8058 \ \ if write : %xxxxWWWW --
8059 \ \ if read : -- %0000RRRR
8060 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8061 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8062 0= IF \ write LCD bits pattern
8064 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8065 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8068 THEN \ read LCD bits pattern
8071 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8072 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8078 CODE LCD_W \ byte -- write byte to LCD
8080 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
8081 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
8082 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8083 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8084 COLON \ high level word starts here
8085 TOP_LCD 2 20_US \ write high nibble first
8090 CODE LCD_WrC \ char -- Write Char
8091 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8096 CODE LCD_WrF \ func -- Write Fonction
8097 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8103 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
8108 $02 LCD_WrF 100 20_us
8112 \ : LCD_Entry_set $04 OR LCD_WrF ;
8114 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
8116 \ : LCD_Display_Shift $10 OR LCD_WrF ;
8118 \ : LCD_Fn_Set $20 OR LCD_WrF ;
8120 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
8122 \ : LCD_Goto $80 OR LCD_WrF ;
8124 \ CODE LCD_R \ -- byte read byte from LCD
8125 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8126 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8127 \ COLON \ starts a FORTH word
8128 \ TOP_LCD 2 20_us \ -- %0000HHHH
8129 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
8130 \ HI2LO \ switch from FORTH to assembler
8131 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
8132 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
8133 \ MOV @RSP+,IP \ restore IP saved by COLON
8138 \ CODE LCD_RdS \ -- status Read Status
8139 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8144 \ CODE LCD_RdC \ -- char Read Char
8145 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8150 \ -------------+------+------+------+------++---+---+---+---+---------+
8151 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
8152 \ -------------+------+------+------+------++---+---+---+---+---------+
8153 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
8154 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
8155 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
8156 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
8157 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
8158 \ -------------+------+------+------+------++---+---+---+---+---------+
8161 \ ******************************\
8162 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8163 \ ******************************\
8164 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
8165 \ ------------------------------\
8166 \ define LPM mode for ACCEPT \
8167 \ ------------------------------\
8168 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8169 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8170 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8171 BIT.B #SW2,&SW2_IN \ test switch S2
8172 0= IF \ case of switch S2 pressed
8173 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
8175 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
8178 BIT.B #SW1,&SW1_IN \ test switch S1 input
8179 0= IF \ case of Switch S1 pressed
8180 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
8182 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
8186 RETI \ CPU is ON, GIE is OFF
8191 \ ------------------------------\
8192 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8193 \ ******************************\
8194 ASM RC5_INT \ wake up on Px.RC5 change interrupt
8195 \ ******************************\
8196 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8197 \ \ SMclock = 8|16|24 MHz
8198 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
8199 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
8200 \ \ SR(9)=new Toggle bit memory (ADD on)
8201 \ ------------------------------\
8202 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
8203 \ ------------------------------\
8204 \ define LPM mode for ACCEPT \
8205 \ ------------------------------\
8206 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8207 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8208 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8209 \ ------------------------------\
8210 \ RC5_FirstStartBitHalfCycle: \
8211 \ ------------------------------\
8212 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
8213 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
8214 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
8215 MOV #1778,X \ RC5_Period in us
8216 MOV #14,W \ count of loop
8218 \ ------------------------------\
8219 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
8220 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
8221 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
8222 \ RC5_Compute_3/4_Period: \ |
8223 RRUM #1,X \ X=1/2 cycle |
8227 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
8228 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
8230 \ ------------------------------\
8231 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
8232 \ ------------------------------\
8233 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8234 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
8235 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8236 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8237 SUB #1,W \ decrement count loop
8238 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
8239 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8240 0<> WHILE \ ----> out of loop ----+
8241 \ RC5_compute_7/4_Time_out: \ |
8242 ADD X,Y \ | out of bound = 7/4 period
8243 \ RC5_WaitHalfCycleP1.2_IFG: \ |
8245 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
8246 0>= IF \ | if cycle time out of bound
8247 BIC #$30,&TA0CTL \ | stop timer_A0
8248 RETI \ | then quit to do nothing
8250 \ ------------------------------\ |
8251 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
8253 MOV &TA0R,X \ | | get new RC5_period value
8254 REPEAT \ ----> loop back --+ |
8255 \ ------------------------------\ |
8256 \ RC5_SampleEndOf: \ <---------------------+
8257 \ ------------------------------\
8258 BIC #$30,&TA0CTL \ stop timer_A0
8259 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
8260 \ ******************************\
8261 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
8262 \ ******************************\
8263 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
8264 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
8265 XOR IP,X \ (new XOR old) Toggle bit (13)
8266 BIT #BIT13,X \ X(13) = New_RC5_command
8267 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
8269 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
8270 \ ******************************\
8271 \ RC5_ComputeNewRC5word \
8272 \ ******************************\
8274 MOV &BASE,2(PSP) \ save variable BASE before use
8275 MOV TOS,0(PSP) \ save TOS before use
8276 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
8277 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
8278 \ ******************************\
8279 \ RC5_ComputeC6bit \
8280 \ ******************************\
8281 BIT #$4000,IP \ test /C6 bit in IP
8282 0= IF BIS #$40,TOS \ set C6 bit in S
8283 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
8284 \ ******************************\
8285 \ RC5_CommandByteIsDone \ RC5_code --
8286 \ ******************************\
8288 \ ------------------------------\
8289 \ Display IR_RC5 code \
8290 \ ------------------------------\
8291 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
8292 \ ------------------------------\
8293 LO2HI \ switch from assembler to FORTH
8294 ['] LCD_CLEAR IS CR \ redirects CR
8295 ['] LCD_WrC IS EMIT \ redirects EMIT
8296 $10 BASE ! \ change BASE to hexadecimal
8297 CR ." $" 2 U.R \ print IR_RC5 code
8298 ['] (CR) IS CR \ restore CR
8299 ['] (EMIT) IS EMIT \ restore EMIT
8300 HI2LO \ switch from FORTH to assembler
8301 \ ------------------------------\
8302 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
8303 \ ------------------------------\
8304 MOV @PSP+,&BASE \ restore variable BASE
8305 RETI \ CPU is ON, GIE is OFF
8310 \ ------------------------------\
8311 \ TB0CTL = %0000 0010 1001 0100\$3C0
8312 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8313 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8314 \ -- \ID input divider \ 10 = /4
8315 \ -- \MC Mode Control \ 01 = up to TB0CCR0
8316 \ - \TBCLR TimerB Clear
8319 \ --------------------------------\\
8320 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8321 \ -- \CM Capture Mode
8326 \ --- \OUTMOD \ 011 = set/reset
8332 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
8334 \ ------------------------------\
8335 \ set TimerB to make 50kHz PWM \
8336 \ ------------------------------\
8337 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
8338 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
8339 \ ------------------------------\
8340 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
8341 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
8342 \ ------------------------------\
8343 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8344 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
8345 \ ------------------------------\
8346 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8347 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
8348 \ ------------------------------\
8349 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8350 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
8351 \ ------------------------------\
8352 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
8353 \ ------------------------------\
8354 \ set TimerB to generate PWM for LCD_Vo
8355 \ ------------------------------\
8356 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
8357 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
8358 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8359 \ ------------------------------\
8360 BIS.B #LCDVo,&LCDVo_DIR \
8361 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
8362 \ ------------------------------\
8363 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8364 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8365 \ ------------------------------\
8366 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8367 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8368 \ ------------------------------\
8369 \ WDT interval init part \
8370 \ ------------------------------\
8371 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
8372 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
8373 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
8374 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
8375 \ ------------------------------\
8377 \ ------------------------------\
8378 BIS.B #RC5,&IR_IE \ enable RC5_Int
8379 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8380 \ ------------------------------\
8381 \ init interrupt vectors
8382 \ ------------------------------\
8383 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
8384 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8385 \ ------------------------------\
8386 \ define LPM mode for ACCEPT \
8387 \ ------------------------------\
8388 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8389 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8390 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8392 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
8394 \ ------------------------------\
8396 \ ------------------------------\
8397 $03E8 20_US \ 1- wait 20 ms
8398 $03 TOP_LCD \ 2- send DB5=DB4=1
8399 $CD 20_US \ 3- wait 4,1 ms
8400 $03 TOP_LCD \ 4- send again DB5=DB4=1
8401 $5 20_US \ 5- wait 0,1 ms
8402 $03 TOP_LCD \ 6- send again again DB5=DB4=1
8403 $2 20_US \ wait 40 us = LCD cycle
8404 $02 TOP_LCD \ 7- send DB5=1 DB4=0
8405 $2 20_US \ wait 40 us = LCD cycle
8406 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8407 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8408 LCD_Clear \ 10- "LCD_Clear"
8409 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8410 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8411 LCD_Clear \ 10- "LCD_Clear"
8412 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8413 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8415 ['] (CR) IS CR \ ' (CR) is CR
8416 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
8418 ." RC5toLCD is running. Type STOP to quit"
8419 \ NOECHO \ uncomment to run this app without terminal connexion
8420 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
8421 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
8425 : STOP \ stops multitasking, must to be used before downloading app
8426 ['] (WARM) IS WARM \ remove START app from FORTH init process
8427 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
8435 CODE MAX \ n1 n2 -- n3 signed maximum
8436 CMP @PSP,TOS \ n2-n1
8437 S< ?GOTO FW1 \ n2<n1
8443 CODE MIN \ n1 n2 -- n3 signed minimum
8444 CMP @PSP,TOS \ n2-n1
8445 S< ?GOTO BW1 \ n2<n1
8451 : U.R \ u n -- display u unsigned in n width (n >= 2)
8453 R> OVER - 0 MAX SPACES TYPE
8457 CODE 20_US \ n -- n * 20 us
8458 BEGIN \ 3 cycles loop + 6~
8459 \ MOV #5,W \ 3 MCLK = 1 MHz
8460 \ MOV #23,W \ 3 MCLK = 4 MHz
8461 MOV #51,W \ 3 MCLK = 8 MHz
8462 \ MOV #104,W \ 3 MCLK = 16 MHz
8463 \ MOV #158,W \ 3 MCLK = 24 MHz
8464 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
8474 CODE TOP_LCD \ LCD Sample
8475 \ \ if write : %xxxxWWWW --
8476 \ \ if read : -- %0000RRRR
8477 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8478 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8479 0= IF \ write LCD bits pattern
8481 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8482 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8485 THEN \ read LCD bits pattern
8488 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8489 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8495 CODE LCD_W \ byte -- write byte to LCD
8497 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
8498 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
8499 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8500 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8501 COLON \ high level word starts here
8502 TOP_LCD 2 20_US \ write high nibble first
8507 CODE LCD_WrC \ char -- Write Char
8508 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8513 CODE LCD_WrF \ func -- Write Fonction
8514 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8520 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
8525 $02 LCD_WrF 100 20_us
8529 \ : LCD_Entry_set $04 OR LCD_WrF ;
8531 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
8533 \ : LCD_Display_Shift $10 OR LCD_WrF ;
8535 \ : LCD_Fn_Set $20 OR LCD_WrF ;
8537 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
8539 \ : LCD_Goto $80 OR LCD_WrF ;
8541 \ CODE LCD_R \ -- byte read byte from LCD
8542 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8543 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8544 \ COLON \ starts a FORTH word
8545 \ TOP_LCD 2 20_us \ -- %0000HHHH
8546 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
8547 \ HI2LO \ switch from FORTH to assembler
8548 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
8549 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
8550 \ MOV @RSP+,IP \ restore IP saved by COLON
8555 \ CODE LCD_RdS \ -- status Read Status
8556 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8561 \ CODE LCD_RdC \ -- char Read Char
8562 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8567 \ -------------+------+------+------+------++---+---+---+---+---------+
8568 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
8569 \ -------------+------+------+------+------++---+---+---+---+---------+
8570 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
8571 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
8572 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
8573 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
8574 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
8575 \ -------------+------+------+------+------++---+---+---+---+---------+
8578 \ ******************************\
8579 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8580 \ ******************************\
8581 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
8582 \ ------------------------------\
8583 \ define LPM mode for ACCEPT \
8584 \ ------------------------------\
8585 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8586 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8587 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8588 BIT.B #SW2,&SW2_IN \ test switch S2
8589 0= IF \ case of switch S2 pressed
8590 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
8592 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
8595 BIT.B #SW1,&SW1_IN \ test switch S1 input
8596 0= IF \ case of Switch S1 pressed
8597 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
8599 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
8603 RETI \ CPU is ON, GIE is OFF
8608 \ ------------------------------\
8609 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8610 \ ******************************\
8611 ASM RC5_INT \ wake up on Px.RC5 change interrupt
8612 \ ******************************\
8613 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8614 \ \ SMclock = 8|16|24 MHz
8615 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
8616 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
8617 \ \ SR(9)=new Toggle bit memory (ADD on)
8618 \ ------------------------------\
8619 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
8620 \ ------------------------------\
8621 \ define LPM mode for ACCEPT \
8622 \ ------------------------------\
8623 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8624 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8625 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8626 \ ------------------------------\
8627 \ RC5_FirstStartBitHalfCycle: \
8628 \ ------------------------------\
8629 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
8630 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
8631 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
8632 MOV #1778,X \ RC5_Period in us
8633 MOV #14,W \ count of loop
8635 \ ------------------------------\
8636 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
8637 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
8638 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
8639 \ RC5_Compute_3/4_Period: \ |
8640 RRUM #1,X \ X=1/2 cycle |
8644 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
8645 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
8647 \ ------------------------------\
8648 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
8649 \ ------------------------------\
8650 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8651 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
8652 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8653 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8654 SUB #1,W \ decrement count loop
8655 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
8656 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8657 0<> WHILE \ ----> out of loop ----+
8658 \ RC5_compute_7/4_Time_out: \ |
8659 ADD X,Y \ | out of bound = 7/4 period
8660 \ RC5_WaitHalfCycleP1.2_IFG: \ |
8662 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
8663 0>= IF \ | if cycle time out of bound
8664 BIC #$30,&TA0CTL \ | stop timer_A0
8665 RETI \ | then quit to do nothing
8667 \ ------------------------------\ |
8668 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
8670 MOV &TA0R,X \ | | get new RC5_period value
8671 REPEAT \ ----> loop back --+ |
8672 \ ------------------------------\ |
8673 \ RC5_SampleEndOf: \ <---------------------+
8674 \ ------------------------------\
8675 BIC #$30,&TA0CTL \ stop timer_A0
8676 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
8677 \ ******************************\
8678 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
8679 \ ******************************\
8680 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
8681 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
8682 XOR IP,X \ (new XOR old) Toggle bit (13)
8683 BIT #BIT13,X \ X(13) = New_RC5_command
8684 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
8686 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
8687 \ ******************************\
8688 \ RC5_ComputeNewRC5word \
8689 \ ******************************\
8691 MOV &BASE,2(PSP) \ save variable BASE before use
8692 MOV TOS,0(PSP) \ save TOS before use
8693 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
8694 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
8695 \ ******************************\
8696 \ RC5_ComputeC6bit \
8697 \ ******************************\
8698 BIT #$4000,IP \ test /C6 bit in IP
8699 0= IF BIS #$40,TOS \ set C6 bit in S
8700 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
8701 \ ******************************\
8702 \ RC5_CommandByteIsDone \ RC5_code --
8703 \ ******************************\
8705 \ ------------------------------\
8706 \ Display IR_RC5 code \
8707 \ ------------------------------\
8708 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
8709 \ ------------------------------\
8710 LO2HI \ switch from assembler to FORTH
8711 ['] LCD_CLEAR IS CR \ redirects CR
8712 ['] LCD_WrC IS EMIT \ redirects EMIT
8713 $10 BASE ! \ change BASE to hexadecimal
8714 CR ." $" 2 U.R \ print IR_RC5 code
8715 ['] (CR) IS CR \ restore CR
8716 ['] (EMIT) IS EMIT \ restore EMIT
8717 HI2LO \ switch from FORTH to assembler
8718 \ ------------------------------\
8719 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
8720 \ ------------------------------\
8721 MOV @PSP+,&BASE \ restore variable BASE
8722 RETI \ CPU is ON, GIE is OFF
8727 \ ------------------------------\
8728 \ TB0CTL = %0000 0010 1001 0100\$3C0
8729 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8730 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8731 \ -- \ID input divider \ 10 = /4
8732 \ -- \MC Mode Control \ 01 = up to TB0CCR0
8733 \ - \TBCLR TimerB Clear
8736 \ --------------------------------\\
8737 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8738 \ -- \CM Capture Mode
8743 \ --- \OUTMOD \ 011 = set/reset
8749 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
8751 \ ------------------------------\
8752 \ set TimerB to make 50kHz PWM \
8753 \ ------------------------------\
8754 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
8755 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
8756 \ ------------------------------\
8757 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
8758 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
8759 \ ------------------------------\
8760 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8761 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
8762 \ ------------------------------\
8763 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8764 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
8765 \ ------------------------------\
8766 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8767 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
8768 \ ------------------------------\
8769 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
8770 \ ------------------------------\
8771 \ set TimerB to generate PWM for LCD_Vo
8772 \ ------------------------------\
8773 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
8774 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
8775 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8776 \ ------------------------------\
8777 BIS.B #LCDVo,&LCDVo_DIR \
8778 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
8779 \ ------------------------------\
8780 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8781 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8782 \ ------------------------------\
8783 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8784 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8785 \ ------------------------------\
8786 \ WDT interval init part \
8787 \ ------------------------------\
8788 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
8789 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
8790 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
8791 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
8792 \ ------------------------------\
8794 \ ------------------------------\
8795 BIS.B #RC5,&IR_IE \ enable RC5_Int
8796 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8797 \ ------------------------------\
8798 \ init interrupt vectors
8799 \ ------------------------------\
8800 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
8801 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8802 \ ------------------------------\
8803 \ define LPM mode for ACCEPT \
8804 \ ------------------------------\
8805 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8806 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8807 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8809 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
8811 \ ------------------------------\
8813 \ ------------------------------\
8814 $03E8 20_US \ 1- wait 20 ms
8815 $03 TOP_LCD \ 2- send DB5=DB4=1
8816 $CD 20_US \ 3- wait 4,1 ms
8817 $03 TOP_LCD \ 4- send again DB5=DB4=1
8818 $5 20_US \ 5- wait 0,1 ms
8819 $03 TOP_LCD \ 6- send again again DB5=DB4=1
8820 $2 20_US \ wait 40 us = LCD cycle
8821 $02 TOP_LCD \ 7- send DB5=1 DB4=0
8822 $2 20_US \ wait 40 us = LCD cycle
8823 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8824 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8825 LCD_Clear \ 10- "LCD_Clear"
8826 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8827 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8828 LCD_Clear \ 10- "LCD_Clear"
8829 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8830 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8832 ['] (CR) IS CR \ ' (CR) is CR
8833 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
8835 ." RC5toLCD is running. Type STOP to quit"
8836 \ NOECHO \ uncomment to run this app without terminal connexion
8837 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
8838 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
8842 : STOP \ stops multitasking, must to be used before downloading app
8843 ['] (WARM) IS WARM \ remove START app from FORTH init process
8844 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
8852 CODE MAX \ n1 n2 -- n3 signed maximum
8853 CMP @PSP,TOS \ n2-n1
8854 S< ?GOTO FW1 \ n2<n1
8860 CODE MIN \ n1 n2 -- n3 signed minimum
8861 CMP @PSP,TOS \ n2-n1
8862 S< ?GOTO BW1 \ n2<n1
8868 : U.R \ u n -- display u unsigned in n width (n >= 2)
8870 R> OVER - 0 MAX SPACES TYPE
8874 CODE 20_US \ n -- n * 20 us
8875 BEGIN \ 3 cycles loop + 6~
8876 \ MOV #5,W \ 3 MCLK = 1 MHz
8877 \ MOV #23,W \ 3 MCLK = 4 MHz
8878 MOV #51,W \ 3 MCLK = 8 MHz
8879 \ MOV #104,W \ 3 MCLK = 16 MHz
8880 \ MOV #158,W \ 3 MCLK = 24 MHz
8881 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
8891 CODE TOP_LCD \ LCD Sample
8892 \ \ if write : %xxxxWWWW --
8893 \ \ if read : -- %0000RRRR
8894 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8895 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8896 0= IF \ write LCD bits pattern
8898 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8899 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8902 THEN \ read LCD bits pattern
8905 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8906 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8912 CODE LCD_W \ byte -- write byte to LCD
8914 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
8915 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
8916 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8917 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8918 COLON \ high level word starts here
8919 TOP_LCD 2 20_US \ write high nibble first
8924 CODE LCD_WrC \ char -- Write Char
8925 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8930 CODE LCD_WrF \ func -- Write Fonction
8931 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8937 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
8942 $02 LCD_WrF 100 20_us
8946 \ : LCD_Entry_set $04 OR LCD_WrF ;
8948 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
8950 \ : LCD_Display_Shift $10 OR LCD_WrF ;
8952 \ : LCD_Fn_Set $20 OR LCD_WrF ;
8954 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
8956 \ : LCD_Goto $80 OR LCD_WrF ;
8958 \ CODE LCD_R \ -- byte read byte from LCD
8959 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8960 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8961 \ COLON \ starts a FORTH word
8962 \ TOP_LCD 2 20_us \ -- %0000HHHH
8963 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
8964 \ HI2LO \ switch from FORTH to assembler
8965 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
8966 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
8967 \ MOV @RSP+,IP \ restore IP saved by COLON
8972 \ CODE LCD_RdS \ -- status Read Status
8973 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8978 \ CODE LCD_RdC \ -- char Read Char
8979 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8984 \ -------------+------+------+------+------++---+---+---+---+---------+
8985 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
8986 \ -------------+------+------+------+------++---+---+---+---+---------+
8987 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
8988 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
8989 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
8990 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
8991 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
8992 \ -------------+------+------+------+------++---+---+---+---+---------+
8995 \ ******************************\
8996 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8997 \ ******************************\
8998 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
8999 \ ------------------------------\
9000 \ define LPM mode for ACCEPT \
9001 \ ------------------------------\
9002 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9003 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9004 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9005 BIT.B #SW2,&SW2_IN \ test switch S2
9006 0= IF \ case of switch S2 pressed
9007 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
9009 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
9012 BIT.B #SW1,&SW1_IN \ test switch S1 input
9013 0= IF \ case of Switch S1 pressed
9014 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
9016 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
9020 RETI \ CPU is ON, GIE is OFF
9025 \ ------------------------------\
9026 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9027 \ ******************************\
9028 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9029 \ ******************************\
9030 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9031 \ \ SMclock = 8|16|24 MHz
9032 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
9033 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
9034 \ \ SR(9)=new Toggle bit memory (ADD on)
9035 \ ------------------------------\
9036 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
9037 \ ------------------------------\
9038 \ define LPM mode for ACCEPT \
9039 \ ------------------------------\
9040 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9041 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9042 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9043 \ ------------------------------\
9044 \ RC5_FirstStartBitHalfCycle: \
9045 \ ------------------------------\
9046 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
9047 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
9048 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
9049 MOV #1778,X \ RC5_Period in us
9050 MOV #14,W \ count of loop
9052 \ ------------------------------\
9053 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
9054 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
9055 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
9056 \ RC5_Compute_3/4_Period: \ |
9057 RRUM #1,X \ X=1/2 cycle |
9061 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
9062 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
9064 \ ------------------------------\
9065 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
9066 \ ------------------------------\
9067 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9068 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
9069 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9070 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9071 SUB #1,W \ decrement count loop
9072 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
9073 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9074 0<> WHILE \ ----> out of loop ----+
9075 \ RC5_compute_7/4_Time_out: \ |
9076 ADD X,Y \ | out of bound = 7/4 period
9077 \ RC5_WaitHalfCycleP1.2_IFG: \ |
9079 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
9080 0>= IF \ | if cycle time out of bound
9081 BIC #$30,&TA0CTL \ | stop timer_A0
9082 RETI \ | then quit to do nothing
9084 \ ------------------------------\ |
9085 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
9087 MOV &TA0R,X \ | | get new RC5_period value
9088 REPEAT \ ----> loop back --+ |
9089 \ ------------------------------\ |
9090 \ RC5_SampleEndOf: \ <---------------------+
9091 \ ------------------------------\
9092 BIC #$30,&TA0CTL \ stop timer_A0
9093 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
9094 \ ******************************\
9095 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9096 \ ******************************\
9097 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
9098 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
9099 XOR IP,X \ (new XOR old) Toggle bit (13)
9100 BIT #BIT13,X \ X(13) = New_RC5_command
9101 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
9103 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
9104 \ ******************************\
9105 \ RC5_ComputeNewRC5word \
9106 \ ******************************\
9108 MOV &BASE,2(PSP) \ save variable BASE before use
9109 MOV TOS,0(PSP) \ save TOS before use
9110 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
9111 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
9112 \ ******************************\
9113 \ RC5_ComputeC6bit \
9114 \ ******************************\
9115 BIT #$4000,IP \ test /C6 bit in IP
9116 0= IF BIS #$40,TOS \ set C6 bit in S
9117 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
9118 \ ******************************\
9119 \ RC5_CommandByteIsDone \ RC5_code --
9120 \ ******************************\
9122 \ ------------------------------\
9123 \ Display IR_RC5 code \
9124 \ ------------------------------\
9125 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
9126 \ ------------------------------\
9127 LO2HI \ switch from assembler to FORTH
9128 ['] LCD_CLEAR IS CR \ redirects CR
9129 ['] LCD_WrC IS EMIT \ redirects EMIT
9130 $10 BASE ! \ change BASE to hexadecimal
9131 CR ." $" 2 U.R \ print IR_RC5 code
9132 ['] (CR) IS CR \ restore CR
9133 ['] (EMIT) IS EMIT \ restore EMIT
9134 HI2LO \ switch from FORTH to assembler
9135 \ ------------------------------\
9136 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
9137 \ ------------------------------\
9138 MOV @PSP+,&BASE \ restore variable BASE
9139 RETI \ CPU is ON, GIE is OFF
9144 \ ------------------------------\
9145 \ TB0CTL = %0000 0010 1001 0100\$3C0
9146 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9147 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9148 \ -- \ID input divider \ 10 = /4
9149 \ -- \MC Mode Control \ 01 = up to TB0CCR0
9150 \ - \TBCLR TimerB Clear
9153 \ --------------------------------\\
9154 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9155 \ -- \CM Capture Mode
9160 \ --- \OUTMOD \ 011 = set/reset
9166 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
9168 \ ------------------------------\
9169 \ set TimerB to make 50kHz PWM \
9170 \ ------------------------------\
9171 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9172 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
9173 \ ------------------------------\
9174 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9175 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
9176 \ ------------------------------\
9177 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9178 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
9179 \ ------------------------------\
9180 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9181 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
9182 \ ------------------------------\
9183 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9184 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
9185 \ ------------------------------\
9186 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
9187 \ ------------------------------\
9188 \ set TimerB to generate PWM for LCD_Vo
9189 \ ------------------------------\
9190 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
9191 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
9192 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9193 \ ------------------------------\
9194 BIS.B #LCDVo,&LCDVo_DIR \
9195 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
9196 \ ------------------------------\
9197 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9198 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9199 \ ------------------------------\
9200 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9201 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9202 \ ------------------------------\
9203 \ WDT interval init part \
9204 \ ------------------------------\
9205 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
9206 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
9207 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
9208 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
9209 \ ------------------------------\
9211 \ ------------------------------\
9212 BIS.B #RC5,&IR_IE \ enable RC5_Int
9213 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9214 \ ------------------------------\
9215 \ init interrupt vectors
9216 \ ------------------------------\
9217 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
9218 MOV #RC5_INT,&IR_Vec \ init interrupt vector
9219 \ ------------------------------\
9220 \ define LPM mode for ACCEPT \
9221 \ ------------------------------\
9222 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9223 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9224 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9226 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
9228 \ ------------------------------\
9230 \ ------------------------------\
9231 $03E8 20_US \ 1- wait 20 ms
9232 $03 TOP_LCD \ 2- send DB5=DB4=1
9233 $CD 20_US \ 3- wait 4,1 ms
9234 $03 TOP_LCD \ 4- send again DB5=DB4=1
9235 $5 20_US \ 5- wait 0,1 ms
9236 $03 TOP_LCD \ 6- send again again DB5=DB4=1
9237 $2 20_US \ wait 40 us = LCD cycle
9238 $02 TOP_LCD \ 7- send DB5=1 DB4=0
9239 $2 20_US \ wait 40 us = LCD cycle
9240 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9241 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9242 LCD_Clear \ 10- "LCD_Clear"
9243 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9244 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9245 LCD_Clear \ 10- "LCD_Clear"
9246 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9247 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9249 ['] (CR) IS CR \ ' (CR) is CR
9250 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
9252 ." RC5toLCD is running. Type STOP to quit"
9253 \ NOECHO \ uncomment to run this app without terminal connexion
9254 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
9255 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
9259 : STOP \ stops multitasking, must to be used before downloading app
9260 ['] (WARM) IS WARM \ remove START app from FORTH init process
9261 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
9269 CODE MAX \ n1 n2 -- n3 signed maximum
9270 CMP @PSP,TOS \ n2-n1
9271 S< ?GOTO FW1 \ n2<n1
9277 CODE MIN \ n1 n2 -- n3 signed minimum
9278 CMP @PSP,TOS \ n2-n1
9279 S< ?GOTO BW1 \ n2<n1
9285 : U.R \ u n -- display u unsigned in n width (n >= 2)
9287 R> OVER - 0 MAX SPACES TYPE
9291 CODE 20_US \ n -- n * 20 us
9292 BEGIN \ 3 cycles loop + 6~
9293 \ MOV #5,W \ 3 MCLK = 1 MHz
9294 \ MOV #23,W \ 3 MCLK = 4 MHz
9295 MOV #51,W \ 3 MCLK = 8 MHz
9296 \ MOV #104,W \ 3 MCLK = 16 MHz
9297 \ MOV #158,W \ 3 MCLK = 24 MHz
9298 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
9308 CODE TOP_LCD \ LCD Sample
9309 \ \ if write : %xxxxWWWW --
9310 \ \ if read : -- %0000RRRR
9311 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9312 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9313 0= IF \ write LCD bits pattern
9315 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9316 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9319 THEN \ read LCD bits pattern
9322 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9323 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9329 CODE LCD_W \ byte -- write byte to LCD
9331 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
9332 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
9333 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9334 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9335 COLON \ high level word starts here
9336 TOP_LCD 2 20_US \ write high nibble first
9341 CODE LCD_WrC \ char -- Write Char
9342 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9347 CODE LCD_WrF \ func -- Write Fonction
9348 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9354 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
9359 $02 LCD_WrF 100 20_us
9363 \ : LCD_Entry_set $04 OR LCD_WrF ;
9365 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
9367 \ : LCD_Display_Shift $10 OR LCD_WrF ;
9369 \ : LCD_Fn_Set $20 OR LCD_WrF ;
9371 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
9373 \ : LCD_Goto $80 OR LCD_WrF ;
9375 \ CODE LCD_R \ -- byte read byte from LCD
9376 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9377 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9378 \ COLON \ starts a FORTH word
9379 \ TOP_LCD 2 20_us \ -- %0000HHHH
9380 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
9381 \ HI2LO \ switch from FORTH to assembler
9382 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
9383 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
9384 \ MOV @RSP+,IP \ restore IP saved by COLON
9389 \ CODE LCD_RdS \ -- status Read Status
9390 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9395 \ CODE LCD_RdC \ -- char Read Char
9396 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9401 \ -------------+------+------+------+------++---+---+---+---+---------+
9402 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
9403 \ -------------+------+------+------+------++---+---+---+---+---------+
9404 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
9405 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
9406 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
9407 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
9408 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
9409 \ -------------+------+------+------+------++---+---+---+---+---------+
9412 \ ******************************\
9413 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9414 \ ******************************\
9415 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
9416 \ ------------------------------\
9417 \ define LPM mode for ACCEPT \
9418 \ ------------------------------\
9419 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9420 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9421 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9422 BIT.B #SW2,&SW2_IN \ test switch S2
9423 0= IF \ case of switch S2 pressed
9424 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
9426 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
9429 BIT.B #SW1,&SW1_IN \ test switch S1 input
9430 0= IF \ case of Switch S1 pressed
9431 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
9433 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
9437 RETI \ CPU is ON, GIE is OFF
9442 \ ------------------------------\
9443 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9444 \ ******************************\
9445 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9446 \ ******************************\
9447 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9448 \ \ SMclock = 8|16|24 MHz
9449 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
9450 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
9451 \ \ SR(9)=new Toggle bit memory (ADD on)
9452 \ ------------------------------\
9453 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
9454 \ ------------------------------\
9455 \ define LPM mode for ACCEPT \
9456 \ ------------------------------\
9457 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9458 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9459 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9460 \ ------------------------------\
9461 \ RC5_FirstStartBitHalfCycle: \
9462 \ ------------------------------\
9463 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
9464 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
9465 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
9466 MOV #1778,X \ RC5_Period in us
9467 MOV #14,W \ count of loop
9469 \ ------------------------------\
9470 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
9471 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
9472 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
9473 \ RC5_Compute_3/4_Period: \ |
9474 RRUM #1,X \ X=1/2 cycle |
9478 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
9479 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
9481 \ ------------------------------\
9482 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
9483 \ ------------------------------\
9484 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9485 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
9486 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9487 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9488 SUB #1,W \ decrement count loop
9489 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
9490 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9491 0<> WHILE \ ----> out of loop ----+
9492 \ RC5_compute_7/4_Time_out: \ |
9493 ADD X,Y \ | out of bound = 7/4 period
9494 \ RC5_WaitHalfCycleP1.2_IFG: \ |
9496 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
9497 0>= IF \ | if cycle time out of bound
9498 BIC #$30,&TA0CTL \ | stop timer_A0
9499 RETI \ | then quit to do nothing
9501 \ ------------------------------\ |
9502 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
9504 MOV &TA0R,X \ | | get new RC5_period value
9505 REPEAT \ ----> loop back --+ |
9506 \ ------------------------------\ |
9507 \ RC5_SampleEndOf: \ <---------------------+
9508 \ ------------------------------\
9509 BIC #$30,&TA0CTL \ stop timer_A0
9510 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
9511 \ ******************************\
9512 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9513 \ ******************************\
9514 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
9515 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
9516 XOR IP,X \ (new XOR old) Toggle bit (13)
9517 BIT #BIT13,X \ X(13) = New_RC5_command
9518 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
9520 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
9521 \ ******************************\
9522 \ RC5_ComputeNewRC5word \
9523 \ ******************************\
9525 MOV &BASE,2(PSP) \ save variable BASE before use
9526 MOV TOS,0(PSP) \ save TOS before use
9527 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
9528 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
9529 \ ******************************\
9530 \ RC5_ComputeC6bit \
9531 \ ******************************\
9532 BIT #$4000,IP \ test /C6 bit in IP
9533 0= IF BIS #$40,TOS \ set C6 bit in S
9534 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
9535 \ ******************************\
9536 \ RC5_CommandByteIsDone \ RC5_code --
9537 \ ******************************\
9539 \ ------------------------------\
9540 \ Display IR_RC5 code \
9541 \ ------------------------------\
9542 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
9543 \ ------------------------------\
9544 LO2HI \ switch from assembler to FORTH
9545 ['] LCD_CLEAR IS CR \ redirects CR
9546 ['] LCD_WrC IS EMIT \ redirects EMIT
9547 $10 BASE ! \ change BASE to hexadecimal
9548 CR ." $" 2 U.R \ print IR_RC5 code
9549 ['] (CR) IS CR \ restore CR
9550 ['] (EMIT) IS EMIT \ restore EMIT
9551 HI2LO \ switch from FORTH to assembler
9552 \ ------------------------------\
9553 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
9554 \ ------------------------------\
9555 MOV @PSP+,&BASE \ restore variable BASE
9556 RETI \ CPU is ON, GIE is OFF
9561 \ ------------------------------\
9562 \ TB0CTL = %0000 0010 1001 0100\$3C0
9563 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9564 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9565 \ -- \ID input divider \ 10 = /4
9566 \ -- \MC Mode Control \ 01 = up to TB0CCR0
9567 \ - \TBCLR TimerB Clear
9570 \ --------------------------------\\
9571 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9572 \ -- \CM Capture Mode
9577 \ --- \OUTMOD \ 011 = set/reset
9583 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
9585 \ ------------------------------\
9586 \ set TimerB to make 50kHz PWM \
9587 \ ------------------------------\
9588 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9589 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
9590 \ ------------------------------\
9591 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9592 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
9593 \ ------------------------------\
9594 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9595 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
9596 \ ------------------------------\
9597 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9598 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
9599 \ ------------------------------\
9600 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9601 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
9602 \ ------------------------------\
9603 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
9604 \ ------------------------------\
9605 \ set TimerB to generate PWM for LCD_Vo
9606 \ ------------------------------\
9607 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
9608 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
9609 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9610 \ ------------------------------\
9611 BIS.B #LCDVo,&LCDVo_DIR \
9612 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
9613 \ ------------------------------\
9614 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9615 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9616 \ ------------------------------\
9617 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9618 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9619 \ ------------------------------\
9620 \ WDT interval init part \
9621 \ ------------------------------\
9622 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
9623 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
9624 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
9625 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
9626 \ ------------------------------\
9628 \ ------------------------------\
9629 BIS.B #RC5,&IR_IE \ enable RC5_Int
9630 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9631 \ ------------------------------\
9632 \ init interrupt vectors
9633 \ ------------------------------\
9634 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
9635 MOV #RC5_INT,&IR_Vec \ init interrupt vector
9636 \ ------------------------------\
9637 \ define LPM mode for ACCEPT \
9638 \ ------------------------------\
9639 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9640 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9641 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9643 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
9645 \ ------------------------------\
9647 \ ------------------------------\
9648 $03E8 20_US \ 1- wait 20 ms
9649 $03 TOP_LCD \ 2- send DB5=DB4=1
9650 $CD 20_US \ 3- wait 4,1 ms
9651 $03 TOP_LCD \ 4- send again DB5=DB4=1
9652 $5 20_US \ 5- wait 0,1 ms
9653 $03 TOP_LCD \ 6- send again again DB5=DB4=1
9654 $2 20_US \ wait 40 us = LCD cycle
9655 $02 TOP_LCD \ 7- send DB5=1 DB4=0
9656 $2 20_US \ wait 40 us = LCD cycle
9657 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9658 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9659 LCD_Clear \ 10- "LCD_Clear"
9660 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9661 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9662 LCD_Clear \ 10- "LCD_Clear"
9663 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9664 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9666 ['] (CR) IS CR \ ' (CR) is CR
9667 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
9669 ." RC5toLCD is running. Type STOP to quit"
9670 \ NOECHO \ uncomment to run this app without terminal connexion
9671 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
9672 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
9676 : STOP \ stops multitasking, must to be used before downloading app
9677 ['] (WARM) IS WARM \ remove START app from FORTH init process
9678 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
9686 CODE MAX \ n1 n2 -- n3 signed maximum
9687 CMP @PSP,TOS \ n2-n1
9688 S< ?GOTO FW1 \ n2<n1
9694 CODE MIN \ n1 n2 -- n3 signed minimum
9695 CMP @PSP,TOS \ n2-n1
9696 S< ?GOTO BW1 \ n2<n1
9702 : U.R \ u n -- display u unsigned in n width (n >= 2)
9704 R> OVER - 0 MAX SPACES TYPE
9708 CODE 20_US \ n -- n * 20 us
9709 BEGIN \ 3 cycles loop + 6~
9710 \ MOV #5,W \ 3 MCLK = 1 MHz
9711 \ MOV #23,W \ 3 MCLK = 4 MHz
9712 MOV #51,W \ 3 MCLK = 8 MHz
9713 \ MOV #104,W \ 3 MCLK = 16 MHz
9714 \ MOV #158,W \ 3 MCLK = 24 MHz
9715 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
9725 CODE TOP_LCD \ LCD Sample
9726 \ \ if write : %xxxxWWWW --
9727 \ \ if read : -- %0000RRRR
9728 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9729 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9730 0= IF \ write LCD bits pattern
9732 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9733 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9736 THEN \ read LCD bits pattern
9739 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9740 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9746 CODE LCD_W \ byte -- write byte to LCD
9748 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
9749 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
9750 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9751 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9752 COLON \ high level word starts here
9753 TOP_LCD 2 20_US \ write high nibble first
9758 CODE LCD_WrC \ char -- Write Char
9759 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9764 CODE LCD_WrF \ func -- Write Fonction
9765 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9771 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
9776 $02 LCD_WrF 100 20_us
9780 \ : LCD_Entry_set $04 OR LCD_WrF ;
9782 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
9784 \ : LCD_Display_Shift $10 OR LCD_WrF ;
9786 \ : LCD_Fn_Set $20 OR LCD_WrF ;
9788 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
9790 \ : LCD_Goto $80 OR LCD_WrF ;
9792 \ CODE LCD_R \ -- byte read byte from LCD
9793 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9794 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9795 \ COLON \ starts a FORTH word
9796 \ TOP_LCD 2 20_us \ -- %0000HHHH
9797 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
9798 \ HI2LO \ switch from FORTH to assembler
9799 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
9800 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
9801 \ MOV @RSP+,IP \ restore IP saved by COLON
9806 \ CODE LCD_RdS \ -- status Read Status
9807 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9812 \ CODE LCD_RdC \ -- char Read Char
9813 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9818 \ -------------+------+------+------+------++---+---+---+---+---------+
9819 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
9820 \ -------------+------+------+------+------++---+---+---+---+---------+
9821 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
9822 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
9823 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
9824 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
9825 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
9826 \ -------------+------+------+------+------++---+---+---+---+---------+
9829 \ ******************************\
9830 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9831 \ ******************************\
9832 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
9833 \ ------------------------------\
9834 \ define LPM mode for ACCEPT \
9835 \ ------------------------------\
9836 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9837 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9838 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9839 BIT.B #SW2,&SW2_IN \ test switch S2
9840 0= IF \ case of switch S2 pressed
9841 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
9843 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
9846 BIT.B #SW1,&SW1_IN \ test switch S1 input
9847 0= IF \ case of Switch S1 pressed
9848 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
9850 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
9854 RETI \ CPU is ON, GIE is OFF
9859 \ ------------------------------\
9860 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9861 \ ******************************\
9862 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9863 \ ******************************\
9864 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9865 \ \ SMclock = 8|16|24 MHz
9866 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
9867 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
9868 \ \ SR(9)=new Toggle bit memory (ADD on)
9869 \ ------------------------------\
9870 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
9871 \ ------------------------------\
9872 \ define LPM mode for ACCEPT \
9873 \ ------------------------------\
9874 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9875 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9876 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9877 \ ------------------------------\
9878 \ RC5_FirstStartBitHalfCycle: \
9879 \ ------------------------------\
9880 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
9881 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
9882 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
9883 MOV #1778,X \ RC5_Period in us
9884 MOV #14,W \ count of loop
9886 \ ------------------------------\
9887 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
9888 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
9889 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
9890 \ RC5_Compute_3/4_Period: \ |
9891 RRUM #1,X \ X=1/2 cycle |
9895 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
9896 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
9898 \ ------------------------------\
9899 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
9900 \ ------------------------------\
9901 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9902 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
9903 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9904 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9905 SUB #1,W \ decrement count loop
9906 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
9907 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9908 0<> WHILE \ ----> out of loop ----+
9909 \ RC5_compute_7/4_Time_out: \ |
9910 ADD X,Y \ | out of bound = 7/4 period
9911 \ RC5_WaitHalfCycleP1.2_IFG: \ |
9913 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
9914 0>= IF \ | if cycle time out of bound
9915 BIC #$30,&TA0CTL \ | stop timer_A0
9916 RETI \ | then quit to do nothing
9918 \ ------------------------------\ |
9919 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
9921 MOV &TA0R,X \ | | get new RC5_period value
9922 REPEAT \ ----> loop back --+ |
9923 \ ------------------------------\ |
9924 \ RC5_SampleEndOf: \ <---------------------+
9925 \ ------------------------------\
9926 BIC #$30,&TA0CTL \ stop timer_A0
9927 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
9928 \ ******************************\
9929 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9930 \ ******************************\
9931 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
9932 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
9933 XOR IP,X \ (new XOR old) Toggle bit (13)
9934 BIT #BIT13,X \ X(13) = New_RC5_command
9935 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
9937 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
9938 \ ******************************\
9939 \ RC5_ComputeNewRC5word \
9940 \ ******************************\
9942 MOV &BASE,2(PSP) \ save variable BASE before use
9943 MOV TOS,0(PSP) \ save TOS before use
9944 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
9945 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
9946 \ ******************************\
9947 \ RC5_ComputeC6bit \
9948 \ ******************************\
9949 BIT #$4000,IP \ test /C6 bit in IP
9950 0= IF BIS #$40,TOS \ set C6 bit in S
9951 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
9952 \ ******************************\
9953 \ RC5_CommandByteIsDone \ RC5_code --
9954 \ ******************************\
9956 \ ------------------------------\
9957 \ Display IR_RC5 code \
9958 \ ------------------------------\
9959 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
9960 \ ------------------------------\
9961 LO2HI \ switch from assembler to FORTH
9962 ['] LCD_CLEAR IS CR \ redirects CR
9963 ['] LCD_WrC IS EMIT \ redirects EMIT
9964 $10 BASE ! \ change BASE to hexadecimal
9965 CR ." $" 2 U.R \ print IR_RC5 code
9966 ['] (CR) IS CR \ restore CR
9967 ['] (EMIT) IS EMIT \ restore EMIT
9968 HI2LO \ switch from FORTH to assembler
9969 \ ------------------------------\
9970 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
9971 \ ------------------------------\
9972 MOV @PSP+,&BASE \ restore variable BASE
9973 RETI \ CPU is ON, GIE is OFF
9978 \ ------------------------------\
9979 \ TB0CTL = %0000 0010 1001 0100\$3C0
9980 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9981 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9982 \ -- \ID input divider \ 10 = /4
9983 \ -- \MC Mode Control \ 01 = up to TB0CCR0
9984 \ - \TBCLR TimerB Clear
9987 \ --------------------------------\\
9988 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9989 \ -- \CM Capture Mode
9994 \ --- \OUTMOD \ 011 = set/reset
10000 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
10002 \ ------------------------------\
10003 \ set TimerB to make 50kHz PWM \
10004 \ ------------------------------\
10005 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10006 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
10007 \ ------------------------------\
10008 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10009 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
10010 \ ------------------------------\
10011 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10012 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
10013 \ ------------------------------\
10014 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10015 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
10016 \ ------------------------------\
10017 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10018 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
10019 \ ------------------------------\
10020 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
10021 \ ------------------------------\
10022 \ set TimerB to generate PWM for LCD_Vo
10023 \ ------------------------------\
10024 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
10025 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
10026 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10027 \ ------------------------------\
10028 BIS.B #LCDVo,&LCDVo_DIR \
10029 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
10030 \ ------------------------------\
10031 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10032 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10033 \ ------------------------------\
10034 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10035 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10036 \ ------------------------------\
10037 \ WDT interval init part \
10038 \ ------------------------------\
10039 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
10040 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
10041 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
10042 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
10043 \ ------------------------------\
10045 \ ------------------------------\
10046 BIS.B #RC5,&IR_IE \ enable RC5_Int
10047 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10048 \ ------------------------------\
10049 \ init interrupt vectors
10050 \ ------------------------------\
10051 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
10052 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10053 \ ------------------------------\
10054 \ define LPM mode for ACCEPT \
10055 \ ------------------------------\
10056 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10057 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10058 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10060 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
10062 \ ------------------------------\
10064 \ ------------------------------\
10065 $03E8 20_US \ 1- wait 20 ms
10066 $03 TOP_LCD \ 2- send DB5=DB4=1
10067 $CD 20_US \ 3- wait 4,1 ms
10068 $03 TOP_LCD \ 4- send again DB5=DB4=1
10069 $5 20_US \ 5- wait 0,1 ms
10070 $03 TOP_LCD \ 6- send again again DB5=DB4=1
10071 $2 20_US \ wait 40 us = LCD cycle
10072 $02 TOP_LCD \ 7- send DB5=1 DB4=0
10073 $2 20_US \ wait 40 us = LCD cycle
10074 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10075 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10076 LCD_Clear \ 10- "LCD_Clear"
10077 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10078 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10079 LCD_Clear \ 10- "LCD_Clear"
10080 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10081 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10083 ['] (CR) IS CR \ ' (CR) is CR
10084 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
10086 ." RC5toLCD is running. Type STOP to quit"
10087 \ NOECHO \ uncomment to run this app without terminal connexion
10088 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
10089 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
10093 : STOP \ stops multitasking, must to be used before downloading app
10094 ['] (WARM) IS WARM \ remove START app from FORTH init process
10095 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
10103 CODE MAX \ n1 n2 -- n3 signed maximum
10104 CMP @PSP,TOS \ n2-n1
10105 S< ?GOTO FW1 \ n2<n1
10111 CODE MIN \ n1 n2 -- n3 signed minimum
10112 CMP @PSP,TOS \ n2-n1
10113 S< ?GOTO BW1 \ n2<n1
10119 : U.R \ u n -- display u unsigned in n width (n >= 2)
10121 R> OVER - 0 MAX SPACES TYPE
10125 CODE 20_US \ n -- n * 20 us
10126 BEGIN \ 3 cycles loop + 6~
10127 \ MOV #5,W \ 3 MCLK = 1 MHz
10128 \ MOV #23,W \ 3 MCLK = 4 MHz
10129 MOV #51,W \ 3 MCLK = 8 MHz
10130 \ MOV #104,W \ 3 MCLK = 16 MHz
10131 \ MOV #158,W \ 3 MCLK = 24 MHz
10132 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
10142 CODE TOP_LCD \ LCD Sample
10143 \ \ if write : %xxxxWWWW --
10144 \ \ if read : -- %0000RRRR
10145 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10146 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10147 0= IF \ write LCD bits pattern
10148 AND.B #LCD_DB,TOS \
10149 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10150 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10153 THEN \ read LCD bits pattern
10156 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10157 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10158 AND.B #LCD_DB,TOS \
10163 CODE LCD_W \ byte -- write byte to LCD
10165 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
10166 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
10167 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10168 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10169 COLON \ high level word starts here
10170 TOP_LCD 2 20_US \ write high nibble first
10175 CODE LCD_WrC \ char -- Write Char
10176 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10181 CODE LCD_WrF \ func -- Write Fonction
10182 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10188 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
10193 $02 LCD_WrF 100 20_us
10197 \ : LCD_Entry_set $04 OR LCD_WrF ;
10199 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
10201 \ : LCD_Display_Shift $10 OR LCD_WrF ;
10203 \ : LCD_Fn_Set $20 OR LCD_WrF ;
10205 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
10207 \ : LCD_Goto $80 OR LCD_WrF ;
10209 \ CODE LCD_R \ -- byte read byte from LCD
10210 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10211 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10212 \ COLON \ starts a FORTH word
10213 \ TOP_LCD 2 20_us \ -- %0000HHHH
10214 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
10215 \ HI2LO \ switch from FORTH to assembler
10216 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
10217 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
10218 \ MOV @RSP+,IP \ restore IP saved by COLON
10223 \ CODE LCD_RdS \ -- status Read Status
10224 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10229 \ CODE LCD_RdC \ -- char Read Char
10230 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10235 \ -------------+------+------+------+------++---+---+---+---+---------+
10236 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
10237 \ -------------+------+------+------+------++---+---+---+---+---------+
10238 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
10239 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
10240 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
10241 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
10242 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
10243 \ -------------+------+------+------+------++---+---+---+---+---------+
10246 \ ******************************\
10247 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10248 \ ******************************\
10249 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
10250 \ ------------------------------\
10251 \ define LPM mode for ACCEPT \
10252 \ ------------------------------\
10253 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10254 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10255 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10256 BIT.B #SW2,&SW2_IN \ test switch S2
10257 0= IF \ case of switch S2 pressed
10258 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
10260 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
10263 BIT.B #SW1,&SW1_IN \ test switch S1 input
10264 0= IF \ case of Switch S1 pressed
10265 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
10267 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
10271 RETI \ CPU is ON, GIE is OFF
10276 \ ------------------------------\
10277 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10278 \ ******************************\
10279 ASM RC5_INT \ wake up on Px.RC5 change interrupt
10280 \ ******************************\
10281 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10282 \ \ SMclock = 8|16|24 MHz
10283 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
10284 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
10285 \ \ SR(9)=new Toggle bit memory (ADD on)
10286 \ ------------------------------\
10287 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
10288 \ ------------------------------\
10289 \ define LPM mode for ACCEPT \
10290 \ ------------------------------\
10291 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10292 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10293 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10294 \ ------------------------------\
10295 \ RC5_FirstStartBitHalfCycle: \
10296 \ ------------------------------\
10297 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
10298 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
10299 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
10300 MOV #1778,X \ RC5_Period in us
10301 MOV #14,W \ count of loop
10303 \ ------------------------------\
10304 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
10305 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
10306 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
10307 \ RC5_Compute_3/4_Period: \ |
10308 RRUM #1,X \ X=1/2 cycle |
10312 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
10313 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
10315 \ ------------------------------\
10316 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
10317 \ ------------------------------\
10318 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10319 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
10320 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10321 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10322 SUB #1,W \ decrement count loop
10323 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
10324 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10325 0<> WHILE \ ----> out of loop ----+
10326 \ RC5_compute_7/4_Time_out: \ |
10327 ADD X,Y \ | out of bound = 7/4 period
10328 \ RC5_WaitHalfCycleP1.2_IFG: \ |
10330 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
10331 0>= IF \ | if cycle time out of bound
10332 BIC #$30,&TA0CTL \ | stop timer_A0
10333 RETI \ | then quit to do nothing
10335 \ ------------------------------\ |
10336 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
10338 MOV &TA0R,X \ | | get new RC5_period value
10339 REPEAT \ ----> loop back --+ |
10340 \ ------------------------------\ |
10341 \ RC5_SampleEndOf: \ <---------------------+
10342 \ ------------------------------\
10343 BIC #$30,&TA0CTL \ stop timer_A0
10344 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
10345 \ ******************************\
10346 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10347 \ ******************************\
10348 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
10349 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
10350 XOR IP,X \ (new XOR old) Toggle bit (13)
10351 BIT #BIT13,X \ X(13) = New_RC5_command
10352 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
10354 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
10355 \ ******************************\
10356 \ RC5_ComputeNewRC5word \
10357 \ ******************************\
10359 MOV &BASE,2(PSP) \ save variable BASE before use
10360 MOV TOS,0(PSP) \ save TOS before use
10361 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
10362 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
10363 \ ******************************\
10364 \ RC5_ComputeC6bit \
10365 \ ******************************\
10366 BIT #$4000,IP \ test /C6 bit in IP
10367 0= IF BIS #$40,TOS \ set C6 bit in S
10368 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
10369 \ ******************************\
10370 \ RC5_CommandByteIsDone \ RC5_code --
10371 \ ******************************\
10373 \ ------------------------------\
10374 \ Display IR_RC5 code \
10375 \ ------------------------------\
10376 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
10377 \ ------------------------------\
10378 LO2HI \ switch from assembler to FORTH
10379 ['] LCD_CLEAR IS CR \ redirects CR
10380 ['] LCD_WrC IS EMIT \ redirects EMIT
10381 $10 BASE ! \ change BASE to hexadecimal
10382 CR ." $" 2 U.R \ print IR_RC5 code
10383 ['] (CR) IS CR \ restore CR
10384 ['] (EMIT) IS EMIT \ restore EMIT
10385 HI2LO \ switch from FORTH to assembler
10386 \ ------------------------------\
10387 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
10388 \ ------------------------------\
10389 MOV @PSP+,&BASE \ restore variable BASE
10390 RETI \ CPU is ON, GIE is OFF
10395 \ ------------------------------\
10396 \ TB0CTL = %0000 0010 1001 0100\$3C0
10397 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10398 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10399 \ -- \ID input divider \ 10 = /4
10400 \ -- \MC Mode Control \ 01 = up to TB0CCR0
10401 \ - \TBCLR TimerB Clear
10404 \ --------------------------------\\
10405 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10406 \ -- \CM Capture Mode
10411 \ --- \OUTMOD \ 011 = set/reset
10417 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
10419 \ ------------------------------\
10420 \ set TimerB to make 50kHz PWM \
10421 \ ------------------------------\
10422 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10423 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
10424 \ ------------------------------\
10425 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10426 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
10427 \ ------------------------------\
10428 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10429 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
10430 \ ------------------------------\
10431 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10432 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
10433 \ ------------------------------\
10434 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10435 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
10436 \ ------------------------------\
10437 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
10438 \ ------------------------------\
10439 \ set TimerB to generate PWM for LCD_Vo
10440 \ ------------------------------\
10441 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
10442 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
10443 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10444 \ ------------------------------\
10445 BIS.B #LCDVo,&LCDVo_DIR \
10446 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
10447 \ ------------------------------\
10448 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10449 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10450 \ ------------------------------\
10451 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10452 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10453 \ ------------------------------\
10454 \ WDT interval init part \
10455 \ ------------------------------\
10456 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
10457 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
10458 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
10459 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
10460 \ ------------------------------\
10462 \ ------------------------------\
10463 BIS.B #RC5,&IR_IE \ enable RC5_Int
10464 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10465 \ ------------------------------\
10466 \ init interrupt vectors
10467 \ ------------------------------\
10468 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
10469 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10470 \ ------------------------------\
10471 \ define LPM mode for ACCEPT \
10472 \ ------------------------------\
10473 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10474 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10475 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10477 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
10479 \ ------------------------------\
10481 \ ------------------------------\
10482 $03E8 20_US \ 1- wait 20 ms
10483 $03 TOP_LCD \ 2- send DB5=DB4=1
10484 $CD 20_US \ 3- wait 4,1 ms
10485 $03 TOP_LCD \ 4- send again DB5=DB4=1
10486 $5 20_US \ 5- wait 0,1 ms
10487 $03 TOP_LCD \ 6- send again again DB5=DB4=1
10488 $2 20_US \ wait 40 us = LCD cycle
10489 $02 TOP_LCD \ 7- send DB5=1 DB4=0
10490 $2 20_US \ wait 40 us = LCD cycle
10491 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10492 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10493 LCD_Clear \ 10- "LCD_Clear"
10494 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10495 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10496 LCD_Clear \ 10- "LCD_Clear"
10497 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10498 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10500 ['] (CR) IS CR \ ' (CR) is CR
10501 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
10503 ." RC5toLCD is running. Type STOP to quit"
10504 \ NOECHO \ uncomment to run this app without terminal connexion
10505 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
10506 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
10510 : STOP \ stops multitasking, must to be used before downloading app
10511 ['] (WARM) IS WARM \ remove START app from FORTH init process
10512 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
10520 CODE MAX \ n1 n2 -- n3 signed maximum
10521 CMP @PSP,TOS \ n2-n1
10522 S< ?GOTO FW1 \ n2<n1
10528 CODE MIN \ n1 n2 -- n3 signed minimum
10529 CMP @PSP,TOS \ n2-n1
10530 S< ?GOTO BW1 \ n2<n1
10536 : U.R \ u n -- display u unsigned in n width (n >= 2)
10538 R> OVER - 0 MAX SPACES TYPE
10542 CODE 20_US \ n -- n * 20 us
10543 BEGIN \ 3 cycles loop + 6~
10544 \ MOV #5,W \ 3 MCLK = 1 MHz
10545 \ MOV #23,W \ 3 MCLK = 4 MHz
10546 MOV #51,W \ 3 MCLK = 8 MHz
10547 \ MOV #104,W \ 3 MCLK = 16 MHz
10548 \ MOV #158,W \ 3 MCLK = 24 MHz
10549 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
10559 CODE TOP_LCD \ LCD Sample
10560 \ \ if write : %xxxxWWWW --
10561 \ \ if read : -- %0000RRRR
10562 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10563 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10564 0= IF \ write LCD bits pattern
10565 AND.B #LCD_DB,TOS \
10566 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10567 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10570 THEN \ read LCD bits pattern
10573 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10574 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10575 AND.B #LCD_DB,TOS \
10580 CODE LCD_W \ byte -- write byte to LCD
10582 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
10583 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
10584 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10585 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10586 COLON \ high level word starts here
10587 TOP_LCD 2 20_US \ write high nibble first
10592 CODE LCD_WrC \ char -- Write Char
10593 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10598 CODE LCD_WrF \ func -- Write Fonction
10599 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10605 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
10610 $02 LCD_WrF 100 20_us
10614 \ : LCD_Entry_set $04 OR LCD_WrF ;
10616 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
10618 \ : LCD_Display_Shift $10 OR LCD_WrF ;
10620 \ : LCD_Fn_Set $20 OR LCD_WrF ;
10622 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
10624 \ : LCD_Goto $80 OR LCD_WrF ;
10626 \ CODE LCD_R \ -- byte read byte from LCD
10627 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10628 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10629 \ COLON \ starts a FORTH word
10630 \ TOP_LCD 2 20_us \ -- %0000HHHH
10631 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
10632 \ HI2LO \ switch from FORTH to assembler
10633 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
10634 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
10635 \ MOV @RSP+,IP \ restore IP saved by COLON
10640 \ CODE LCD_RdS \ -- status Read Status
10641 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10646 \ CODE LCD_RdC \ -- char Read Char
10647 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10652 \ -------------+------+------+------+------++---+---+---+---+---------+
10653 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
10654 \ -------------+------+------+------+------++---+---+---+---+---------+
10655 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
10656 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
10657 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
10658 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
10659 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
10660 \ -------------+------+------+------+------++---+---+---+---+---------+
10663 \ ******************************\
10664 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10665 \ ******************************\
10666 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
10667 \ ------------------------------\
10668 \ define LPM mode for ACCEPT \
10669 \ ------------------------------\
10670 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10671 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10672 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10673 BIT.B #SW2,&SW2_IN \ test switch S2
10674 0= IF \ case of switch S2 pressed
10675 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
10677 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
10680 BIT.B #SW1,&SW1_IN \ test switch S1 input
10681 0= IF \ case of Switch S1 pressed
10682 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
10684 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
10688 RETI \ CPU is ON, GIE is OFF
10693 \ ------------------------------\
10694 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10695 \ ******************************\
10696 ASM RC5_INT \ wake up on Px.RC5 change interrupt
10697 \ ******************************\
10698 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10699 \ \ SMclock = 8|16|24 MHz
10700 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
10701 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
10702 \ \ SR(9)=new Toggle bit memory (ADD on)
10703 \ ------------------------------\
10704 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
10705 \ ------------------------------\
10706 \ define LPM mode for ACCEPT \
10707 \ ------------------------------\
10708 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10709 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10710 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10711 \ ------------------------------\
10712 \ RC5_FirstStartBitHalfCycle: \
10713 \ ------------------------------\
10714 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
10715 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
10716 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
10717 MOV #1778,X \ RC5_Period in us
10718 MOV #14,W \ count of loop
10720 \ ------------------------------\
10721 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
10722 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
10723 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
10724 \ RC5_Compute_3/4_Period: \ |
10725 RRUM #1,X \ X=1/2 cycle |
10729 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
10730 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
10732 \ ------------------------------\
10733 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
10734 \ ------------------------------\
10735 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10736 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
10737 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10738 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10739 SUB #1,W \ decrement count loop
10740 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
10741 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10742 0<> WHILE \ ----> out of loop ----+
10743 \ RC5_compute_7/4_Time_out: \ |
10744 ADD X,Y \ | out of bound = 7/4 period
10745 \ RC5_WaitHalfCycleP1.2_IFG: \ |
10747 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
10748 0>= IF \ | if cycle time out of bound
10749 BIC #$30,&TA0CTL \ | stop timer_A0
10750 RETI \ | then quit to do nothing
10752 \ ------------------------------\ |
10753 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
10755 MOV &TA0R,X \ | | get new RC5_period value
10756 REPEAT \ ----> loop back --+ |
10757 \ ------------------------------\ |
10758 \ RC5_SampleEndOf: \ <---------------------+
10759 \ ------------------------------\
10760 BIC #$30,&TA0CTL \ stop timer_A0
10761 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
10762 \ ******************************\
10763 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10764 \ ******************************\
10765 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
10766 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
10767 XOR IP,X \ (new XOR old) Toggle bit (13)
10768 BIT #BIT13,X \ X(13) = New_RC5_command
10769 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
10771 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
10772 \ ******************************\
10773 \ RC5_ComputeNewRC5word \
10774 \ ******************************\
10776 MOV &BASE,2(PSP) \ save variable BASE before use
10777 MOV TOS,0(PSP) \ save TOS before use
10778 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
10779 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
10780 \ ******************************\
10781 \ RC5_ComputeC6bit \
10782 \ ******************************\
10783 BIT #$4000,IP \ test /C6 bit in IP
10784 0= IF BIS #$40,TOS \ set C6 bit in S
10785 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
10786 \ ******************************\
10787 \ RC5_CommandByteIsDone \ RC5_code --
10788 \ ******************************\
10790 \ ------------------------------\
10791 \ Display IR_RC5 code \
10792 \ ------------------------------\
10793 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
10794 \ ------------------------------\
10795 LO2HI \ switch from assembler to FORTH
10796 ['] LCD_CLEAR IS CR \ redirects CR
10797 ['] LCD_WrC IS EMIT \ redirects EMIT
10798 $10 BASE ! \ change BASE to hexadecimal
10799 CR ." $" 2 U.R \ print IR_RC5 code
10800 ['] (CR) IS CR \ restore CR
10801 ['] (EMIT) IS EMIT \ restore EMIT
10802 HI2LO \ switch from FORTH to assembler
10803 \ ------------------------------\
10804 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
10805 \ ------------------------------\
10806 MOV @PSP+,&BASE \ restore variable BASE
10807 RETI \ CPU is ON, GIE is OFF
10812 \ ------------------------------\
10813 \ TB0CTL = %0000 0010 1001 0100\$3C0
10814 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10815 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10816 \ -- \ID input divider \ 10 = /4
10817 \ -- \MC Mode Control \ 01 = up to TB0CCR0
10818 \ - \TBCLR TimerB Clear
10821 \ --------------------------------\\
10822 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10823 \ -- \CM Capture Mode
10828 \ --- \OUTMOD \ 011 = set/reset
10834 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
10836 \ ------------------------------\
10837 \ set TimerB to make 50kHz PWM \
10838 \ ------------------------------\
10839 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10840 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
10841 \ ------------------------------\
10842 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10843 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
10844 \ ------------------------------\
10845 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10846 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
10847 \ ------------------------------\
10848 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10849 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
10850 \ ------------------------------\
10851 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10852 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
10853 \ ------------------------------\
10854 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
10855 \ ------------------------------\
10856 \ set TimerB to generate PWM for LCD_Vo
10857 \ ------------------------------\
10858 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
10859 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
10860 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10861 \ ------------------------------\
10862 BIS.B #LCDVo,&LCDVo_DIR \
10863 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
10864 \ ------------------------------\
10865 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10866 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10867 \ ------------------------------\
10868 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10869 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10870 \ ------------------------------\
10871 \ WDT interval init part \
10872 \ ------------------------------\
10873 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
10874 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
10875 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
10876 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
10877 \ ------------------------------\
10879 \ ------------------------------\
10880 BIS.B #RC5,&IR_IE \ enable RC5_Int
10881 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10882 \ ------------------------------\
10883 \ init interrupt vectors
10884 \ ------------------------------\
10885 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
10886 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10887 \ ------------------------------\
10888 \ define LPM mode for ACCEPT \
10889 \ ------------------------------\
10890 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10891 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10892 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10894 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
10896 \ ------------------------------\
10898 \ ------------------------------\
10899 $03E8 20_US \ 1- wait 20 ms
10900 $03 TOP_LCD \ 2- send DB5=DB4=1
10901 $CD 20_US \ 3- wait 4,1 ms
10902 $03 TOP_LCD \ 4- send again DB5=DB4=1
10903 $5 20_US \ 5- wait 0,1 ms
10904 $03 TOP_LCD \ 6- send again again DB5=DB4=1
10905 $2 20_US \ wait 40 us = LCD cycle
10906 $02 TOP_LCD \ 7- send DB5=1 DB4=0
10907 $2 20_US \ wait 40 us = LCD cycle
10908 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10909 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10910 LCD_Clear \ 10- "LCD_Clear"
10911 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10912 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10913 LCD_Clear \ 10- "LCD_Clear"
10914 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10915 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10917 ['] (CR) IS CR \ ' (CR) is CR
10918 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
10920 ." RC5toLCD is running. Type STOP to quit"
10921 \ NOECHO \ uncomment to run this app without terminal connexion
10922 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
10923 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
10927 : STOP \ stops multitasking, must to be used before downloading app
10928 ['] (WARM) IS WARM \ remove START app from FORTH init process
10929 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
10937 CODE MAX \ n1 n2 -- n3 signed maximum
10938 CMP @PSP,TOS \ n2-n1
10939 S< ?GOTO FW1 \ n2<n1
10945 CODE MIN \ n1 n2 -- n3 signed minimum
10946 CMP @PSP,TOS \ n2-n1
10947 S< ?GOTO BW1 \ n2<n1
10953 : U.R \ u n -- display u unsigned in n width (n >= 2)
10955 R> OVER - 0 MAX SPACES TYPE
10959 CODE 20_US \ n -- n * 20 us
10960 BEGIN \ 3 cycles loop + 6~
10961 \ MOV #5,W \ 3 MCLK = 1 MHz
10962 \ MOV #23,W \ 3 MCLK = 4 MHz
10963 MOV #51,W \ 3 MCLK = 8 MHz
10964 \ MOV #104,W \ 3 MCLK = 16 MHz
10965 \ MOV #158,W \ 3 MCLK = 24 MHz
10966 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
10976 CODE TOP_LCD \ LCD Sample
10977 \ \ if write : %xxxxWWWW --
10978 \ \ if read : -- %0000RRRR
10979 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10980 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10981 0= IF \ write LCD bits pattern
10982 AND.B #LCD_DB,TOS \
10983 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10984 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10987 THEN \ read LCD bits pattern
10990 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10991 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10992 AND.B #LCD_DB,TOS \
10997 CODE LCD_W \ byte -- write byte to LCD
10999 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
11000 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
11001 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11002 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11003 COLON \ high level word starts here
11004 TOP_LCD 2 20_US \ write high nibble first
11009 CODE LCD_WrC \ char -- Write Char
11010 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11015 CODE LCD_WrF \ func -- Write Fonction
11016 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11022 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
11027 $02 LCD_WrF 100 20_us
11031 \ : LCD_Entry_set $04 OR LCD_WrF ;
11033 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
11035 \ : LCD_Display_Shift $10 OR LCD_WrF ;
11037 \ : LCD_Fn_Set $20 OR LCD_WrF ;
11039 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
11041 \ : LCD_Goto $80 OR LCD_WrF ;
11043 \ CODE LCD_R \ -- byte read byte from LCD
11044 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11045 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11046 \ COLON \ starts a FORTH word
11047 \ TOP_LCD 2 20_us \ -- %0000HHHH
11048 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11049 \ HI2LO \ switch from FORTH to assembler
11050 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11051 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11052 \ MOV @RSP+,IP \ restore IP saved by COLON
11057 \ CODE LCD_RdS \ -- status Read Status
11058 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11063 \ CODE LCD_RdC \ -- char Read Char
11064 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11069 \ -------------+------+------+------+------++---+---+---+---+---------+
11070 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
11071 \ -------------+------+------+------+------++---+---+---+---+---------+
11072 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
11073 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
11074 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
11075 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
11076 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
11077 \ -------------+------+------+------+------++---+---+---+---+---------+
11080 \ ******************************\
11081 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11082 \ ******************************\
11083 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
11084 \ ------------------------------\
11085 \ define LPM mode for ACCEPT \
11086 \ ------------------------------\
11087 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11088 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11089 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11090 BIT.B #SW2,&SW2_IN \ test switch S2
11091 0= IF \ case of switch S2 pressed
11092 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
11094 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
11097 BIT.B #SW1,&SW1_IN \ test switch S1 input
11098 0= IF \ case of Switch S1 pressed
11099 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
11101 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
11105 RETI \ CPU is ON, GIE is OFF
11110 \ ------------------------------\
11111 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11112 \ ******************************\
11113 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11114 \ ******************************\
11115 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11116 \ \ SMclock = 8|16|24 MHz
11117 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
11118 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
11119 \ \ SR(9)=new Toggle bit memory (ADD on)
11120 \ ------------------------------\
11121 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
11122 \ ------------------------------\
11123 \ define LPM mode for ACCEPT \
11124 \ ------------------------------\
11125 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11126 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11127 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11128 \ ------------------------------\
11129 \ RC5_FirstStartBitHalfCycle: \
11130 \ ------------------------------\
11131 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
11132 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
11133 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
11134 MOV #1778,X \ RC5_Period in us
11135 MOV #14,W \ count of loop
11137 \ ------------------------------\
11138 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
11139 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
11140 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
11141 \ RC5_Compute_3/4_Period: \ |
11142 RRUM #1,X \ X=1/2 cycle |
11146 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
11147 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
11149 \ ------------------------------\
11150 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
11151 \ ------------------------------\
11152 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11153 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
11154 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11155 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11156 SUB #1,W \ decrement count loop
11157 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
11158 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11159 0<> WHILE \ ----> out of loop ----+
11160 \ RC5_compute_7/4_Time_out: \ |
11161 ADD X,Y \ | out of bound = 7/4 period
11162 \ RC5_WaitHalfCycleP1.2_IFG: \ |
11164 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
11165 0>= IF \ | if cycle time out of bound
11166 BIC #$30,&TA0CTL \ | stop timer_A0
11167 RETI \ | then quit to do nothing
11169 \ ------------------------------\ |
11170 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
11172 MOV &TA0R,X \ | | get new RC5_period value
11173 REPEAT \ ----> loop back --+ |
11174 \ ------------------------------\ |
11175 \ RC5_SampleEndOf: \ <---------------------+
11176 \ ------------------------------\
11177 BIC #$30,&TA0CTL \ stop timer_A0
11178 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
11179 \ ******************************\
11180 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
11181 \ ******************************\
11182 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
11183 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
11184 XOR IP,X \ (new XOR old) Toggle bit (13)
11185 BIT #BIT13,X \ X(13) = New_RC5_command
11186 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
11188 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
11189 \ ******************************\
11190 \ RC5_ComputeNewRC5word \
11191 \ ******************************\
11193 MOV &BASE,2(PSP) \ save variable BASE before use
11194 MOV TOS,0(PSP) \ save TOS before use
11195 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
11196 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
11197 \ ******************************\
11198 \ RC5_ComputeC6bit \
11199 \ ******************************\
11200 BIT #$4000,IP \ test /C6 bit in IP
11201 0= IF BIS #$40,TOS \ set C6 bit in S
11202 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
11203 \ ******************************\
11204 \ RC5_CommandByteIsDone \ RC5_code --
11205 \ ******************************\
11207 \ ------------------------------\
11208 \ Display IR_RC5 code \
11209 \ ------------------------------\
11210 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
11211 \ ------------------------------\
11212 LO2HI \ switch from assembler to FORTH
11213 ['] LCD_CLEAR IS CR \ redirects CR
11214 ['] LCD_WrC IS EMIT \ redirects EMIT
11215 $10 BASE ! \ change BASE to hexadecimal
11216 CR ." $" 2 U.R \ print IR_RC5 code
11217 ['] (CR) IS CR \ restore CR
11218 ['] (EMIT) IS EMIT \ restore EMIT
11219 HI2LO \ switch from FORTH to assembler
11220 \ ------------------------------\
11221 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
11222 \ ------------------------------\
11223 MOV @PSP+,&BASE \ restore variable BASE
11224 RETI \ CPU is ON, GIE is OFF
11229 \ ------------------------------\
11230 \ TB0CTL = %0000 0010 1001 0100\$3C0
11231 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11232 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11233 \ -- \ID input divider \ 10 = /4
11234 \ -- \MC Mode Control \ 01 = up to TB0CCR0
11235 \ - \TBCLR TimerB Clear
11238 \ --------------------------------\\
11239 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11240 \ -- \CM Capture Mode
11245 \ --- \OUTMOD \ 011 = set/reset
11251 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
11253 \ ------------------------------\
11254 \ set TimerB to make 50kHz PWM \
11255 \ ------------------------------\
11256 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
11257 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
11258 \ ------------------------------\
11259 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
11260 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
11261 \ ------------------------------\
11262 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11263 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
11264 \ ------------------------------\
11265 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11266 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
11267 \ ------------------------------\
11268 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11269 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
11270 \ ------------------------------\
11271 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
11272 \ ------------------------------\
11273 \ set TimerB to generate PWM for LCD_Vo
11274 \ ------------------------------\
11275 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
11276 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
11277 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11278 \ ------------------------------\
11279 BIS.B #LCDVo,&LCDVo_DIR \
11280 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
11281 \ ------------------------------\
11282 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11283 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11284 \ ------------------------------\
11285 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11286 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11287 \ ------------------------------\
11288 \ WDT interval init part \
11289 \ ------------------------------\
11290 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
11291 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
11292 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
11293 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
11294 \ ------------------------------\
11296 \ ------------------------------\
11297 BIS.B #RC5,&IR_IE \ enable RC5_Int
11298 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11299 \ ------------------------------\
11300 \ init interrupt vectors
11301 \ ------------------------------\
11302 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
11303 MOV #RC5_INT,&IR_Vec \ init interrupt vector
11304 \ ------------------------------\
11305 \ define LPM mode for ACCEPT \
11306 \ ------------------------------\
11307 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11308 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11309 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11311 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
11313 \ ------------------------------\
11315 \ ------------------------------\
11316 $03E8 20_US \ 1- wait 20 ms
11317 $03 TOP_LCD \ 2- send DB5=DB4=1
11318 $CD 20_US \ 3- wait 4,1 ms
11319 $03 TOP_LCD \ 4- send again DB5=DB4=1
11320 $5 20_US \ 5- wait 0,1 ms
11321 $03 TOP_LCD \ 6- send again again DB5=DB4=1
11322 $2 20_US \ wait 40 us = LCD cycle
11323 $02 TOP_LCD \ 7- send DB5=1 DB4=0
11324 $2 20_US \ wait 40 us = LCD cycle
11325 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11326 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11327 LCD_Clear \ 10- "LCD_Clear"
11328 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11329 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11330 LCD_Clear \ 10- "LCD_Clear"
11331 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11332 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11334 ['] (CR) IS CR \ ' (CR) is CR
11335 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
11337 ." RC5toLCD is running. Type STOP to quit"
11338 \ NOECHO \ uncomment to run this app without terminal connexion
11339 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
11340 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
11344 : STOP \ stops multitasking, must to be used before downloading app
11345 ['] (WARM) IS WARM \ remove START app from FORTH init process
11346 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
11354 CODE MAX \ n1 n2 -- n3 signed maximum
11355 CMP @PSP,TOS \ n2-n1
11356 S< ?GOTO FW1 \ n2<n1
11362 CODE MIN \ n1 n2 -- n3 signed minimum
11363 CMP @PSP,TOS \ n2-n1
11364 S< ?GOTO BW1 \ n2<n1
11370 : U.R \ u n -- display u unsigned in n width (n >= 2)
11372 R> OVER - 0 MAX SPACES TYPE
11376 CODE 20_US \ n -- n * 20 us
11377 BEGIN \ 3 cycles loop + 6~
11378 \ MOV #5,W \ 3 MCLK = 1 MHz
11379 \ MOV #23,W \ 3 MCLK = 4 MHz
11380 MOV #51,W \ 3 MCLK = 8 MHz
11381 \ MOV #104,W \ 3 MCLK = 16 MHz
11382 \ MOV #158,W \ 3 MCLK = 24 MHz
11383 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
11393 CODE TOP_LCD \ LCD Sample
11394 \ \ if write : %xxxxWWWW --
11395 \ \ if read : -- %0000RRRR
11396 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11397 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11398 0= IF \ write LCD bits pattern
11399 AND.B #LCD_DB,TOS \
11400 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11401 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11404 THEN \ read LCD bits pattern
11407 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11408 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11409 AND.B #LCD_DB,TOS \
11414 CODE LCD_W \ byte -- write byte to LCD
11416 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
11417 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
11418 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11419 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11420 COLON \ high level word starts here
11421 TOP_LCD 2 20_US \ write high nibble first
11426 CODE LCD_WrC \ char -- Write Char
11427 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11432 CODE LCD_WrF \ func -- Write Fonction
11433 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11439 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
11444 $02 LCD_WrF 100 20_us
11448 \ : LCD_Entry_set $04 OR LCD_WrF ;
11450 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
11452 \ : LCD_Display_Shift $10 OR LCD_WrF ;
11454 \ : LCD_Fn_Set $20 OR LCD_WrF ;
11456 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
11458 \ : LCD_Goto $80 OR LCD_WrF ;
11460 \ CODE LCD_R \ -- byte read byte from LCD
11461 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11462 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11463 \ COLON \ starts a FORTH word
11464 \ TOP_LCD 2 20_us \ -- %0000HHHH
11465 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11466 \ HI2LO \ switch from FORTH to assembler
11467 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11468 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11469 \ MOV @RSP+,IP \ restore IP saved by COLON
11474 \ CODE LCD_RdS \ -- status Read Status
11475 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11480 \ CODE LCD_RdC \ -- char Read Char
11481 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11486 \ -------------+------+------+------+------++---+---+---+---+---------+
11487 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
11488 \ -------------+------+------+------+------++---+---+---+---+---------+
11489 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
11490 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
11491 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
11492 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
11493 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
11494 \ -------------+------+------+------+------++---+---+---+---+---------+
11497 \ ******************************\
11498 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11499 \ ******************************\
11500 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
11501 \ ------------------------------\
11502 \ define LPM mode for ACCEPT \
11503 \ ------------------------------\
11504 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11505 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11506 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11507 BIT.B #SW2,&SW2_IN \ test switch S2
11508 0= IF \ case of switch S2 pressed
11509 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
11511 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
11514 BIT.B #SW1,&SW1_IN \ test switch S1 input
11515 0= IF \ case of Switch S1 pressed
11516 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
11518 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
11522 RETI \ CPU is ON, GIE is OFF
11527 \ ------------------------------\
11528 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11529 \ ******************************\
11530 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11531 \ ******************************\
11532 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11533 \ \ SMclock = 8|16|24 MHz
11534 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
11535 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
11536 \ \ SR(9)=new Toggle bit memory (ADD on)
11537 \ ------------------------------\
11538 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
11539 \ ------------------------------\
11540 \ define LPM mode for ACCEPT \
11541 \ ------------------------------\
11542 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11543 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11544 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11545 \ ------------------------------\
11546 \ RC5_FirstStartBitHalfCycle: \
11547 \ ------------------------------\
11548 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
11549 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
11550 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
11551 MOV #1778,X \ RC5_Period in us
11552 MOV #14,W \ count of loop
11554 \ ------------------------------\
11555 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
11556 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
11557 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
11558 \ RC5_Compute_3/4_Period: \ |
11559 RRUM #1,X \ X=1/2 cycle |
11563 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
11564 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
11566 \ ------------------------------\
11567 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
11568 \ ------------------------------\
11569 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11570 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
11571 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11572 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11573 SUB #1,W \ decrement count loop
11574 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
11575 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11576 0<> WHILE \ ----> out of loop ----+
11577 \ RC5_compute_7/4_Time_out: \ |
11578 ADD X,Y \ | out of bound = 7/4 period
11579 \ RC5_WaitHalfCycleP1.2_IFG: \ |
11581 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
11582 0>= IF \ | if cycle time out of bound
11583 BIC #$30,&TA0CTL \ | stop timer_A0
11584 RETI \ | then quit to do nothing
11586 \ ------------------------------\ |
11587 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
11589 MOV &TA0R,X \ | | get new RC5_period value
11590 REPEAT \ ----> loop back --+ |
11591 \ ------------------------------\ |
11592 \ RC5_SampleEndOf: \ <---------------------+
11593 \ ------------------------------\
11594 BIC #$30,&TA0CTL \ stop timer_A0
11595 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
11596 \ ******************************\
11597 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
11598 \ ******************************\
11599 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
11600 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
11601 XOR IP,X \ (new XOR old) Toggle bit (13)
11602 BIT #BIT13,X \ X(13) = New_RC5_command
11603 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
11605 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
11606 \ ******************************\
11607 \ RC5_ComputeNewRC5word \
11608 \ ******************************\
11610 MOV &BASE,2(PSP) \ save variable BASE before use
11611 MOV TOS,0(PSP) \ save TOS before use
11612 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
11613 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
11614 \ ******************************\
11615 \ RC5_ComputeC6bit \
11616 \ ******************************\
11617 BIT #$4000,IP \ test /C6 bit in IP
11618 0= IF BIS #$40,TOS \ set C6 bit in S
11619 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
11620 \ ******************************\
11621 \ RC5_CommandByteIsDone \ RC5_code --
11622 \ ******************************\
11624 \ ------------------------------\
11625 \ Display IR_RC5 code \
11626 \ ------------------------------\
11627 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
11628 \ ------------------------------\
11629 LO2HI \ switch from assembler to FORTH
11630 ['] LCD_CLEAR IS CR \ redirects CR
11631 ['] LCD_WrC IS EMIT \ redirects EMIT
11632 $10 BASE ! \ change BASE to hexadecimal
11633 CR ." $" 2 U.R \ print IR_RC5 code
11634 ['] (CR) IS CR \ restore CR
11635 ['] (EMIT) IS EMIT \ restore EMIT
11636 HI2LO \ switch from FORTH to assembler
11637 \ ------------------------------\
11638 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
11639 \ ------------------------------\
11640 MOV @PSP+,&BASE \ restore variable BASE
11641 RETI \ CPU is ON, GIE is OFF
11646 \ ------------------------------\
11647 \ TB0CTL = %0000 0010 1001 0100\$3C0
11648 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11649 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11650 \ -- \ID input divider \ 10 = /4
11651 \ -- \MC Mode Control \ 01 = up to TB0CCR0
11652 \ - \TBCLR TimerB Clear
11655 \ --------------------------------\\
11656 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11657 \ -- \CM Capture Mode
11662 \ --- \OUTMOD \ 011 = set/reset
11668 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
11670 \ ------------------------------\
11671 \ set TimerB to make 50kHz PWM \
11672 \ ------------------------------\
11673 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
11674 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
11675 \ ------------------------------\
11676 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
11677 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
11678 \ ------------------------------\
11679 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11680 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
11681 \ ------------------------------\
11682 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11683 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
11684 \ ------------------------------\
11685 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11686 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
11687 \ ------------------------------\
11688 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
11689 \ ------------------------------\
11690 \ set TimerB to generate PWM for LCD_Vo
11691 \ ------------------------------\
11692 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
11693 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
11694 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11695 \ ------------------------------\
11696 BIS.B #LCDVo,&LCDVo_DIR \
11697 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
11698 \ ------------------------------\
11699 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11700 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11701 \ ------------------------------\
11702 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11703 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11704 \ ------------------------------\
11705 \ WDT interval init part \
11706 \ ------------------------------\
11707 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
11708 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
11709 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
11710 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
11711 \ ------------------------------\
11713 \ ------------------------------\
11714 BIS.B #RC5,&IR_IE \ enable RC5_Int
11715 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11716 \ ------------------------------\
11717 \ init interrupt vectors
11718 \ ------------------------------\
11719 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
11720 MOV #RC5_INT,&IR_Vec \ init interrupt vector
11721 \ ------------------------------\
11722 \ define LPM mode for ACCEPT \
11723 \ ------------------------------\
11724 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11725 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11726 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11728 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
11730 \ ------------------------------\
11732 \ ------------------------------\
11733 $03E8 20_US \ 1- wait 20 ms
11734 $03 TOP_LCD \ 2- send DB5=DB4=1
11735 $CD 20_US \ 3- wait 4,1 ms
11736 $03 TOP_LCD \ 4- send again DB5=DB4=1
11737 $5 20_US \ 5- wait 0,1 ms
11738 $03 TOP_LCD \ 6- send again again DB5=DB4=1
11739 $2 20_US \ wait 40 us = LCD cycle
11740 $02 TOP_LCD \ 7- send DB5=1 DB4=0
11741 $2 20_US \ wait 40 us = LCD cycle
11742 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11743 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11744 LCD_Clear \ 10- "LCD_Clear"
11745 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11746 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11747 LCD_Clear \ 10- "LCD_Clear"
11748 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11749 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11751 ['] (CR) IS CR \ ' (CR) is CR
11752 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
11754 ." RC5toLCD is running. Type STOP to quit"
11755 \ NOECHO \ uncomment to run this app without terminal connexion
11756 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
11757 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
11761 : STOP \ stops multitasking, must to be used before downloading app
11762 ['] (WARM) IS WARM \ remove START app from FORTH init process
11763 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
11771 CODE MAX \ n1 n2 -- n3 signed maximum
11772 CMP @PSP,TOS \ n2-n1
11773 S< ?GOTO FW1 \ n2<n1
11779 CODE MIN \ n1 n2 -- n3 signed minimum
11780 CMP @PSP,TOS \ n2-n1
11781 S< ?GOTO BW1 \ n2<n1
11787 : U.R \ u n -- display u unsigned in n width (n >= 2)
11789 R> OVER - 0 MAX SPACES TYPE
11793 CODE 20_US \ n -- n * 20 us
11794 BEGIN \ 3 cycles loop + 6~
11795 \ MOV #5,W \ 3 MCLK = 1 MHz
11796 \ MOV #23,W \ 3 MCLK = 4 MHz
11797 MOV #51,W \ 3 MCLK = 8 MHz
11798 \ MOV #104,W \ 3 MCLK = 16 MHz
11799 \ MOV #158,W \ 3 MCLK = 24 MHz
11800 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
11810 CODE TOP_LCD \ LCD Sample
11811 \ \ if write : %xxxxWWWW --
11812 \ \ if read : -- %0000RRRR
11813 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11814 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11815 0= IF \ write LCD bits pattern
11816 AND.B #LCD_DB,TOS \
11817 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11818 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11821 THEN \ read LCD bits pattern
11824 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11825 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11826 AND.B #LCD_DB,TOS \
11831 CODE LCD_W \ byte -- write byte to LCD
11833 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
11834 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
11835 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11836 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11837 COLON \ high level word starts here
11838 TOP_LCD 2 20_US \ write high nibble first
11843 CODE LCD_WrC \ char -- Write Char
11844 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11849 CODE LCD_WrF \ func -- Write Fonction
11850 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11856 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
11861 $02 LCD_WrF 100 20_us
11865 \ : LCD_Entry_set $04 OR LCD_WrF ;
11867 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
11869 \ : LCD_Display_Shift $10 OR LCD_WrF ;
11871 \ : LCD_Fn_Set $20 OR LCD_WrF ;
11873 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
11875 \ : LCD_Goto $80 OR LCD_WrF ;
11877 \ CODE LCD_R \ -- byte read byte from LCD
11878 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11879 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11880 \ COLON \ starts a FORTH word
11881 \ TOP_LCD 2 20_us \ -- %0000HHHH
11882 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11883 \ HI2LO \ switch from FORTH to assembler
11884 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11885 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11886 \ MOV @RSP+,IP \ restore IP saved by COLON
11891 \ CODE LCD_RdS \ -- status Read Status
11892 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11897 \ CODE LCD_RdC \ -- char Read Char
11898 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11903 \ -------------+------+------+------+------++---+---+---+---+---------+
11904 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
11905 \ -------------+------+------+------+------++---+---+---+---+---------+
11906 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
11907 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
11908 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
11909 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
11910 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
11911 \ -------------+------+------+------+------++---+---+---+---+---------+
11914 \ ******************************\
11915 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11916 \ ******************************\
11917 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
11918 \ ------------------------------\
11919 \ define LPM mode for ACCEPT \
11920 \ ------------------------------\
11921 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11922 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11923 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11924 BIT.B #SW2,&SW2_IN \ test switch S2
11925 0= IF \ case of switch S2 pressed
11926 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
11928 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
11931 BIT.B #SW1,&SW1_IN \ test switch S1 input
11932 0= IF \ case of Switch S1 pressed
11933 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
11935 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
11939 RETI \ CPU is ON, GIE is OFF
11944 \ ------------------------------\
11945 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11946 \ ******************************\
11947 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11948 \ ******************************\
11949 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11950 \ \ SMclock = 8|16|24 MHz
11951 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
11952 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
11953 \ \ SR(9)=new Toggle bit memory (ADD on)
11954 \ ------------------------------\
11955 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
11956 \ ------------------------------\
11957 \ define LPM mode for ACCEPT \
11958 \ ------------------------------\
11959 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11960 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11961 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11962 \ ------------------------------\
11963 \ RC5_FirstStartBitHalfCycle: \
11964 \ ------------------------------\
11965 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
11966 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
11967 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
11968 MOV #1778,X \ RC5_Period in us
11969 MOV #14,W \ count of loop
11971 \ ------------------------------\
11972 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
11973 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
11974 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
11975 \ RC5_Compute_3/4_Period: \ |
11976 RRUM #1,X \ X=1/2 cycle |
11980 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
11981 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
11983 \ ------------------------------\
11984 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
11985 \ ------------------------------\
11986 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11987 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
11988 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11989 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11990 SUB #1,W \ decrement count loop
11991 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
11992 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11993 0<> WHILE \ ----> out of loop ----+
11994 \ RC5_compute_7/4_Time_out: \ |
11995 ADD X,Y \ | out of bound = 7/4 period
11996 \ RC5_WaitHalfCycleP1.2_IFG: \ |
11998 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
11999 0>= IF \ | if cycle time out of bound
12000 BIC #$30,&TA0CTL \ | stop timer_A0
12001 RETI \ | then quit to do nothing
12003 \ ------------------------------\ |
12004 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
12006 MOV &TA0R,X \ | | get new RC5_period value
12007 REPEAT \ ----> loop back --+ |
12008 \ ------------------------------\ |
12009 \ RC5_SampleEndOf: \ <---------------------+
12010 \ ------------------------------\
12011 BIC #$30,&TA0CTL \ stop timer_A0
12012 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
12013 \ ******************************\
12014 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12015 \ ******************************\
12016 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
12017 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
12018 XOR IP,X \ (new XOR old) Toggle bit (13)
12019 BIT #BIT13,X \ X(13) = New_RC5_command
12020 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
12022 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
12023 \ ******************************\
12024 \ RC5_ComputeNewRC5word \
12025 \ ******************************\
12027 MOV &BASE,2(PSP) \ save variable BASE before use
12028 MOV TOS,0(PSP) \ save TOS before use
12029 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
12030 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
12031 \ ******************************\
12032 \ RC5_ComputeC6bit \
12033 \ ******************************\
12034 BIT #$4000,IP \ test /C6 bit in IP
12035 0= IF BIS #$40,TOS \ set C6 bit in S
12036 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
12037 \ ******************************\
12038 \ RC5_CommandByteIsDone \ RC5_code --
12039 \ ******************************\
12041 \ ------------------------------\
12042 \ Display IR_RC5 code \
12043 \ ------------------------------\
12044 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
12045 \ ------------------------------\
12046 LO2HI \ switch from assembler to FORTH
12047 ['] LCD_CLEAR IS CR \ redirects CR
12048 ['] LCD_WrC IS EMIT \ redirects EMIT
12049 $10 BASE ! \ change BASE to hexadecimal
12050 CR ." $" 2 U.R \ print IR_RC5 code
12051 ['] (CR) IS CR \ restore CR
12052 ['] (EMIT) IS EMIT \ restore EMIT
12053 HI2LO \ switch from FORTH to assembler
12054 \ ------------------------------\
12055 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
12056 \ ------------------------------\
12057 MOV @PSP+,&BASE \ restore variable BASE
12058 RETI \ CPU is ON, GIE is OFF
12063 \ ------------------------------\
12064 \ TB0CTL = %0000 0010 1001 0100\$3C0
12065 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12066 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12067 \ -- \ID input divider \ 10 = /4
12068 \ -- \MC Mode Control \ 01 = up to TB0CCR0
12069 \ - \TBCLR TimerB Clear
12072 \ --------------------------------\\
12073 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12074 \ -- \CM Capture Mode
12079 \ --- \OUTMOD \ 011 = set/reset
12085 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
12087 \ ------------------------------\
12088 \ set TimerB to make 50kHz PWM \
12089 \ ------------------------------\
12090 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12091 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
12092 \ ------------------------------\
12093 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12094 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
12095 \ ------------------------------\
12096 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12097 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
12098 \ ------------------------------\
12099 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12100 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
12101 \ ------------------------------\
12102 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12103 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
12104 \ ------------------------------\
12105 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
12106 \ ------------------------------\
12107 \ set TimerB to generate PWM for LCD_Vo
12108 \ ------------------------------\
12109 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
12110 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
12111 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12112 \ ------------------------------\
12113 BIS.B #LCDVo,&LCDVo_DIR \
12114 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
12115 \ ------------------------------\
12116 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12117 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12118 \ ------------------------------\
12119 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12120 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12121 \ ------------------------------\
12122 \ WDT interval init part \
12123 \ ------------------------------\
12124 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
12125 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
12126 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
12127 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
12128 \ ------------------------------\
12130 \ ------------------------------\
12131 BIS.B #RC5,&IR_IE \ enable RC5_Int
12132 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12133 \ ------------------------------\
12134 \ init interrupt vectors
12135 \ ------------------------------\
12136 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
12137 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12138 \ ------------------------------\
12139 \ define LPM mode for ACCEPT \
12140 \ ------------------------------\
12141 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12142 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12143 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12145 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
12147 \ ------------------------------\
12149 \ ------------------------------\
12150 $03E8 20_US \ 1- wait 20 ms
12151 $03 TOP_LCD \ 2- send DB5=DB4=1
12152 $CD 20_US \ 3- wait 4,1 ms
12153 $03 TOP_LCD \ 4- send again DB5=DB4=1
12154 $5 20_US \ 5- wait 0,1 ms
12155 $03 TOP_LCD \ 6- send again again DB5=DB4=1
12156 $2 20_US \ wait 40 us = LCD cycle
12157 $02 TOP_LCD \ 7- send DB5=1 DB4=0
12158 $2 20_US \ wait 40 us = LCD cycle
12159 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12160 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12161 LCD_Clear \ 10- "LCD_Clear"
12162 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12163 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12164 LCD_Clear \ 10- "LCD_Clear"
12165 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12166 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12168 ['] (CR) IS CR \ ' (CR) is CR
12169 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
12171 ." RC5toLCD is running. Type STOP to quit"
12172 \ NOECHO \ uncomment to run this app without terminal connexion
12173 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
12174 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
12178 : STOP \ stops multitasking, must to be used before downloading app
12179 ['] (WARM) IS WARM \ remove START app from FORTH init process
12180 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
12188 CODE MAX \ n1 n2 -- n3 signed maximum
12189 CMP @PSP,TOS \ n2-n1
12190 S< ?GOTO FW1 \ n2<n1
12196 CODE MIN \ n1 n2 -- n3 signed minimum
12197 CMP @PSP,TOS \ n2-n1
12198 S< ?GOTO BW1 \ n2<n1
12204 : U.R \ u n -- display u unsigned in n width (n >= 2)
12206 R> OVER - 0 MAX SPACES TYPE
12210 CODE 20_US \ n -- n * 20 us
12211 BEGIN \ 3 cycles loop + 6~
12212 \ MOV #5,W \ 3 MCLK = 1 MHz
12213 \ MOV #23,W \ 3 MCLK = 4 MHz
12214 MOV #51,W \ 3 MCLK = 8 MHz
12215 \ MOV #104,W \ 3 MCLK = 16 MHz
12216 \ MOV #158,W \ 3 MCLK = 24 MHz
12217 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
12227 CODE TOP_LCD \ LCD Sample
12228 \ \ if write : %xxxxWWWW --
12229 \ \ if read : -- %0000RRRR
12230 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12231 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12232 0= IF \ write LCD bits pattern
12233 AND.B #LCD_DB,TOS \
12234 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12235 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12238 THEN \ read LCD bits pattern
12241 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12242 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12243 AND.B #LCD_DB,TOS \
12248 CODE LCD_W \ byte -- write byte to LCD
12250 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
12251 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
12252 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12253 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12254 COLON \ high level word starts here
12255 TOP_LCD 2 20_US \ write high nibble first
12260 CODE LCD_WrC \ char -- Write Char
12261 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12266 CODE LCD_WrF \ func -- Write Fonction
12267 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12273 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
12278 $02 LCD_WrF 100 20_us
12282 \ : LCD_Entry_set $04 OR LCD_WrF ;
12284 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
12286 \ : LCD_Display_Shift $10 OR LCD_WrF ;
12288 \ : LCD_Fn_Set $20 OR LCD_WrF ;
12290 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
12292 \ : LCD_Goto $80 OR LCD_WrF ;
12294 \ CODE LCD_R \ -- byte read byte from LCD
12295 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12296 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12297 \ COLON \ starts a FORTH word
12298 \ TOP_LCD 2 20_us \ -- %0000HHHH
12299 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
12300 \ HI2LO \ switch from FORTH to assembler
12301 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
12302 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
12303 \ MOV @RSP+,IP \ restore IP saved by COLON
12308 \ CODE LCD_RdS \ -- status Read Status
12309 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12314 \ CODE LCD_RdC \ -- char Read Char
12315 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12320 \ -------------+------+------+------+------++---+---+---+---+---------+
12321 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
12322 \ -------------+------+------+------+------++---+---+---+---+---------+
12323 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
12324 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
12325 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
12326 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
12327 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
12328 \ -------------+------+------+------+------++---+---+---+---+---------+
12331 \ ******************************\
12332 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12333 \ ******************************\
12334 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
12335 \ ------------------------------\
12336 \ define LPM mode for ACCEPT \
12337 \ ------------------------------\
12338 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12339 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12340 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12341 BIT.B #SW2,&SW2_IN \ test switch S2
12342 0= IF \ case of switch S2 pressed
12343 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
12345 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
12348 BIT.B #SW1,&SW1_IN \ test switch S1 input
12349 0= IF \ case of Switch S1 pressed
12350 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
12352 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
12356 RETI \ CPU is ON, GIE is OFF
12361 \ ------------------------------\
12362 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12363 \ ******************************\
12364 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12365 \ ******************************\
12366 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12367 \ \ SMclock = 8|16|24 MHz
12368 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
12369 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
12370 \ \ SR(9)=new Toggle bit memory (ADD on)
12371 \ ------------------------------\
12372 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
12373 \ ------------------------------\
12374 \ define LPM mode for ACCEPT \
12375 \ ------------------------------\
12376 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12377 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12378 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12379 \ ------------------------------\
12380 \ RC5_FirstStartBitHalfCycle: \
12381 \ ------------------------------\
12382 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
12383 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
12384 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
12385 MOV #1778,X \ RC5_Period in us
12386 MOV #14,W \ count of loop
12388 \ ------------------------------\
12389 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
12390 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
12391 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
12392 \ RC5_Compute_3/4_Period: \ |
12393 RRUM #1,X \ X=1/2 cycle |
12397 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
12398 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
12400 \ ------------------------------\
12401 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
12402 \ ------------------------------\
12403 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12404 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
12405 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12406 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12407 SUB #1,W \ decrement count loop
12408 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
12409 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12410 0<> WHILE \ ----> out of loop ----+
12411 \ RC5_compute_7/4_Time_out: \ |
12412 ADD X,Y \ | out of bound = 7/4 period
12413 \ RC5_WaitHalfCycleP1.2_IFG: \ |
12415 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
12416 0>= IF \ | if cycle time out of bound
12417 BIC #$30,&TA0CTL \ | stop timer_A0
12418 RETI \ | then quit to do nothing
12420 \ ------------------------------\ |
12421 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
12423 MOV &TA0R,X \ | | get new RC5_period value
12424 REPEAT \ ----> loop back --+ |
12425 \ ------------------------------\ |
12426 \ RC5_SampleEndOf: \ <---------------------+
12427 \ ------------------------------\
12428 BIC #$30,&TA0CTL \ stop timer_A0
12429 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
12430 \ ******************************\
12431 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12432 \ ******************************\
12433 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
12434 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
12435 XOR IP,X \ (new XOR old) Toggle bit (13)
12436 BIT #BIT13,X \ X(13) = New_RC5_command
12437 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
12439 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
12440 \ ******************************\
12441 \ RC5_ComputeNewRC5word \
12442 \ ******************************\
12444 MOV &BASE,2(PSP) \ save variable BASE before use
12445 MOV TOS,0(PSP) \ save TOS before use
12446 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
12447 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
12448 \ ******************************\
12449 \ RC5_ComputeC6bit \
12450 \ ******************************\
12451 BIT #$4000,IP \ test /C6 bit in IP
12452 0= IF BIS #$40,TOS \ set C6 bit in S
12453 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
12454 \ ******************************\
12455 \ RC5_CommandByteIsDone \ RC5_code --
12456 \ ******************************\
12458 \ ------------------------------\
12459 \ Display IR_RC5 code \
12460 \ ------------------------------\
12461 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
12462 \ ------------------------------\
12463 LO2HI \ switch from assembler to FORTH
12464 ['] LCD_CLEAR IS CR \ redirects CR
12465 ['] LCD_WrC IS EMIT \ redirects EMIT
12466 $10 BASE ! \ change BASE to hexadecimal
12467 CR ." $" 2 U.R \ print IR_RC5 code
12468 ['] (CR) IS CR \ restore CR
12469 ['] (EMIT) IS EMIT \ restore EMIT
12470 HI2LO \ switch from FORTH to assembler
12471 \ ------------------------------\
12472 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
12473 \ ------------------------------\
12474 MOV @PSP+,&BASE \ restore variable BASE
12475 RETI \ CPU is ON, GIE is OFF
12480 \ ------------------------------\
12481 \ TB0CTL = %0000 0010 1001 0100\$3C0
12482 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12483 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12484 \ -- \ID input divider \ 10 = /4
12485 \ -- \MC Mode Control \ 01 = up to TB0CCR0
12486 \ - \TBCLR TimerB Clear
12489 \ --------------------------------\\
12490 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12491 \ -- \CM Capture Mode
12496 \ --- \OUTMOD \ 011 = set/reset
12502 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
12504 \ ------------------------------\
12505 \ set TimerB to make 50kHz PWM \
12506 \ ------------------------------\
12507 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12508 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
12509 \ ------------------------------\
12510 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12511 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
12512 \ ------------------------------\
12513 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12514 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
12515 \ ------------------------------\
12516 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12517 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
12518 \ ------------------------------\
12519 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12520 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
12521 \ ------------------------------\
12522 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
12523 \ ------------------------------\
12524 \ set TimerB to generate PWM for LCD_Vo
12525 \ ------------------------------\
12526 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
12527 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
12528 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12529 \ ------------------------------\
12530 BIS.B #LCDVo,&LCDVo_DIR \
12531 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
12532 \ ------------------------------\
12533 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12534 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12535 \ ------------------------------\
12536 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12537 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12538 \ ------------------------------\
12539 \ WDT interval init part \
12540 \ ------------------------------\
12541 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
12542 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
12543 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
12544 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
12545 \ ------------------------------\
12547 \ ------------------------------\
12548 BIS.B #RC5,&IR_IE \ enable RC5_Int
12549 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12550 \ ------------------------------\
12551 \ init interrupt vectors
12552 \ ------------------------------\
12553 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
12554 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12555 \ ------------------------------\
12556 \ define LPM mode for ACCEPT \
12557 \ ------------------------------\
12558 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12559 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12560 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12562 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
12564 \ ------------------------------\
12566 \ ------------------------------\
12567 $03E8 20_US \ 1- wait 20 ms
12568 $03 TOP_LCD \ 2- send DB5=DB4=1
12569 $CD 20_US \ 3- wait 4,1 ms
12570 $03 TOP_LCD \ 4- send again DB5=DB4=1
12571 $5 20_US \ 5- wait 0,1 ms
12572 $03 TOP_LCD \ 6- send again again DB5=DB4=1
12573 $2 20_US \ wait 40 us = LCD cycle
12574 $02 TOP_LCD \ 7- send DB5=1 DB4=0
12575 $2 20_US \ wait 40 us = LCD cycle
12576 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12577 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12578 LCD_Clear \ 10- "LCD_Clear"
12579 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12580 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12581 LCD_Clear \ 10- "LCD_Clear"
12582 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12583 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12585 ['] (CR) IS CR \ ' (CR) is CR
12586 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
12588 ." RC5toLCD is running. Type STOP to quit"
12589 \ NOECHO \ uncomment to run this app without terminal connexion
12590 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
12591 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
12595 : STOP \ stops multitasking, must to be used before downloading app
12596 ['] (WARM) IS WARM \ remove START app from FORTH init process
12597 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
12605 CODE MAX \ n1 n2 -- n3 signed maximum
12606 CMP @PSP,TOS \ n2-n1
12607 S< ?GOTO FW1 \ n2<n1
12613 CODE MIN \ n1 n2 -- n3 signed minimum
12614 CMP @PSP,TOS \ n2-n1
12615 S< ?GOTO BW1 \ n2<n1
12621 : U.R \ u n -- display u unsigned in n width (n >= 2)
12623 R> OVER - 0 MAX SPACES TYPE
12627 CODE 20_US \ n -- n * 20 us
12628 BEGIN \ 3 cycles loop + 6~
12629 \ MOV #5,W \ 3 MCLK = 1 MHz
12630 \ MOV #23,W \ 3 MCLK = 4 MHz
12631 MOV #51,W \ 3 MCLK = 8 MHz
12632 \ MOV #104,W \ 3 MCLK = 16 MHz
12633 \ MOV #158,W \ 3 MCLK = 24 MHz
12634 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
12644 CODE TOP_LCD \ LCD Sample
12645 \ \ if write : %xxxxWWWW --
12646 \ \ if read : -- %0000RRRR
12647 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12648 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12649 0= IF \ write LCD bits pattern
12650 AND.B #LCD_DB,TOS \
12651 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12652 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12655 THEN \ read LCD bits pattern
12658 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12659 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12660 AND.B #LCD_DB,TOS \
12665 CODE LCD_W \ byte -- write byte to LCD
12667 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
12668 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
12669 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12670 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12671 COLON \ high level word starts here
12672 TOP_LCD 2 20_US \ write high nibble first
12677 CODE LCD_WrC \ char -- Write Char
12678 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12683 CODE LCD_WrF \ func -- Write Fonction
12684 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12690 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
12695 $02 LCD_WrF 100 20_us
12699 \ : LCD_Entry_set $04 OR LCD_WrF ;
12701 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
12703 \ : LCD_Display_Shift $10 OR LCD_WrF ;
12705 \ : LCD_Fn_Set $20 OR LCD_WrF ;
12707 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
12709 \ : LCD_Goto $80 OR LCD_WrF ;
12711 \ CODE LCD_R \ -- byte read byte from LCD
12712 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12713 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12714 \ COLON \ starts a FORTH word
12715 \ TOP_LCD 2 20_us \ -- %0000HHHH
12716 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
12717 \ HI2LO \ switch from FORTH to assembler
12718 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
12719 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
12720 \ MOV @RSP+,IP \ restore IP saved by COLON
12725 \ CODE LCD_RdS \ -- status Read Status
12726 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12731 \ CODE LCD_RdC \ -- char Read Char
12732 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12737 \ -------------+------+------+------+------++---+---+---+---+---------+
12738 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
12739 \ -------------+------+------+------+------++---+---+---+---+---------+
12740 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
12741 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
12742 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
12743 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
12744 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
12745 \ -------------+------+------+------+------++---+---+---+---+---------+
12748 \ ******************************\
12749 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12750 \ ******************************\
12751 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
12752 \ ------------------------------\
12753 \ define LPM mode for ACCEPT \
12754 \ ------------------------------\
12755 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12756 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12757 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12758 BIT.B #SW2,&SW2_IN \ test switch S2
12759 0= IF \ case of switch S2 pressed
12760 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
12762 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
12765 BIT.B #SW1,&SW1_IN \ test switch S1 input
12766 0= IF \ case of Switch S1 pressed
12767 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
12769 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
12773 RETI \ CPU is ON, GIE is OFF
12778 \ ------------------------------\
12779 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12780 \ ******************************\
12781 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12782 \ ******************************\
12783 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12784 \ \ SMclock = 8|16|24 MHz
12785 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
12786 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
12787 \ \ SR(9)=new Toggle bit memory (ADD on)
12788 \ ------------------------------\
12789 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
12790 \ ------------------------------\
12791 \ define LPM mode for ACCEPT \
12792 \ ------------------------------\
12793 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12794 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12795 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12796 \ ------------------------------\
12797 \ RC5_FirstStartBitHalfCycle: \
12798 \ ------------------------------\
12799 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
12800 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
12801 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
12802 MOV #1778,X \ RC5_Period in us
12803 MOV #14,W \ count of loop
12805 \ ------------------------------\
12806 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
12807 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
12808 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
12809 \ RC5_Compute_3/4_Period: \ |
12810 RRUM #1,X \ X=1/2 cycle |
12814 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
12815 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
12817 \ ------------------------------\
12818 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
12819 \ ------------------------------\
12820 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12821 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
12822 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12823 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12824 SUB #1,W \ decrement count loop
12825 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
12826 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12827 0<> WHILE \ ----> out of loop ----+
12828 \ RC5_compute_7/4_Time_out: \ |
12829 ADD X,Y \ | out of bound = 7/4 period
12830 \ RC5_WaitHalfCycleP1.2_IFG: \ |
12832 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
12833 0>= IF \ | if cycle time out of bound
12834 BIC #$30,&TA0CTL \ | stop timer_A0
12835 RETI \ | then quit to do nothing
12837 \ ------------------------------\ |
12838 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
12840 MOV &TA0R,X \ | | get new RC5_period value
12841 REPEAT \ ----> loop back --+ |
12842 \ ------------------------------\ |
12843 \ RC5_SampleEndOf: \ <---------------------+
12844 \ ------------------------------\
12845 BIC #$30,&TA0CTL \ stop timer_A0
12846 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
12847 \ ******************************\
12848 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12849 \ ******************************\
12850 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
12851 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
12852 XOR IP,X \ (new XOR old) Toggle bit (13)
12853 BIT #BIT13,X \ X(13) = New_RC5_command
12854 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
12856 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
12857 \ ******************************\
12858 \ RC5_ComputeNewRC5word \
12859 \ ******************************\
12861 MOV &BASE,2(PSP) \ save variable BASE before use
12862 MOV TOS,0(PSP) \ save TOS before use
12863 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
12864 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
12865 \ ******************************\
12866 \ RC5_ComputeC6bit \
12867 \ ******************************\
12868 BIT #$4000,IP \ test /C6 bit in IP
12869 0= IF BIS #$40,TOS \ set C6 bit in S
12870 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
12871 \ ******************************\
12872 \ RC5_CommandByteIsDone \ RC5_code --
12873 \ ******************************\
12875 \ ------------------------------\
12876 \ Display IR_RC5 code \
12877 \ ------------------------------\
12878 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
12879 \ ------------------------------\
12880 LO2HI \ switch from assembler to FORTH
12881 ['] LCD_CLEAR IS CR \ redirects CR
12882 ['] LCD_WrC IS EMIT \ redirects EMIT
12883 $10 BASE ! \ change BASE to hexadecimal
12884 CR ." $" 2 U.R \ print IR_RC5 code
12885 ['] (CR) IS CR \ restore CR
12886 ['] (EMIT) IS EMIT \ restore EMIT
12887 HI2LO \ switch from FORTH to assembler
12888 \ ------------------------------\
12889 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
12890 \ ------------------------------\
12891 MOV @PSP+,&BASE \ restore variable BASE
12892 RETI \ CPU is ON, GIE is OFF
12897 \ ------------------------------\
12898 \ TB0CTL = %0000 0010 1001 0100\$3C0
12899 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12900 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12901 \ -- \ID input divider \ 10 = /4
12902 \ -- \MC Mode Control \ 01 = up to TB0CCR0
12903 \ - \TBCLR TimerB Clear
12906 \ --------------------------------\\
12907 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12908 \ -- \CM Capture Mode
12913 \ --- \OUTMOD \ 011 = set/reset
12919 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
12921 \ ------------------------------\
12922 \ set TimerB to make 50kHz PWM \
12923 \ ------------------------------\
12924 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12925 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
12926 \ ------------------------------\
12927 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12928 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
12929 \ ------------------------------\
12930 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12931 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
12932 \ ------------------------------\
12933 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12934 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
12935 \ ------------------------------\
12936 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12937 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
12938 \ ------------------------------\
12939 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
12940 \ ------------------------------\
12941 \ set TimerB to generate PWM for LCD_Vo
12942 \ ------------------------------\
12943 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
12944 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
12945 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12946 \ ------------------------------\
12947 BIS.B #LCDVo,&LCDVo_DIR \
12948 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
12949 \ ------------------------------\
12950 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12951 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12952 \ ------------------------------\
12953 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12954 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12955 \ ------------------------------\
12956 \ WDT interval init part \
12957 \ ------------------------------\
12958 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
12959 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
12960 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
12961 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
12962 \ ------------------------------\
12964 \ ------------------------------\
12965 BIS.B #RC5,&IR_IE \ enable RC5_Int
12966 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12967 \ ------------------------------\
12968 \ init interrupt vectors
12969 \ ------------------------------\
12970 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
12971 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12972 \ ------------------------------\
12973 \ define LPM mode for ACCEPT \
12974 \ ------------------------------\
12975 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12976 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12977 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12979 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
12981 \ ------------------------------\
12983 \ ------------------------------\
12984 $03E8 20_US \ 1- wait 20 ms
12985 $03 TOP_LCD \ 2- send DB5=DB4=1
12986 $CD 20_US \ 3- wait 4,1 ms
12987 $03 TOP_LCD \ 4- send again DB5=DB4=1
12988 $5 20_US \ 5- wait 0,1 ms
12989 $03 TOP_LCD \ 6- send again again DB5=DB4=1
12990 $2 20_US \ wait 40 us = LCD cycle
12991 $02 TOP_LCD \ 7- send DB5=1 DB4=0
12992 $2 20_US \ wait 40 us = LCD cycle
12993 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12994 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12995 LCD_Clear \ 10- "LCD_Clear"
12996 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12997 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12998 LCD_Clear \ 10- "LCD_Clear"
12999 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13000 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13002 ['] (CR) IS CR \ ' (CR) is CR
13003 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
13005 ." RC5toLCD is running. Type STOP to quit"
13006 \ NOECHO \ uncomment to run this app without terminal connexion
13007 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
13008 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
13012 : STOP \ stops multitasking, must to be used before downloading app
13013 ['] (WARM) IS WARM \ remove START app from FORTH init process
13014 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
13022 CODE MAX \ n1 n2 -- n3 signed maximum
13023 CMP @PSP,TOS \ n2-n1
13024 S< ?GOTO FW1 \ n2<n1
13030 CODE MIN \ n1 n2 -- n3 signed minimum
13031 CMP @PSP,TOS \ n2-n1
13032 S< ?GOTO BW1 \ n2<n1
13038 : U.R \ u n -- display u unsigned in n width (n >= 2)
13040 R> OVER - 0 MAX SPACES TYPE
13044 CODE 20_US \ n -- n * 20 us
13045 BEGIN \ 3 cycles loop + 6~
13046 \ MOV #5,W \ 3 MCLK = 1 MHz
13047 \ MOV #23,W \ 3 MCLK = 4 MHz
13048 MOV #51,W \ 3 MCLK = 8 MHz
13049 \ MOV #104,W \ 3 MCLK = 16 MHz
13050 \ MOV #158,W \ 3 MCLK = 24 MHz
13051 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
13061 CODE TOP_LCD \ LCD Sample
13062 \ \ if write : %xxxxWWWW --
13063 \ \ if read : -- %0000RRRR
13064 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13065 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13066 0= IF \ write LCD bits pattern
13067 AND.B #LCD_DB,TOS \
13068 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13069 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13072 THEN \ read LCD bits pattern
13075 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13076 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13077 AND.B #LCD_DB,TOS \
13082 CODE LCD_W \ byte -- write byte to LCD
13084 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13085 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13086 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13087 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13088 COLON \ high level word starts here
13089 TOP_LCD 2 20_US \ write high nibble first
13094 CODE LCD_WrC \ char -- Write Char
13095 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13100 CODE LCD_WrF \ func -- Write Fonction
13101 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13107 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
13112 $02 LCD_WrF 100 20_us
13116 \ : LCD_Entry_set $04 OR LCD_WrF ;
13118 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
13120 \ : LCD_Display_Shift $10 OR LCD_WrF ;
13122 \ : LCD_Fn_Set $20 OR LCD_WrF ;
13124 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
13126 \ : LCD_Goto $80 OR LCD_WrF ;
13128 \ CODE LCD_R \ -- byte read byte from LCD
13129 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13130 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13131 \ COLON \ starts a FORTH word
13132 \ TOP_LCD 2 20_us \ -- %0000HHHH
13133 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
13134 \ HI2LO \ switch from FORTH to assembler
13135 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
13136 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
13137 \ MOV @RSP+,IP \ restore IP saved by COLON
13142 \ CODE LCD_RdS \ -- status Read Status
13143 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13148 \ CODE LCD_RdC \ -- char Read Char
13149 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13154 \ -------------+------+------+------+------++---+---+---+---+---------+
13155 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
13156 \ -------------+------+------+------+------++---+---+---+---+---------+
13157 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
13158 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
13159 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
13160 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
13161 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
13162 \ -------------+------+------+------+------++---+---+---+---+---------+
13165 \ ******************************\
13166 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13167 \ ******************************\
13168 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
13169 \ ------------------------------\
13170 \ define LPM mode for ACCEPT \
13171 \ ------------------------------\
13172 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13173 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13174 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13175 BIT.B #SW2,&SW2_IN \ test switch S2
13176 0= IF \ case of switch S2 pressed
13177 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
13179 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
13182 BIT.B #SW1,&SW1_IN \ test switch S1 input
13183 0= IF \ case of Switch S1 pressed
13184 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
13186 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
13190 RETI \ CPU is ON, GIE is OFF
13195 \ ------------------------------\
13196 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13197 \ ******************************\
13198 ASM RC5_INT \ wake up on Px.RC5 change interrupt
13199 \ ******************************\
13200 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13201 \ \ SMclock = 8|16|24 MHz
13202 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
13203 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
13204 \ \ SR(9)=new Toggle bit memory (ADD on)
13205 \ ------------------------------\
13206 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
13207 \ ------------------------------\
13208 \ define LPM mode for ACCEPT \
13209 \ ------------------------------\
13210 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13211 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13212 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13213 \ ------------------------------\
13214 \ RC5_FirstStartBitHalfCycle: \
13215 \ ------------------------------\
13216 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
13217 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
13218 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
13219 MOV #1778,X \ RC5_Period in us
13220 MOV #14,W \ count of loop
13222 \ ------------------------------\
13223 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
13224 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
13225 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
13226 \ RC5_Compute_3/4_Period: \ |
13227 RRUM #1,X \ X=1/2 cycle |
13231 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
13232 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
13234 \ ------------------------------\
13235 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
13236 \ ------------------------------\
13237 BIT.B #RC5,&IR_IN \ C_flag = IR bit
13238 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
13239 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
13240 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
13241 SUB #1,W \ decrement count loop
13242 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
13243 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
13244 0<> WHILE \ ----> out of loop ----+
13245 \ RC5_compute_7/4_Time_out: \ |
13246 ADD X,Y \ | out of bound = 7/4 period
13247 \ RC5_WaitHalfCycleP1.2_IFG: \ |
13249 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
13250 0>= IF \ | if cycle time out of bound
13251 BIC #$30,&TA0CTL \ | stop timer_A0
13252 RETI \ | then quit to do nothing
13254 \ ------------------------------\ |
13255 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
13257 MOV &TA0R,X \ | | get new RC5_period value
13258 REPEAT \ ----> loop back --+ |
13259 \ ------------------------------\ |
13260 \ RC5_SampleEndOf: \ <---------------------+
13261 \ ------------------------------\
13262 BIC #$30,&TA0CTL \ stop timer_A0
13263 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
13264 \ ******************************\
13265 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
13266 \ ******************************\
13267 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
13268 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
13269 XOR IP,X \ (new XOR old) Toggle bit (13)
13270 BIT #BIT13,X \ X(13) = New_RC5_command
13271 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
13273 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
13274 \ ******************************\
13275 \ RC5_ComputeNewRC5word \
13276 \ ******************************\
13278 MOV &BASE,2(PSP) \ save variable BASE before use
13279 MOV TOS,0(PSP) \ save TOS before use
13280 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
13281 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
13282 \ ******************************\
13283 \ RC5_ComputeC6bit \
13284 \ ******************************\
13285 BIT #$4000,IP \ test /C6 bit in IP
13286 0= IF BIS #$40,TOS \ set C6 bit in S
13287 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
13288 \ ******************************\
13289 \ RC5_CommandByteIsDone \ RC5_code --
13290 \ ******************************\
13292 \ ------------------------------\
13293 \ Display IR_RC5 code \
13294 \ ------------------------------\
13295 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
13296 \ ------------------------------\
13297 LO2HI \ switch from assembler to FORTH
13298 ['] LCD_CLEAR IS CR \ redirects CR
13299 ['] LCD_WrC IS EMIT \ redirects EMIT
13300 $10 BASE ! \ change BASE to hexadecimal
13301 CR ." $" 2 U.R \ print IR_RC5 code
13302 ['] (CR) IS CR \ restore CR
13303 ['] (EMIT) IS EMIT \ restore EMIT
13304 HI2LO \ switch from FORTH to assembler
13305 \ ------------------------------\
13306 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
13307 \ ------------------------------\
13308 MOV @PSP+,&BASE \ restore variable BASE
13309 RETI \ CPU is ON, GIE is OFF
13314 \ ------------------------------\
13315 \ TB0CTL = %0000 0010 1001 0100\$3C0
13316 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13317 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13318 \ -- \ID input divider \ 10 = /4
13319 \ -- \MC Mode Control \ 01 = up to TB0CCR0
13320 \ - \TBCLR TimerB Clear
13323 \ --------------------------------\\
13324 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13325 \ -- \CM Capture Mode
13330 \ --- \OUTMOD \ 011 = set/reset
13336 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
13338 \ ------------------------------\
13339 \ set TimerB to make 50kHz PWM \
13340 \ ------------------------------\
13341 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
13342 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
13343 \ ------------------------------\
13344 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
13345 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
13346 \ ------------------------------\
13347 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13348 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
13349 \ ------------------------------\
13350 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13351 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
13352 \ ------------------------------\
13353 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13354 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
13355 \ ------------------------------\
13356 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
13357 \ ------------------------------\
13358 \ set TimerB to generate PWM for LCD_Vo
13359 \ ------------------------------\
13360 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
13361 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
13362 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13363 \ ------------------------------\
13364 BIS.B #LCDVo,&LCDVo_DIR \
13365 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
13366 \ ------------------------------\
13367 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13368 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13369 \ ------------------------------\
13370 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13371 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13372 \ ------------------------------\
13373 \ WDT interval init part \
13374 \ ------------------------------\
13375 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
13376 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
13377 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
13378 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
13379 \ ------------------------------\
13381 \ ------------------------------\
13382 BIS.B #RC5,&IR_IE \ enable RC5_Int
13383 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13384 \ ------------------------------\
13385 \ init interrupt vectors
13386 \ ------------------------------\
13387 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
13388 MOV #RC5_INT,&IR_Vec \ init interrupt vector
13389 \ ------------------------------\
13390 \ define LPM mode for ACCEPT \
13391 \ ------------------------------\
13392 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13393 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13394 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13396 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
13398 \ ------------------------------\
13400 \ ------------------------------\
13401 $03E8 20_US \ 1- wait 20 ms
13402 $03 TOP_LCD \ 2- send DB5=DB4=1
13403 $CD 20_US \ 3- wait 4,1 ms
13404 $03 TOP_LCD \ 4- send again DB5=DB4=1
13405 $5 20_US \ 5- wait 0,1 ms
13406 $03 TOP_LCD \ 6- send again again DB5=DB4=1
13407 $2 20_US \ wait 40 us = LCD cycle
13408 $02 TOP_LCD \ 7- send DB5=1 DB4=0
13409 $2 20_US \ wait 40 us = LCD cycle
13410 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13411 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13412 LCD_Clear \ 10- "LCD_Clear"
13413 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13414 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13415 LCD_Clear \ 10- "LCD_Clear"
13416 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13417 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13419 ['] (CR) IS CR \ ' (CR) is CR
13420 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
13422 ." RC5toLCD is running. Type STOP to quit"
13423 \ NOECHO \ uncomment to run this app without terminal connexion
13424 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
13425 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
13429 : STOP \ stops multitasking, must to be used before downloading app
13430 ['] (WARM) IS WARM \ remove START app from FORTH init process
13431 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
13439 CODE MAX \ n1 n2 -- n3 signed maximum
13440 CMP @PSP,TOS \ n2-n1
13441 S< ?GOTO FW1 \ n2<n1
13447 CODE MIN \ n1 n2 -- n3 signed minimum
13448 CMP @PSP,TOS \ n2-n1
13449 S< ?GOTO BW1 \ n2<n1
13455 : U.R \ u n -- display u unsigned in n width (n >= 2)
13457 R> OVER - 0 MAX SPACES TYPE
13461 CODE 20_US \ n -- n * 20 us
13462 BEGIN \ 3 cycles loop + 6~
13463 \ MOV #5,W \ 3 MCLK = 1 MHz
13464 \ MOV #23,W \ 3 MCLK = 4 MHz
13465 MOV #51,W \ 3 MCLK = 8 MHz
13466 \ MOV #104,W \ 3 MCLK = 16 MHz
13467 \ MOV #158,W \ 3 MCLK = 24 MHz
13468 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
13478 CODE TOP_LCD \ LCD Sample
13479 \ \ if write : %xxxxWWWW --
13480 \ \ if read : -- %0000RRRR
13481 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13482 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13483 0= IF \ write LCD bits pattern
13484 AND.B #LCD_DB,TOS \
13485 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13486 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13489 THEN \ read LCD bits pattern
13492 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13493 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13494 AND.B #LCD_DB,TOS \
13499 CODE LCD_W \ byte -- write byte to LCD
13501 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13502 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13503 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13504 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13505 COLON \ high level word starts here
13506 TOP_LCD 2 20_US \ write high nibble first
13511 CODE LCD_WrC \ char -- Write Char
13512 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13517 CODE LCD_WrF \ func -- Write Fonction
13518 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13524 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
13529 $02 LCD_WrF 100 20_us
13533 \ : LCD_Entry_set $04 OR LCD_WrF ;
13535 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
13537 \ : LCD_Display_Shift $10 OR LCD_WrF ;
13539 \ : LCD_Fn_Set $20 OR LCD_WrF ;
13541 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
13543 \ : LCD_Goto $80 OR LCD_WrF ;
13545 \ CODE LCD_R \ -- byte read byte from LCD
13546 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13547 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13548 \ COLON \ starts a FORTH word
13549 \ TOP_LCD 2 20_us \ -- %0000HHHH
13550 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
13551 \ HI2LO \ switch from FORTH to assembler
13552 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
13553 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
13554 \ MOV @RSP+,IP \ restore IP saved by COLON
13559 \ CODE LCD_RdS \ -- status Read Status
13560 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13565 \ CODE LCD_RdC \ -- char Read Char
13566 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13571 \ -------------+------+------+------+------++---+---+---+---+---------+
13572 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
13573 \ -------------+------+------+------+------++---+---+---+---+---------+
13574 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
13575 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
13576 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
13577 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
13578 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
13579 \ -------------+------+------+------+------++---+---+---+---+---------+
13582 \ ******************************\
13583 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13584 \ ******************************\
13585 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
13586 \ ------------------------------\
13587 \ define LPM mode for ACCEPT \
13588 \ ------------------------------\
13589 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13590 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13591 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13592 BIT.B #SW2,&SW2_IN \ test switch S2
13593 0= IF \ case of switch S2 pressed
13594 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
13596 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
13599 BIT.B #SW1,&SW1_IN \ test switch S1 input
13600 0= IF \ case of Switch S1 pressed
13601 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
13603 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
13607 RETI \ CPU is ON, GIE is OFF
13612 \ ------------------------------\
13613 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13614 \ ******************************\
13615 ASM RC5_INT \ wake up on Px.RC5 change interrupt
13616 \ ******************************\
13617 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13618 \ \ SMclock = 8|16|24 MHz
13619 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
13620 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
13621 \ \ SR(9)=new Toggle bit memory (ADD on)
13622 \ ------------------------------\
13623 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
13624 \ ------------------------------\
13625 \ define LPM mode for ACCEPT \
13626 \ ------------------------------\
13627 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13628 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13629 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13630 \ ------------------------------\
13631 \ RC5_FirstStartBitHalfCycle: \
13632 \ ------------------------------\
13633 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
13634 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
13635 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
13636 MOV #1778,X \ RC5_Period in us
13637 MOV #14,W \ count of loop
13639 \ ------------------------------\
13640 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
13641 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
13642 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
13643 \ RC5_Compute_3/4_Period: \ |
13644 RRUM #1,X \ X=1/2 cycle |
13648 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
13649 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
13651 \ ------------------------------\
13652 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
13653 \ ------------------------------\
13654 BIT.B #RC5,&IR_IN \ C_flag = IR bit
13655 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
13656 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
13657 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
13658 SUB #1,W \ decrement count loop
13659 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
13660 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
13661 0<> WHILE \ ----> out of loop ----+
13662 \ RC5_compute_7/4_Time_out: \ |
13663 ADD X,Y \ | out of bound = 7/4 period
13664 \ RC5_WaitHalfCycleP1.2_IFG: \ |
13666 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
13667 0>= IF \ | if cycle time out of bound
13668 BIC #$30,&TA0CTL \ | stop timer_A0
13669 RETI \ | then quit to do nothing
13671 \ ------------------------------\ |
13672 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
13674 MOV &TA0R,X \ | | get new RC5_period value
13675 REPEAT \ ----> loop back --+ |
13676 \ ------------------------------\ |
13677 \ RC5_SampleEndOf: \ <---------------------+
13678 \ ------------------------------\
13679 BIC #$30,&TA0CTL \ stop timer_A0
13680 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
13681 \ ******************************\
13682 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
13683 \ ******************************\
13684 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
13685 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
13686 XOR IP,X \ (new XOR old) Toggle bit (13)
13687 BIT #BIT13,X \ X(13) = New_RC5_command
13688 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
13690 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
13691 \ ******************************\
13692 \ RC5_ComputeNewRC5word \
13693 \ ******************************\
13695 MOV &BASE,2(PSP) \ save variable BASE before use
13696 MOV TOS,0(PSP) \ save TOS before use
13697 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
13698 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
13699 \ ******************************\
13700 \ RC5_ComputeC6bit \
13701 \ ******************************\
13702 BIT #$4000,IP \ test /C6 bit in IP
13703 0= IF BIS #$40,TOS \ set C6 bit in S
13704 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
13705 \ ******************************\
13706 \ RC5_CommandByteIsDone \ RC5_code --
13707 \ ******************************\
13709 \ ------------------------------\
13710 \ Display IR_RC5 code \
13711 \ ------------------------------\
13712 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
13713 \ ------------------------------\
13714 LO2HI \ switch from assembler to FORTH
13715 ['] LCD_CLEAR IS CR \ redirects CR
13716 ['] LCD_WrC IS EMIT \ redirects EMIT
13717 $10 BASE ! \ change BASE to hexadecimal
13718 CR ." $" 2 U.R \ print IR_RC5 code
13719 ['] (CR) IS CR \ restore CR
13720 ['] (EMIT) IS EMIT \ restore EMIT
13721 HI2LO \ switch from FORTH to assembler
13722 \ ------------------------------\
13723 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
13724 \ ------------------------------\
13725 MOV @PSP+,&BASE \ restore variable BASE
13726 RETI \ CPU is ON, GIE is OFF
13731 \ ------------------------------\
13732 \ TB0CTL = %0000 0010 1001 0100\$3C0
13733 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13734 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13735 \ -- \ID input divider \ 10 = /4
13736 \ -- \MC Mode Control \ 01 = up to TB0CCR0
13737 \ - \TBCLR TimerB Clear
13740 \ --------------------------------\\
13741 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13742 \ -- \CM Capture Mode
13747 \ --- \OUTMOD \ 011 = set/reset
13753 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
13755 \ ------------------------------\
13756 \ set TimerB to make 50kHz PWM \
13757 \ ------------------------------\
13758 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
13759 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
13760 \ ------------------------------\
13761 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
13762 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
13763 \ ------------------------------\
13764 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13765 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
13766 \ ------------------------------\
13767 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13768 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
13769 \ ------------------------------\
13770 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13771 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
13772 \ ------------------------------\
13773 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
13774 \ ------------------------------\
13775 \ set TimerB to generate PWM for LCD_Vo
13776 \ ------------------------------\
13777 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
13778 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
13779 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13780 \ ------------------------------\
13781 BIS.B #LCDVo,&LCDVo_DIR \
13782 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
13783 \ ------------------------------\
13784 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13785 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13786 \ ------------------------------\
13787 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13788 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13789 \ ------------------------------\
13790 \ WDT interval init part \
13791 \ ------------------------------\
13792 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
13793 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
13794 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
13795 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
13796 \ ------------------------------\
13798 \ ------------------------------\
13799 BIS.B #RC5,&IR_IE \ enable RC5_Int
13800 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13801 \ ------------------------------\
13802 \ init interrupt vectors
13803 \ ------------------------------\
13804 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
13805 MOV #RC5_INT,&IR_Vec \ init interrupt vector
13806 \ ------------------------------\
13807 \ define LPM mode for ACCEPT \
13808 \ ------------------------------\
13809 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13810 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13811 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13813 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
13815 \ ------------------------------\
13817 \ ------------------------------\
13818 $03E8 20_US \ 1- wait 20 ms
13819 $03 TOP_LCD \ 2- send DB5=DB4=1
13820 $CD 20_US \ 3- wait 4,1 ms
13821 $03 TOP_LCD \ 4- send again DB5=DB4=1
13822 $5 20_US \ 5- wait 0,1 ms
13823 $03 TOP_LCD \ 6- send again again DB5=DB4=1
13824 $2 20_US \ wait 40 us = LCD cycle
13825 $02 TOP_LCD \ 7- send DB5=1 DB4=0
13826 $2 20_US \ wait 40 us = LCD cycle
13827 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13828 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13829 LCD_Clear \ 10- "LCD_Clear"
13830 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13831 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13832 LCD_Clear \ 10- "LCD_Clear"
13833 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13834 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13836 ['] (CR) IS CR \ ' (CR) is CR
13837 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
13839 ." RC5toLCD is running. Type STOP to quit"
13840 \ NOECHO \ uncomment to run this app without terminal connexion
13841 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
13842 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
13846 : STOP \ stops multitasking, must to be used before downloading app
13847 ['] (WARM) IS WARM \ remove START app from FORTH init process
13848 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
13856 CODE MAX \ n1 n2 -- n3 signed maximum
13857 CMP @PSP,TOS \ n2-n1
13858 S< ?GOTO FW1 \ n2<n1
13864 CODE MIN \ n1 n2 -- n3 signed minimum
13865 CMP @PSP,TOS \ n2-n1
13866 S< ?GOTO BW1 \ n2<n1
13872 : U.R \ u n -- display u unsigned in n width (n >= 2)
13874 R> OVER - 0 MAX SPACES TYPE
13878 CODE 20_US \ n -- n * 20 us
13879 BEGIN \ 3 cycles loop + 6~
13880 \ MOV #5,W \ 3 MCLK = 1 MHz
13881 \ MOV #23,W \ 3 MCLK = 4 MHz
13882 MOV #51,W \ 3 MCLK = 8 MHz
13883 \ MOV #104,W \ 3 MCLK = 16 MHz
13884 \ MOV #158,W \ 3 MCLK = 24 MHz
13885 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
13895 CODE TOP_LCD \ LCD Sample
13896 \ \ if write : %xxxxWWWW --
13897 \ \ if read : -- %0000RRRR
13898 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13899 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13900 0= IF \ write LCD bits pattern
13901 AND.B #LCD_DB,TOS \
13902 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13903 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13906 THEN \ read LCD bits pattern
13909 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13910 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13911 AND.B #LCD_DB,TOS \
13916 CODE LCD_W \ byte -- write byte to LCD
13918 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13919 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13920 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13921 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13922 COLON \ high level word starts here
13923 TOP_LCD 2 20_US \ write high nibble first
13928 CODE LCD_WrC \ char -- Write Char
13929 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13934 CODE LCD_WrF \ func -- Write Fonction
13935 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13941 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
13946 $02 LCD_WrF 100 20_us
13950 \ : LCD_Entry_set $04 OR LCD_WrF ;
13952 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
13954 \ : LCD_Display_Shift $10 OR LCD_WrF ;
13956 \ : LCD_Fn_Set $20 OR LCD_WrF ;
13958 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
13960 \ : LCD_Goto $80 OR LCD_WrF ;
13962 \ CODE LCD_R \ -- byte read byte from LCD
13963 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13964 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13965 \ COLON \ starts a FORTH word
13966 \ TOP_LCD 2 20_us \ -- %0000HHHH
13967 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
13968 \ HI2LO \ switch from FORTH to assembler
13969 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
13970 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
13971 \ MOV @RSP+,IP \ restore IP saved by COLON
13976 \ CODE LCD_RdS \ -- status Read Status
13977 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13982 \ CODE LCD_RdC \ -- char Read Char
13983 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13988 \ -------------+------+------+------+------++---+---+---+---+---------+
13989 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
13990 \ -------------+------+------+------+------++---+---+---+---+---------+
13991 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
13992 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
13993 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
13994 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
13995 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
13996 \ -------------+------+------+------+------++---+---+---+---+---------+
13999 \ ******************************\
14000 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14001 \ ******************************\
14002 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
14003 \ ------------------------------\
14004 \ define LPM mode for ACCEPT \
14005 \ ------------------------------\
14006 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14007 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14008 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14009 BIT.B #SW2,&SW2_IN \ test switch S2
14010 0= IF \ case of switch S2 pressed
14011 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
14013 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
14016 BIT.B #SW1,&SW1_IN \ test switch S1 input
14017 0= IF \ case of Switch S1 pressed
14018 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
14020 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
14024 RETI \ CPU is ON, GIE is OFF
14029 \ ------------------------------\
14030 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14031 \ ******************************\
14032 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14033 \ ******************************\
14034 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14035 \ \ SMclock = 8|16|24 MHz
14036 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
14037 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
14038 \ \ SR(9)=new Toggle bit memory (ADD on)
14039 \ ------------------------------\
14040 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
14041 \ ------------------------------\
14042 \ define LPM mode for ACCEPT \
14043 \ ------------------------------\
14044 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14045 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14046 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14047 \ ------------------------------\
14048 \ RC5_FirstStartBitHalfCycle: \
14049 \ ------------------------------\
14050 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
14051 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
14052 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
14053 MOV #1778,X \ RC5_Period in us
14054 MOV #14,W \ count of loop
14056 \ ------------------------------\
14057 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
14058 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
14059 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
14060 \ RC5_Compute_3/4_Period: \ |
14061 RRUM #1,X \ X=1/2 cycle |
14065 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
14066 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
14068 \ ------------------------------\
14069 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
14070 \ ------------------------------\
14071 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14072 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
14073 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14074 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14075 SUB #1,W \ decrement count loop
14076 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
14077 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14078 0<> WHILE \ ----> out of loop ----+
14079 \ RC5_compute_7/4_Time_out: \ |
14080 ADD X,Y \ | out of bound = 7/4 period
14081 \ RC5_WaitHalfCycleP1.2_IFG: \ |
14083 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
14084 0>= IF \ | if cycle time out of bound
14085 BIC #$30,&TA0CTL \ | stop timer_A0
14086 RETI \ | then quit to do nothing
14088 \ ------------------------------\ |
14089 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
14091 MOV &TA0R,X \ | | get new RC5_period value
14092 REPEAT \ ----> loop back --+ |
14093 \ ------------------------------\ |
14094 \ RC5_SampleEndOf: \ <---------------------+
14095 \ ------------------------------\
14096 BIC #$30,&TA0CTL \ stop timer_A0
14097 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
14098 \ ******************************\
14099 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14100 \ ******************************\
14101 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
14102 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
14103 XOR IP,X \ (new XOR old) Toggle bit (13)
14104 BIT #BIT13,X \ X(13) = New_RC5_command
14105 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
14107 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
14108 \ ******************************\
14109 \ RC5_ComputeNewRC5word \
14110 \ ******************************\
14112 MOV &BASE,2(PSP) \ save variable BASE before use
14113 MOV TOS,0(PSP) \ save TOS before use
14114 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
14115 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
14116 \ ******************************\
14117 \ RC5_ComputeC6bit \
14118 \ ******************************\
14119 BIT #$4000,IP \ test /C6 bit in IP
14120 0= IF BIS #$40,TOS \ set C6 bit in S
14121 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
14122 \ ******************************\
14123 \ RC5_CommandByteIsDone \ RC5_code --
14124 \ ******************************\
14126 \ ------------------------------\
14127 \ Display IR_RC5 code \
14128 \ ------------------------------\
14129 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
14130 \ ------------------------------\
14131 LO2HI \ switch from assembler to FORTH
14132 ['] LCD_CLEAR IS CR \ redirects CR
14133 ['] LCD_WrC IS EMIT \ redirects EMIT
14134 $10 BASE ! \ change BASE to hexadecimal
14135 CR ." $" 2 U.R \ print IR_RC5 code
14136 ['] (CR) IS CR \ restore CR
14137 ['] (EMIT) IS EMIT \ restore EMIT
14138 HI2LO \ switch from FORTH to assembler
14139 \ ------------------------------\
14140 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
14141 \ ------------------------------\
14142 MOV @PSP+,&BASE \ restore variable BASE
14143 RETI \ CPU is ON, GIE is OFF
14148 \ ------------------------------\
14149 \ TB0CTL = %0000 0010 1001 0100\$3C0
14150 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14151 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14152 \ -- \ID input divider \ 10 = /4
14153 \ -- \MC Mode Control \ 01 = up to TB0CCR0
14154 \ - \TBCLR TimerB Clear
14157 \ --------------------------------\\
14158 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14159 \ -- \CM Capture Mode
14164 \ --- \OUTMOD \ 011 = set/reset
14170 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
14172 \ ------------------------------\
14173 \ set TimerB to make 50kHz PWM \
14174 \ ------------------------------\
14175 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
14176 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
14177 \ ------------------------------\
14178 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
14179 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
14180 \ ------------------------------\
14181 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14182 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
14183 \ ------------------------------\
14184 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14185 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
14186 \ ------------------------------\
14187 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14188 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
14189 \ ------------------------------\
14190 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
14191 \ ------------------------------\
14192 \ set TimerB to generate PWM for LCD_Vo
14193 \ ------------------------------\
14194 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
14195 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
14196 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14197 \ ------------------------------\
14198 BIS.B #LCDVo,&LCDVo_DIR \
14199 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
14200 \ ------------------------------\
14201 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14202 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14203 \ ------------------------------\
14204 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14205 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14206 \ ------------------------------\
14207 \ WDT interval init part \
14208 \ ------------------------------\
14209 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
14210 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
14211 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
14212 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
14213 \ ------------------------------\
14215 \ ------------------------------\
14216 BIS.B #RC5,&IR_IE \ enable RC5_Int
14217 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14218 \ ------------------------------\
14219 \ init interrupt vectors
14220 \ ------------------------------\
14221 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
14222 MOV #RC5_INT,&IR_Vec \ init interrupt vector
14223 \ ------------------------------\
14224 \ define LPM mode for ACCEPT \
14225 \ ------------------------------\
14226 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14227 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14228 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14230 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
14232 \ ------------------------------\
14234 \ ------------------------------\
14235 $03E8 20_US \ 1- wait 20 ms
14236 $03 TOP_LCD \ 2- send DB5=DB4=1
14237 $CD 20_US \ 3- wait 4,1 ms
14238 $03 TOP_LCD \ 4- send again DB5=DB4=1
14239 $5 20_US \ 5- wait 0,1 ms
14240 $03 TOP_LCD \ 6- send again again DB5=DB4=1
14241 $2 20_US \ wait 40 us = LCD cycle
14242 $02 TOP_LCD \ 7- send DB5=1 DB4=0
14243 $2 20_US \ wait 40 us = LCD cycle
14244 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14245 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14246 LCD_Clear \ 10- "LCD_Clear"
14247 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14248 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14249 LCD_Clear \ 10- "LCD_Clear"
14250 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14251 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14253 ['] (CR) IS CR \ ' (CR) is CR
14254 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
14256 ." RC5toLCD is running. Type STOP to quit"
14257 \ NOECHO \ uncomment to run this app without terminal connexion
14258 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
14259 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
14263 : STOP \ stops multitasking, must to be used before downloading app
14264 ['] (WARM) IS WARM \ remove START app from FORTH init process
14265 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
14273 CODE MAX \ n1 n2 -- n3 signed maximum
14274 CMP @PSP,TOS \ n2-n1
14275 S< ?GOTO FW1 \ n2<n1
14281 CODE MIN \ n1 n2 -- n3 signed minimum
14282 CMP @PSP,TOS \ n2-n1
14283 S< ?GOTO BW1 \ n2<n1
14289 : U.R \ u n -- display u unsigned in n width (n >= 2)
14291 R> OVER - 0 MAX SPACES TYPE
14295 CODE 20_US \ n -- n * 20 us
14296 BEGIN \ 3 cycles loop + 6~
14297 \ MOV #5,W \ 3 MCLK = 1 MHz
14298 \ MOV #23,W \ 3 MCLK = 4 MHz
14299 MOV #51,W \ 3 MCLK = 8 MHz
14300 \ MOV #104,W \ 3 MCLK = 16 MHz
14301 \ MOV #158,W \ 3 MCLK = 24 MHz
14302 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
14312 CODE TOP_LCD \ LCD Sample
14313 \ \ if write : %xxxxWWWW --
14314 \ \ if read : -- %0000RRRR
14315 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
14316 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
14317 0= IF \ write LCD bits pattern
14318 AND.B #LCD_DB,TOS \
14319 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
14320 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14323 THEN \ read LCD bits pattern
14326 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14327 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
14328 AND.B #LCD_DB,TOS \
14333 CODE LCD_W \ byte -- write byte to LCD
14335 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
14336 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
14337 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
14338 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
14339 COLON \ high level word starts here
14340 TOP_LCD 2 20_US \ write high nibble first
14345 CODE LCD_WrC \ char -- Write Char
14346 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14351 CODE LCD_WrF \ func -- Write Fonction
14352 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14358 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
14363 $02 LCD_WrF 100 20_us
14367 \ : LCD_Entry_set $04 OR LCD_WrF ;
14369 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
14371 \ : LCD_Display_Shift $10 OR LCD_WrF ;
14373 \ : LCD_Fn_Set $20 OR LCD_WrF ;
14375 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
14377 \ : LCD_Goto $80 OR LCD_WrF ;
14379 \ CODE LCD_R \ -- byte read byte from LCD
14380 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14381 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14382 \ COLON \ starts a FORTH word
14383 \ TOP_LCD 2 20_us \ -- %0000HHHH
14384 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
14385 \ HI2LO \ switch from FORTH to assembler
14386 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
14387 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
14388 \ MOV @RSP+,IP \ restore IP saved by COLON
14393 \ CODE LCD_RdS \ -- status Read Status
14394 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14399 \ CODE LCD_RdC \ -- char Read Char
14400 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14405 \ -------------+------+------+------+------++---+---+---+---+---------+
14406 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
14407 \ -------------+------+------+------+------++---+---+---+---+---------+
14408 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
14409 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
14410 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
14411 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
14412 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
14413 \ -------------+------+------+------+------++---+---+---+---+---------+
14416 \ ******************************\
14417 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14418 \ ******************************\
14419 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
14420 \ ------------------------------\
14421 \ define LPM mode for ACCEPT \
14422 \ ------------------------------\
14423 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14424 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14425 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14426 BIT.B #SW2,&SW2_IN \ test switch S2
14427 0= IF \ case of switch S2 pressed
14428 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
14430 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
14433 BIT.B #SW1,&SW1_IN \ test switch S1 input
14434 0= IF \ case of Switch S1 pressed
14435 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
14437 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
14441 RETI \ CPU is ON, GIE is OFF
14446 \ ------------------------------\
14447 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14448 \ ******************************\
14449 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14450 \ ******************************\
14451 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14452 \ \ SMclock = 8|16|24 MHz
14453 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
14454 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
14455 \ \ SR(9)=new Toggle bit memory (ADD on)
14456 \ ------------------------------\
14457 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
14458 \ ------------------------------\
14459 \ define LPM mode for ACCEPT \
14460 \ ------------------------------\
14461 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14462 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14463 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14464 \ ------------------------------\
14465 \ RC5_FirstStartBitHalfCycle: \
14466 \ ------------------------------\
14467 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
14468 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
14469 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
14470 MOV #1778,X \ RC5_Period in us
14471 MOV #14,W \ count of loop
14473 \ ------------------------------\
14474 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
14475 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
14476 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
14477 \ RC5_Compute_3/4_Period: \ |
14478 RRUM #1,X \ X=1/2 cycle |
14482 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
14483 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
14485 \ ------------------------------\
14486 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
14487 \ ------------------------------\
14488 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14489 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
14490 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14491 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14492 SUB #1,W \ decrement count loop
14493 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
14494 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14495 0<> WHILE \ ----> out of loop ----+
14496 \ RC5_compute_7/4_Time_out: \ |
14497 ADD X,Y \ | out of bound = 7/4 period
14498 \ RC5_WaitHalfCycleP1.2_IFG: \ |
14500 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
14501 0>= IF \ | if cycle time out of bound
14502 BIC #$30,&TA0CTL \ | stop timer_A0
14503 RETI \ | then quit to do nothing
14505 \ ------------------------------\ |
14506 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
14508 MOV &TA0R,X \ | | get new RC5_period value
14509 REPEAT \ ----> loop back --+ |
14510 \ ------------------------------\ |
14511 \ RC5_SampleEndOf: \ <---------------------+
14512 \ ------------------------------\
14513 BIC #$30,&TA0CTL \ stop timer_A0
14514 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
14515 \ ******************************\
14516 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14517 \ ******************************\
14518 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
14519 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
14520 XOR IP,X \ (new XOR old) Toggle bit (13)
14521 BIT #BIT13,X \ X(13) = New_RC5_command
14522 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
14524 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
14525 \ ******************************\
14526 \ RC5_ComputeNewRC5word \
14527 \ ******************************\
14529 MOV &BASE,2(PSP) \ save variable BASE before use
14530 MOV TOS,0(PSP) \ save TOS before use
14531 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
14532 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
14533 \ ******************************\
14534 \ RC5_ComputeC6bit \
14535 \ ******************************\
14536 BIT #$4000,IP \ test /C6 bit in IP
14537 0= IF BIS #$40,TOS \ set C6 bit in S
14538 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
14539 \ ******************************\
14540 \ RC5_CommandByteIsDone \ RC5_code --
14541 \ ******************************\
14543 \ ------------------------------\
14544 \ Display IR_RC5 code \
14545 \ ------------------------------\
14546 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
14547 \ ------------------------------\
14548 LO2HI \ switch from assembler to FORTH
14549 ['] LCD_CLEAR IS CR \ redirects CR
14550 ['] LCD_WrC IS EMIT \ redirects EMIT
14551 $10 BASE ! \ change BASE to hexadecimal
14552 CR ." $" 2 U.R \ print IR_RC5 code
14553 ['] (CR) IS CR \ restore CR
14554 ['] (EMIT) IS EMIT \ restore EMIT
14555 HI2LO \ switch from FORTH to assembler
14556 \ ------------------------------\
14557 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
14558 \ ------------------------------\
14559 MOV @PSP+,&BASE \ restore variable BASE
14560 RETI \ CPU is ON, GIE is OFF
14565 \ ------------------------------\
14566 \ TB0CTL = %0000 0010 1001 0100\$3C0
14567 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14568 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14569 \ -- \ID input divider \ 10 = /4
14570 \ -- \MC Mode Control \ 01 = up to TB0CCR0
14571 \ - \TBCLR TimerB Clear
14574 \ --------------------------------\\
14575 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14576 \ -- \CM Capture Mode
14581 \ --- \OUTMOD \ 011 = set/reset
14587 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
14589 \ ------------------------------\
14590 \ set TimerB to make 50kHz PWM \
14591 \ ------------------------------\
14592 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
14593 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
14594 \ ------------------------------\
14595 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
14596 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
14597 \ ------------------------------\
14598 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14599 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
14600 \ ------------------------------\
14601 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14602 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
14603 \ ------------------------------\
14604 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14605 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
14606 \ ------------------------------\
14607 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
14608 \ ------------------------------\
14609 \ set TimerB to generate PWM for LCD_Vo
14610 \ ------------------------------\
14611 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
14612 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
14613 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14614 \ ------------------------------\
14615 BIS.B #LCDVo,&LCDVo_DIR \
14616 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
14617 \ ------------------------------\
14618 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14619 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14620 \ ------------------------------\
14621 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14622 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14623 \ ------------------------------\
14624 \ WDT interval init part \
14625 \ ------------------------------\
14626 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
14627 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
14628 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
14629 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
14630 \ ------------------------------\
14632 \ ------------------------------\
14633 BIS.B #RC5,&IR_IE \ enable RC5_Int
14634 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14635 \ ------------------------------\
14636 \ init interrupt vectors
14637 \ ------------------------------\
14638 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
14639 MOV #RC5_INT,&IR_Vec \ init interrupt vector
14640 \ ------------------------------\
14641 \ define LPM mode for ACCEPT \
14642 \ ------------------------------\
14643 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14644 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14645 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14647 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
14649 \ ------------------------------\
14651 \ ------------------------------\
14652 $03E8 20_US \ 1- wait 20 ms
14653 $03 TOP_LCD \ 2- send DB5=DB4=1
14654 $CD 20_US \ 3- wait 4,1 ms
14655 $03 TOP_LCD \ 4- send again DB5=DB4=1
14656 $5 20_US \ 5- wait 0,1 ms
14657 $03 TOP_LCD \ 6- send again again DB5=DB4=1
14658 $2 20_US \ wait 40 us = LCD cycle
14659 $02 TOP_LCD \ 7- send DB5=1 DB4=0
14660 $2 20_US \ wait 40 us = LCD cycle
14661 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14662 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14663 LCD_Clear \ 10- "LCD_Clear"
14664 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14665 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14666 LCD_Clear \ 10- "LCD_Clear"
14667 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14668 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14670 ['] (CR) IS CR \ ' (CR) is CR
14671 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
14673 ." RC5toLCD is running. Type STOP to quit"
14674 \ NOECHO \ uncomment to run this app without terminal connexion
14675 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
14676 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
14680 : STOP \ stops multitasking, must to be used before downloading app
14681 ['] (WARM) IS WARM \ remove START app from FORTH init process
14682 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
14690 CODE MAX \ n1 n2 -- n3 signed maximum
14691 CMP @PSP,TOS \ n2-n1
14692 S< ?GOTO FW1 \ n2<n1
14698 CODE MIN \ n1 n2 -- n3 signed minimum
14699 CMP @PSP,TOS \ n2-n1
14700 S< ?GOTO BW1 \ n2<n1
14706 : U.R \ u n -- display u unsigned in n width (n >= 2)
14708 R> OVER - 0 MAX SPACES TYPE
14712 CODE 20_US \ n -- n * 20 us
14713 BEGIN \ 3 cycles loop + 6~
14714 \ MOV #5,W \ 3 MCLK = 1 MHz
14715 \ MOV #23,W \ 3 MCLK = 4 MHz
14716 MOV #51,W \ 3 MCLK = 8 MHz
14717 \ MOV #104,W \ 3 MCLK = 16 MHz
14718 \ MOV #158,W \ 3 MCLK = 24 MHz
14719 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
14729 CODE TOP_LCD \ LCD Sample
14730 \ \ if write : %xxxxWWWW --
14731 \ \ if read : -- %0000RRRR
14732 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
14733 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
14734 0= IF \ write LCD bits pattern
14735 AND.B #LCD_DB,TOS \
14736 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
14737 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14740 THEN \ read LCD bits pattern
14743 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14744 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
14745 AND.B #LCD_DB,TOS \
14750 CODE LCD_W \ byte -- write byte to LCD
14752 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
14753 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
14754 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
14755 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
14756 COLON \ high level word starts here
14757 TOP_LCD 2 20_US \ write high nibble first
14762 CODE LCD_WrC \ char -- Write Char
14763 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14768 CODE LCD_WrF \ func -- Write Fonction
14769 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14775 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
14780 $02 LCD_WrF 100 20_us
14784 \ : LCD_Entry_set $04 OR LCD_WrF ;
14786 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
14788 \ : LCD_Display_Shift $10 OR LCD_WrF ;
14790 \ : LCD_Fn_Set $20 OR LCD_WrF ;
14792 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
14794 \ : LCD_Goto $80 OR LCD_WrF ;
14796 \ CODE LCD_R \ -- byte read byte from LCD
14797 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14798 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14799 \ COLON \ starts a FORTH word
14800 \ TOP_LCD 2 20_us \ -- %0000HHHH
14801 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
14802 \ HI2LO \ switch from FORTH to assembler
14803 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
14804 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
14805 \ MOV @RSP+,IP \ restore IP saved by COLON
14810 \ CODE LCD_RdS \ -- status Read Status
14811 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14816 \ CODE LCD_RdC \ -- char Read Char
14817 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14822 \ -------------+------+------+------+------++---+---+---+---+---------+
14823 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
14824 \ -------------+------+------+------+------++---+---+---+---+---------+
14825 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
14826 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
14827 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
14828 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
14829 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
14830 \ -------------+------+------+------+------++---+---+---+---+---------+
14833 \ ******************************\
14834 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14835 \ ******************************\
14836 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
14837 \ ------------------------------\
14838 \ define LPM mode for ACCEPT \
14839 \ ------------------------------\
14840 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14841 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14842 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14843 BIT.B #SW2,&SW2_IN \ test switch S2
14844 0= IF \ case of switch S2 pressed
14845 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
14847 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
14850 BIT.B #SW1,&SW1_IN \ test switch S1 input
14851 0= IF \ case of Switch S1 pressed
14852 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
14854 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
14858 RETI \ CPU is ON, GIE is OFF
14863 \ ------------------------------\
14864 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14865 \ ******************************\
14866 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14867 \ ******************************\
14868 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14869 \ \ SMclock = 8|16|24 MHz
14870 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
14871 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
14872 \ \ SR(9)=new Toggle bit memory (ADD on)
14873 \ ------------------------------\
14874 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
14875 \ ------------------------------\
14876 \ define LPM mode for ACCEPT \
14877 \ ------------------------------\
14878 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14879 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14880 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14881 \ ------------------------------\
14882 \ RC5_FirstStartBitHalfCycle: \
14883 \ ------------------------------\
14884 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
14885 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
14886 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
14887 MOV #1778,X \ RC5_Period in us
14888 MOV #14,W \ count of loop
14890 \ ------------------------------\
14891 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
14892 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
14893 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
14894 \ RC5_Compute_3/4_Period: \ |
14895 RRUM #1,X \ X=1/2 cycle |
14899 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
14900 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
14902 \ ------------------------------\
14903 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
14904 \ ------------------------------\
14905 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14906 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
14907 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14908 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14909 SUB #1,W \ decrement count loop
14910 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
14911 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14912 0<> WHILE \ ----> out of loop ----+
14913 \ RC5_compute_7/4_Time_out: \ |
14914 ADD X,Y \ | out of bound = 7/4 period
14915 \ RC5_WaitHalfCycleP1.2_IFG: \ |
14917 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
14918 0>= IF \ | if cycle time out of bound
14919 BIC #$30,&TA0CTL \ | stop timer_A0
14920 RETI \ | then quit to do nothing
14922 \ ------------------------------\ |
14923 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
14925 MOV &TA0R,X \ | | get new RC5_period value
14926 REPEAT \ ----> loop back --+ |
14927 \ ------------------------------\ |
14928 \ RC5_SampleEndOf: \ <---------------------+
14929 \ ------------------------------\
14930 BIC #$30,&TA0CTL \ stop timer_A0
14931 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
14932 \ ******************************\
14933 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14934 \ ******************************\
14935 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
14936 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
14937 XOR IP,X \ (new XOR old) Toggle bit (13)
14938 BIT #BIT13,X \ X(13) = New_RC5_command
14939 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
14941 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
14942 \ ******************************\
14943 \ RC5_ComputeNewRC5word \
14944 \ ******************************\
14946 MOV &BASE,2(PSP) \ save variable BASE before use
14947 MOV TOS,0(PSP) \ save TOS before use
14948 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
14949 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
14950 \ ******************************\
14951 \ RC5_ComputeC6bit \
14952 \ ******************************\
14953 BIT #$4000,IP \ test /C6 bit in IP
14954 0= IF BIS #$40,TOS \ set C6 bit in S
14955 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
14956 \ ******************************\
14957 \ RC5_CommandByteIsDone \ RC5_code --
14958 \ ******************************\
14960 \ ------------------------------\
14961 \ Display IR_RC5 code \
14962 \ ------------------------------\
14963 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
14964 \ ------------------------------\
14965 LO2HI \ switch from assembler to FORTH
14966 ['] LCD_CLEAR IS CR \ redirects CR
14967 ['] LCD_WrC IS EMIT \ redirects EMIT
14968 $10 BASE ! \ change BASE to hexadecimal
14969 CR ." $" 2 U.R \ print IR_RC5 code
14970 ['] (CR) IS CR \ restore CR
14971 ['] (EMIT) IS EMIT \ restore EMIT
14972 HI2LO \ switch from FORTH to assembler
14973 \ ------------------------------\
14974 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
14975 \ ------------------------------\
14976 MOV @PSP+,&BASE \ restore variable BASE
14977 RETI \ CPU is ON, GIE is OFF
14982 \ ------------------------------\
14983 \ TB0CTL = %0000 0010 1001 0100\$3C0
14984 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14985 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14986 \ -- \ID input divider \ 10 = /4
14987 \ -- \MC Mode Control \ 01 = up to TB0CCR0
14988 \ - \TBCLR TimerB Clear
14991 \ --------------------------------\\
14992 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14993 \ -- \CM Capture Mode
14998 \ --- \OUTMOD \ 011 = set/reset
15004 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
15006 \ ------------------------------\
15007 \ set TimerB to make 50kHz PWM \
15008 \ ------------------------------\
15009 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15010 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
15011 \ ------------------------------\
15012 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15013 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
15014 \ ------------------------------\
15015 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15016 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
15017 \ ------------------------------\
15018 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15019 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
15020 \ ------------------------------\
15021 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15022 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
15023 \ ------------------------------\
15024 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
15025 \ ------------------------------\
15026 \ set TimerB to generate PWM for LCD_Vo
15027 \ ------------------------------\
15028 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
15029 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
15030 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15031 \ ------------------------------\
15032 BIS.B #LCDVo,&LCDVo_DIR \
15033 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
15034 \ ------------------------------\
15035 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15036 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15037 \ ------------------------------\
15038 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15039 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15040 \ ------------------------------\
15041 \ WDT interval init part \
15042 \ ------------------------------\
15043 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
15044 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
15045 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
15046 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
15047 \ ------------------------------\
15049 \ ------------------------------\
15050 BIS.B #RC5,&IR_IE \ enable RC5_Int
15051 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15052 \ ------------------------------\
15053 \ init interrupt vectors
15054 \ ------------------------------\
15055 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
15056 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15057 \ ------------------------------\
15058 \ define LPM mode for ACCEPT \
15059 \ ------------------------------\
15060 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15061 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15062 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15064 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
15066 \ ------------------------------\
15068 \ ------------------------------\
15069 $03E8 20_US \ 1- wait 20 ms
15070 $03 TOP_LCD \ 2- send DB5=DB4=1
15071 $CD 20_US \ 3- wait 4,1 ms
15072 $03 TOP_LCD \ 4- send again DB5=DB4=1
15073 $5 20_US \ 5- wait 0,1 ms
15074 $03 TOP_LCD \ 6- send again again DB5=DB4=1
15075 $2 20_US \ wait 40 us = LCD cycle
15076 $02 TOP_LCD \ 7- send DB5=1 DB4=0
15077 $2 20_US \ wait 40 us = LCD cycle
15078 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15079 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15080 LCD_Clear \ 10- "LCD_Clear"
15081 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15082 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15083 LCD_Clear \ 10- "LCD_Clear"
15084 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15085 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15087 ['] (CR) IS CR \ ' (CR) is CR
15088 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
15090 ." RC5toLCD is running. Type STOP to quit"
15091 \ NOECHO \ uncomment to run this app without terminal connexion
15092 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
15093 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
15097 : STOP \ stops multitasking, must to be used before downloading app
15098 ['] (WARM) IS WARM \ remove START app from FORTH init process
15099 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
15107 CODE MAX \ n1 n2 -- n3 signed maximum
15108 CMP @PSP,TOS \ n2-n1
15109 S< ?GOTO FW1 \ n2<n1
15115 CODE MIN \ n1 n2 -- n3 signed minimum
15116 CMP @PSP,TOS \ n2-n1
15117 S< ?GOTO BW1 \ n2<n1
15123 : U.R \ u n -- display u unsigned in n width (n >= 2)
15125 R> OVER - 0 MAX SPACES TYPE
15129 CODE 20_US \ n -- n * 20 us
15130 BEGIN \ 3 cycles loop + 6~
15131 \ MOV #5,W \ 3 MCLK = 1 MHz
15132 \ MOV #23,W \ 3 MCLK = 4 MHz
15133 MOV #51,W \ 3 MCLK = 8 MHz
15134 \ MOV #104,W \ 3 MCLK = 16 MHz
15135 \ MOV #158,W \ 3 MCLK = 24 MHz
15136 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
15146 CODE TOP_LCD \ LCD Sample
15147 \ \ if write : %xxxxWWWW --
15148 \ \ if read : -- %0000RRRR
15149 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15150 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15151 0= IF \ write LCD bits pattern
15152 AND.B #LCD_DB,TOS \
15153 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15154 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15157 THEN \ read LCD bits pattern
15160 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15161 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15162 AND.B #LCD_DB,TOS \
15167 CODE LCD_W \ byte -- write byte to LCD
15169 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
15170 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
15171 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15172 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15173 COLON \ high level word starts here
15174 TOP_LCD 2 20_US \ write high nibble first
15179 CODE LCD_WrC \ char -- Write Char
15180 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15185 CODE LCD_WrF \ func -- Write Fonction
15186 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15192 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
15197 $02 LCD_WrF 100 20_us
15201 \ : LCD_Entry_set $04 OR LCD_WrF ;
15203 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
15205 \ : LCD_Display_Shift $10 OR LCD_WrF ;
15207 \ : LCD_Fn_Set $20 OR LCD_WrF ;
15209 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
15211 \ : LCD_Goto $80 OR LCD_WrF ;
15213 \ CODE LCD_R \ -- byte read byte from LCD
15214 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15215 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15216 \ COLON \ starts a FORTH word
15217 \ TOP_LCD 2 20_us \ -- %0000HHHH
15218 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
15219 \ HI2LO \ switch from FORTH to assembler
15220 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
15221 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
15222 \ MOV @RSP+,IP \ restore IP saved by COLON
15227 \ CODE LCD_RdS \ -- status Read Status
15228 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15233 \ CODE LCD_RdC \ -- char Read Char
15234 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15239 \ -------------+------+------+------+------++---+---+---+---+---------+
15240 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
15241 \ -------------+------+------+------+------++---+---+---+---+---------+
15242 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
15243 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
15244 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
15245 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
15246 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
15247 \ -------------+------+------+------+------++---+---+---+---+---------+
15250 \ ******************************\
15251 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15252 \ ******************************\
15253 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
15254 \ ------------------------------\
15255 \ define LPM mode for ACCEPT \
15256 \ ------------------------------\
15257 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15258 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15259 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15260 BIT.B #SW2,&SW2_IN \ test switch S2
15261 0= IF \ case of switch S2 pressed
15262 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
15264 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
15267 BIT.B #SW1,&SW1_IN \ test switch S1 input
15268 0= IF \ case of Switch S1 pressed
15269 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
15271 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
15275 RETI \ CPU is ON, GIE is OFF
15280 \ ------------------------------\
15281 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15282 \ ******************************\
15283 ASM RC5_INT \ wake up on Px.RC5 change interrupt
15284 \ ******************************\
15285 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15286 \ \ SMclock = 8|16|24 MHz
15287 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
15288 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
15289 \ \ SR(9)=new Toggle bit memory (ADD on)
15290 \ ------------------------------\
15291 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
15292 \ ------------------------------\
15293 \ define LPM mode for ACCEPT \
15294 \ ------------------------------\
15295 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15296 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15297 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15298 \ ------------------------------\
15299 \ RC5_FirstStartBitHalfCycle: \
15300 \ ------------------------------\
15301 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
15302 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
15303 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
15304 MOV #1778,X \ RC5_Period in us
15305 MOV #14,W \ count of loop
15307 \ ------------------------------\
15308 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
15309 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
15310 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
15311 \ RC5_Compute_3/4_Period: \ |
15312 RRUM #1,X \ X=1/2 cycle |
15316 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
15317 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
15319 \ ------------------------------\
15320 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
15321 \ ------------------------------\
15322 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15323 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
15324 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15325 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15326 SUB #1,W \ decrement count loop
15327 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
15328 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15329 0<> WHILE \ ----> out of loop ----+
15330 \ RC5_compute_7/4_Time_out: \ |
15331 ADD X,Y \ | out of bound = 7/4 period
15332 \ RC5_WaitHalfCycleP1.2_IFG: \ |
15334 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
15335 0>= IF \ | if cycle time out of bound
15336 BIC #$30,&TA0CTL \ | stop timer_A0
15337 RETI \ | then quit to do nothing
15339 \ ------------------------------\ |
15340 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
15342 MOV &TA0R,X \ | | get new RC5_period value
15343 REPEAT \ ----> loop back --+ |
15344 \ ------------------------------\ |
15345 \ RC5_SampleEndOf: \ <---------------------+
15346 \ ------------------------------\
15347 BIC #$30,&TA0CTL \ stop timer_A0
15348 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
15349 \ ******************************\
15350 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
15351 \ ******************************\
15352 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
15353 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
15354 XOR IP,X \ (new XOR old) Toggle bit (13)
15355 BIT #BIT13,X \ X(13) = New_RC5_command
15356 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
15358 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
15359 \ ******************************\
15360 \ RC5_ComputeNewRC5word \
15361 \ ******************************\
15363 MOV &BASE,2(PSP) \ save variable BASE before use
15364 MOV TOS,0(PSP) \ save TOS before use
15365 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
15366 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
15367 \ ******************************\
15368 \ RC5_ComputeC6bit \
15369 \ ******************************\
15370 BIT #$4000,IP \ test /C6 bit in IP
15371 0= IF BIS #$40,TOS \ set C6 bit in S
15372 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
15373 \ ******************************\
15374 \ RC5_CommandByteIsDone \ RC5_code --
15375 \ ******************************\
15377 \ ------------------------------\
15378 \ Display IR_RC5 code \
15379 \ ------------------------------\
15380 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
15381 \ ------------------------------\
15382 LO2HI \ switch from assembler to FORTH
15383 ['] LCD_CLEAR IS CR \ redirects CR
15384 ['] LCD_WrC IS EMIT \ redirects EMIT
15385 $10 BASE ! \ change BASE to hexadecimal
15386 CR ." $" 2 U.R \ print IR_RC5 code
15387 ['] (CR) IS CR \ restore CR
15388 ['] (EMIT) IS EMIT \ restore EMIT
15389 HI2LO \ switch from FORTH to assembler
15390 \ ------------------------------\
15391 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
15392 \ ------------------------------\
15393 MOV @PSP+,&BASE \ restore variable BASE
15394 RETI \ CPU is ON, GIE is OFF
15399 \ ------------------------------\
15400 \ TB0CTL = %0000 0010 1001 0100\$3C0
15401 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15402 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15403 \ -- \ID input divider \ 10 = /4
15404 \ -- \MC Mode Control \ 01 = up to TB0CCR0
15405 \ - \TBCLR TimerB Clear
15408 \ --------------------------------\\
15409 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15410 \ -- \CM Capture Mode
15415 \ --- \OUTMOD \ 011 = set/reset
15421 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
15423 \ ------------------------------\
15424 \ set TimerB to make 50kHz PWM \
15425 \ ------------------------------\
15426 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15427 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
15428 \ ------------------------------\
15429 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15430 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
15431 \ ------------------------------\
15432 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15433 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
15434 \ ------------------------------\
15435 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15436 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
15437 \ ------------------------------\
15438 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15439 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
15440 \ ------------------------------\
15441 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
15442 \ ------------------------------\
15443 \ set TimerB to generate PWM for LCD_Vo
15444 \ ------------------------------\
15445 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
15446 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
15447 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15448 \ ------------------------------\
15449 BIS.B #LCDVo,&LCDVo_DIR \
15450 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
15451 \ ------------------------------\
15452 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15453 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15454 \ ------------------------------\
15455 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15456 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15457 \ ------------------------------\
15458 \ WDT interval init part \
15459 \ ------------------------------\
15460 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
15461 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
15462 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
15463 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
15464 \ ------------------------------\
15466 \ ------------------------------\
15467 BIS.B #RC5,&IR_IE \ enable RC5_Int
15468 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15469 \ ------------------------------\
15470 \ init interrupt vectors
15471 \ ------------------------------\
15472 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
15473 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15474 \ ------------------------------\
15475 \ define LPM mode for ACCEPT \
15476 \ ------------------------------\
15477 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15478 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15479 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15481 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
15483 \ ------------------------------\
15485 \ ------------------------------\
15486 $03E8 20_US \ 1- wait 20 ms
15487 $03 TOP_LCD \ 2- send DB5=DB4=1
15488 $CD 20_US \ 3- wait 4,1 ms
15489 $03 TOP_LCD \ 4- send again DB5=DB4=1
15490 $5 20_US \ 5- wait 0,1 ms
15491 $03 TOP_LCD \ 6- send again again DB5=DB4=1
15492 $2 20_US \ wait 40 us = LCD cycle
15493 $02 TOP_LCD \ 7- send DB5=1 DB4=0
15494 $2 20_US \ wait 40 us = LCD cycle
15495 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15496 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15497 LCD_Clear \ 10- "LCD_Clear"
15498 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15499 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15500 LCD_Clear \ 10- "LCD_Clear"
15501 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15502 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15504 ['] (CR) IS CR \ ' (CR) is CR
15505 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
15507 ." RC5toLCD is running. Type STOP to quit"
15508 \ NOECHO \ uncomment to run this app without terminal connexion
15509 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
15510 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
15514 : STOP \ stops multitasking, must to be used before downloading app
15515 ['] (WARM) IS WARM \ remove START app from FORTH init process
15516 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
15524 CODE MAX \ n1 n2 -- n3 signed maximum
15525 CMP @PSP,TOS \ n2-n1
15526 S< ?GOTO FW1 \ n2<n1
15532 CODE MIN \ n1 n2 -- n3 signed minimum
15533 CMP @PSP,TOS \ n2-n1
15534 S< ?GOTO BW1 \ n2<n1
15540 : U.R \ u n -- display u unsigned in n width (n >= 2)
15542 R> OVER - 0 MAX SPACES TYPE
15546 CODE 20_US \ n -- n * 20 us
15547 BEGIN \ 3 cycles loop + 6~
15548 \ MOV #5,W \ 3 MCLK = 1 MHz
15549 \ MOV #23,W \ 3 MCLK = 4 MHz
15550 MOV #51,W \ 3 MCLK = 8 MHz
15551 \ MOV #104,W \ 3 MCLK = 16 MHz
15552 \ MOV #158,W \ 3 MCLK = 24 MHz
15553 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
15563 CODE TOP_LCD \ LCD Sample
15564 \ \ if write : %xxxxWWWW --
15565 \ \ if read : -- %0000RRRR
15566 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15567 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15568 0= IF \ write LCD bits pattern
15569 AND.B #LCD_DB,TOS \
15570 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15571 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15574 THEN \ read LCD bits pattern
15577 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15578 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15579 AND.B #LCD_DB,TOS \
15584 CODE LCD_W \ byte -- write byte to LCD
15586 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
15587 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
15588 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15589 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15590 COLON \ high level word starts here
15591 TOP_LCD 2 20_US \ write high nibble first
15596 CODE LCD_WrC \ char -- Write Char
15597 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15602 CODE LCD_WrF \ func -- Write Fonction
15603 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15609 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
15614 $02 LCD_WrF 100 20_us
15618 \ : LCD_Entry_set $04 OR LCD_WrF ;
15620 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
15622 \ : LCD_Display_Shift $10 OR LCD_WrF ;
15624 \ : LCD_Fn_Set $20 OR LCD_WrF ;
15626 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
15628 \ : LCD_Goto $80 OR LCD_WrF ;
15630 \ CODE LCD_R \ -- byte read byte from LCD
15631 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15632 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15633 \ COLON \ starts a FORTH word
15634 \ TOP_LCD 2 20_us \ -- %0000HHHH
15635 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
15636 \ HI2LO \ switch from FORTH to assembler
15637 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
15638 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
15639 \ MOV @RSP+,IP \ restore IP saved by COLON
15644 \ CODE LCD_RdS \ -- status Read Status
15645 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15650 \ CODE LCD_RdC \ -- char Read Char
15651 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15656 \ -------------+------+------+------+------++---+---+---+---+---------+
15657 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
15658 \ -------------+------+------+------+------++---+---+---+---+---------+
15659 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
15660 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
15661 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
15662 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
15663 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
15664 \ -------------+------+------+------+------++---+---+---+---+---------+
15667 \ ******************************\
15668 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15669 \ ******************************\
15670 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
15671 \ ------------------------------\
15672 \ define LPM mode for ACCEPT \
15673 \ ------------------------------\
15674 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15675 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15676 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15677 BIT.B #SW2,&SW2_IN \ test switch S2
15678 0= IF \ case of switch S2 pressed
15679 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
15681 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
15684 BIT.B #SW1,&SW1_IN \ test switch S1 input
15685 0= IF \ case of Switch S1 pressed
15686 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
15688 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
15692 RETI \ CPU is ON, GIE is OFF
15697 \ ------------------------------\
15698 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15699 \ ******************************\
15700 ASM RC5_INT \ wake up on Px.RC5 change interrupt
15701 \ ******************************\
15702 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15703 \ \ SMclock = 8|16|24 MHz
15704 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
15705 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
15706 \ \ SR(9)=new Toggle bit memory (ADD on)
15707 \ ------------------------------\
15708 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
15709 \ ------------------------------\
15710 \ define LPM mode for ACCEPT \
15711 \ ------------------------------\
15712 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15713 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15714 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15715 \ ------------------------------\
15716 \ RC5_FirstStartBitHalfCycle: \
15717 \ ------------------------------\
15718 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
15719 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
15720 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
15721 MOV #1778,X \ RC5_Period in us
15722 MOV #14,W \ count of loop
15724 \ ------------------------------\
15725 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
15726 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
15727 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
15728 \ RC5_Compute_3/4_Period: \ |
15729 RRUM #1,X \ X=1/2 cycle |
15733 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
15734 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
15736 \ ------------------------------\
15737 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
15738 \ ------------------------------\
15739 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15740 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
15741 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15742 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15743 SUB #1,W \ decrement count loop
15744 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
15745 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15746 0<> WHILE \ ----> out of loop ----+
15747 \ RC5_compute_7/4_Time_out: \ |
15748 ADD X,Y \ | out of bound = 7/4 period
15749 \ RC5_WaitHalfCycleP1.2_IFG: \ |
15751 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
15752 0>= IF \ | if cycle time out of bound
15753 BIC #$30,&TA0CTL \ | stop timer_A0
15754 RETI \ | then quit to do nothing
15756 \ ------------------------------\ |
15757 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
15759 MOV &TA0R,X \ | | get new RC5_period value
15760 REPEAT \ ----> loop back --+ |
15761 \ ------------------------------\ |
15762 \ RC5_SampleEndOf: \ <---------------------+
15763 \ ------------------------------\
15764 BIC #$30,&TA0CTL \ stop timer_A0
15765 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
15766 \ ******************************\
15767 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
15768 \ ******************************\
15769 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
15770 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
15771 XOR IP,X \ (new XOR old) Toggle bit (13)
15772 BIT #BIT13,X \ X(13) = New_RC5_command
15773 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
15775 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
15776 \ ******************************\
15777 \ RC5_ComputeNewRC5word \
15778 \ ******************************\
15780 MOV &BASE,2(PSP) \ save variable BASE before use
15781 MOV TOS,0(PSP) \ save TOS before use
15782 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
15783 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
15784 \ ******************************\
15785 \ RC5_ComputeC6bit \
15786 \ ******************************\
15787 BIT #$4000,IP \ test /C6 bit in IP
15788 0= IF BIS #$40,TOS \ set C6 bit in S
15789 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
15790 \ ******************************\
15791 \ RC5_CommandByteIsDone \ RC5_code --
15792 \ ******************************\
15794 \ ------------------------------\
15795 \ Display IR_RC5 code \
15796 \ ------------------------------\
15797 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
15798 \ ------------------------------\
15799 LO2HI \ switch from assembler to FORTH
15800 ['] LCD_CLEAR IS CR \ redirects CR
15801 ['] LCD_WrC IS EMIT \ redirects EMIT
15802 $10 BASE ! \ change BASE to hexadecimal
15803 CR ." $" 2 U.R \ print IR_RC5 code
15804 ['] (CR) IS CR \ restore CR
15805 ['] (EMIT) IS EMIT \ restore EMIT
15806 HI2LO \ switch from FORTH to assembler
15807 \ ------------------------------\
15808 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
15809 \ ------------------------------\
15810 MOV @PSP+,&BASE \ restore variable BASE
15811 RETI \ CPU is ON, GIE is OFF
15816 \ ------------------------------\
15817 \ TB0CTL = %0000 0010 1001 0100\$3C0
15818 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15819 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15820 \ -- \ID input divider \ 10 = /4
15821 \ -- \MC Mode Control \ 01 = up to TB0CCR0
15822 \ - \TBCLR TimerB Clear
15825 \ --------------------------------\\
15826 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15827 \ -- \CM Capture Mode
15832 \ --- \OUTMOD \ 011 = set/reset
15838 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
15840 \ ------------------------------\
15841 \ set TimerB to make 50kHz PWM \
15842 \ ------------------------------\
15843 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15844 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
15845 \ ------------------------------\
15846 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15847 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
15848 \ ------------------------------\
15849 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15850 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
15851 \ ------------------------------\
15852 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15853 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
15854 \ ------------------------------\
15855 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15856 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
15857 \ ------------------------------\
15858 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
15859 \ ------------------------------\
15860 \ set TimerB to generate PWM for LCD_Vo
15861 \ ------------------------------\
15862 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
15863 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
15864 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15865 \ ------------------------------\
15866 BIS.B #LCDVo,&LCDVo_DIR \
15867 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
15868 \ ------------------------------\
15869 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15870 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15871 \ ------------------------------\
15872 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15873 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15874 \ ------------------------------\
15875 \ WDT interval init part \
15876 \ ------------------------------\
15877 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
15878 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
15879 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
15880 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
15881 \ ------------------------------\
15883 \ ------------------------------\
15884 BIS.B #RC5,&IR_IE \ enable RC5_Int
15885 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15886 \ ------------------------------\
15887 \ init interrupt vectors
15888 \ ------------------------------\
15889 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
15890 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15891 \ ------------------------------\
15892 \ define LPM mode for ACCEPT \
15893 \ ------------------------------\
15894 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15895 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15896 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15898 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
15900 \ ------------------------------\
15902 \ ------------------------------\
15903 $03E8 20_US \ 1- wait 20 ms
15904 $03 TOP_LCD \ 2- send DB5=DB4=1
15905 $CD 20_US \ 3- wait 4,1 ms
15906 $03 TOP_LCD \ 4- send again DB5=DB4=1
15907 $5 20_US \ 5- wait 0,1 ms
15908 $03 TOP_LCD \ 6- send again again DB5=DB4=1
15909 $2 20_US \ wait 40 us = LCD cycle
15910 $02 TOP_LCD \ 7- send DB5=1 DB4=0
15911 $2 20_US \ wait 40 us = LCD cycle
15912 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15913 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15914 LCD_Clear \ 10- "LCD_Clear"
15915 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15916 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15917 LCD_Clear \ 10- "LCD_Clear"
15918 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15919 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15921 ['] (CR) IS CR \ ' (CR) is CR
15922 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
15924 ." RC5toLCD is running. Type STOP to quit"
15925 \ NOECHO \ uncomment to run this app without terminal connexion
15926 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
15927 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
15931 : STOP \ stops multitasking, must to be used before downloading app
15932 ['] (WARM) IS WARM \ remove START app from FORTH init process
15933 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
15941 CODE MAX \ n1 n2 -- n3 signed maximum
15942 CMP @PSP,TOS \ n2-n1
15943 S< ?GOTO FW1 \ n2<n1
15949 CODE MIN \ n1 n2 -- n3 signed minimum
15950 CMP @PSP,TOS \ n2-n1
15951 S< ?GOTO BW1 \ n2<n1
15957 : U.R \ u n -- display u unsigned in n width (n >= 2)
15959 R> OVER - 0 MAX SPACES TYPE
15963 CODE 20_US \ n -- n * 20 us
15964 BEGIN \ 3 cycles loop + 6~
15965 \ MOV #5,W \ 3 MCLK = 1 MHz
15966 \ MOV #23,W \ 3 MCLK = 4 MHz
15967 MOV #51,W \ 3 MCLK = 8 MHz
15968 \ MOV #104,W \ 3 MCLK = 16 MHz
15969 \ MOV #158,W \ 3 MCLK = 24 MHz
15970 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
15980 CODE TOP_LCD \ LCD Sample
15981 \ \ if write : %xxxxWWWW --
15982 \ \ if read : -- %0000RRRR
15983 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15984 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15985 0= IF \ write LCD bits pattern
15986 AND.B #LCD_DB,TOS \
15987 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15988 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15991 THEN \ read LCD bits pattern
15994 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15995 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15996 AND.B #LCD_DB,TOS \
16001 CODE LCD_W \ byte -- write byte to LCD
16003 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
16004 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
16005 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16006 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16007 COLON \ high level word starts here
16008 TOP_LCD 2 20_US \ write high nibble first
16013 CODE LCD_WrC \ char -- Write Char
16014 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16019 CODE LCD_WrF \ func -- Write Fonction
16020 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16026 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
16031 $02 LCD_WrF 100 20_us
16035 \ : LCD_Entry_set $04 OR LCD_WrF ;
16037 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
16039 \ : LCD_Display_Shift $10 OR LCD_WrF ;
16041 \ : LCD_Fn_Set $20 OR LCD_WrF ;
16043 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
16045 \ : LCD_Goto $80 OR LCD_WrF ;
16047 \ CODE LCD_R \ -- byte read byte from LCD
16048 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16049 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16050 \ COLON \ starts a FORTH word
16051 \ TOP_LCD 2 20_us \ -- %0000HHHH
16052 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
16053 \ HI2LO \ switch from FORTH to assembler
16054 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
16055 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
16056 \ MOV @RSP+,IP \ restore IP saved by COLON
16061 \ CODE LCD_RdS \ -- status Read Status
16062 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16067 \ CODE LCD_RdC \ -- char Read Char
16068 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16073 \ -------------+------+------+------+------++---+---+---+---+---------+
16074 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
16075 \ -------------+------+------+------+------++---+---+---+---+---------+
16076 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
16077 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
16078 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
16079 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
16080 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
16081 \ -------------+------+------+------+------++---+---+---+---+---------+
16084 \ ******************************\
16085 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16086 \ ******************************\
16087 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
16088 \ ------------------------------\
16089 \ define LPM mode for ACCEPT \
16090 \ ------------------------------\
16091 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16092 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16093 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16094 BIT.B #SW2,&SW2_IN \ test switch S2
16095 0= IF \ case of switch S2 pressed
16096 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
16098 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
16101 BIT.B #SW1,&SW1_IN \ test switch S1 input
16102 0= IF \ case of Switch S1 pressed
16103 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
16105 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
16109 RETI \ CPU is ON, GIE is OFF
16114 \ ------------------------------\
16115 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16116 \ ******************************\
16117 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16118 \ ******************************\
16119 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16120 \ \ SMclock = 8|16|24 MHz
16121 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
16122 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
16123 \ \ SR(9)=new Toggle bit memory (ADD on)
16124 \ ------------------------------\
16125 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
16126 \ ------------------------------\
16127 \ define LPM mode for ACCEPT \
16128 \ ------------------------------\
16129 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16130 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16131 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16132 \ ------------------------------\
16133 \ RC5_FirstStartBitHalfCycle: \
16134 \ ------------------------------\
16135 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
16136 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
16137 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
16138 MOV #1778,X \ RC5_Period in us
16139 MOV #14,W \ count of loop
16141 \ ------------------------------\
16142 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
16143 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
16144 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
16145 \ RC5_Compute_3/4_Period: \ |
16146 RRUM #1,X \ X=1/2 cycle |
16150 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
16151 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
16153 \ ------------------------------\
16154 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
16155 \ ------------------------------\
16156 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16157 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
16158 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16159 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16160 SUB #1,W \ decrement count loop
16161 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
16162 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16163 0<> WHILE \ ----> out of loop ----+
16164 \ RC5_compute_7/4_Time_out: \ |
16165 ADD X,Y \ | out of bound = 7/4 period
16166 \ RC5_WaitHalfCycleP1.2_IFG: \ |
16168 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
16169 0>= IF \ | if cycle time out of bound
16170 BIC #$30,&TA0CTL \ | stop timer_A0
16171 RETI \ | then quit to do nothing
16173 \ ------------------------------\ |
16174 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
16176 MOV &TA0R,X \ | | get new RC5_period value
16177 REPEAT \ ----> loop back --+ |
16178 \ ------------------------------\ |
16179 \ RC5_SampleEndOf: \ <---------------------+
16180 \ ------------------------------\
16181 BIC #$30,&TA0CTL \ stop timer_A0
16182 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
16183 \ ******************************\
16184 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
16185 \ ******************************\
16186 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
16187 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
16188 XOR IP,X \ (new XOR old) Toggle bit (13)
16189 BIT #BIT13,X \ X(13) = New_RC5_command
16190 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
16192 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
16193 \ ******************************\
16194 \ RC5_ComputeNewRC5word \
16195 \ ******************************\
16197 MOV &BASE,2(PSP) \ save variable BASE before use
16198 MOV TOS,0(PSP) \ save TOS before use
16199 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
16200 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
16201 \ ******************************\
16202 \ RC5_ComputeC6bit \
16203 \ ******************************\
16204 BIT #$4000,IP \ test /C6 bit in IP
16205 0= IF BIS #$40,TOS \ set C6 bit in S
16206 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
16207 \ ******************************\
16208 \ RC5_CommandByteIsDone \ RC5_code --
16209 \ ******************************\
16211 \ ------------------------------\
16212 \ Display IR_RC5 code \
16213 \ ------------------------------\
16214 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
16215 \ ------------------------------\
16216 LO2HI \ switch from assembler to FORTH
16217 ['] LCD_CLEAR IS CR \ redirects CR
16218 ['] LCD_WrC IS EMIT \ redirects EMIT
16219 $10 BASE ! \ change BASE to hexadecimal
16220 CR ." $" 2 U.R \ print IR_RC5 code
16221 ['] (CR) IS CR \ restore CR
16222 ['] (EMIT) IS EMIT \ restore EMIT
16223 HI2LO \ switch from FORTH to assembler
16224 \ ------------------------------\
16225 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
16226 \ ------------------------------\
16227 MOV @PSP+,&BASE \ restore variable BASE
16228 RETI \ CPU is ON, GIE is OFF
16233 \ ------------------------------\
16234 \ TB0CTL = %0000 0010 1001 0100\$3C0
16235 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16236 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16237 \ -- \ID input divider \ 10 = /4
16238 \ -- \MC Mode Control \ 01 = up to TB0CCR0
16239 \ - \TBCLR TimerB Clear
16242 \ --------------------------------\\
16243 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16244 \ -- \CM Capture Mode
16249 \ --- \OUTMOD \ 011 = set/reset
16255 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
16257 \ ------------------------------\
16258 \ set TimerB to make 50kHz PWM \
16259 \ ------------------------------\
16260 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
16261 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
16262 \ ------------------------------\
16263 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
16264 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
16265 \ ------------------------------\
16266 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16267 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
16268 \ ------------------------------\
16269 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16270 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
16271 \ ------------------------------\
16272 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16273 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
16274 \ ------------------------------\
16275 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
16276 \ ------------------------------\
16277 \ set TimerB to generate PWM for LCD_Vo
16278 \ ------------------------------\
16279 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
16280 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
16281 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16282 \ ------------------------------\
16283 BIS.B #LCDVo,&LCDVo_DIR \
16284 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
16285 \ ------------------------------\
16286 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16287 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16288 \ ------------------------------\
16289 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16290 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16291 \ ------------------------------\
16292 \ WDT interval init part \
16293 \ ------------------------------\
16294 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
16295 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
16296 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
16297 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
16298 \ ------------------------------\
16300 \ ------------------------------\
16301 BIS.B #RC5,&IR_IE \ enable RC5_Int
16302 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16303 \ ------------------------------\
16304 \ init interrupt vectors
16305 \ ------------------------------\
16306 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
16307 MOV #RC5_INT,&IR_Vec \ init interrupt vector
16308 \ ------------------------------\
16309 \ define LPM mode for ACCEPT \
16310 \ ------------------------------\
16311 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16312 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16313 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16315 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
16317 \ ------------------------------\
16319 \ ------------------------------\
16320 $03E8 20_US \ 1- wait 20 ms
16321 $03 TOP_LCD \ 2- send DB5=DB4=1
16322 $CD 20_US \ 3- wait 4,1 ms
16323 $03 TOP_LCD \ 4- send again DB5=DB4=1
16324 $5 20_US \ 5- wait 0,1 ms
16325 $03 TOP_LCD \ 6- send again again DB5=DB4=1
16326 $2 20_US \ wait 40 us = LCD cycle
16327 $02 TOP_LCD \ 7- send DB5=1 DB4=0
16328 $2 20_US \ wait 40 us = LCD cycle
16329 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16330 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16331 LCD_Clear \ 10- "LCD_Clear"
16332 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16333 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16334 LCD_Clear \ 10- "LCD_Clear"
16335 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16336 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16338 ['] (CR) IS CR \ ' (CR) is CR
16339 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
16341 ." RC5toLCD is running. Type STOP to quit"
16342 \ NOECHO \ uncomment to run this app without terminal connexion
16343 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
16344 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
16348 : STOP \ stops multitasking, must to be used before downloading app
16349 ['] (WARM) IS WARM \ remove START app from FORTH init process
16350 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
16358 CODE MAX \ n1 n2 -- n3 signed maximum
16359 CMP @PSP,TOS \ n2-n1
16360 S< ?GOTO FW1 \ n2<n1
16366 CODE MIN \ n1 n2 -- n3 signed minimum
16367 CMP @PSP,TOS \ n2-n1
16368 S< ?GOTO BW1 \ n2<n1
16374 : U.R \ u n -- display u unsigned in n width (n >= 2)
16376 R> OVER - 0 MAX SPACES TYPE
16380 CODE 20_US \ n -- n * 20 us
16381 BEGIN \ 3 cycles loop + 6~
16382 \ MOV #5,W \ 3 MCLK = 1 MHz
16383 \ MOV #23,W \ 3 MCLK = 4 MHz
16384 MOV #51,W \ 3 MCLK = 8 MHz
16385 \ MOV #104,W \ 3 MCLK = 16 MHz
16386 \ MOV #158,W \ 3 MCLK = 24 MHz
16387 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
16397 CODE TOP_LCD \ LCD Sample
16398 \ \ if write : %xxxxWWWW --
16399 \ \ if read : -- %0000RRRR
16400 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16401 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16402 0= IF \ write LCD bits pattern
16403 AND.B #LCD_DB,TOS \
16404 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16405 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16408 THEN \ read LCD bits pattern
16411 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16412 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16413 AND.B #LCD_DB,TOS \
16418 CODE LCD_W \ byte -- write byte to LCD
16420 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
16421 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
16422 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16423 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16424 COLON \ high level word starts here
16425 TOP_LCD 2 20_US \ write high nibble first
16430 CODE LCD_WrC \ char -- Write Char
16431 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16436 CODE LCD_WrF \ func -- Write Fonction
16437 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16443 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
16448 $02 LCD_WrF 100 20_us
16452 \ : LCD_Entry_set $04 OR LCD_WrF ;
16454 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
16456 \ : LCD_Display_Shift $10 OR LCD_WrF ;
16458 \ : LCD_Fn_Set $20 OR LCD_WrF ;
16460 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
16462 \ : LCD_Goto $80 OR LCD_WrF ;
16464 \ CODE LCD_R \ -- byte read byte from LCD
16465 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16466 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16467 \ COLON \ starts a FORTH word
16468 \ TOP_LCD 2 20_us \ -- %0000HHHH
16469 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
16470 \ HI2LO \ switch from FORTH to assembler
16471 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
16472 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
16473 \ MOV @RSP+,IP \ restore IP saved by COLON
16478 \ CODE LCD_RdS \ -- status Read Status
16479 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16484 \ CODE LCD_RdC \ -- char Read Char
16485 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16490 \ -------------+------+------+------+------++---+---+---+---+---------+
16491 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
16492 \ -------------+------+------+------+------++---+---+---+---+---------+
16493 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
16494 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
16495 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
16496 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
16497 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
16498 \ -------------+------+------+------+------++---+---+---+---+---------+
16501 \ ******************************\
16502 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16503 \ ******************************\
16504 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
16505 \ ------------------------------\
16506 \ define LPM mode for ACCEPT \
16507 \ ------------------------------\
16508 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16509 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16510 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16511 BIT.B #SW2,&SW2_IN \ test switch S2
16512 0= IF \ case of switch S2 pressed
16513 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
16515 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
16518 BIT.B #SW1,&SW1_IN \ test switch S1 input
16519 0= IF \ case of Switch S1 pressed
16520 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
16522 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
16526 RETI \ CPU is ON, GIE is OFF
16531 \ ------------------------------\
16532 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16533 \ ******************************\
16534 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16535 \ ******************************\
16536 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16537 \ \ SMclock = 8|16|24 MHz
16538 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
16539 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
16540 \ \ SR(9)=new Toggle bit memory (ADD on)
16541 \ ------------------------------\
16542 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
16543 \ ------------------------------\
16544 \ define LPM mode for ACCEPT \
16545 \ ------------------------------\
16546 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16547 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16548 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16549 \ ------------------------------\
16550 \ RC5_FirstStartBitHalfCycle: \
16551 \ ------------------------------\
16552 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
16553 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
16554 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
16555 MOV #1778,X \ RC5_Period in us
16556 MOV #14,W \ count of loop
16558 \ ------------------------------\
16559 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
16560 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
16561 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
16562 \ RC5_Compute_3/4_Period: \ |
16563 RRUM #1,X \ X=1/2 cycle |
16567 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
16568 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
16570 \ ------------------------------\
16571 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
16572 \ ------------------------------\
16573 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16574 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
16575 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16576 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16577 SUB #1,W \ decrement count loop
16578 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
16579 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16580 0<> WHILE \ ----> out of loop ----+
16581 \ RC5_compute_7/4_Time_out: \ |
16582 ADD X,Y \ | out of bound = 7/4 period
16583 \ RC5_WaitHalfCycleP1.2_IFG: \ |
16585 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
16586 0>= IF \ | if cycle time out of bound
16587 BIC #$30,&TA0CTL \ | stop timer_A0
16588 RETI \ | then quit to do nothing
16590 \ ------------------------------\ |
16591 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
16593 MOV &TA0R,X \ | | get new RC5_period value
16594 REPEAT \ ----> loop back --+ |
16595 \ ------------------------------\ |
16596 \ RC5_SampleEndOf: \ <---------------------+
16597 \ ------------------------------\
16598 BIC #$30,&TA0CTL \ stop timer_A0
16599 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
16600 \ ******************************\
16601 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
16602 \ ******************************\
16603 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
16604 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
16605 XOR IP,X \ (new XOR old) Toggle bit (13)
16606 BIT #BIT13,X \ X(13) = New_RC5_command
16607 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
16609 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
16610 \ ******************************\
16611 \ RC5_ComputeNewRC5word \
16612 \ ******************************\
16614 MOV &BASE,2(PSP) \ save variable BASE before use
16615 MOV TOS,0(PSP) \ save TOS before use
16616 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
16617 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
16618 \ ******************************\
16619 \ RC5_ComputeC6bit \
16620 \ ******************************\
16621 BIT #$4000,IP \ test /C6 bit in IP
16622 0= IF BIS #$40,TOS \ set C6 bit in S
16623 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
16624 \ ******************************\
16625 \ RC5_CommandByteIsDone \ RC5_code --
16626 \ ******************************\
16628 \ ------------------------------\
16629 \ Display IR_RC5 code \
16630 \ ------------------------------\
16631 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
16632 \ ------------------------------\
16633 LO2HI \ switch from assembler to FORTH
16634 ['] LCD_CLEAR IS CR \ redirects CR
16635 ['] LCD_WrC IS EMIT \ redirects EMIT
16636 $10 BASE ! \ change BASE to hexadecimal
16637 CR ." $" 2 U.R \ print IR_RC5 code
16638 ['] (CR) IS CR \ restore CR
16639 ['] (EMIT) IS EMIT \ restore EMIT
16640 HI2LO \ switch from FORTH to assembler
16641 \ ------------------------------\
16642 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
16643 \ ------------------------------\
16644 MOV @PSP+,&BASE \ restore variable BASE
16645 RETI \ CPU is ON, GIE is OFF
16650 \ ------------------------------\
16651 \ TB0CTL = %0000 0010 1001 0100\$3C0
16652 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16653 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16654 \ -- \ID input divider \ 10 = /4
16655 \ -- \MC Mode Control \ 01 = up to TB0CCR0
16656 \ - \TBCLR TimerB Clear
16659 \ --------------------------------\\
16660 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16661 \ -- \CM Capture Mode
16666 \ --- \OUTMOD \ 011 = set/reset
16672 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
16674 \ ------------------------------\
16675 \ set TimerB to make 50kHz PWM \
16676 \ ------------------------------\
16677 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
16678 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
16679 \ ------------------------------\
16680 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
16681 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
16682 \ ------------------------------\
16683 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16684 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
16685 \ ------------------------------\
16686 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16687 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
16688 \ ------------------------------\
16689 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16690 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
16691 \ ------------------------------\
16692 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
16693 \ ------------------------------\
16694 \ set TimerB to generate PWM for LCD_Vo
16695 \ ------------------------------\
16696 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
16697 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
16698 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16699 \ ------------------------------\
16700 BIS.B #LCDVo,&LCDVo_DIR \
16701 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
16702 \ ------------------------------\
16703 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16704 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16705 \ ------------------------------\
16706 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16707 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16708 \ ------------------------------\
16709 \ WDT interval init part \
16710 \ ------------------------------\
16711 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
16712 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
16713 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
16714 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
16715 \ ------------------------------\
16717 \ ------------------------------\
16718 BIS.B #RC5,&IR_IE \ enable RC5_Int
16719 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16720 \ ------------------------------\
16721 \ init interrupt vectors
16722 \ ------------------------------\
16723 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
16724 MOV #RC5_INT,&IR_Vec \ init interrupt vector
16725 \ ------------------------------\
16726 \ define LPM mode for ACCEPT \
16727 \ ------------------------------\
16728 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16729 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16730 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16732 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
16734 \ ------------------------------\
16736 \ ------------------------------\
16737 $03E8 20_US \ 1- wait 20 ms
16738 $03 TOP_LCD \ 2- send DB5=DB4=1
16739 $CD 20_US \ 3- wait 4,1 ms
16740 $03 TOP_LCD \ 4- send again DB5=DB4=1
16741 $5 20_US \ 5- wait 0,1 ms
16742 $03 TOP_LCD \ 6- send again again DB5=DB4=1
16743 $2 20_US \ wait 40 us = LCD cycle
16744 $02 TOP_LCD \ 7- send DB5=1 DB4=0
16745 $2 20_US \ wait 40 us = LCD cycle
16746 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16747 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16748 LCD_Clear \ 10- "LCD_Clear"
16749 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16750 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16751 LCD_Clear \ 10- "LCD_Clear"
16752 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16753 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16755 ['] (CR) IS CR \ ' (CR) is CR
16756 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
16758 ." RC5toLCD is running. Type STOP to quit"
16759 \ NOECHO \ uncomment to run this app without terminal connexion
16760 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
16761 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
16765 : STOP \ stops multitasking, must to be used before downloading app
16766 ['] (WARM) IS WARM \ remove START app from FORTH init process
16767 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
16775 CODE MAX \ n1 n2 -- n3 signed maximum
16776 CMP @PSP,TOS \ n2-n1
16777 S< ?GOTO FW1 \ n2<n1
16783 CODE MIN \ n1 n2 -- n3 signed minimum
16784 CMP @PSP,TOS \ n2-n1
16785 S< ?GOTO BW1 \ n2<n1
16791 : U.R \ u n -- display u unsigned in n width (n >= 2)
16793 R> OVER - 0 MAX SPACES TYPE
16797 CODE 20_US \ n -- n * 20 us
16798 BEGIN \ 3 cycles loop + 6~
16799 \ MOV #5,W \ 3 MCLK = 1 MHz
16800 \ MOV #23,W \ 3 MCLK = 4 MHz
16801 MOV #51,W \ 3 MCLK = 8 MHz
16802 \ MOV #104,W \ 3 MCLK = 16 MHz
16803 \ MOV #158,W \ 3 MCLK = 24 MHz
16804 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
16814 CODE TOP_LCD \ LCD Sample
16815 \ \ if write : %xxxxWWWW --
16816 \ \ if read : -- %0000RRRR
16817 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16818 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16819 0= IF \ write LCD bits pattern
16820 AND.B #LCD_DB,TOS \
16821 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16822 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16825 THEN \ read LCD bits pattern
16828 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16829 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16830 AND.B #LCD_DB,TOS \
16835 CODE LCD_W \ byte -- write byte to LCD
16837 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
16838 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
16839 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16840 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16841 COLON \ high level word starts here
16842 TOP_LCD 2 20_US \ write high nibble first
16847 CODE LCD_WrC \ char -- Write Char
16848 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16853 CODE LCD_WrF \ func -- Write Fonction
16854 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16860 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
16865 $02 LCD_WrF 100 20_us
16869 \ : LCD_Entry_set $04 OR LCD_WrF ;
16871 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
16873 \ : LCD_Display_Shift $10 OR LCD_WrF ;
16875 \ : LCD_Fn_Set $20 OR LCD_WrF ;
16877 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
16879 \ : LCD_Goto $80 OR LCD_WrF ;
16881 \ CODE LCD_R \ -- byte read byte from LCD
16882 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16883 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16884 \ COLON \ starts a FORTH word
16885 \ TOP_LCD 2 20_us \ -- %0000HHHH
16886 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
16887 \ HI2LO \ switch from FORTH to assembler
16888 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
16889 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
16890 \ MOV @RSP+,IP \ restore IP saved by COLON
16895 \ CODE LCD_RdS \ -- status Read Status
16896 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16901 \ CODE LCD_RdC \ -- char Read Char
16902 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16907 \ -------------+------+------+------+------++---+---+---+---+---------+
16908 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
16909 \ -------------+------+------+------+------++---+---+---+---+---------+
16910 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
16911 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
16912 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
16913 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
16914 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
16915 \ -------------+------+------+------+------++---+---+---+---+---------+
16918 \ ******************************\
16919 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16920 \ ******************************\
16921 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
16922 \ ------------------------------\
16923 \ define LPM mode for ACCEPT \
16924 \ ------------------------------\
16925 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16926 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16927 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16928 BIT.B #SW2,&SW2_IN \ test switch S2
16929 0= IF \ case of switch S2 pressed
16930 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
16932 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
16935 BIT.B #SW1,&SW1_IN \ test switch S1 input
16936 0= IF \ case of Switch S1 pressed
16937 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
16939 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
16943 RETI \ CPU is ON, GIE is OFF
16948 \ ------------------------------\
16949 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16950 \ ******************************\
16951 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16952 \ ******************************\
16953 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16954 \ \ SMclock = 8|16|24 MHz
16955 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
16956 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
16957 \ \ SR(9)=new Toggle bit memory (ADD on)
16958 \ ------------------------------\
16959 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
16960 \ ------------------------------\
16961 \ define LPM mode for ACCEPT \
16962 \ ------------------------------\
16963 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16964 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16965 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16966 \ ------------------------------\
16967 \ RC5_FirstStartBitHalfCycle: \
16968 \ ------------------------------\
16969 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
16970 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
16971 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
16972 MOV #1778,X \ RC5_Period in us
16973 MOV #14,W \ count of loop
16975 \ ------------------------------\
16976 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
16977 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
16978 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
16979 \ RC5_Compute_3/4_Period: \ |
16980 RRUM #1,X \ X=1/2 cycle |
16984 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
16985 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
16987 \ ------------------------------\
16988 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
16989 \ ------------------------------\
16990 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16991 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
16992 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16993 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16994 SUB #1,W \ decrement count loop
16995 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
16996 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16997 0<> WHILE \ ----> out of loop ----+
16998 \ RC5_compute_7/4_Time_out: \ |
16999 ADD X,Y \ | out of bound = 7/4 period
17000 \ RC5_WaitHalfCycleP1.2_IFG: \ |
17002 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
17003 0>= IF \ | if cycle time out of bound
17004 BIC #$30,&TA0CTL \ | stop timer_A0
17005 RETI \ | then quit to do nothing
17007 \ ------------------------------\ |
17008 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
17010 MOV &TA0R,X \ | | get new RC5_period value
17011 REPEAT \ ----> loop back --+ |
17012 \ ------------------------------\ |
17013 \ RC5_SampleEndOf: \ <---------------------+
17014 \ ------------------------------\
17015 BIC #$30,&TA0CTL \ stop timer_A0
17016 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
17017 \ ******************************\
17018 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17019 \ ******************************\
17020 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
17021 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
17022 XOR IP,X \ (new XOR old) Toggle bit (13)
17023 BIT #BIT13,X \ X(13) = New_RC5_command
17024 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
17026 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
17027 \ ******************************\
17028 \ RC5_ComputeNewRC5word \
17029 \ ******************************\
17031 MOV &BASE,2(PSP) \ save variable BASE before use
17032 MOV TOS,0(PSP) \ save TOS before use
17033 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
17034 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
17035 \ ******************************\
17036 \ RC5_ComputeC6bit \
17037 \ ******************************\
17038 BIT #$4000,IP \ test /C6 bit in IP
17039 0= IF BIS #$40,TOS \ set C6 bit in S
17040 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
17041 \ ******************************\
17042 \ RC5_CommandByteIsDone \ RC5_code --
17043 \ ******************************\
17045 \ ------------------------------\
17046 \ Display IR_RC5 code \
17047 \ ------------------------------\
17048 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
17049 \ ------------------------------\
17050 LO2HI \ switch from assembler to FORTH
17051 ['] LCD_CLEAR IS CR \ redirects CR
17052 ['] LCD_WrC IS EMIT \ redirects EMIT
17053 $10 BASE ! \ change BASE to hexadecimal
17054 CR ." $" 2 U.R \ print IR_RC5 code
17055 ['] (CR) IS CR \ restore CR
17056 ['] (EMIT) IS EMIT \ restore EMIT
17057 HI2LO \ switch from FORTH to assembler
17058 \ ------------------------------\
17059 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
17060 \ ------------------------------\
17061 MOV @PSP+,&BASE \ restore variable BASE
17062 RETI \ CPU is ON, GIE is OFF
17067 \ ------------------------------\
17068 \ TB0CTL = %0000 0010 1001 0100\$3C0
17069 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17070 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17071 \ -- \ID input divider \ 10 = /4
17072 \ -- \MC Mode Control \ 01 = up to TB0CCR0
17073 \ - \TBCLR TimerB Clear
17076 \ --------------------------------\\
17077 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17078 \ -- \CM Capture Mode
17083 \ --- \OUTMOD \ 011 = set/reset
17089 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
17091 \ ------------------------------\
17092 \ set TimerB to make 50kHz PWM \
17093 \ ------------------------------\
17094 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17095 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
17096 \ ------------------------------\
17097 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17098 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
17099 \ ------------------------------\
17100 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17101 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
17102 \ ------------------------------\
17103 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17104 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
17105 \ ------------------------------\
17106 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17107 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
17108 \ ------------------------------\
17109 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
17110 \ ------------------------------\
17111 \ set TimerB to generate PWM for LCD_Vo
17112 \ ------------------------------\
17113 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
17114 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
17115 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17116 \ ------------------------------\
17117 BIS.B #LCDVo,&LCDVo_DIR \
17118 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
17119 \ ------------------------------\
17120 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17121 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17122 \ ------------------------------\
17123 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17124 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17125 \ ------------------------------\
17126 \ WDT interval init part \
17127 \ ------------------------------\
17128 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
17129 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
17130 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
17131 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
17132 \ ------------------------------\
17134 \ ------------------------------\
17135 BIS.B #RC5,&IR_IE \ enable RC5_Int
17136 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17137 \ ------------------------------\
17138 \ init interrupt vectors
17139 \ ------------------------------\
17140 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
17141 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17142 \ ------------------------------\
17143 \ define LPM mode for ACCEPT \
17144 \ ------------------------------\
17145 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17146 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17147 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17149 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
17151 \ ------------------------------\
17153 \ ------------------------------\
17154 $03E8 20_US \ 1- wait 20 ms
17155 $03 TOP_LCD \ 2- send DB5=DB4=1
17156 $CD 20_US \ 3- wait 4,1 ms
17157 $03 TOP_LCD \ 4- send again DB5=DB4=1
17158 $5 20_US \ 5- wait 0,1 ms
17159 $03 TOP_LCD \ 6- send again again DB5=DB4=1
17160 $2 20_US \ wait 40 us = LCD cycle
17161 $02 TOP_LCD \ 7- send DB5=1 DB4=0
17162 $2 20_US \ wait 40 us = LCD cycle
17163 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17164 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17165 LCD_Clear \ 10- "LCD_Clear"
17166 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17167 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17168 LCD_Clear \ 10- "LCD_Clear"
17169 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17170 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17172 ['] (CR) IS CR \ ' (CR) is CR
17173 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
17175 ." RC5toLCD is running. Type STOP to quit"
17176 \ NOECHO \ uncomment to run this app without terminal connexion
17177 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
17178 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
17182 : STOP \ stops multitasking, must to be used before downloading app
17183 ['] (WARM) IS WARM \ remove START app from FORTH init process
17184 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
17192 CODE MAX \ n1 n2 -- n3 signed maximum
17193 CMP @PSP,TOS \ n2-n1
17194 S< ?GOTO FW1 \ n2<n1
17200 CODE MIN \ n1 n2 -- n3 signed minimum
17201 CMP @PSP,TOS \ n2-n1
17202 S< ?GOTO BW1 \ n2<n1
17208 : U.R \ u n -- display u unsigned in n width (n >= 2)
17210 R> OVER - 0 MAX SPACES TYPE
17214 CODE 20_US \ n -- n * 20 us
17215 BEGIN \ 3 cycles loop + 6~
17216 \ MOV #5,W \ 3 MCLK = 1 MHz
17217 \ MOV #23,W \ 3 MCLK = 4 MHz
17218 MOV #51,W \ 3 MCLK = 8 MHz
17219 \ MOV #104,W \ 3 MCLK = 16 MHz
17220 \ MOV #158,W \ 3 MCLK = 24 MHz
17221 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
17231 CODE TOP_LCD \ LCD Sample
17232 \ \ if write : %xxxxWWWW --
17233 \ \ if read : -- %0000RRRR
17234 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17235 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17236 0= IF \ write LCD bits pattern
17237 AND.B #LCD_DB,TOS \
17238 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17239 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17242 THEN \ read LCD bits pattern
17245 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17246 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17247 AND.B #LCD_DB,TOS \
17252 CODE LCD_W \ byte -- write byte to LCD
17254 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
17255 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
17256 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17257 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17258 COLON \ high level word starts here
17259 TOP_LCD 2 20_US \ write high nibble first
17264 CODE LCD_WrC \ char -- Write Char
17265 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17270 CODE LCD_WrF \ func -- Write Fonction
17271 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17277 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
17282 $02 LCD_WrF 100 20_us
17286 \ : LCD_Entry_set $04 OR LCD_WrF ;
17288 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
17290 \ : LCD_Display_Shift $10 OR LCD_WrF ;
17292 \ : LCD_Fn_Set $20 OR LCD_WrF ;
17294 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
17296 \ : LCD_Goto $80 OR LCD_WrF ;
17298 \ CODE LCD_R \ -- byte read byte from LCD
17299 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17300 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17301 \ COLON \ starts a FORTH word
17302 \ TOP_LCD 2 20_us \ -- %0000HHHH
17303 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
17304 \ HI2LO \ switch from FORTH to assembler
17305 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
17306 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
17307 \ MOV @RSP+,IP \ restore IP saved by COLON
17312 \ CODE LCD_RdS \ -- status Read Status
17313 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17318 \ CODE LCD_RdC \ -- char Read Char
17319 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17324 \ -------------+------+------+------+------++---+---+---+---+---------+
17325 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
17326 \ -------------+------+------+------+------++---+---+---+---+---------+
17327 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
17328 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
17329 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
17330 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
17331 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
17332 \ -------------+------+------+------+------++---+---+---+---+---------+
17335 \ ******************************\
17336 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17337 \ ******************************\
17338 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
17339 \ ------------------------------\
17340 \ define LPM mode for ACCEPT \
17341 \ ------------------------------\
17342 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17343 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17344 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17345 BIT.B #SW2,&SW2_IN \ test switch S2
17346 0= IF \ case of switch S2 pressed
17347 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
17349 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
17352 BIT.B #SW1,&SW1_IN \ test switch S1 input
17353 0= IF \ case of Switch S1 pressed
17354 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
17356 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
17360 RETI \ CPU is ON, GIE is OFF
17365 \ ------------------------------\
17366 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17367 \ ******************************\
17368 ASM RC5_INT \ wake up on Px.RC5 change interrupt
17369 \ ******************************\
17370 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17371 \ \ SMclock = 8|16|24 MHz
17372 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
17373 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
17374 \ \ SR(9)=new Toggle bit memory (ADD on)
17375 \ ------------------------------\
17376 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
17377 \ ------------------------------\
17378 \ define LPM mode for ACCEPT \
17379 \ ------------------------------\
17380 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17381 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17382 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17383 \ ------------------------------\
17384 \ RC5_FirstStartBitHalfCycle: \
17385 \ ------------------------------\
17386 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
17387 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
17388 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
17389 MOV #1778,X \ RC5_Period in us
17390 MOV #14,W \ count of loop
17392 \ ------------------------------\
17393 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
17394 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
17395 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
17396 \ RC5_Compute_3/4_Period: \ |
17397 RRUM #1,X \ X=1/2 cycle |
17401 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
17402 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
17404 \ ------------------------------\
17405 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
17406 \ ------------------------------\
17407 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17408 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
17409 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17410 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17411 SUB #1,W \ decrement count loop
17412 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
17413 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17414 0<> WHILE \ ----> out of loop ----+
17415 \ RC5_compute_7/4_Time_out: \ |
17416 ADD X,Y \ | out of bound = 7/4 period
17417 \ RC5_WaitHalfCycleP1.2_IFG: \ |
17419 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
17420 0>= IF \ | if cycle time out of bound
17421 BIC #$30,&TA0CTL \ | stop timer_A0
17422 RETI \ | then quit to do nothing
17424 \ ------------------------------\ |
17425 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
17427 MOV &TA0R,X \ | | get new RC5_period value
17428 REPEAT \ ----> loop back --+ |
17429 \ ------------------------------\ |
17430 \ RC5_SampleEndOf: \ <---------------------+
17431 \ ------------------------------\
17432 BIC #$30,&TA0CTL \ stop timer_A0
17433 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
17434 \ ******************************\
17435 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17436 \ ******************************\
17437 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
17438 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
17439 XOR IP,X \ (new XOR old) Toggle bit (13)
17440 BIT #BIT13,X \ X(13) = New_RC5_command
17441 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
17443 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
17444 \ ******************************\
17445 \ RC5_ComputeNewRC5word \
17446 \ ******************************\
17448 MOV &BASE,2(PSP) \ save variable BASE before use
17449 MOV TOS,0(PSP) \ save TOS before use
17450 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
17451 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
17452 \ ******************************\
17453 \ RC5_ComputeC6bit \
17454 \ ******************************\
17455 BIT #$4000,IP \ test /C6 bit in IP
17456 0= IF BIS #$40,TOS \ set C6 bit in S
17457 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
17458 \ ******************************\
17459 \ RC5_CommandByteIsDone \ RC5_code --
17460 \ ******************************\
17462 \ ------------------------------\
17463 \ Display IR_RC5 code \
17464 \ ------------------------------\
17465 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
17466 \ ------------------------------\
17467 LO2HI \ switch from assembler to FORTH
17468 ['] LCD_CLEAR IS CR \ redirects CR
17469 ['] LCD_WrC IS EMIT \ redirects EMIT
17470 $10 BASE ! \ change BASE to hexadecimal
17471 CR ." $" 2 U.R \ print IR_RC5 code
17472 ['] (CR) IS CR \ restore CR
17473 ['] (EMIT) IS EMIT \ restore EMIT
17474 HI2LO \ switch from FORTH to assembler
17475 \ ------------------------------\
17476 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
17477 \ ------------------------------\
17478 MOV @PSP+,&BASE \ restore variable BASE
17479 RETI \ CPU is ON, GIE is OFF
17484 \ ------------------------------\
17485 \ TB0CTL = %0000 0010 1001 0100\$3C0
17486 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17487 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17488 \ -- \ID input divider \ 10 = /4
17489 \ -- \MC Mode Control \ 01 = up to TB0CCR0
17490 \ - \TBCLR TimerB Clear
17493 \ --------------------------------\\
17494 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17495 \ -- \CM Capture Mode
17500 \ --- \OUTMOD \ 011 = set/reset
17506 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
17508 \ ------------------------------\
17509 \ set TimerB to make 50kHz PWM \
17510 \ ------------------------------\
17511 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17512 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
17513 \ ------------------------------\
17514 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17515 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
17516 \ ------------------------------\
17517 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17518 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
17519 \ ------------------------------\
17520 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17521 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
17522 \ ------------------------------\
17523 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17524 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
17525 \ ------------------------------\
17526 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
17527 \ ------------------------------\
17528 \ set TimerB to generate PWM for LCD_Vo
17529 \ ------------------------------\
17530 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
17531 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
17532 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17533 \ ------------------------------\
17534 BIS.B #LCDVo,&LCDVo_DIR \
17535 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
17536 \ ------------------------------\
17537 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17538 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17539 \ ------------------------------\
17540 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17541 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17542 \ ------------------------------\
17543 \ WDT interval init part \
17544 \ ------------------------------\
17545 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
17546 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
17547 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
17548 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
17549 \ ------------------------------\
17551 \ ------------------------------\
17552 BIS.B #RC5,&IR_IE \ enable RC5_Int
17553 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17554 \ ------------------------------\
17555 \ init interrupt vectors
17556 \ ------------------------------\
17557 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
17558 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17559 \ ------------------------------\
17560 \ define LPM mode for ACCEPT \
17561 \ ------------------------------\
17562 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17563 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17564 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17566 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
17568 \ ------------------------------\
17570 \ ------------------------------\
17571 $03E8 20_US \ 1- wait 20 ms
17572 $03 TOP_LCD \ 2- send DB5=DB4=1
17573 $CD 20_US \ 3- wait 4,1 ms
17574 $03 TOP_LCD \ 4- send again DB5=DB4=1
17575 $5 20_US \ 5- wait 0,1 ms
17576 $03 TOP_LCD \ 6- send again again DB5=DB4=1
17577 $2 20_US \ wait 40 us = LCD cycle
17578 $02 TOP_LCD \ 7- send DB5=1 DB4=0
17579 $2 20_US \ wait 40 us = LCD cycle
17580 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17581 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17582 LCD_Clear \ 10- "LCD_Clear"
17583 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17584 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17585 LCD_Clear \ 10- "LCD_Clear"
17586 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17587 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17589 ['] (CR) IS CR \ ' (CR) is CR
17590 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
17592 ." RC5toLCD is running. Type STOP to quit"
17593 \ NOECHO \ uncomment to run this app without terminal connexion
17594 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
17595 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
17599 : STOP \ stops multitasking, must to be used before downloading app
17600 ['] (WARM) IS WARM \ remove START app from FORTH init process
17601 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
17609 CODE MAX \ n1 n2 -- n3 signed maximum
17610 CMP @PSP,TOS \ n2-n1
17611 S< ?GOTO FW1 \ n2<n1
17617 CODE MIN \ n1 n2 -- n3 signed minimum
17618 CMP @PSP,TOS \ n2-n1
17619 S< ?GOTO BW1 \ n2<n1
17625 : U.R \ u n -- display u unsigned in n width (n >= 2)
17627 R> OVER - 0 MAX SPACES TYPE
17631 CODE 20_US \ n -- n * 20 us
17632 BEGIN \ 3 cycles loop + 6~
17633 \ MOV #5,W \ 3 MCLK = 1 MHz
17634 \ MOV #23,W \ 3 MCLK = 4 MHz
17635 MOV #51,W \ 3 MCLK = 8 MHz
17636 \ MOV #104,W \ 3 MCLK = 16 MHz
17637 \ MOV #158,W \ 3 MCLK = 24 MHz
17638 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
17648 CODE TOP_LCD \ LCD Sample
17649 \ \ if write : %xxxxWWWW --
17650 \ \ if read : -- %0000RRRR
17651 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17652 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17653 0= IF \ write LCD bits pattern
17654 AND.B #LCD_DB,TOS \
17655 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17656 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17659 THEN \ read LCD bits pattern
17662 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17663 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17664 AND.B #LCD_DB,TOS \
17669 CODE LCD_W \ byte -- write byte to LCD
17671 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
17672 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
17673 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17674 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17675 COLON \ high level word starts here
17676 TOP_LCD 2 20_US \ write high nibble first
17681 CODE LCD_WrC \ char -- Write Char
17682 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17687 CODE LCD_WrF \ func -- Write Fonction
17688 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17694 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
17699 $02 LCD_WrF 100 20_us
17703 \ : LCD_Entry_set $04 OR LCD_WrF ;
17705 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
17707 \ : LCD_Display_Shift $10 OR LCD_WrF ;
17709 \ : LCD_Fn_Set $20 OR LCD_WrF ;
17711 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
17713 \ : LCD_Goto $80 OR LCD_WrF ;
17715 \ CODE LCD_R \ -- byte read byte from LCD
17716 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17717 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17718 \ COLON \ starts a FORTH word
17719 \ TOP_LCD 2 20_us \ -- %0000HHHH
17720 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
17721 \ HI2LO \ switch from FORTH to assembler
17722 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
17723 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
17724 \ MOV @RSP+,IP \ restore IP saved by COLON
17729 \ CODE LCD_RdS \ -- status Read Status
17730 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17735 \ CODE LCD_RdC \ -- char Read Char
17736 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17741 \ -------------+------+------+------+------++---+---+---+---+---------+
17742 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
17743 \ -------------+------+------+------+------++---+---+---+---+---------+
17744 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
17745 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
17746 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
17747 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
17748 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
17749 \ -------------+------+------+------+------++---+---+---+---+---------+
17752 \ ******************************\
17753 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17754 \ ******************************\
17755 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
17756 \ ------------------------------\
17757 \ define LPM mode for ACCEPT \
17758 \ ------------------------------\
17759 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17760 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17761 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17762 BIT.B #SW2,&SW2_IN \ test switch S2
17763 0= IF \ case of switch S2 pressed
17764 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
17766 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
17769 BIT.B #SW1,&SW1_IN \ test switch S1 input
17770 0= IF \ case of Switch S1 pressed
17771 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
17773 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
17777 RETI \ CPU is ON, GIE is OFF
17782 \ ------------------------------\
17783 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17784 \ ******************************\
17785 ASM RC5_INT \ wake up on Px.RC5 change interrupt
17786 \ ******************************\
17787 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17788 \ \ SMclock = 8|16|24 MHz
17789 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
17790 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
17791 \ \ SR(9)=new Toggle bit memory (ADD on)
17792 \ ------------------------------\
17793 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
17794 \ ------------------------------\
17795 \ define LPM mode for ACCEPT \
17796 \ ------------------------------\
17797 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17798 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17799 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17800 \ ------------------------------\
17801 \ RC5_FirstStartBitHalfCycle: \
17802 \ ------------------------------\
17803 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
17804 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
17805 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
17806 MOV #1778,X \ RC5_Period in us
17807 MOV #14,W \ count of loop
17809 \ ------------------------------\
17810 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
17811 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
17812 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
17813 \ RC5_Compute_3/4_Period: \ |
17814 RRUM #1,X \ X=1/2 cycle |
17818 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
17819 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
17821 \ ------------------------------\
17822 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
17823 \ ------------------------------\
17824 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17825 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
17826 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17827 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17828 SUB #1,W \ decrement count loop
17829 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
17830 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17831 0<> WHILE \ ----> out of loop ----+
17832 \ RC5_compute_7/4_Time_out: \ |
17833 ADD X,Y \ | out of bound = 7/4 period
17834 \ RC5_WaitHalfCycleP1.2_IFG: \ |
17836 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
17837 0>= IF \ | if cycle time out of bound
17838 BIC #$30,&TA0CTL \ | stop timer_A0
17839 RETI \ | then quit to do nothing
17841 \ ------------------------------\ |
17842 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
17844 MOV &TA0R,X \ | | get new RC5_period value
17845 REPEAT \ ----> loop back --+ |
17846 \ ------------------------------\ |
17847 \ RC5_SampleEndOf: \ <---------------------+
17848 \ ------------------------------\
17849 BIC #$30,&TA0CTL \ stop timer_A0
17850 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
17851 \ ******************************\
17852 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17853 \ ******************************\
17854 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
17855 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
17856 XOR IP,X \ (new XOR old) Toggle bit (13)
17857 BIT #BIT13,X \ X(13) = New_RC5_command
17858 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
17860 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
17861 \ ******************************\
17862 \ RC5_ComputeNewRC5word \
17863 \ ******************************\
17865 MOV &BASE,2(PSP) \ save variable BASE before use
17866 MOV TOS,0(PSP) \ save TOS before use
17867 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
17868 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
17869 \ ******************************\
17870 \ RC5_ComputeC6bit \
17871 \ ******************************\
17872 BIT #$4000,IP \ test /C6 bit in IP
17873 0= IF BIS #$40,TOS \ set C6 bit in S
17874 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
17875 \ ******************************\
17876 \ RC5_CommandByteIsDone \ RC5_code --
17877 \ ******************************\
17879 \ ------------------------------\
17880 \ Display IR_RC5 code \
17881 \ ------------------------------\
17882 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
17883 \ ------------------------------\
17884 LO2HI \ switch from assembler to FORTH
17885 ['] LCD_CLEAR IS CR \ redirects CR
17886 ['] LCD_WrC IS EMIT \ redirects EMIT
17887 $10 BASE ! \ change BASE to hexadecimal
17888 CR ." $" 2 U.R \ print IR_RC5 code
17889 ['] (CR) IS CR \ restore CR
17890 ['] (EMIT) IS EMIT \ restore EMIT
17891 HI2LO \ switch from FORTH to assembler
17892 \ ------------------------------\
17893 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
17894 \ ------------------------------\
17895 MOV @PSP+,&BASE \ restore variable BASE
17896 RETI \ CPU is ON, GIE is OFF
17901 \ ------------------------------\
17902 \ TB0CTL = %0000 0010 1001 0100\$3C0
17903 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17904 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17905 \ -- \ID input divider \ 10 = /4
17906 \ -- \MC Mode Control \ 01 = up to TB0CCR0
17907 \ - \TBCLR TimerB Clear
17910 \ --------------------------------\\
17911 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17912 \ -- \CM Capture Mode
17917 \ --- \OUTMOD \ 011 = set/reset
17923 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
17925 \ ------------------------------\
17926 \ set TimerB to make 50kHz PWM \
17927 \ ------------------------------\
17928 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17929 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
17930 \ ------------------------------\
17931 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17932 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
17933 \ ------------------------------\
17934 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17935 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
17936 \ ------------------------------\
17937 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17938 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
17939 \ ------------------------------\
17940 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17941 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
17942 \ ------------------------------\
17943 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
17944 \ ------------------------------\
17945 \ set TimerB to generate PWM for LCD_Vo
17946 \ ------------------------------\
17947 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
17948 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
17949 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17950 \ ------------------------------\
17951 BIS.B #LCDVo,&LCDVo_DIR \
17952 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
17953 \ ------------------------------\
17954 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17955 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17956 \ ------------------------------\
17957 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17958 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17959 \ ------------------------------\
17960 \ WDT interval init part \
17961 \ ------------------------------\
17962 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
17963 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
17964 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
17965 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
17966 \ ------------------------------\
17968 \ ------------------------------\
17969 BIS.B #RC5,&IR_IE \ enable RC5_Int
17970 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17971 \ ------------------------------\
17972 \ init interrupt vectors
17973 \ ------------------------------\
17974 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
17975 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17976 \ ------------------------------\
17977 \ define LPM mode for ACCEPT \
17978 \ ------------------------------\
17979 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17980 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17981 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17983 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
17985 \ ------------------------------\
17987 \ ------------------------------\
17988 $03E8 20_US \ 1- wait 20 ms
17989 $03 TOP_LCD \ 2- send DB5=DB4=1
17990 $CD 20_US \ 3- wait 4,1 ms
17991 $03 TOP_LCD \ 4- send again DB5=DB4=1
17992 $5 20_US \ 5- wait 0,1 ms
17993 $03 TOP_LCD \ 6- send again again DB5=DB4=1
17994 $2 20_US \ wait 40 us = LCD cycle
17995 $02 TOP_LCD \ 7- send DB5=1 DB4=0
17996 $2 20_US \ wait 40 us = LCD cycle
17997 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17998 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17999 LCD_Clear \ 10- "LCD_Clear"
18000 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18001 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18002 LCD_Clear \ 10- "LCD_Clear"
18003 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18004 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18006 ['] (CR) IS CR \ ' (CR) is CR
18007 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
18009 ." RC5toLCD is running. Type STOP to quit"
18010 \ NOECHO \ uncomment to run this app without terminal connexion
18011 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
18012 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
18016 : STOP \ stops multitasking, must to be used before downloading app
18017 ['] (WARM) IS WARM \ remove START app from FORTH init process
18018 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
18026 CODE MAX \ n1 n2 -- n3 signed maximum
18027 CMP @PSP,TOS \ n2-n1
18028 S< ?GOTO FW1 \ n2<n1
18034 CODE MIN \ n1 n2 -- n3 signed minimum
18035 CMP @PSP,TOS \ n2-n1
18036 S< ?GOTO BW1 \ n2<n1
18042 : U.R \ u n -- display u unsigned in n width (n >= 2)
18044 R> OVER - 0 MAX SPACES TYPE
18048 CODE 20_US \ n -- n * 20 us
18049 BEGIN \ 3 cycles loop + 6~
18050 \ MOV #5,W \ 3 MCLK = 1 MHz
18051 \ MOV #23,W \ 3 MCLK = 4 MHz
18052 MOV #51,W \ 3 MCLK = 8 MHz
18053 \ MOV #104,W \ 3 MCLK = 16 MHz
18054 \ MOV #158,W \ 3 MCLK = 24 MHz
18055 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
18065 CODE TOP_LCD \ LCD Sample
18066 \ \ if write : %xxxxWWWW --
18067 \ \ if read : -- %0000RRRR
18068 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18069 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18070 0= IF \ write LCD bits pattern
18071 AND.B #LCD_DB,TOS \
18072 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18073 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18076 THEN \ read LCD bits pattern
18079 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18080 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18081 AND.B #LCD_DB,TOS \
18086 CODE LCD_W \ byte -- write byte to LCD
18088 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18089 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18090 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18091 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18092 COLON \ high level word starts here
18093 TOP_LCD 2 20_US \ write high nibble first
18098 CODE LCD_WrC \ char -- Write Char
18099 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18104 CODE LCD_WrF \ func -- Write Fonction
18105 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18111 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
18116 $02 LCD_WrF 100 20_us
18120 \ : LCD_Entry_set $04 OR LCD_WrF ;
18122 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
18124 \ : LCD_Display_Shift $10 OR LCD_WrF ;
18126 \ : LCD_Fn_Set $20 OR LCD_WrF ;
18128 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
18130 \ : LCD_Goto $80 OR LCD_WrF ;
18132 \ CODE LCD_R \ -- byte read byte from LCD
18133 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18134 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18135 \ COLON \ starts a FORTH word
18136 \ TOP_LCD 2 20_us \ -- %0000HHHH
18137 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18138 \ HI2LO \ switch from FORTH to assembler
18139 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18140 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18141 \ MOV @RSP+,IP \ restore IP saved by COLON
18146 \ CODE LCD_RdS \ -- status Read Status
18147 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18152 \ CODE LCD_RdC \ -- char Read Char
18153 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18158 \ -------------+------+------+------+------++---+---+---+---+---------+
18159 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
18160 \ -------------+------+------+------+------++---+---+---+---+---------+
18161 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
18162 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
18163 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
18164 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
18165 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
18166 \ -------------+------+------+------+------++---+---+---+---+---------+
18169 \ ******************************\
18170 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18171 \ ******************************\
18172 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
18173 \ ------------------------------\
18174 \ define LPM mode for ACCEPT \
18175 \ ------------------------------\
18176 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18177 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18178 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18179 BIT.B #SW2,&SW2_IN \ test switch S2
18180 0= IF \ case of switch S2 pressed
18181 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
18183 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
18186 BIT.B #SW1,&SW1_IN \ test switch S1 input
18187 0= IF \ case of Switch S1 pressed
18188 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
18190 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
18194 RETI \ CPU is ON, GIE is OFF
18199 \ ------------------------------\
18200 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18201 \ ******************************\
18202 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18203 \ ******************************\
18204 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18205 \ \ SMclock = 8|16|24 MHz
18206 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
18207 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
18208 \ \ SR(9)=new Toggle bit memory (ADD on)
18209 \ ------------------------------\
18210 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
18211 \ ------------------------------\
18212 \ define LPM mode for ACCEPT \
18213 \ ------------------------------\
18214 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18215 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18216 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18217 \ ------------------------------\
18218 \ RC5_FirstStartBitHalfCycle: \
18219 \ ------------------------------\
18220 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
18221 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
18222 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
18223 MOV #1778,X \ RC5_Period in us
18224 MOV #14,W \ count of loop
18226 \ ------------------------------\
18227 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
18228 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
18229 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
18230 \ RC5_Compute_3/4_Period: \ |
18231 RRUM #1,X \ X=1/2 cycle |
18235 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
18236 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
18238 \ ------------------------------\
18239 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
18240 \ ------------------------------\
18241 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18242 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
18243 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18244 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18245 SUB #1,W \ decrement count loop
18246 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
18247 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18248 0<> WHILE \ ----> out of loop ----+
18249 \ RC5_compute_7/4_Time_out: \ |
18250 ADD X,Y \ | out of bound = 7/4 period
18251 \ RC5_WaitHalfCycleP1.2_IFG: \ |
18253 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
18254 0>= IF \ | if cycle time out of bound
18255 BIC #$30,&TA0CTL \ | stop timer_A0
18256 RETI \ | then quit to do nothing
18258 \ ------------------------------\ |
18259 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
18261 MOV &TA0R,X \ | | get new RC5_period value
18262 REPEAT \ ----> loop back --+ |
18263 \ ------------------------------\ |
18264 \ RC5_SampleEndOf: \ <---------------------+
18265 \ ------------------------------\
18266 BIC #$30,&TA0CTL \ stop timer_A0
18267 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
18268 \ ******************************\
18269 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
18270 \ ******************************\
18271 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
18272 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
18273 XOR IP,X \ (new XOR old) Toggle bit (13)
18274 BIT #BIT13,X \ X(13) = New_RC5_command
18275 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
18277 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
18278 \ ******************************\
18279 \ RC5_ComputeNewRC5word \
18280 \ ******************************\
18282 MOV &BASE,2(PSP) \ save variable BASE before use
18283 MOV TOS,0(PSP) \ save TOS before use
18284 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
18285 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
18286 \ ******************************\
18287 \ RC5_ComputeC6bit \
18288 \ ******************************\
18289 BIT #$4000,IP \ test /C6 bit in IP
18290 0= IF BIS #$40,TOS \ set C6 bit in S
18291 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
18292 \ ******************************\
18293 \ RC5_CommandByteIsDone \ RC5_code --
18294 \ ******************************\
18296 \ ------------------------------\
18297 \ Display IR_RC5 code \
18298 \ ------------------------------\
18299 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
18300 \ ------------------------------\
18301 LO2HI \ switch from assembler to FORTH
18302 ['] LCD_CLEAR IS CR \ redirects CR
18303 ['] LCD_WrC IS EMIT \ redirects EMIT
18304 $10 BASE ! \ change BASE to hexadecimal
18305 CR ." $" 2 U.R \ print IR_RC5 code
18306 ['] (CR) IS CR \ restore CR
18307 ['] (EMIT) IS EMIT \ restore EMIT
18308 HI2LO \ switch from FORTH to assembler
18309 \ ------------------------------\
18310 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
18311 \ ------------------------------\
18312 MOV @PSP+,&BASE \ restore variable BASE
18313 RETI \ CPU is ON, GIE is OFF
18318 \ ------------------------------\
18319 \ TB0CTL = %0000 0010 1001 0100\$3C0
18320 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18321 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18322 \ -- \ID input divider \ 10 = /4
18323 \ -- \MC Mode Control \ 01 = up to TB0CCR0
18324 \ - \TBCLR TimerB Clear
18327 \ --------------------------------\\
18328 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18329 \ -- \CM Capture Mode
18334 \ --- \OUTMOD \ 011 = set/reset
18340 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
18342 \ ------------------------------\
18343 \ set TimerB to make 50kHz PWM \
18344 \ ------------------------------\
18345 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
18346 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
18347 \ ------------------------------\
18348 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
18349 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
18350 \ ------------------------------\
18351 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18352 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
18353 \ ------------------------------\
18354 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18355 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
18356 \ ------------------------------\
18357 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18358 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
18359 \ ------------------------------\
18360 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
18361 \ ------------------------------\
18362 \ set TimerB to generate PWM for LCD_Vo
18363 \ ------------------------------\
18364 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
18365 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
18366 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18367 \ ------------------------------\
18368 BIS.B #LCDVo,&LCDVo_DIR \
18369 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
18370 \ ------------------------------\
18371 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18372 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18373 \ ------------------------------\
18374 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18375 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18376 \ ------------------------------\
18377 \ WDT interval init part \
18378 \ ------------------------------\
18379 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
18380 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
18381 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
18382 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
18383 \ ------------------------------\
18385 \ ------------------------------\
18386 BIS.B #RC5,&IR_IE \ enable RC5_Int
18387 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18388 \ ------------------------------\
18389 \ init interrupt vectors
18390 \ ------------------------------\
18391 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
18392 MOV #RC5_INT,&IR_Vec \ init interrupt vector
18393 \ ------------------------------\
18394 \ define LPM mode for ACCEPT \
18395 \ ------------------------------\
18396 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18397 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18398 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18400 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
18402 \ ------------------------------\
18404 \ ------------------------------\
18405 $03E8 20_US \ 1- wait 20 ms
18406 $03 TOP_LCD \ 2- send DB5=DB4=1
18407 $CD 20_US \ 3- wait 4,1 ms
18408 $03 TOP_LCD \ 4- send again DB5=DB4=1
18409 $5 20_US \ 5- wait 0,1 ms
18410 $03 TOP_LCD \ 6- send again again DB5=DB4=1
18411 $2 20_US \ wait 40 us = LCD cycle
18412 $02 TOP_LCD \ 7- send DB5=1 DB4=0
18413 $2 20_US \ wait 40 us = LCD cycle
18414 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18415 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18416 LCD_Clear \ 10- "LCD_Clear"
18417 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18418 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18419 LCD_Clear \ 10- "LCD_Clear"
18420 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18421 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18423 ['] (CR) IS CR \ ' (CR) is CR
18424 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
18426 ." RC5toLCD is running. Type STOP to quit"
18427 \ NOECHO \ uncomment to run this app without terminal connexion
18428 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
18429 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
18433 : STOP \ stops multitasking, must to be used before downloading app
18434 ['] (WARM) IS WARM \ remove START app from FORTH init process
18435 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
18443 CODE MAX \ n1 n2 -- n3 signed maximum
18444 CMP @PSP,TOS \ n2-n1
18445 S< ?GOTO FW1 \ n2<n1
18451 CODE MIN \ n1 n2 -- n3 signed minimum
18452 CMP @PSP,TOS \ n2-n1
18453 S< ?GOTO BW1 \ n2<n1
18459 : U.R \ u n -- display u unsigned in n width (n >= 2)
18461 R> OVER - 0 MAX SPACES TYPE
18465 CODE 20_US \ n -- n * 20 us
18466 BEGIN \ 3 cycles loop + 6~
18467 \ MOV #5,W \ 3 MCLK = 1 MHz
18468 \ MOV #23,W \ 3 MCLK = 4 MHz
18469 MOV #51,W \ 3 MCLK = 8 MHz
18470 \ MOV #104,W \ 3 MCLK = 16 MHz
18471 \ MOV #158,W \ 3 MCLK = 24 MHz
18472 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
18482 CODE TOP_LCD \ LCD Sample
18483 \ \ if write : %xxxxWWWW --
18484 \ \ if read : -- %0000RRRR
18485 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18486 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18487 0= IF \ write LCD bits pattern
18488 AND.B #LCD_DB,TOS \
18489 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18490 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18493 THEN \ read LCD bits pattern
18496 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18497 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18498 AND.B #LCD_DB,TOS \
18503 CODE LCD_W \ byte -- write byte to LCD
18505 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18506 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18507 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18508 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18509 COLON \ high level word starts here
18510 TOP_LCD 2 20_US \ write high nibble first
18515 CODE LCD_WrC \ char -- Write Char
18516 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18521 CODE LCD_WrF \ func -- Write Fonction
18522 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18528 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
18533 $02 LCD_WrF 100 20_us
18537 \ : LCD_Entry_set $04 OR LCD_WrF ;
18539 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
18541 \ : LCD_Display_Shift $10 OR LCD_WrF ;
18543 \ : LCD_Fn_Set $20 OR LCD_WrF ;
18545 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
18547 \ : LCD_Goto $80 OR LCD_WrF ;
18549 \ CODE LCD_R \ -- byte read byte from LCD
18550 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18551 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18552 \ COLON \ starts a FORTH word
18553 \ TOP_LCD 2 20_us \ -- %0000HHHH
18554 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18555 \ HI2LO \ switch from FORTH to assembler
18556 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18557 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18558 \ MOV @RSP+,IP \ restore IP saved by COLON
18563 \ CODE LCD_RdS \ -- status Read Status
18564 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18569 \ CODE LCD_RdC \ -- char Read Char
18570 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18575 \ -------------+------+------+------+------++---+---+---+---+---------+
18576 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
18577 \ -------------+------+------+------+------++---+---+---+---+---------+
18578 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
18579 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
18580 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
18581 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
18582 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
18583 \ -------------+------+------+------+------++---+---+---+---+---------+
18586 \ ******************************\
18587 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18588 \ ******************************\
18589 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
18590 \ ------------------------------\
18591 \ define LPM mode for ACCEPT \
18592 \ ------------------------------\
18593 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18594 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18595 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18596 BIT.B #SW2,&SW2_IN \ test switch S2
18597 0= IF \ case of switch S2 pressed
18598 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
18600 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
18603 BIT.B #SW1,&SW1_IN \ test switch S1 input
18604 0= IF \ case of Switch S1 pressed
18605 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
18607 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
18611 RETI \ CPU is ON, GIE is OFF
18616 \ ------------------------------\
18617 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18618 \ ******************************\
18619 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18620 \ ******************************\
18621 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18622 \ \ SMclock = 8|16|24 MHz
18623 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
18624 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
18625 \ \ SR(9)=new Toggle bit memory (ADD on)
18626 \ ------------------------------\
18627 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
18628 \ ------------------------------\
18629 \ define LPM mode for ACCEPT \
18630 \ ------------------------------\
18631 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18632 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18633 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18634 \ ------------------------------\
18635 \ RC5_FirstStartBitHalfCycle: \
18636 \ ------------------------------\
18637 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
18638 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
18639 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
18640 MOV #1778,X \ RC5_Period in us
18641 MOV #14,W \ count of loop
18643 \ ------------------------------\
18644 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
18645 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
18646 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
18647 \ RC5_Compute_3/4_Period: \ |
18648 RRUM #1,X \ X=1/2 cycle |
18652 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
18653 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
18655 \ ------------------------------\
18656 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
18657 \ ------------------------------\
18658 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18659 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
18660 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18661 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18662 SUB #1,W \ decrement count loop
18663 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
18664 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18665 0<> WHILE \ ----> out of loop ----+
18666 \ RC5_compute_7/4_Time_out: \ |
18667 ADD X,Y \ | out of bound = 7/4 period
18668 \ RC5_WaitHalfCycleP1.2_IFG: \ |
18670 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
18671 0>= IF \ | if cycle time out of bound
18672 BIC #$30,&TA0CTL \ | stop timer_A0
18673 RETI \ | then quit to do nothing
18675 \ ------------------------------\ |
18676 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
18678 MOV &TA0R,X \ | | get new RC5_period value
18679 REPEAT \ ----> loop back --+ |
18680 \ ------------------------------\ |
18681 \ RC5_SampleEndOf: \ <---------------------+
18682 \ ------------------------------\
18683 BIC #$30,&TA0CTL \ stop timer_A0
18684 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
18685 \ ******************************\
18686 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
18687 \ ******************************\
18688 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
18689 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
18690 XOR IP,X \ (new XOR old) Toggle bit (13)
18691 BIT #BIT13,X \ X(13) = New_RC5_command
18692 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
18694 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
18695 \ ******************************\
18696 \ RC5_ComputeNewRC5word \
18697 \ ******************************\
18699 MOV &BASE,2(PSP) \ save variable BASE before use
18700 MOV TOS,0(PSP) \ save TOS before use
18701 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
18702 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
18703 \ ******************************\
18704 \ RC5_ComputeC6bit \
18705 \ ******************************\
18706 BIT #$4000,IP \ test /C6 bit in IP
18707 0= IF BIS #$40,TOS \ set C6 bit in S
18708 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
18709 \ ******************************\
18710 \ RC5_CommandByteIsDone \ RC5_code --
18711 \ ******************************\
18713 \ ------------------------------\
18714 \ Display IR_RC5 code \
18715 \ ------------------------------\
18716 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
18717 \ ------------------------------\
18718 LO2HI \ switch from assembler to FORTH
18719 ['] LCD_CLEAR IS CR \ redirects CR
18720 ['] LCD_WrC IS EMIT \ redirects EMIT
18721 $10 BASE ! \ change BASE to hexadecimal
18722 CR ." $" 2 U.R \ print IR_RC5 code
18723 ['] (CR) IS CR \ restore CR
18724 ['] (EMIT) IS EMIT \ restore EMIT
18725 HI2LO \ switch from FORTH to assembler
18726 \ ------------------------------\
18727 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
18728 \ ------------------------------\
18729 MOV @PSP+,&BASE \ restore variable BASE
18730 RETI \ CPU is ON, GIE is OFF
18735 \ ------------------------------\
18736 \ TB0CTL = %0000 0010 1001 0100\$3C0
18737 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18738 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18739 \ -- \ID input divider \ 10 = /4
18740 \ -- \MC Mode Control \ 01 = up to TB0CCR0
18741 \ - \TBCLR TimerB Clear
18744 \ --------------------------------\\
18745 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18746 \ -- \CM Capture Mode
18751 \ --- \OUTMOD \ 011 = set/reset
18757 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
18759 \ ------------------------------\
18760 \ set TimerB to make 50kHz PWM \
18761 \ ------------------------------\
18762 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
18763 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
18764 \ ------------------------------\
18765 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
18766 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
18767 \ ------------------------------\
18768 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18769 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
18770 \ ------------------------------\
18771 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18772 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
18773 \ ------------------------------\
18774 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18775 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
18776 \ ------------------------------\
18777 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
18778 \ ------------------------------\
18779 \ set TimerB to generate PWM for LCD_Vo
18780 \ ------------------------------\
18781 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
18782 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
18783 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18784 \ ------------------------------\
18785 BIS.B #LCDVo,&LCDVo_DIR \
18786 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
18787 \ ------------------------------\
18788 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18789 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18790 \ ------------------------------\
18791 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18792 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18793 \ ------------------------------\
18794 \ WDT interval init part \
18795 \ ------------------------------\
18796 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
18797 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
18798 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
18799 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
18800 \ ------------------------------\
18802 \ ------------------------------\
18803 BIS.B #RC5,&IR_IE \ enable RC5_Int
18804 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18805 \ ------------------------------\
18806 \ init interrupt vectors
18807 \ ------------------------------\
18808 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
18809 MOV #RC5_INT,&IR_Vec \ init interrupt vector
18810 \ ------------------------------\
18811 \ define LPM mode for ACCEPT \
18812 \ ------------------------------\
18813 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18814 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18815 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18817 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
18819 \ ------------------------------\
18821 \ ------------------------------\
18822 $03E8 20_US \ 1- wait 20 ms
18823 $03 TOP_LCD \ 2- send DB5=DB4=1
18824 $CD 20_US \ 3- wait 4,1 ms
18825 $03 TOP_LCD \ 4- send again DB5=DB4=1
18826 $5 20_US \ 5- wait 0,1 ms
18827 $03 TOP_LCD \ 6- send again again DB5=DB4=1
18828 $2 20_US \ wait 40 us = LCD cycle
18829 $02 TOP_LCD \ 7- send DB5=1 DB4=0
18830 $2 20_US \ wait 40 us = LCD cycle
18831 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18832 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18833 LCD_Clear \ 10- "LCD_Clear"
18834 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18835 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18836 LCD_Clear \ 10- "LCD_Clear"
18837 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18838 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18840 ['] (CR) IS CR \ ' (CR) is CR
18841 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
18843 ." RC5toLCD is running. Type STOP to quit"
18844 \ NOECHO \ uncomment to run this app without terminal connexion
18845 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
18846 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
18850 : STOP \ stops multitasking, must to be used before downloading app
18851 ['] (WARM) IS WARM \ remove START app from FORTH init process
18852 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
18860 CODE MAX \ n1 n2 -- n3 signed maximum
18861 CMP @PSP,TOS \ n2-n1
18862 S< ?GOTO FW1 \ n2<n1
18868 CODE MIN \ n1 n2 -- n3 signed minimum
18869 CMP @PSP,TOS \ n2-n1
18870 S< ?GOTO BW1 \ n2<n1
18876 : U.R \ u n -- display u unsigned in n width (n >= 2)
18878 R> OVER - 0 MAX SPACES TYPE
18882 CODE 20_US \ n -- n * 20 us
18883 BEGIN \ 3 cycles loop + 6~
18884 \ MOV #5,W \ 3 MCLK = 1 MHz
18885 \ MOV #23,W \ 3 MCLK = 4 MHz
18886 MOV #51,W \ 3 MCLK = 8 MHz
18887 \ MOV #104,W \ 3 MCLK = 16 MHz
18888 \ MOV #158,W \ 3 MCLK = 24 MHz
18889 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
18899 CODE TOP_LCD \ LCD Sample
18900 \ \ if write : %xxxxWWWW --
18901 \ \ if read : -- %0000RRRR
18902 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18903 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18904 0= IF \ write LCD bits pattern
18905 AND.B #LCD_DB,TOS \
18906 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18907 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18910 THEN \ read LCD bits pattern
18913 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18914 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18915 AND.B #LCD_DB,TOS \
18920 CODE LCD_W \ byte -- write byte to LCD
18922 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18923 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18924 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18925 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18926 COLON \ high level word starts here
18927 TOP_LCD 2 20_US \ write high nibble first
18932 CODE LCD_WrC \ char -- Write Char
18933 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18938 CODE LCD_WrF \ func -- Write Fonction
18939 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18945 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
18950 $02 LCD_WrF 100 20_us
18954 \ : LCD_Entry_set $04 OR LCD_WrF ;
18956 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
18958 \ : LCD_Display_Shift $10 OR LCD_WrF ;
18960 \ : LCD_Fn_Set $20 OR LCD_WrF ;
18962 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
18964 \ : LCD_Goto $80 OR LCD_WrF ;
18966 \ CODE LCD_R \ -- byte read byte from LCD
18967 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18968 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18969 \ COLON \ starts a FORTH word
18970 \ TOP_LCD 2 20_us \ -- %0000HHHH
18971 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18972 \ HI2LO \ switch from FORTH to assembler
18973 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18974 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18975 \ MOV @RSP+,IP \ restore IP saved by COLON
18980 \ CODE LCD_RdS \ -- status Read Status
18981 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18986 \ CODE LCD_RdC \ -- char Read Char
18987 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18992 \ -------------+------+------+------+------++---+---+---+---+---------+
18993 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
18994 \ -------------+------+------+------+------++---+---+---+---+---------+
18995 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
18996 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
18997 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
18998 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
18999 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
19000 \ -------------+------+------+------+------++---+---+---+---+---------+
19003 \ ******************************\
19004 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19005 \ ******************************\
19006 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
19007 \ ------------------------------\
19008 \ define LPM mode for ACCEPT \
19009 \ ------------------------------\
19010 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19011 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19012 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19013 BIT.B #SW2,&SW2_IN \ test switch S2
19014 0= IF \ case of switch S2 pressed
19015 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
19017 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
19020 BIT.B #SW1,&SW1_IN \ test switch S1 input
19021 0= IF \ case of Switch S1 pressed
19022 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
19024 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
19028 RETI \ CPU is ON, GIE is OFF
19033 \ ------------------------------\
19034 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19035 \ ******************************\
19036 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19037 \ ******************************\
19038 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19039 \ \ SMclock = 8|16|24 MHz
19040 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
19041 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
19042 \ \ SR(9)=new Toggle bit memory (ADD on)
19043 \ ------------------------------\
19044 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
19045 \ ------------------------------\
19046 \ define LPM mode for ACCEPT \
19047 \ ------------------------------\
19048 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19049 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19050 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19051 \ ------------------------------\
19052 \ RC5_FirstStartBitHalfCycle: \
19053 \ ------------------------------\
19054 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
19055 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
19056 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
19057 MOV #1778,X \ RC5_Period in us
19058 MOV #14,W \ count of loop
19060 \ ------------------------------\
19061 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
19062 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
19063 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
19064 \ RC5_Compute_3/4_Period: \ |
19065 RRUM #1,X \ X=1/2 cycle |
19069 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
19070 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
19072 \ ------------------------------\
19073 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
19074 \ ------------------------------\
19075 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19076 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
19077 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19078 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19079 SUB #1,W \ decrement count loop
19080 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
19081 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19082 0<> WHILE \ ----> out of loop ----+
19083 \ RC5_compute_7/4_Time_out: \ |
19084 ADD X,Y \ | out of bound = 7/4 period
19085 \ RC5_WaitHalfCycleP1.2_IFG: \ |
19087 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
19088 0>= IF \ | if cycle time out of bound
19089 BIC #$30,&TA0CTL \ | stop timer_A0
19090 RETI \ | then quit to do nothing
19092 \ ------------------------------\ |
19093 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
19095 MOV &TA0R,X \ | | get new RC5_period value
19096 REPEAT \ ----> loop back --+ |
19097 \ ------------------------------\ |
19098 \ RC5_SampleEndOf: \ <---------------------+
19099 \ ------------------------------\
19100 BIC #$30,&TA0CTL \ stop timer_A0
19101 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
19102 \ ******************************\
19103 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19104 \ ******************************\
19105 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
19106 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
19107 XOR IP,X \ (new XOR old) Toggle bit (13)
19108 BIT #BIT13,X \ X(13) = New_RC5_command
19109 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
19111 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
19112 \ ******************************\
19113 \ RC5_ComputeNewRC5word \
19114 \ ******************************\
19116 MOV &BASE,2(PSP) \ save variable BASE before use
19117 MOV TOS,0(PSP) \ save TOS before use
19118 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
19119 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
19120 \ ******************************\
19121 \ RC5_ComputeC6bit \
19122 \ ******************************\
19123 BIT #$4000,IP \ test /C6 bit in IP
19124 0= IF BIS #$40,TOS \ set C6 bit in S
19125 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
19126 \ ******************************\
19127 \ RC5_CommandByteIsDone \ RC5_code --
19128 \ ******************************\
19130 \ ------------------------------\
19131 \ Display IR_RC5 code \
19132 \ ------------------------------\
19133 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
19134 \ ------------------------------\
19135 LO2HI \ switch from assembler to FORTH
19136 ['] LCD_CLEAR IS CR \ redirects CR
19137 ['] LCD_WrC IS EMIT \ redirects EMIT
19138 $10 BASE ! \ change BASE to hexadecimal
19139 CR ." $" 2 U.R \ print IR_RC5 code
19140 ['] (CR) IS CR \ restore CR
19141 ['] (EMIT) IS EMIT \ restore EMIT
19142 HI2LO \ switch from FORTH to assembler
19143 \ ------------------------------\
19144 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
19145 \ ------------------------------\
19146 MOV @PSP+,&BASE \ restore variable BASE
19147 RETI \ CPU is ON, GIE is OFF
19152 \ ------------------------------\
19153 \ TB0CTL = %0000 0010 1001 0100\$3C0
19154 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19155 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19156 \ -- \ID input divider \ 10 = /4
19157 \ -- \MC Mode Control \ 01 = up to TB0CCR0
19158 \ - \TBCLR TimerB Clear
19161 \ --------------------------------\\
19162 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19163 \ -- \CM Capture Mode
19168 \ --- \OUTMOD \ 011 = set/reset
19174 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
19176 \ ------------------------------\
19177 \ set TimerB to make 50kHz PWM \
19178 \ ------------------------------\
19179 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
19180 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
19181 \ ------------------------------\
19182 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
19183 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
19184 \ ------------------------------\
19185 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19186 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
19187 \ ------------------------------\
19188 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19189 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
19190 \ ------------------------------\
19191 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19192 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
19193 \ ------------------------------\
19194 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
19195 \ ------------------------------\
19196 \ set TimerB to generate PWM for LCD_Vo
19197 \ ------------------------------\
19198 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
19199 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
19200 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19201 \ ------------------------------\
19202 BIS.B #LCDVo,&LCDVo_DIR \
19203 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
19204 \ ------------------------------\
19205 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19206 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19207 \ ------------------------------\
19208 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19209 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19210 \ ------------------------------\
19211 \ WDT interval init part \
19212 \ ------------------------------\
19213 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
19214 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
19215 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
19216 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
19217 \ ------------------------------\
19219 \ ------------------------------\
19220 BIS.B #RC5,&IR_IE \ enable RC5_Int
19221 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19222 \ ------------------------------\
19223 \ init interrupt vectors
19224 \ ------------------------------\
19225 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
19226 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19227 \ ------------------------------\
19228 \ define LPM mode for ACCEPT \
19229 \ ------------------------------\
19230 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19231 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19232 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19234 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
19236 \ ------------------------------\
19238 \ ------------------------------\
19239 $03E8 20_US \ 1- wait 20 ms
19240 $03 TOP_LCD \ 2- send DB5=DB4=1
19241 $CD 20_US \ 3- wait 4,1 ms
19242 $03 TOP_LCD \ 4- send again DB5=DB4=1
19243 $5 20_US \ 5- wait 0,1 ms
19244 $03 TOP_LCD \ 6- send again again DB5=DB4=1
19245 $2 20_US \ wait 40 us = LCD cycle
19246 $02 TOP_LCD \ 7- send DB5=1 DB4=0
19247 $2 20_US \ wait 40 us = LCD cycle
19248 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19249 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19250 LCD_Clear \ 10- "LCD_Clear"
19251 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19252 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19253 LCD_Clear \ 10- "LCD_Clear"
19254 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19255 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19257 ['] (CR) IS CR \ ' (CR) is CR
19258 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
19260 ." RC5toLCD is running. Type STOP to quit"
19261 \ NOECHO \ uncomment to run this app without terminal connexion
19262 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
19263 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
19267 : STOP \ stops multitasking, must to be used before downloading app
19268 ['] (WARM) IS WARM \ remove START app from FORTH init process
19269 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
19277 CODE MAX \ n1 n2 -- n3 signed maximum
19278 CMP @PSP,TOS \ n2-n1
19279 S< ?GOTO FW1 \ n2<n1
19285 CODE MIN \ n1 n2 -- n3 signed minimum
19286 CMP @PSP,TOS \ n2-n1
19287 S< ?GOTO BW1 \ n2<n1
19293 : U.R \ u n -- display u unsigned in n width (n >= 2)
19295 R> OVER - 0 MAX SPACES TYPE
19299 CODE 20_US \ n -- n * 20 us
19300 BEGIN \ 3 cycles loop + 6~
19301 \ MOV #5,W \ 3 MCLK = 1 MHz
19302 \ MOV #23,W \ 3 MCLK = 4 MHz
19303 MOV #51,W \ 3 MCLK = 8 MHz
19304 \ MOV #104,W \ 3 MCLK = 16 MHz
19305 \ MOV #158,W \ 3 MCLK = 24 MHz
19306 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
19316 CODE TOP_LCD \ LCD Sample
19317 \ \ if write : %xxxxWWWW --
19318 \ \ if read : -- %0000RRRR
19319 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19320 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19321 0= IF \ write LCD bits pattern
19322 AND.B #LCD_DB,TOS \
19323 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19324 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19327 THEN \ read LCD bits pattern
19330 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19331 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19332 AND.B #LCD_DB,TOS \
19337 CODE LCD_W \ byte -- write byte to LCD
19339 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
19340 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
19341 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19342 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19343 COLON \ high level word starts here
19344 TOP_LCD 2 20_US \ write high nibble first
19349 CODE LCD_WrC \ char -- Write Char
19350 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19355 CODE LCD_WrF \ func -- Write Fonction
19356 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19362 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
19367 $02 LCD_WrF 100 20_us
19371 \ : LCD_Entry_set $04 OR LCD_WrF ;
19373 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
19375 \ : LCD_Display_Shift $10 OR LCD_WrF ;
19377 \ : LCD_Fn_Set $20 OR LCD_WrF ;
19379 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
19381 \ : LCD_Goto $80 OR LCD_WrF ;
19383 \ CODE LCD_R \ -- byte read byte from LCD
19384 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19385 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19386 \ COLON \ starts a FORTH word
19387 \ TOP_LCD 2 20_us \ -- %0000HHHH
19388 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
19389 \ HI2LO \ switch from FORTH to assembler
19390 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
19391 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
19392 \ MOV @RSP+,IP \ restore IP saved by COLON
19397 \ CODE LCD_RdS \ -- status Read Status
19398 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19403 \ CODE LCD_RdC \ -- char Read Char
19404 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19409 \ -------------+------+------+------+------++---+---+---+---+---------+
19410 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
19411 \ -------------+------+------+------+------++---+---+---+---+---------+
19412 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
19413 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
19414 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
19415 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
19416 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
19417 \ -------------+------+------+------+------++---+---+---+---+---------+
19420 \ ******************************\
19421 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19422 \ ******************************\
19423 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
19424 \ ------------------------------\
19425 \ define LPM mode for ACCEPT \
19426 \ ------------------------------\
19427 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19428 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19429 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19430 BIT.B #SW2,&SW2_IN \ test switch S2
19431 0= IF \ case of switch S2 pressed
19432 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
19434 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
19437 BIT.B #SW1,&SW1_IN \ test switch S1 input
19438 0= IF \ case of Switch S1 pressed
19439 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
19441 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
19445 RETI \ CPU is ON, GIE is OFF
19450 \ ------------------------------\
19451 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19452 \ ******************************\
19453 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19454 \ ******************************\
19455 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19456 \ \ SMclock = 8|16|24 MHz
19457 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
19458 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
19459 \ \ SR(9)=new Toggle bit memory (ADD on)
19460 \ ------------------------------\
19461 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
19462 \ ------------------------------\
19463 \ define LPM mode for ACCEPT \
19464 \ ------------------------------\
19465 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19466 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19467 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19468 \ ------------------------------\
19469 \ RC5_FirstStartBitHalfCycle: \
19470 \ ------------------------------\
19471 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
19472 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
19473 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
19474 MOV #1778,X \ RC5_Period in us
19475 MOV #14,W \ count of loop
19477 \ ------------------------------\
19478 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
19479 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
19480 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
19481 \ RC5_Compute_3/4_Period: \ |
19482 RRUM #1,X \ X=1/2 cycle |
19486 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
19487 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
19489 \ ------------------------------\
19490 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
19491 \ ------------------------------\
19492 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19493 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
19494 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19495 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19496 SUB #1,W \ decrement count loop
19497 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
19498 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19499 0<> WHILE \ ----> out of loop ----+
19500 \ RC5_compute_7/4_Time_out: \ |
19501 ADD X,Y \ | out of bound = 7/4 period
19502 \ RC5_WaitHalfCycleP1.2_IFG: \ |
19504 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
19505 0>= IF \ | if cycle time out of bound
19506 BIC #$30,&TA0CTL \ | stop timer_A0
19507 RETI \ | then quit to do nothing
19509 \ ------------------------------\ |
19510 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
19512 MOV &TA0R,X \ | | get new RC5_period value
19513 REPEAT \ ----> loop back --+ |
19514 \ ------------------------------\ |
19515 \ RC5_SampleEndOf: \ <---------------------+
19516 \ ------------------------------\
19517 BIC #$30,&TA0CTL \ stop timer_A0
19518 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
19519 \ ******************************\
19520 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19521 \ ******************************\
19522 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
19523 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
19524 XOR IP,X \ (new XOR old) Toggle bit (13)
19525 BIT #BIT13,X \ X(13) = New_RC5_command
19526 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
19528 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
19529 \ ******************************\
19530 \ RC5_ComputeNewRC5word \
19531 \ ******************************\
19533 MOV &BASE,2(PSP) \ save variable BASE before use
19534 MOV TOS,0(PSP) \ save TOS before use
19535 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
19536 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
19537 \ ******************************\
19538 \ RC5_ComputeC6bit \
19539 \ ******************************\
19540 BIT #$4000,IP \ test /C6 bit in IP
19541 0= IF BIS #$40,TOS \ set C6 bit in S
19542 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
19543 \ ******************************\
19544 \ RC5_CommandByteIsDone \ RC5_code --
19545 \ ******************************\
19547 \ ------------------------------\
19548 \ Display IR_RC5 code \
19549 \ ------------------------------\
19550 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
19551 \ ------------------------------\
19552 LO2HI \ switch from assembler to FORTH
19553 ['] LCD_CLEAR IS CR \ redirects CR
19554 ['] LCD_WrC IS EMIT \ redirects EMIT
19555 $10 BASE ! \ change BASE to hexadecimal
19556 CR ." $" 2 U.R \ print IR_RC5 code
19557 ['] (CR) IS CR \ restore CR
19558 ['] (EMIT) IS EMIT \ restore EMIT
19559 HI2LO \ switch from FORTH to assembler
19560 \ ------------------------------\
19561 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
19562 \ ------------------------------\
19563 MOV @PSP+,&BASE \ restore variable BASE
19564 RETI \ CPU is ON, GIE is OFF
19569 \ ------------------------------\
19570 \ TB0CTL = %0000 0010 1001 0100\$3C0
19571 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19572 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19573 \ -- \ID input divider \ 10 = /4
19574 \ -- \MC Mode Control \ 01 = up to TB0CCR0
19575 \ - \TBCLR TimerB Clear
19578 \ --------------------------------\\
19579 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19580 \ -- \CM Capture Mode
19585 \ --- \OUTMOD \ 011 = set/reset
19591 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
19593 \ ------------------------------\
19594 \ set TimerB to make 50kHz PWM \
19595 \ ------------------------------\
19596 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
19597 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
19598 \ ------------------------------\
19599 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
19600 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
19601 \ ------------------------------\
19602 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19603 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
19604 \ ------------------------------\
19605 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19606 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
19607 \ ------------------------------\
19608 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19609 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
19610 \ ------------------------------\
19611 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
19612 \ ------------------------------\
19613 \ set TimerB to generate PWM for LCD_Vo
19614 \ ------------------------------\
19615 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
19616 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
19617 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19618 \ ------------------------------\
19619 BIS.B #LCDVo,&LCDVo_DIR \
19620 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
19621 \ ------------------------------\
19622 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19623 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19624 \ ------------------------------\
19625 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19626 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19627 \ ------------------------------\
19628 \ WDT interval init part \
19629 \ ------------------------------\
19630 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
19631 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
19632 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
19633 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
19634 \ ------------------------------\
19636 \ ------------------------------\
19637 BIS.B #RC5,&IR_IE \ enable RC5_Int
19638 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19639 \ ------------------------------\
19640 \ init interrupt vectors
19641 \ ------------------------------\
19642 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
19643 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19644 \ ------------------------------\
19645 \ define LPM mode for ACCEPT \
19646 \ ------------------------------\
19647 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19648 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19649 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19651 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
19653 \ ------------------------------\
19655 \ ------------------------------\
19656 $03E8 20_US \ 1- wait 20 ms
19657 $03 TOP_LCD \ 2- send DB5=DB4=1
19658 $CD 20_US \ 3- wait 4,1 ms
19659 $03 TOP_LCD \ 4- send again DB5=DB4=1
19660 $5 20_US \ 5- wait 0,1 ms
19661 $03 TOP_LCD \ 6- send again again DB5=DB4=1
19662 $2 20_US \ wait 40 us = LCD cycle
19663 $02 TOP_LCD \ 7- send DB5=1 DB4=0
19664 $2 20_US \ wait 40 us = LCD cycle
19665 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19666 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19667 LCD_Clear \ 10- "LCD_Clear"
19668 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19669 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19670 LCD_Clear \ 10- "LCD_Clear"
19671 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19672 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19674 ['] (CR) IS CR \ ' (CR) is CR
19675 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
19677 ." RC5toLCD is running. Type STOP to quit"
19678 \ NOECHO \ uncomment to run this app without terminal connexion
19679 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
19680 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
19684 : STOP \ stops multitasking, must to be used before downloading app
19685 ['] (WARM) IS WARM \ remove START app from FORTH init process
19686 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
19694 CODE MAX \ n1 n2 -- n3 signed maximum
19695 CMP @PSP,TOS \ n2-n1
19696 S< ?GOTO FW1 \ n2<n1
19702 CODE MIN \ n1 n2 -- n3 signed minimum
19703 CMP @PSP,TOS \ n2-n1
19704 S< ?GOTO BW1 \ n2<n1
19710 : U.R \ u n -- display u unsigned in n width (n >= 2)
19712 R> OVER - 0 MAX SPACES TYPE
19716 CODE 20_US \ n -- n * 20 us
19717 BEGIN \ 3 cycles loop + 6~
19718 \ MOV #5,W \ 3 MCLK = 1 MHz
19719 \ MOV #23,W \ 3 MCLK = 4 MHz
19720 MOV #51,W \ 3 MCLK = 8 MHz
19721 \ MOV #104,W \ 3 MCLK = 16 MHz
19722 \ MOV #158,W \ 3 MCLK = 24 MHz
19723 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
19733 CODE TOP_LCD \ LCD Sample
19734 \ \ if write : %xxxxWWWW --
19735 \ \ if read : -- %0000RRRR
19736 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19737 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19738 0= IF \ write LCD bits pattern
19739 AND.B #LCD_DB,TOS \
19740 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19741 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19744 THEN \ read LCD bits pattern
19747 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19748 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19749 AND.B #LCD_DB,TOS \
19754 CODE LCD_W \ byte -- write byte to LCD
19756 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
19757 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
19758 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19759 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19760 COLON \ high level word starts here
19761 TOP_LCD 2 20_US \ write high nibble first
19766 CODE LCD_WrC \ char -- Write Char
19767 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19772 CODE LCD_WrF \ func -- Write Fonction
19773 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19779 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
19784 $02 LCD_WrF 100 20_us
19788 \ : LCD_Entry_set $04 OR LCD_WrF ;
19790 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
19792 \ : LCD_Display_Shift $10 OR LCD_WrF ;
19794 \ : LCD_Fn_Set $20 OR LCD_WrF ;
19796 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
19798 \ : LCD_Goto $80 OR LCD_WrF ;
19800 \ CODE LCD_R \ -- byte read byte from LCD
19801 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19802 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19803 \ COLON \ starts a FORTH word
19804 \ TOP_LCD 2 20_us \ -- %0000HHHH
19805 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
19806 \ HI2LO \ switch from FORTH to assembler
19807 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
19808 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
19809 \ MOV @RSP+,IP \ restore IP saved by COLON
19814 \ CODE LCD_RdS \ -- status Read Status
19815 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19820 \ CODE LCD_RdC \ -- char Read Char
19821 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19826 \ -------------+------+------+------+------++---+---+---+---+---------+
19827 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
19828 \ -------------+------+------+------+------++---+---+---+---+---------+
19829 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
19830 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
19831 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
19832 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
19833 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
19834 \ -------------+------+------+------+------++---+---+---+---+---------+
19837 \ ******************************\
19838 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19839 \ ******************************\
19840 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
19841 \ ------------------------------\
19842 \ define LPM mode for ACCEPT \
19843 \ ------------------------------\
19844 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19845 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19846 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19847 BIT.B #SW2,&SW2_IN \ test switch S2
19848 0= IF \ case of switch S2 pressed
19849 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
19851 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
19854 BIT.B #SW1,&SW1_IN \ test switch S1 input
19855 0= IF \ case of Switch S1 pressed
19856 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
19858 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
19862 RETI \ CPU is ON, GIE is OFF
19867 \ ------------------------------\
19868 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19869 \ ******************************\
19870 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19871 \ ******************************\
19872 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19873 \ \ SMclock = 8|16|24 MHz
19874 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
19875 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
19876 \ \ SR(9)=new Toggle bit memory (ADD on)
19877 \ ------------------------------\
19878 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
19879 \ ------------------------------\
19880 \ define LPM mode for ACCEPT \
19881 \ ------------------------------\
19882 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19883 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19884 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19885 \ ------------------------------\
19886 \ RC5_FirstStartBitHalfCycle: \
19887 \ ------------------------------\
19888 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
19889 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
19890 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
19891 MOV #1778,X \ RC5_Period in us
19892 MOV #14,W \ count of loop
19894 \ ------------------------------\
19895 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
19896 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
19897 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
19898 \ RC5_Compute_3/4_Period: \ |
19899 RRUM #1,X \ X=1/2 cycle |
19903 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
19904 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
19906 \ ------------------------------\
19907 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
19908 \ ------------------------------\
19909 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19910 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
19911 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19912 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19913 SUB #1,W \ decrement count loop
19914 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
19915 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19916 0<> WHILE \ ----> out of loop ----+
19917 \ RC5_compute_7/4_Time_out: \ |
19918 ADD X,Y \ | out of bound = 7/4 period
19919 \ RC5_WaitHalfCycleP1.2_IFG: \ |
19921 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
19922 0>= IF \ | if cycle time out of bound
19923 BIC #$30,&TA0CTL \ | stop timer_A0
19924 RETI \ | then quit to do nothing
19926 \ ------------------------------\ |
19927 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
19929 MOV &TA0R,X \ | | get new RC5_period value
19930 REPEAT \ ----> loop back --+ |
19931 \ ------------------------------\ |
19932 \ RC5_SampleEndOf: \ <---------------------+
19933 \ ------------------------------\
19934 BIC #$30,&TA0CTL \ stop timer_A0
19935 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
19936 \ ******************************\
19937 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19938 \ ******************************\
19939 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
19940 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
19941 XOR IP,X \ (new XOR old) Toggle bit (13)
19942 BIT #BIT13,X \ X(13) = New_RC5_command
19943 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
19945 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
19946 \ ******************************\
19947 \ RC5_ComputeNewRC5word \
19948 \ ******************************\
19950 MOV &BASE,2(PSP) \ save variable BASE before use
19951 MOV TOS,0(PSP) \ save TOS before use
19952 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
19953 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
19954 \ ******************************\
19955 \ RC5_ComputeC6bit \
19956 \ ******************************\
19957 BIT #$4000,IP \ test /C6 bit in IP
19958 0= IF BIS #$40,TOS \ set C6 bit in S
19959 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
19960 \ ******************************\
19961 \ RC5_CommandByteIsDone \ RC5_code --
19962 \ ******************************\
19964 \ ------------------------------\
19965 \ Display IR_RC5 code \
19966 \ ------------------------------\
19967 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
19968 \ ------------------------------\
19969 LO2HI \ switch from assembler to FORTH
19970 ['] LCD_CLEAR IS CR \ redirects CR
19971 ['] LCD_WrC IS EMIT \ redirects EMIT
19972 $10 BASE ! \ change BASE to hexadecimal
19973 CR ." $" 2 U.R \ print IR_RC5 code
19974 ['] (CR) IS CR \ restore CR
19975 ['] (EMIT) IS EMIT \ restore EMIT
19976 HI2LO \ switch from FORTH to assembler
19977 \ ------------------------------\
19978 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
19979 \ ------------------------------\
19980 MOV @PSP+,&BASE \ restore variable BASE
19981 RETI \ CPU is ON, GIE is OFF
19986 \ ------------------------------\
19987 \ TB0CTL = %0000 0010 1001 0100\$3C0
19988 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19989 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19990 \ -- \ID input divider \ 10 = /4
19991 \ -- \MC Mode Control \ 01 = up to TB0CCR0
19992 \ - \TBCLR TimerB Clear
19995 \ --------------------------------\\
19996 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19997 \ -- \CM Capture Mode
20002 \ --- \OUTMOD \ 011 = set/reset
20008 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
20010 \ ------------------------------\
20011 \ set TimerB to make 50kHz PWM \
20012 \ ------------------------------\
20013 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20014 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
20015 \ ------------------------------\
20016 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20017 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
20018 \ ------------------------------\
20019 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20020 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
20021 \ ------------------------------\
20022 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20023 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
20024 \ ------------------------------\
20025 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20026 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
20027 \ ------------------------------\
20028 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
20029 \ ------------------------------\
20030 \ set TimerB to generate PWM for LCD_Vo
20031 \ ------------------------------\
20032 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
20033 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
20034 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20035 \ ------------------------------\
20036 BIS.B #LCDVo,&LCDVo_DIR \
20037 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
20038 \ ------------------------------\
20039 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20040 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20041 \ ------------------------------\
20042 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20043 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20044 \ ------------------------------\
20045 \ WDT interval init part \
20046 \ ------------------------------\
20047 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
20048 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
20049 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
20050 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
20051 \ ------------------------------\
20053 \ ------------------------------\
20054 BIS.B #RC5,&IR_IE \ enable RC5_Int
20055 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20056 \ ------------------------------\
20057 \ init interrupt vectors
20058 \ ------------------------------\
20059 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
20060 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20061 \ ------------------------------\
20062 \ define LPM mode for ACCEPT \
20063 \ ------------------------------\
20064 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20065 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20066 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20068 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
20070 \ ------------------------------\
20072 \ ------------------------------\
20073 $03E8 20_US \ 1- wait 20 ms
20074 $03 TOP_LCD \ 2- send DB5=DB4=1
20075 $CD 20_US \ 3- wait 4,1 ms
20076 $03 TOP_LCD \ 4- send again DB5=DB4=1
20077 $5 20_US \ 5- wait 0,1 ms
20078 $03 TOP_LCD \ 6- send again again DB5=DB4=1
20079 $2 20_US \ wait 40 us = LCD cycle
20080 $02 TOP_LCD \ 7- send DB5=1 DB4=0
20081 $2 20_US \ wait 40 us = LCD cycle
20082 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20083 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20084 LCD_Clear \ 10- "LCD_Clear"
20085 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20086 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20087 LCD_Clear \ 10- "LCD_Clear"
20088 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20089 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20091 ['] (CR) IS CR \ ' (CR) is CR
20092 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
20094 ." RC5toLCD is running. Type STOP to quit"
20095 \ NOECHO \ uncomment to run this app without terminal connexion
20096 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
20097 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
20101 : STOP \ stops multitasking, must to be used before downloading app
20102 ['] (WARM) IS WARM \ remove START app from FORTH init process
20103 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
20111 CODE MAX \ n1 n2 -- n3 signed maximum
20112 CMP @PSP,TOS \ n2-n1
20113 S< ?GOTO FW1 \ n2<n1
20119 CODE MIN \ n1 n2 -- n3 signed minimum
20120 CMP @PSP,TOS \ n2-n1
20121 S< ?GOTO BW1 \ n2<n1
20127 : U.R \ u n -- display u unsigned in n width (n >= 2)
20129 R> OVER - 0 MAX SPACES TYPE
20133 CODE 20_US \ n -- n * 20 us
20134 BEGIN \ 3 cycles loop + 6~
20135 \ MOV #5,W \ 3 MCLK = 1 MHz
20136 \ MOV #23,W \ 3 MCLK = 4 MHz
20137 MOV #51,W \ 3 MCLK = 8 MHz
20138 \ MOV #104,W \ 3 MCLK = 16 MHz
20139 \ MOV #158,W \ 3 MCLK = 24 MHz
20140 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
20150 CODE TOP_LCD \ LCD Sample
20151 \ \ if write : %xxxxWWWW --
20152 \ \ if read : -- %0000RRRR
20153 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20154 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20155 0= IF \ write LCD bits pattern
20156 AND.B #LCD_DB,TOS \
20157 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20158 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20161 THEN \ read LCD bits pattern
20164 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20165 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20166 AND.B #LCD_DB,TOS \
20171 CODE LCD_W \ byte -- write byte to LCD
20173 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
20174 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
20175 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20176 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20177 COLON \ high level word starts here
20178 TOP_LCD 2 20_US \ write high nibble first
20183 CODE LCD_WrC \ char -- Write Char
20184 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20189 CODE LCD_WrF \ func -- Write Fonction
20190 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20196 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
20201 $02 LCD_WrF 100 20_us
20205 \ : LCD_Entry_set $04 OR LCD_WrF ;
20207 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
20209 \ : LCD_Display_Shift $10 OR LCD_WrF ;
20211 \ : LCD_Fn_Set $20 OR LCD_WrF ;
20213 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
20215 \ : LCD_Goto $80 OR LCD_WrF ;
20217 \ CODE LCD_R \ -- byte read byte from LCD
20218 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20219 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20220 \ COLON \ starts a FORTH word
20221 \ TOP_LCD 2 20_us \ -- %0000HHHH
20222 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
20223 \ HI2LO \ switch from FORTH to assembler
20224 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
20225 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
20226 \ MOV @RSP+,IP \ restore IP saved by COLON
20231 \ CODE LCD_RdS \ -- status Read Status
20232 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20237 \ CODE LCD_RdC \ -- char Read Char
20238 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20243 \ -------------+------+------+------+------++---+---+---+---+---------+
20244 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
20245 \ -------------+------+------+------+------++---+---+---+---+---------+
20246 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
20247 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
20248 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
20249 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
20250 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
20251 \ -------------+------+------+------+------++---+---+---+---+---------+
20254 \ ******************************\
20255 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20256 \ ******************************\
20257 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
20258 \ ------------------------------\
20259 \ define LPM mode for ACCEPT \
20260 \ ------------------------------\
20261 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20262 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20263 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20264 BIT.B #SW2,&SW2_IN \ test switch S2
20265 0= IF \ case of switch S2 pressed
20266 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
20268 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
20271 BIT.B #SW1,&SW1_IN \ test switch S1 input
20272 0= IF \ case of Switch S1 pressed
20273 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
20275 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
20279 RETI \ CPU is ON, GIE is OFF
20284 \ ------------------------------\
20285 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20286 \ ******************************\
20287 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20288 \ ******************************\
20289 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20290 \ \ SMclock = 8|16|24 MHz
20291 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
20292 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
20293 \ \ SR(9)=new Toggle bit memory (ADD on)
20294 \ ------------------------------\
20295 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
20296 \ ------------------------------\
20297 \ define LPM mode for ACCEPT \
20298 \ ------------------------------\
20299 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20300 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20301 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20302 \ ------------------------------\
20303 \ RC5_FirstStartBitHalfCycle: \
20304 \ ------------------------------\
20305 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
20306 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
20307 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
20308 MOV #1778,X \ RC5_Period in us
20309 MOV #14,W \ count of loop
20311 \ ------------------------------\
20312 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
20313 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
20314 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
20315 \ RC5_Compute_3/4_Period: \ |
20316 RRUM #1,X \ X=1/2 cycle |
20320 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
20321 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
20323 \ ------------------------------\
20324 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
20325 \ ------------------------------\
20326 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20327 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
20328 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20329 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20330 SUB #1,W \ decrement count loop
20331 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
20332 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20333 0<> WHILE \ ----> out of loop ----+
20334 \ RC5_compute_7/4_Time_out: \ |
20335 ADD X,Y \ | out of bound = 7/4 period
20336 \ RC5_WaitHalfCycleP1.2_IFG: \ |
20338 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
20339 0>= IF \ | if cycle time out of bound
20340 BIC #$30,&TA0CTL \ | stop timer_A0
20341 RETI \ | then quit to do nothing
20343 \ ------------------------------\ |
20344 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
20346 MOV &TA0R,X \ | | get new RC5_period value
20347 REPEAT \ ----> loop back --+ |
20348 \ ------------------------------\ |
20349 \ RC5_SampleEndOf: \ <---------------------+
20350 \ ------------------------------\
20351 BIC #$30,&TA0CTL \ stop timer_A0
20352 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
20353 \ ******************************\
20354 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
20355 \ ******************************\
20356 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
20357 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
20358 XOR IP,X \ (new XOR old) Toggle bit (13)
20359 BIT #BIT13,X \ X(13) = New_RC5_command
20360 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
20362 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
20363 \ ******************************\
20364 \ RC5_ComputeNewRC5word \
20365 \ ******************************\
20367 MOV &BASE,2(PSP) \ save variable BASE before use
20368 MOV TOS,0(PSP) \ save TOS before use
20369 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
20370 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
20371 \ ******************************\
20372 \ RC5_ComputeC6bit \
20373 \ ******************************\
20374 BIT #$4000,IP \ test /C6 bit in IP
20375 0= IF BIS #$40,TOS \ set C6 bit in S
20376 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
20377 \ ******************************\
20378 \ RC5_CommandByteIsDone \ RC5_code --
20379 \ ******************************\
20381 \ ------------------------------\
20382 \ Display IR_RC5 code \
20383 \ ------------------------------\
20384 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
20385 \ ------------------------------\
20386 LO2HI \ switch from assembler to FORTH
20387 ['] LCD_CLEAR IS CR \ redirects CR
20388 ['] LCD_WrC IS EMIT \ redirects EMIT
20389 $10 BASE ! \ change BASE to hexadecimal
20390 CR ." $" 2 U.R \ print IR_RC5 code
20391 ['] (CR) IS CR \ restore CR
20392 ['] (EMIT) IS EMIT \ restore EMIT
20393 HI2LO \ switch from FORTH to assembler
20394 \ ------------------------------\
20395 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
20396 \ ------------------------------\
20397 MOV @PSP+,&BASE \ restore variable BASE
20398 RETI \ CPU is ON, GIE is OFF
20403 \ ------------------------------\
20404 \ TB0CTL = %0000 0010 1001 0100\$3C0
20405 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20406 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20407 \ -- \ID input divider \ 10 = /4
20408 \ -- \MC Mode Control \ 01 = up to TB0CCR0
20409 \ - \TBCLR TimerB Clear
20412 \ --------------------------------\\
20413 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20414 \ -- \CM Capture Mode
20419 \ --- \OUTMOD \ 011 = set/reset
20425 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
20427 \ ------------------------------\
20428 \ set TimerB to make 50kHz PWM \
20429 \ ------------------------------\
20430 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20431 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
20432 \ ------------------------------\
20433 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20434 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
20435 \ ------------------------------\
20436 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20437 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
20438 \ ------------------------------\
20439 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20440 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
20441 \ ------------------------------\
20442 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20443 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
20444 \ ------------------------------\
20445 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
20446 \ ------------------------------\
20447 \ set TimerB to generate PWM for LCD_Vo
20448 \ ------------------------------\
20449 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
20450 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
20451 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20452 \ ------------------------------\
20453 BIS.B #LCDVo,&LCDVo_DIR \
20454 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
20455 \ ------------------------------\
20456 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20457 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20458 \ ------------------------------\
20459 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20460 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20461 \ ------------------------------\
20462 \ WDT interval init part \
20463 \ ------------------------------\
20464 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
20465 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
20466 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
20467 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
20468 \ ------------------------------\
20470 \ ------------------------------\
20471 BIS.B #RC5,&IR_IE \ enable RC5_Int
20472 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20473 \ ------------------------------\
20474 \ init interrupt vectors
20475 \ ------------------------------\
20476 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
20477 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20478 \ ------------------------------\
20479 \ define LPM mode for ACCEPT \
20480 \ ------------------------------\
20481 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20482 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20483 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20485 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
20487 \ ------------------------------\
20489 \ ------------------------------\
20490 $03E8 20_US \ 1- wait 20 ms
20491 $03 TOP_LCD \ 2- send DB5=DB4=1
20492 $CD 20_US \ 3- wait 4,1 ms
20493 $03 TOP_LCD \ 4- send again DB5=DB4=1
20494 $5 20_US \ 5- wait 0,1 ms
20495 $03 TOP_LCD \ 6- send again again DB5=DB4=1
20496 $2 20_US \ wait 40 us = LCD cycle
20497 $02 TOP_LCD \ 7- send DB5=1 DB4=0
20498 $2 20_US \ wait 40 us = LCD cycle
20499 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20500 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20501 LCD_Clear \ 10- "LCD_Clear"
20502 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20503 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20504 LCD_Clear \ 10- "LCD_Clear"
20505 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20506 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20508 ['] (CR) IS CR \ ' (CR) is CR
20509 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
20511 ." RC5toLCD is running. Type STOP to quit"
20512 \ NOECHO \ uncomment to run this app without terminal connexion
20513 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
20514 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
20518 : STOP \ stops multitasking, must to be used before downloading app
20519 ['] (WARM) IS WARM \ remove START app from FORTH init process
20520 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
20528 CODE MAX \ n1 n2 -- n3 signed maximum
20529 CMP @PSP,TOS \ n2-n1
20530 S< ?GOTO FW1 \ n2<n1
20536 CODE MIN \ n1 n2 -- n3 signed minimum
20537 CMP @PSP,TOS \ n2-n1
20538 S< ?GOTO BW1 \ n2<n1
20544 : U.R \ u n -- display u unsigned in n width (n >= 2)
20546 R> OVER - 0 MAX SPACES TYPE
20550 CODE 20_US \ n -- n * 20 us
20551 BEGIN \ 3 cycles loop + 6~
20552 \ MOV #5,W \ 3 MCLK = 1 MHz
20553 \ MOV #23,W \ 3 MCLK = 4 MHz
20554 MOV #51,W \ 3 MCLK = 8 MHz
20555 \ MOV #104,W \ 3 MCLK = 16 MHz
20556 \ MOV #158,W \ 3 MCLK = 24 MHz
20557 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
20567 CODE TOP_LCD \ LCD Sample
20568 \ \ if write : %xxxxWWWW --
20569 \ \ if read : -- %0000RRRR
20570 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20571 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20572 0= IF \ write LCD bits pattern
20573 AND.B #LCD_DB,TOS \
20574 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20575 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20578 THEN \ read LCD bits pattern
20581 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20582 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20583 AND.B #LCD_DB,TOS \
20588 CODE LCD_W \ byte -- write byte to LCD
20590 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
20591 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
20592 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20593 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20594 COLON \ high level word starts here
20595 TOP_LCD 2 20_US \ write high nibble first
20600 CODE LCD_WrC \ char -- Write Char
20601 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20606 CODE LCD_WrF \ func -- Write Fonction
20607 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20613 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
20618 $02 LCD_WrF 100 20_us
20622 \ : LCD_Entry_set $04 OR LCD_WrF ;
20624 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
20626 \ : LCD_Display_Shift $10 OR LCD_WrF ;
20628 \ : LCD_Fn_Set $20 OR LCD_WrF ;
20630 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
20632 \ : LCD_Goto $80 OR LCD_WrF ;
20634 \ CODE LCD_R \ -- byte read byte from LCD
20635 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20636 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20637 \ COLON \ starts a FORTH word
20638 \ TOP_LCD 2 20_us \ -- %0000HHHH
20639 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
20640 \ HI2LO \ switch from FORTH to assembler
20641 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
20642 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
20643 \ MOV @RSP+,IP \ restore IP saved by COLON
20648 \ CODE LCD_RdS \ -- status Read Status
20649 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20654 \ CODE LCD_RdC \ -- char Read Char
20655 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20660 \ -------------+------+------+------+------++---+---+---+---+---------+
20661 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
20662 \ -------------+------+------+------+------++---+---+---+---+---------+
20663 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
20664 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
20665 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
20666 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
20667 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
20668 \ -------------+------+------+------+------++---+---+---+---+---------+
20671 \ ******************************\
20672 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20673 \ ******************************\
20674 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
20675 \ ------------------------------\
20676 \ define LPM mode for ACCEPT \
20677 \ ------------------------------\
20678 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20679 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20680 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20681 BIT.B #SW2,&SW2_IN \ test switch S2
20682 0= IF \ case of switch S2 pressed
20683 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
20685 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
20688 BIT.B #SW1,&SW1_IN \ test switch S1 input
20689 0= IF \ case of Switch S1 pressed
20690 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
20692 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
20696 RETI \ CPU is ON, GIE is OFF
20701 \ ------------------------------\
20702 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20703 \ ******************************\
20704 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20705 \ ******************************\
20706 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20707 \ \ SMclock = 8|16|24 MHz
20708 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
20709 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
20710 \ \ SR(9)=new Toggle bit memory (ADD on)
20711 \ ------------------------------\
20712 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
20713 \ ------------------------------\
20714 \ define LPM mode for ACCEPT \
20715 \ ------------------------------\
20716 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20717 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20718 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20719 \ ------------------------------\
20720 \ RC5_FirstStartBitHalfCycle: \
20721 \ ------------------------------\
20722 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
20723 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
20724 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
20725 MOV #1778,X \ RC5_Period in us
20726 MOV #14,W \ count of loop
20728 \ ------------------------------\
20729 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
20730 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
20731 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
20732 \ RC5_Compute_3/4_Period: \ |
20733 RRUM #1,X \ X=1/2 cycle |
20737 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
20738 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
20740 \ ------------------------------\
20741 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
20742 \ ------------------------------\
20743 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20744 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
20745 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20746 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20747 SUB #1,W \ decrement count loop
20748 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
20749 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20750 0<> WHILE \ ----> out of loop ----+
20751 \ RC5_compute_7/4_Time_out: \ |
20752 ADD X,Y \ | out of bound = 7/4 period
20753 \ RC5_WaitHalfCycleP1.2_IFG: \ |
20755 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
20756 0>= IF \ | if cycle time out of bound
20757 BIC #$30,&TA0CTL \ | stop timer_A0
20758 RETI \ | then quit to do nothing
20760 \ ------------------------------\ |
20761 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
20763 MOV &TA0R,X \ | | get new RC5_period value
20764 REPEAT \ ----> loop back --+ |
20765 \ ------------------------------\ |
20766 \ RC5_SampleEndOf: \ <---------------------+
20767 \ ------------------------------\
20768 BIC #$30,&TA0CTL \ stop timer_A0
20769 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
20770 \ ******************************\
20771 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
20772 \ ******************************\
20773 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
20774 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
20775 XOR IP,X \ (new XOR old) Toggle bit (13)
20776 BIT #BIT13,X \ X(13) = New_RC5_command
20777 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
20779 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
20780 \ ******************************\
20781 \ RC5_ComputeNewRC5word \
20782 \ ******************************\
20784 MOV &BASE,2(PSP) \ save variable BASE before use
20785 MOV TOS,0(PSP) \ save TOS before use
20786 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
20787 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
20788 \ ******************************\
20789 \ RC5_ComputeC6bit \
20790 \ ******************************\
20791 BIT #$4000,IP \ test /C6 bit in IP
20792 0= IF BIS #$40,TOS \ set C6 bit in S
20793 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
20794 \ ******************************\
20795 \ RC5_CommandByteIsDone \ RC5_code --
20796 \ ******************************\
20798 \ ------------------------------\
20799 \ Display IR_RC5 code \
20800 \ ------------------------------\
20801 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
20802 \ ------------------------------\
20803 LO2HI \ switch from assembler to FORTH
20804 ['] LCD_CLEAR IS CR \ redirects CR
20805 ['] LCD_WrC IS EMIT \ redirects EMIT
20806 $10 BASE ! \ change BASE to hexadecimal
20807 CR ." $" 2 U.R \ print IR_RC5 code
20808 ['] (CR) IS CR \ restore CR
20809 ['] (EMIT) IS EMIT \ restore EMIT
20810 HI2LO \ switch from FORTH to assembler
20811 \ ------------------------------\
20812 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
20813 \ ------------------------------\
20814 MOV @PSP+,&BASE \ restore variable BASE
20815 RETI \ CPU is ON, GIE is OFF
20820 \ ------------------------------\
20821 \ TB0CTL = %0000 0010 1001 0100\$3C0
20822 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20823 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20824 \ -- \ID input divider \ 10 = /4
20825 \ -- \MC Mode Control \ 01 = up to TB0CCR0
20826 \ - \TBCLR TimerB Clear
20829 \ --------------------------------\\
20830 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20831 \ -- \CM Capture Mode
20836 \ --- \OUTMOD \ 011 = set/reset
20842 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
20844 \ ------------------------------\
20845 \ set TimerB to make 50kHz PWM \
20846 \ ------------------------------\
20847 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20848 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
20849 \ ------------------------------\
20850 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20851 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
20852 \ ------------------------------\
20853 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20854 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
20855 \ ------------------------------\
20856 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20857 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
20858 \ ------------------------------\
20859 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20860 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
20861 \ ------------------------------\
20862 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
20863 \ ------------------------------\
20864 \ set TimerB to generate PWM for LCD_Vo
20865 \ ------------------------------\
20866 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
20867 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
20868 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20869 \ ------------------------------\
20870 BIS.B #LCDVo,&LCDVo_DIR \
20871 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
20872 \ ------------------------------\
20873 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20874 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20875 \ ------------------------------\
20876 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20877 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20878 \ ------------------------------\
20879 \ WDT interval init part \
20880 \ ------------------------------\
20881 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
20882 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
20883 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
20884 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
20885 \ ------------------------------\
20887 \ ------------------------------\
20888 BIS.B #RC5,&IR_IE \ enable RC5_Int
20889 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20890 \ ------------------------------\
20891 \ init interrupt vectors
20892 \ ------------------------------\
20893 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
20894 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20895 \ ------------------------------\
20896 \ define LPM mode for ACCEPT \
20897 \ ------------------------------\
20898 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20899 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20900 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20902 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
20904 \ ------------------------------\
20906 \ ------------------------------\
20907 $03E8 20_US \ 1- wait 20 ms
20908 $03 TOP_LCD \ 2- send DB5=DB4=1
20909 $CD 20_US \ 3- wait 4,1 ms
20910 $03 TOP_LCD \ 4- send again DB5=DB4=1
20911 $5 20_US \ 5- wait 0,1 ms
20912 $03 TOP_LCD \ 6- send again again DB5=DB4=1
20913 $2 20_US \ wait 40 us = LCD cycle
20914 $02 TOP_LCD \ 7- send DB5=1 DB4=0
20915 $2 20_US \ wait 40 us = LCD cycle
20916 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20917 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20918 LCD_Clear \ 10- "LCD_Clear"
20919 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20920 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20921 LCD_Clear \ 10- "LCD_Clear"
20922 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20923 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20925 ['] (CR) IS CR \ ' (CR) is CR
20926 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
20928 ." RC5toLCD is running. Type STOP to quit"
20929 \ NOECHO \ uncomment to run this app without terminal connexion
20930 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
20931 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
20935 : STOP \ stops multitasking, must to be used before downloading app
20936 ['] (WARM) IS WARM \ remove START app from FORTH init process
20937 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
20945 CODE MAX \ n1 n2 -- n3 signed maximum
20946 CMP @PSP,TOS \ n2-n1
20947 S< ?GOTO FW1 \ n2<n1
20953 CODE MIN \ n1 n2 -- n3 signed minimum
20954 CMP @PSP,TOS \ n2-n1
20955 S< ?GOTO BW1 \ n2<n1
20961 : U.R \ u n -- display u unsigned in n width (n >= 2)
20963 R> OVER - 0 MAX SPACES TYPE
20967 CODE 20_US \ n -- n * 20 us
20968 BEGIN \ 3 cycles loop + 6~
20969 \ MOV #5,W \ 3 MCLK = 1 MHz
20970 \ MOV #23,W \ 3 MCLK = 4 MHz
20971 MOV #51,W \ 3 MCLK = 8 MHz
20972 \ MOV #104,W \ 3 MCLK = 16 MHz
20973 \ MOV #158,W \ 3 MCLK = 24 MHz
20974 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
20984 CODE TOP_LCD \ LCD Sample
20985 \ \ if write : %xxxxWWWW --
20986 \ \ if read : -- %0000RRRR
20987 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20988 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20989 0= IF \ write LCD bits pattern
20990 AND.B #LCD_DB,TOS \
20991 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20992 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20995 THEN \ read LCD bits pattern
20998 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20999 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21000 AND.B #LCD_DB,TOS \
21005 CODE LCD_W \ byte -- write byte to LCD
21007 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
21008 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
21009 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21010 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21011 COLON \ high level word starts here
21012 TOP_LCD 2 20_US \ write high nibble first
21017 CODE LCD_WrC \ char -- Write Char
21018 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21023 CODE LCD_WrF \ func -- Write Fonction
21024 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21030 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
21035 $02 LCD_WrF 100 20_us
21039 \ : LCD_Entry_set $04 OR LCD_WrF ;
21041 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
21043 \ : LCD_Display_Shift $10 OR LCD_WrF ;
21045 \ : LCD_Fn_Set $20 OR LCD_WrF ;
21047 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
21049 \ : LCD_Goto $80 OR LCD_WrF ;
21051 \ CODE LCD_R \ -- byte read byte from LCD
21052 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21053 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21054 \ COLON \ starts a FORTH word
21055 \ TOP_LCD 2 20_us \ -- %0000HHHH
21056 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
21057 \ HI2LO \ switch from FORTH to assembler
21058 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
21059 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
21060 \ MOV @RSP+,IP \ restore IP saved by COLON
21065 \ CODE LCD_RdS \ -- status Read Status
21066 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21071 \ CODE LCD_RdC \ -- char Read Char
21072 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21077 \ -------------+------+------+------+------++---+---+---+---+---------+
21078 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
21079 \ -------------+------+------+------+------++---+---+---+---+---------+
21080 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
21081 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
21082 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
21083 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
21084 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
21085 \ -------------+------+------+------+------++---+---+---+---+---------+
21088 \ ******************************\
21089 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21090 \ ******************************\
21091 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
21092 \ ------------------------------\
21093 \ define LPM mode for ACCEPT \
21094 \ ------------------------------\
21095 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21096 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21097 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21098 BIT.B #SW2,&SW2_IN \ test switch S2
21099 0= IF \ case of switch S2 pressed
21100 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
21102 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
21105 BIT.B #SW1,&SW1_IN \ test switch S1 input
21106 0= IF \ case of Switch S1 pressed
21107 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
21109 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
21113 RETI \ CPU is ON, GIE is OFF
21118 \ ------------------------------\
21119 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21120 \ ******************************\
21121 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21122 \ ******************************\
21123 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21124 \ \ SMclock = 8|16|24 MHz
21125 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
21126 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
21127 \ \ SR(9)=new Toggle bit memory (ADD on)
21128 \ ------------------------------\
21129 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
21130 \ ------------------------------\
21131 \ define LPM mode for ACCEPT \
21132 \ ------------------------------\
21133 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21134 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21135 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21136 \ ------------------------------\
21137 \ RC5_FirstStartBitHalfCycle: \
21138 \ ------------------------------\
21139 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
21140 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
21141 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
21142 MOV #1778,X \ RC5_Period in us
21143 MOV #14,W \ count of loop
21145 \ ------------------------------\
21146 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
21147 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
21148 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
21149 \ RC5_Compute_3/4_Period: \ |
21150 RRUM #1,X \ X=1/2 cycle |
21154 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
21155 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
21157 \ ------------------------------\
21158 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
21159 \ ------------------------------\
21160 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21161 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
21162 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21163 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21164 SUB #1,W \ decrement count loop
21165 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
21166 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21167 0<> WHILE \ ----> out of loop ----+
21168 \ RC5_compute_7/4_Time_out: \ |
21169 ADD X,Y \ | out of bound = 7/4 period
21170 \ RC5_WaitHalfCycleP1.2_IFG: \ |
21172 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
21173 0>= IF \ | if cycle time out of bound
21174 BIC #$30,&TA0CTL \ | stop timer_A0
21175 RETI \ | then quit to do nothing
21177 \ ------------------------------\ |
21178 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
21180 MOV &TA0R,X \ | | get new RC5_period value
21181 REPEAT \ ----> loop back --+ |
21182 \ ------------------------------\ |
21183 \ RC5_SampleEndOf: \ <---------------------+
21184 \ ------------------------------\
21185 BIC #$30,&TA0CTL \ stop timer_A0
21186 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
21187 \ ******************************\
21188 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
21189 \ ******************************\
21190 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
21191 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
21192 XOR IP,X \ (new XOR old) Toggle bit (13)
21193 BIT #BIT13,X \ X(13) = New_RC5_command
21194 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
21196 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
21197 \ ******************************\
21198 \ RC5_ComputeNewRC5word \
21199 \ ******************************\
21201 MOV &BASE,2(PSP) \ save variable BASE before use
21202 MOV TOS,0(PSP) \ save TOS before use
21203 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
21204 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
21205 \ ******************************\
21206 \ RC5_ComputeC6bit \
21207 \ ******************************\
21208 BIT #$4000,IP \ test /C6 bit in IP
21209 0= IF BIS #$40,TOS \ set C6 bit in S
21210 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
21211 \ ******************************\
21212 \ RC5_CommandByteIsDone \ RC5_code --
21213 \ ******************************\
21215 \ ------------------------------\
21216 \ Display IR_RC5 code \
21217 \ ------------------------------\
21218 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
21219 \ ------------------------------\
21220 LO2HI \ switch from assembler to FORTH
21221 ['] LCD_CLEAR IS CR \ redirects CR
21222 ['] LCD_WrC IS EMIT \ redirects EMIT
21223 $10 BASE ! \ change BASE to hexadecimal
21224 CR ." $" 2 U.R \ print IR_RC5 code
21225 ['] (CR) IS CR \ restore CR
21226 ['] (EMIT) IS EMIT \ restore EMIT
21227 HI2LO \ switch from FORTH to assembler
21228 \ ------------------------------\
21229 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
21230 \ ------------------------------\
21231 MOV @PSP+,&BASE \ restore variable BASE
21232 RETI \ CPU is ON, GIE is OFF
21237 \ ------------------------------\
21238 \ TB0CTL = %0000 0010 1001 0100\$3C0
21239 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21240 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21241 \ -- \ID input divider \ 10 = /4
21242 \ -- \MC Mode Control \ 01 = up to TB0CCR0
21243 \ - \TBCLR TimerB Clear
21246 \ --------------------------------\\
21247 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21248 \ -- \CM Capture Mode
21253 \ --- \OUTMOD \ 011 = set/reset
21259 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
21261 \ ------------------------------\
21262 \ set TimerB to make 50kHz PWM \
21263 \ ------------------------------\
21264 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
21265 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
21266 \ ------------------------------\
21267 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
21268 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
21269 \ ------------------------------\
21270 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21271 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
21272 \ ------------------------------\
21273 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21274 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
21275 \ ------------------------------\
21276 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21277 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
21278 \ ------------------------------\
21279 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
21280 \ ------------------------------\
21281 \ set TimerB to generate PWM for LCD_Vo
21282 \ ------------------------------\
21283 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
21284 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
21285 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21286 \ ------------------------------\
21287 BIS.B #LCDVo,&LCDVo_DIR \
21288 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
21289 \ ------------------------------\
21290 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21291 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21292 \ ------------------------------\
21293 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21294 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21295 \ ------------------------------\
21296 \ WDT interval init part \
21297 \ ------------------------------\
21298 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
21299 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
21300 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
21301 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
21302 \ ------------------------------\
21304 \ ------------------------------\
21305 BIS.B #RC5,&IR_IE \ enable RC5_Int
21306 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21307 \ ------------------------------\
21308 \ init interrupt vectors
21309 \ ------------------------------\
21310 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
21311 MOV #RC5_INT,&IR_Vec \ init interrupt vector
21312 \ ------------------------------\
21313 \ define LPM mode for ACCEPT \
21314 \ ------------------------------\
21315 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21316 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21317 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21319 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
21321 \ ------------------------------\
21323 \ ------------------------------\
21324 $03E8 20_US \ 1- wait 20 ms
21325 $03 TOP_LCD \ 2- send DB5=DB4=1
21326 $CD 20_US \ 3- wait 4,1 ms
21327 $03 TOP_LCD \ 4- send again DB5=DB4=1
21328 $5 20_US \ 5- wait 0,1 ms
21329 $03 TOP_LCD \ 6- send again again DB5=DB4=1
21330 $2 20_US \ wait 40 us = LCD cycle
21331 $02 TOP_LCD \ 7- send DB5=1 DB4=0
21332 $2 20_US \ wait 40 us = LCD cycle
21333 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21334 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21335 LCD_Clear \ 10- "LCD_Clear"
21336 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21337 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21338 LCD_Clear \ 10- "LCD_Clear"
21339 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21340 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21342 ['] (CR) IS CR \ ' (CR) is CR
21343 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
21345 ." RC5toLCD is running. Type STOP to quit"
21346 \ NOECHO \ uncomment to run this app without terminal connexion
21347 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
21348 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
21352 : STOP \ stops multitasking, must to be used before downloading app
21353 ['] (WARM) IS WARM \ remove START app from FORTH init process
21354 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
21362 CODE MAX \ n1 n2 -- n3 signed maximum
21363 CMP @PSP,TOS \ n2-n1
21364 S< ?GOTO FW1 \ n2<n1
21370 CODE MIN \ n1 n2 -- n3 signed minimum
21371 CMP @PSP,TOS \ n2-n1
21372 S< ?GOTO BW1 \ n2<n1
21378 : U.R \ u n -- display u unsigned in n width (n >= 2)
21380 R> OVER - 0 MAX SPACES TYPE
21384 CODE 20_US \ n -- n * 20 us
21385 BEGIN \ 3 cycles loop + 6~
21386 \ MOV #5,W \ 3 MCLK = 1 MHz
21387 \ MOV #23,W \ 3 MCLK = 4 MHz
21388 MOV #51,W \ 3 MCLK = 8 MHz
21389 \ MOV #104,W \ 3 MCLK = 16 MHz
21390 \ MOV #158,W \ 3 MCLK = 24 MHz
21391 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
21401 CODE TOP_LCD \ LCD Sample
21402 \ \ if write : %xxxxWWWW --
21403 \ \ if read : -- %0000RRRR
21404 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21405 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21406 0= IF \ write LCD bits pattern
21407 AND.B #LCD_DB,TOS \
21408 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21409 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21412 THEN \ read LCD bits pattern
21415 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21416 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21417 AND.B #LCD_DB,TOS \
21422 CODE LCD_W \ byte -- write byte to LCD
21424 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
21425 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
21426 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21427 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21428 COLON \ high level word starts here
21429 TOP_LCD 2 20_US \ write high nibble first
21434 CODE LCD_WrC \ char -- Write Char
21435 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21440 CODE LCD_WrF \ func -- Write Fonction
21441 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21447 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
21452 $02 LCD_WrF 100 20_us
21456 \ : LCD_Entry_set $04 OR LCD_WrF ;
21458 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
21460 \ : LCD_Display_Shift $10 OR LCD_WrF ;
21462 \ : LCD_Fn_Set $20 OR LCD_WrF ;
21464 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
21466 \ : LCD_Goto $80 OR LCD_WrF ;
21468 \ CODE LCD_R \ -- byte read byte from LCD
21469 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21470 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21471 \ COLON \ starts a FORTH word
21472 \ TOP_LCD 2 20_us \ -- %0000HHHH
21473 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
21474 \ HI2LO \ switch from FORTH to assembler
21475 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
21476 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
21477 \ MOV @RSP+,IP \ restore IP saved by COLON
21482 \ CODE LCD_RdS \ -- status Read Status
21483 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21488 \ CODE LCD_RdC \ -- char Read Char
21489 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21494 \ -------------+------+------+------+------++---+---+---+---+---------+
21495 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
21496 \ -------------+------+------+------+------++---+---+---+---+---------+
21497 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
21498 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
21499 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
21500 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
21501 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
21502 \ -------------+------+------+------+------++---+---+---+---+---------+
21505 \ ******************************\
21506 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21507 \ ******************************\
21508 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
21509 \ ------------------------------\
21510 \ define LPM mode for ACCEPT \
21511 \ ------------------------------\
21512 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21513 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21514 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21515 BIT.B #SW2,&SW2_IN \ test switch S2
21516 0= IF \ case of switch S2 pressed
21517 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
21519 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
21522 BIT.B #SW1,&SW1_IN \ test switch S1 input
21523 0= IF \ case of Switch S1 pressed
21524 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
21526 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
21530 RETI \ CPU is ON, GIE is OFF
21535 \ ------------------------------\
21536 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21537 \ ******************************\
21538 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21539 \ ******************************\
21540 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21541 \ \ SMclock = 8|16|24 MHz
21542 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
21543 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
21544 \ \ SR(9)=new Toggle bit memory (ADD on)
21545 \ ------------------------------\
21546 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
21547 \ ------------------------------\
21548 \ define LPM mode for ACCEPT \
21549 \ ------------------------------\
21550 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21551 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21552 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21553 \ ------------------------------\
21554 \ RC5_FirstStartBitHalfCycle: \
21555 \ ------------------------------\
21556 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
21557 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
21558 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
21559 MOV #1778,X \ RC5_Period in us
21560 MOV #14,W \ count of loop
21562 \ ------------------------------\
21563 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
21564 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
21565 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
21566 \ RC5_Compute_3/4_Period: \ |
21567 RRUM #1,X \ X=1/2 cycle |
21571 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
21572 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
21574 \ ------------------------------\
21575 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
21576 \ ------------------------------\
21577 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21578 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
21579 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21580 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21581 SUB #1,W \ decrement count loop
21582 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
21583 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21584 0<> WHILE \ ----> out of loop ----+
21585 \ RC5_compute_7/4_Time_out: \ |
21586 ADD X,Y \ | out of bound = 7/4 period
21587 \ RC5_WaitHalfCycleP1.2_IFG: \ |
21589 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
21590 0>= IF \ | if cycle time out of bound
21591 BIC #$30,&TA0CTL \ | stop timer_A0
21592 RETI \ | then quit to do nothing
21594 \ ------------------------------\ |
21595 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
21597 MOV &TA0R,X \ | | get new RC5_period value
21598 REPEAT \ ----> loop back --+ |
21599 \ ------------------------------\ |
21600 \ RC5_SampleEndOf: \ <---------------------+
21601 \ ------------------------------\
21602 BIC #$30,&TA0CTL \ stop timer_A0
21603 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
21604 \ ******************************\
21605 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
21606 \ ******************************\
21607 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
21608 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
21609 XOR IP,X \ (new XOR old) Toggle bit (13)
21610 BIT #BIT13,X \ X(13) = New_RC5_command
21611 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
21613 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
21614 \ ******************************\
21615 \ RC5_ComputeNewRC5word \
21616 \ ******************************\
21618 MOV &BASE,2(PSP) \ save variable BASE before use
21619 MOV TOS,0(PSP) \ save TOS before use
21620 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
21621 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
21622 \ ******************************\
21623 \ RC5_ComputeC6bit \
21624 \ ******************************\
21625 BIT #$4000,IP \ test /C6 bit in IP
21626 0= IF BIS #$40,TOS \ set C6 bit in S
21627 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
21628 \ ******************************\
21629 \ RC5_CommandByteIsDone \ RC5_code --
21630 \ ******************************\
21632 \ ------------------------------\
21633 \ Display IR_RC5 code \
21634 \ ------------------------------\
21635 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
21636 \ ------------------------------\
21637 LO2HI \ switch from assembler to FORTH
21638 ['] LCD_CLEAR IS CR \ redirects CR
21639 ['] LCD_WrC IS EMIT \ redirects EMIT
21640 $10 BASE ! \ change BASE to hexadecimal
21641 CR ." $" 2 U.R \ print IR_RC5 code
21642 ['] (CR) IS CR \ restore CR
21643 ['] (EMIT) IS EMIT \ restore EMIT
21644 HI2LO \ switch from FORTH to assembler
21645 \ ------------------------------\
21646 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
21647 \ ------------------------------\
21648 MOV @PSP+,&BASE \ restore variable BASE
21649 RETI \ CPU is ON, GIE is OFF
21654 \ ------------------------------\
21655 \ TB0CTL = %0000 0010 1001 0100\$3C0
21656 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21657 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21658 \ -- \ID input divider \ 10 = /4
21659 \ -- \MC Mode Control \ 01 = up to TB0CCR0
21660 \ - \TBCLR TimerB Clear
21663 \ --------------------------------\\
21664 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21665 \ -- \CM Capture Mode
21670 \ --- \OUTMOD \ 011 = set/reset
21676 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
21678 \ ------------------------------\
21679 \ set TimerB to make 50kHz PWM \
21680 \ ------------------------------\
21681 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
21682 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
21683 \ ------------------------------\
21684 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
21685 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
21686 \ ------------------------------\
21687 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21688 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
21689 \ ------------------------------\
21690 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21691 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
21692 \ ------------------------------\
21693 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21694 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
21695 \ ------------------------------\
21696 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
21697 \ ------------------------------\
21698 \ set TimerB to generate PWM for LCD_Vo
21699 \ ------------------------------\
21700 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
21701 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
21702 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21703 \ ------------------------------\
21704 BIS.B #LCDVo,&LCDVo_DIR \
21705 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
21706 \ ------------------------------\
21707 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21708 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21709 \ ------------------------------\
21710 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21711 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21712 \ ------------------------------\
21713 \ WDT interval init part \
21714 \ ------------------------------\
21715 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
21716 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
21717 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
21718 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
21719 \ ------------------------------\
21721 \ ------------------------------\
21722 BIS.B #RC5,&IR_IE \ enable RC5_Int
21723 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21724 \ ------------------------------\
21725 \ init interrupt vectors
21726 \ ------------------------------\
21727 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
21728 MOV #RC5_INT,&IR_Vec \ init interrupt vector
21729 \ ------------------------------\
21730 \ define LPM mode for ACCEPT \
21731 \ ------------------------------\
21732 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21733 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21734 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21736 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
21738 \ ------------------------------\
21740 \ ------------------------------\
21741 $03E8 20_US \ 1- wait 20 ms
21742 $03 TOP_LCD \ 2- send DB5=DB4=1
21743 $CD 20_US \ 3- wait 4,1 ms
21744 $03 TOP_LCD \ 4- send again DB5=DB4=1
21745 $5 20_US \ 5- wait 0,1 ms
21746 $03 TOP_LCD \ 6- send again again DB5=DB4=1
21747 $2 20_US \ wait 40 us = LCD cycle
21748 $02 TOP_LCD \ 7- send DB5=1 DB4=0
21749 $2 20_US \ wait 40 us = LCD cycle
21750 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21751 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21752 LCD_Clear \ 10- "LCD_Clear"
21753 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21754 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21755 LCD_Clear \ 10- "LCD_Clear"
21756 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21757 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21759 ['] (CR) IS CR \ ' (CR) is CR
21760 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
21762 ." RC5toLCD is running. Type STOP to quit"
21763 \ NOECHO \ uncomment to run this app without terminal connexion
21764 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
21765 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
21769 : STOP \ stops multitasking, must to be used before downloading app
21770 ['] (WARM) IS WARM \ remove START app from FORTH init process
21771 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
21779 CODE MAX \ n1 n2 -- n3 signed maximum
21780 CMP @PSP,TOS \ n2-n1
21781 S< ?GOTO FW1 \ n2<n1
21787 CODE MIN \ n1 n2 -- n3 signed minimum
21788 CMP @PSP,TOS \ n2-n1
21789 S< ?GOTO BW1 \ n2<n1
21795 : U.R \ u n -- display u unsigned in n width (n >= 2)
21797 R> OVER - 0 MAX SPACES TYPE
21801 CODE 20_US \ n -- n * 20 us
21802 BEGIN \ 3 cycles loop + 6~
21803 \ MOV #5,W \ 3 MCLK = 1 MHz
21804 \ MOV #23,W \ 3 MCLK = 4 MHz
21805 MOV #51,W \ 3 MCLK = 8 MHz
21806 \ MOV #104,W \ 3 MCLK = 16 MHz
21807 \ MOV #158,W \ 3 MCLK = 24 MHz
21808 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
21818 CODE TOP_LCD \ LCD Sample
21819 \ \ if write : %xxxxWWWW --
21820 \ \ if read : -- %0000RRRR
21821 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21822 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21823 0= IF \ write LCD bits pattern
21824 AND.B #LCD_DB,TOS \
21825 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21826 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21829 THEN \ read LCD bits pattern
21832 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21833 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21834 AND.B #LCD_DB,TOS \
21839 CODE LCD_W \ byte -- write byte to LCD
21841 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
21842 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
21843 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21844 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21845 COLON \ high level word starts here
21846 TOP_LCD 2 20_US \ write high nibble first
21851 CODE LCD_WrC \ char -- Write Char
21852 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21857 CODE LCD_WrF \ func -- Write Fonction
21858 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21864 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
21869 $02 LCD_WrF 100 20_us
21873 \ : LCD_Entry_set $04 OR LCD_WrF ;
21875 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
21877 \ : LCD_Display_Shift $10 OR LCD_WrF ;
21879 \ : LCD_Fn_Set $20 OR LCD_WrF ;
21881 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
21883 \ : LCD_Goto $80 OR LCD_WrF ;
21885 \ CODE LCD_R \ -- byte read byte from LCD
21886 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21887 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21888 \ COLON \ starts a FORTH word
21889 \ TOP_LCD 2 20_us \ -- %0000HHHH
21890 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
21891 \ HI2LO \ switch from FORTH to assembler
21892 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
21893 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
21894 \ MOV @RSP+,IP \ restore IP saved by COLON
21899 \ CODE LCD_RdS \ -- status Read Status
21900 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21905 \ CODE LCD_RdC \ -- char Read Char
21906 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21911 \ -------------+------+------+------+------++---+---+---+---+---------+
21912 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
21913 \ -------------+------+------+------+------++---+---+---+---+---------+
21914 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
21915 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
21916 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
21917 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
21918 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
21919 \ -------------+------+------+------+------++---+---+---+---+---------+
21922 \ ******************************\
21923 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21924 \ ******************************\
21925 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
21926 \ ------------------------------\
21927 \ define LPM mode for ACCEPT \
21928 \ ------------------------------\
21929 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21930 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21931 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21932 BIT.B #SW2,&SW2_IN \ test switch S2
21933 0= IF \ case of switch S2 pressed
21934 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
21936 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
21939 BIT.B #SW1,&SW1_IN \ test switch S1 input
21940 0= IF \ case of Switch S1 pressed
21941 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
21943 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
21947 RETI \ CPU is ON, GIE is OFF
21952 \ ------------------------------\
21953 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21954 \ ******************************\
21955 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21956 \ ******************************\
21957 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21958 \ \ SMclock = 8|16|24 MHz
21959 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
21960 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
21961 \ \ SR(9)=new Toggle bit memory (ADD on)
21962 \ ------------------------------\
21963 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
21964 \ ------------------------------\
21965 \ define LPM mode for ACCEPT \
21966 \ ------------------------------\
21967 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21968 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21969 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21970 \ ------------------------------\
21971 \ RC5_FirstStartBitHalfCycle: \
21972 \ ------------------------------\
21973 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
21974 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
21975 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
21976 MOV #1778,X \ RC5_Period in us
21977 MOV #14,W \ count of loop
21979 \ ------------------------------\
21980 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
21981 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
21982 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
21983 \ RC5_Compute_3/4_Period: \ |
21984 RRUM #1,X \ X=1/2 cycle |
21988 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
21989 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
21991 \ ------------------------------\
21992 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
21993 \ ------------------------------\
21994 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21995 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
21996 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21997 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21998 SUB #1,W \ decrement count loop
21999 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
22000 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22001 0<> WHILE \ ----> out of loop ----+
22002 \ RC5_compute_7/4_Time_out: \ |
22003 ADD X,Y \ | out of bound = 7/4 period
22004 \ RC5_WaitHalfCycleP1.2_IFG: \ |
22006 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
22007 0>= IF \ | if cycle time out of bound
22008 BIC #$30,&TA0CTL \ | stop timer_A0
22009 RETI \ | then quit to do nothing
22011 \ ------------------------------\ |
22012 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
22014 MOV &TA0R,X \ | | get new RC5_period value
22015 REPEAT \ ----> loop back --+ |
22016 \ ------------------------------\ |
22017 \ RC5_SampleEndOf: \ <---------------------+
22018 \ ------------------------------\
22019 BIC #$30,&TA0CTL \ stop timer_A0
22020 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
22021 \ ******************************\
22022 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22023 \ ******************************\
22024 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
22025 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
22026 XOR IP,X \ (new XOR old) Toggle bit (13)
22027 BIT #BIT13,X \ X(13) = New_RC5_command
22028 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
22030 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
22031 \ ******************************\
22032 \ RC5_ComputeNewRC5word \
22033 \ ******************************\
22035 MOV &BASE,2(PSP) \ save variable BASE before use
22036 MOV TOS,0(PSP) \ save TOS before use
22037 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
22038 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
22039 \ ******************************\
22040 \ RC5_ComputeC6bit \
22041 \ ******************************\
22042 BIT #$4000,IP \ test /C6 bit in IP
22043 0= IF BIS #$40,TOS \ set C6 bit in S
22044 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
22045 \ ******************************\
22046 \ RC5_CommandByteIsDone \ RC5_code --
22047 \ ******************************\
22049 \ ------------------------------\
22050 \ Display IR_RC5 code \
22051 \ ------------------------------\
22052 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
22053 \ ------------------------------\
22054 LO2HI \ switch from assembler to FORTH
22055 ['] LCD_CLEAR IS CR \ redirects CR
22056 ['] LCD_WrC IS EMIT \ redirects EMIT
22057 $10 BASE ! \ change BASE to hexadecimal
22058 CR ." $" 2 U.R \ print IR_RC5 code
22059 ['] (CR) IS CR \ restore CR
22060 ['] (EMIT) IS EMIT \ restore EMIT
22061 HI2LO \ switch from FORTH to assembler
22062 \ ------------------------------\
22063 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
22064 \ ------------------------------\
22065 MOV @PSP+,&BASE \ restore variable BASE
22066 RETI \ CPU is ON, GIE is OFF
22071 \ ------------------------------\
22072 \ TB0CTL = %0000 0010 1001 0100\$3C0
22073 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22074 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22075 \ -- \ID input divider \ 10 = /4
22076 \ -- \MC Mode Control \ 01 = up to TB0CCR0
22077 \ - \TBCLR TimerB Clear
22080 \ --------------------------------\\
22081 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22082 \ -- \CM Capture Mode
22087 \ --- \OUTMOD \ 011 = set/reset
22093 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
22095 \ ------------------------------\
22096 \ set TimerB to make 50kHz PWM \
22097 \ ------------------------------\
22098 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22099 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
22100 \ ------------------------------\
22101 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22102 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
22103 \ ------------------------------\
22104 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22105 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
22106 \ ------------------------------\
22107 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22108 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
22109 \ ------------------------------\
22110 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22111 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
22112 \ ------------------------------\
22113 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
22114 \ ------------------------------\
22115 \ set TimerB to generate PWM for LCD_Vo
22116 \ ------------------------------\
22117 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
22118 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
22119 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22120 \ ------------------------------\
22121 BIS.B #LCDVo,&LCDVo_DIR \
22122 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
22123 \ ------------------------------\
22124 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22125 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22126 \ ------------------------------\
22127 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22128 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22129 \ ------------------------------\
22130 \ WDT interval init part \
22131 \ ------------------------------\
22132 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
22133 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
22134 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
22135 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
22136 \ ------------------------------\
22138 \ ------------------------------\
22139 BIS.B #RC5,&IR_IE \ enable RC5_Int
22140 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22141 \ ------------------------------\
22142 \ init interrupt vectors
22143 \ ------------------------------\
22144 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
22145 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22146 \ ------------------------------\
22147 \ define LPM mode for ACCEPT \
22148 \ ------------------------------\
22149 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22150 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22151 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22153 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
22155 \ ------------------------------\
22157 \ ------------------------------\
22158 $03E8 20_US \ 1- wait 20 ms
22159 $03 TOP_LCD \ 2- send DB5=DB4=1
22160 $CD 20_US \ 3- wait 4,1 ms
22161 $03 TOP_LCD \ 4- send again DB5=DB4=1
22162 $5 20_US \ 5- wait 0,1 ms
22163 $03 TOP_LCD \ 6- send again again DB5=DB4=1
22164 $2 20_US \ wait 40 us = LCD cycle
22165 $02 TOP_LCD \ 7- send DB5=1 DB4=0
22166 $2 20_US \ wait 40 us = LCD cycle
22167 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22168 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22169 LCD_Clear \ 10- "LCD_Clear"
22170 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22171 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22172 LCD_Clear \ 10- "LCD_Clear"
22173 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22174 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22176 ['] (CR) IS CR \ ' (CR) is CR
22177 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
22179 ." RC5toLCD is running. Type STOP to quit"
22180 \ NOECHO \ uncomment to run this app without terminal connexion
22181 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
22182 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
22186 : STOP \ stops multitasking, must to be used before downloading app
22187 ['] (WARM) IS WARM \ remove START app from FORTH init process
22188 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
22196 CODE MAX \ n1 n2 -- n3 signed maximum
22197 CMP @PSP,TOS \ n2-n1
22198 S< ?GOTO FW1 \ n2<n1
22204 CODE MIN \ n1 n2 -- n3 signed minimum
22205 CMP @PSP,TOS \ n2-n1
22206 S< ?GOTO BW1 \ n2<n1
22212 : U.R \ u n -- display u unsigned in n width (n >= 2)
22214 R> OVER - 0 MAX SPACES TYPE
22218 CODE 20_US \ n -- n * 20 us
22219 BEGIN \ 3 cycles loop + 6~
22220 \ MOV #5,W \ 3 MCLK = 1 MHz
22221 \ MOV #23,W \ 3 MCLK = 4 MHz
22222 MOV #51,W \ 3 MCLK = 8 MHz
22223 \ MOV #104,W \ 3 MCLK = 16 MHz
22224 \ MOV #158,W \ 3 MCLK = 24 MHz
22225 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
22235 CODE TOP_LCD \ LCD Sample
22236 \ \ if write : %xxxxWWWW --
22237 \ \ if read : -- %0000RRRR
22238 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22239 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22240 0= IF \ write LCD bits pattern
22241 AND.B #LCD_DB,TOS \
22242 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22243 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22246 THEN \ read LCD bits pattern
22249 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22250 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22251 AND.B #LCD_DB,TOS \
22256 CODE LCD_W \ byte -- write byte to LCD
22258 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
22259 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
22260 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22261 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22262 COLON \ high level word starts here
22263 TOP_LCD 2 20_US \ write high nibble first
22268 CODE LCD_WrC \ char -- Write Char
22269 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22274 CODE LCD_WrF \ func -- Write Fonction
22275 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22281 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
22286 $02 LCD_WrF 100 20_us
22290 \ : LCD_Entry_set $04 OR LCD_WrF ;
22292 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
22294 \ : LCD_Display_Shift $10 OR LCD_WrF ;
22296 \ : LCD_Fn_Set $20 OR LCD_WrF ;
22298 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
22300 \ : LCD_Goto $80 OR LCD_WrF ;
22302 \ CODE LCD_R \ -- byte read byte from LCD
22303 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22304 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22305 \ COLON \ starts a FORTH word
22306 \ TOP_LCD 2 20_us \ -- %0000HHHH
22307 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
22308 \ HI2LO \ switch from FORTH to assembler
22309 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
22310 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
22311 \ MOV @RSP+,IP \ restore IP saved by COLON
22316 \ CODE LCD_RdS \ -- status Read Status
22317 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22322 \ CODE LCD_RdC \ -- char Read Char
22323 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22328 \ -------------+------+------+------+------++---+---+---+---+---------+
22329 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
22330 \ -------------+------+------+------+------++---+---+---+---+---------+
22331 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
22332 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
22333 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
22334 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
22335 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
22336 \ -------------+------+------+------+------++---+---+---+---+---------+
22339 \ ******************************\
22340 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22341 \ ******************************\
22342 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
22343 \ ------------------------------\
22344 \ define LPM mode for ACCEPT \
22345 \ ------------------------------\
22346 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22347 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22348 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22349 BIT.B #SW2,&SW2_IN \ test switch S2
22350 0= IF \ case of switch S2 pressed
22351 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
22353 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
22356 BIT.B #SW1,&SW1_IN \ test switch S1 input
22357 0= IF \ case of Switch S1 pressed
22358 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
22360 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
22364 RETI \ CPU is ON, GIE is OFF
22369 \ ------------------------------\
22370 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22371 \ ******************************\
22372 ASM RC5_INT \ wake up on Px.RC5 change interrupt
22373 \ ******************************\
22374 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22375 \ \ SMclock = 8|16|24 MHz
22376 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
22377 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
22378 \ \ SR(9)=new Toggle bit memory (ADD on)
22379 \ ------------------------------\
22380 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
22381 \ ------------------------------\
22382 \ define LPM mode for ACCEPT \
22383 \ ------------------------------\
22384 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22385 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22386 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22387 \ ------------------------------\
22388 \ RC5_FirstStartBitHalfCycle: \
22389 \ ------------------------------\
22390 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
22391 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
22392 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
22393 MOV #1778,X \ RC5_Period in us
22394 MOV #14,W \ count of loop
22396 \ ------------------------------\
22397 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
22398 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
22399 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
22400 \ RC5_Compute_3/4_Period: \ |
22401 RRUM #1,X \ X=1/2 cycle |
22405 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
22406 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
22408 \ ------------------------------\
22409 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
22410 \ ------------------------------\
22411 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22412 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
22413 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22414 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22415 SUB #1,W \ decrement count loop
22416 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
22417 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22418 0<> WHILE \ ----> out of loop ----+
22419 \ RC5_compute_7/4_Time_out: \ |
22420 ADD X,Y \ | out of bound = 7/4 period
22421 \ RC5_WaitHalfCycleP1.2_IFG: \ |
22423 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
22424 0>= IF \ | if cycle time out of bound
22425 BIC #$30,&TA0CTL \ | stop timer_A0
22426 RETI \ | then quit to do nothing
22428 \ ------------------------------\ |
22429 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
22431 MOV &TA0R,X \ | | get new RC5_period value
22432 REPEAT \ ----> loop back --+ |
22433 \ ------------------------------\ |
22434 \ RC5_SampleEndOf: \ <---------------------+
22435 \ ------------------------------\
22436 BIC #$30,&TA0CTL \ stop timer_A0
22437 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
22438 \ ******************************\
22439 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22440 \ ******************************\
22441 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
22442 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
22443 XOR IP,X \ (new XOR old) Toggle bit (13)
22444 BIT #BIT13,X \ X(13) = New_RC5_command
22445 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
22447 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
22448 \ ******************************\
22449 \ RC5_ComputeNewRC5word \
22450 \ ******************************\
22452 MOV &BASE,2(PSP) \ save variable BASE before use
22453 MOV TOS,0(PSP) \ save TOS before use
22454 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
22455 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
22456 \ ******************************\
22457 \ RC5_ComputeC6bit \
22458 \ ******************************\
22459 BIT #$4000,IP \ test /C6 bit in IP
22460 0= IF BIS #$40,TOS \ set C6 bit in S
22461 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
22462 \ ******************************\
22463 \ RC5_CommandByteIsDone \ RC5_code --
22464 \ ******************************\
22466 \ ------------------------------\
22467 \ Display IR_RC5 code \
22468 \ ------------------------------\
22469 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
22470 \ ------------------------------\
22471 LO2HI \ switch from assembler to FORTH
22472 ['] LCD_CLEAR IS CR \ redirects CR
22473 ['] LCD_WrC IS EMIT \ redirects EMIT
22474 $10 BASE ! \ change BASE to hexadecimal
22475 CR ." $" 2 U.R \ print IR_RC5 code
22476 ['] (CR) IS CR \ restore CR
22477 ['] (EMIT) IS EMIT \ restore EMIT
22478 HI2LO \ switch from FORTH to assembler
22479 \ ------------------------------\
22480 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
22481 \ ------------------------------\
22482 MOV @PSP+,&BASE \ restore variable BASE
22483 RETI \ CPU is ON, GIE is OFF
22488 \ ------------------------------\
22489 \ TB0CTL = %0000 0010 1001 0100\$3C0
22490 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22491 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22492 \ -- \ID input divider \ 10 = /4
22493 \ -- \MC Mode Control \ 01 = up to TB0CCR0
22494 \ - \TBCLR TimerB Clear
22497 \ --------------------------------\\
22498 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22499 \ -- \CM Capture Mode
22504 \ --- \OUTMOD \ 011 = set/reset
22510 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
22512 \ ------------------------------\
22513 \ set TimerB to make 50kHz PWM \
22514 \ ------------------------------\
22515 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22516 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
22517 \ ------------------------------\
22518 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22519 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
22520 \ ------------------------------\
22521 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22522 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
22523 \ ------------------------------\
22524 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22525 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
22526 \ ------------------------------\
22527 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22528 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
22529 \ ------------------------------\
22530 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
22531 \ ------------------------------\
22532 \ set TimerB to generate PWM for LCD_Vo
22533 \ ------------------------------\
22534 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
22535 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
22536 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22537 \ ------------------------------\
22538 BIS.B #LCDVo,&LCDVo_DIR \
22539 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
22540 \ ------------------------------\
22541 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22542 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22543 \ ------------------------------\
22544 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22545 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22546 \ ------------------------------\
22547 \ WDT interval init part \
22548 \ ------------------------------\
22549 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
22550 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
22551 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
22552 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
22553 \ ------------------------------\
22555 \ ------------------------------\
22556 BIS.B #RC5,&IR_IE \ enable RC5_Int
22557 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22558 \ ------------------------------\
22559 \ init interrupt vectors
22560 \ ------------------------------\
22561 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
22562 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22563 \ ------------------------------\
22564 \ define LPM mode for ACCEPT \
22565 \ ------------------------------\
22566 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22567 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22568 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22570 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
22572 \ ------------------------------\
22574 \ ------------------------------\
22575 $03E8 20_US \ 1- wait 20 ms
22576 $03 TOP_LCD \ 2- send DB5=DB4=1
22577 $CD 20_US \ 3- wait 4,1 ms
22578 $03 TOP_LCD \ 4- send again DB5=DB4=1
22579 $5 20_US \ 5- wait 0,1 ms
22580 $03 TOP_LCD \ 6- send again again DB5=DB4=1
22581 $2 20_US \ wait 40 us = LCD cycle
22582 $02 TOP_LCD \ 7- send DB5=1 DB4=0
22583 $2 20_US \ wait 40 us = LCD cycle
22584 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22585 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22586 LCD_Clear \ 10- "LCD_Clear"
22587 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22588 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22589 LCD_Clear \ 10- "LCD_Clear"
22590 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22591 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22593 ['] (CR) IS CR \ ' (CR) is CR
22594 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
22596 ." RC5toLCD is running. Type STOP to quit"
22597 \ NOECHO \ uncomment to run this app without terminal connexion
22598 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
22599 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
22603 : STOP \ stops multitasking, must to be used before downloading app
22604 ['] (WARM) IS WARM \ remove START app from FORTH init process
22605 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
22613 CODE MAX \ n1 n2 -- n3 signed maximum
22614 CMP @PSP,TOS \ n2-n1
22615 S< ?GOTO FW1 \ n2<n1
22621 CODE MIN \ n1 n2 -- n3 signed minimum
22622 CMP @PSP,TOS \ n2-n1
22623 S< ?GOTO BW1 \ n2<n1
22629 : U.R \ u n -- display u unsigned in n width (n >= 2)
22631 R> OVER - 0 MAX SPACES TYPE
22635 CODE 20_US \ n -- n * 20 us
22636 BEGIN \ 3 cycles loop + 6~
22637 \ MOV #5,W \ 3 MCLK = 1 MHz
22638 \ MOV #23,W \ 3 MCLK = 4 MHz
22639 MOV #51,W \ 3 MCLK = 8 MHz
22640 \ MOV #104,W \ 3 MCLK = 16 MHz
22641 \ MOV #158,W \ 3 MCLK = 24 MHz
22642 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
22652 CODE TOP_LCD \ LCD Sample
22653 \ \ if write : %xxxxWWWW --
22654 \ \ if read : -- %0000RRRR
22655 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22656 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22657 0= IF \ write LCD bits pattern
22658 AND.B #LCD_DB,TOS \
22659 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22660 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22663 THEN \ read LCD bits pattern
22666 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22667 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22668 AND.B #LCD_DB,TOS \
22673 CODE LCD_W \ byte -- write byte to LCD
22675 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
22676 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
22677 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22678 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22679 COLON \ high level word starts here
22680 TOP_LCD 2 20_US \ write high nibble first
22685 CODE LCD_WrC \ char -- Write Char
22686 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22691 CODE LCD_WrF \ func -- Write Fonction
22692 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22698 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
22703 $02 LCD_WrF 100 20_us
22707 \ : LCD_Entry_set $04 OR LCD_WrF ;
22709 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
22711 \ : LCD_Display_Shift $10 OR LCD_WrF ;
22713 \ : LCD_Fn_Set $20 OR LCD_WrF ;
22715 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
22717 \ : LCD_Goto $80 OR LCD_WrF ;
22719 \ CODE LCD_R \ -- byte read byte from LCD
22720 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22721 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22722 \ COLON \ starts a FORTH word
22723 \ TOP_LCD 2 20_us \ -- %0000HHHH
22724 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
22725 \ HI2LO \ switch from FORTH to assembler
22726 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
22727 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
22728 \ MOV @RSP+,IP \ restore IP saved by COLON
22733 \ CODE LCD_RdS \ -- status Read Status
22734 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22739 \ CODE LCD_RdC \ -- char Read Char
22740 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22745 \ -------------+------+------+------+------++---+---+---+---+---------+
22746 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
22747 \ -------------+------+------+------+------++---+---+---+---+---------+
22748 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
22749 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
22750 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
22751 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
22752 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
22753 \ -------------+------+------+------+------++---+---+---+---+---------+
22756 \ ******************************\
22757 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22758 \ ******************************\
22759 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
22760 \ ------------------------------\
22761 \ define LPM mode for ACCEPT \
22762 \ ------------------------------\
22763 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22764 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22765 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22766 BIT.B #SW2,&SW2_IN \ test switch S2
22767 0= IF \ case of switch S2 pressed
22768 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
22770 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
22773 BIT.B #SW1,&SW1_IN \ test switch S1 input
22774 0= IF \ case of Switch S1 pressed
22775 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
22777 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
22781 RETI \ CPU is ON, GIE is OFF
22786 \ ------------------------------\
22787 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22788 \ ******************************\
22789 ASM RC5_INT \ wake up on Px.RC5 change interrupt
22790 \ ******************************\
22791 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22792 \ \ SMclock = 8|16|24 MHz
22793 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
22794 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
22795 \ \ SR(9)=new Toggle bit memory (ADD on)
22796 \ ------------------------------\
22797 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
22798 \ ------------------------------\
22799 \ define LPM mode for ACCEPT \
22800 \ ------------------------------\
22801 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22802 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22803 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22804 \ ------------------------------\
22805 \ RC5_FirstStartBitHalfCycle: \
22806 \ ------------------------------\
22807 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
22808 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
22809 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
22810 MOV #1778,X \ RC5_Period in us
22811 MOV #14,W \ count of loop
22813 \ ------------------------------\
22814 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
22815 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
22816 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
22817 \ RC5_Compute_3/4_Period: \ |
22818 RRUM #1,X \ X=1/2 cycle |
22822 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
22823 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
22825 \ ------------------------------\
22826 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
22827 \ ------------------------------\
22828 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22829 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
22830 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22831 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22832 SUB #1,W \ decrement count loop
22833 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
22834 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22835 0<> WHILE \ ----> out of loop ----+
22836 \ RC5_compute_7/4_Time_out: \ |
22837 ADD X,Y \ | out of bound = 7/4 period
22838 \ RC5_WaitHalfCycleP1.2_IFG: \ |
22840 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
22841 0>= IF \ | if cycle time out of bound
22842 BIC #$30,&TA0CTL \ | stop timer_A0
22843 RETI \ | then quit to do nothing
22845 \ ------------------------------\ |
22846 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
22848 MOV &TA0R,X \ | | get new RC5_period value
22849 REPEAT \ ----> loop back --+ |
22850 \ ------------------------------\ |
22851 \ RC5_SampleEndOf: \ <---------------------+
22852 \ ------------------------------\
22853 BIC #$30,&TA0CTL \ stop timer_A0
22854 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
22855 \ ******************************\
22856 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22857 \ ******************************\
22858 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
22859 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
22860 XOR IP,X \ (new XOR old) Toggle bit (13)
22861 BIT #BIT13,X \ X(13) = New_RC5_command
22862 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
22864 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
22865 \ ******************************\
22866 \ RC5_ComputeNewRC5word \
22867 \ ******************************\
22869 MOV &BASE,2(PSP) \ save variable BASE before use
22870 MOV TOS,0(PSP) \ save TOS before use
22871 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
22872 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
22873 \ ******************************\
22874 \ RC5_ComputeC6bit \
22875 \ ******************************\
22876 BIT #$4000,IP \ test /C6 bit in IP
22877 0= IF BIS #$40,TOS \ set C6 bit in S
22878 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
22879 \ ******************************\
22880 \ RC5_CommandByteIsDone \ RC5_code --
22881 \ ******************************\
22883 \ ------------------------------\
22884 \ Display IR_RC5 code \
22885 \ ------------------------------\
22886 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
22887 \ ------------------------------\
22888 LO2HI \ switch from assembler to FORTH
22889 ['] LCD_CLEAR IS CR \ redirects CR
22890 ['] LCD_WrC IS EMIT \ redirects EMIT
22891 $10 BASE ! \ change BASE to hexadecimal
22892 CR ." $" 2 U.R \ print IR_RC5 code
22893 ['] (CR) IS CR \ restore CR
22894 ['] (EMIT) IS EMIT \ restore EMIT
22895 HI2LO \ switch from FORTH to assembler
22896 \ ------------------------------\
22897 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
22898 \ ------------------------------\
22899 MOV @PSP+,&BASE \ restore variable BASE
22900 RETI \ CPU is ON, GIE is OFF
22905 \ ------------------------------\
22906 \ TB0CTL = %0000 0010 1001 0100\$3C0
22907 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22908 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22909 \ -- \ID input divider \ 10 = /4
22910 \ -- \MC Mode Control \ 01 = up to TB0CCR0
22911 \ - \TBCLR TimerB Clear
22914 \ --------------------------------\\
22915 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22916 \ -- \CM Capture Mode
22921 \ --- \OUTMOD \ 011 = set/reset
22927 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
22929 \ ------------------------------\
22930 \ set TimerB to make 50kHz PWM \
22931 \ ------------------------------\
22932 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22933 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
22934 \ ------------------------------\
22935 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22936 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
22937 \ ------------------------------\
22938 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22939 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
22940 \ ------------------------------\
22941 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22942 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
22943 \ ------------------------------\
22944 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22945 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
22946 \ ------------------------------\
22947 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
22948 \ ------------------------------\
22949 \ set TimerB to generate PWM for LCD_Vo
22950 \ ------------------------------\
22951 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
22952 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
22953 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22954 \ ------------------------------\
22955 BIS.B #LCDVo,&LCDVo_DIR \
22956 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
22957 \ ------------------------------\
22958 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22959 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22960 \ ------------------------------\
22961 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22962 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22963 \ ------------------------------\
22964 \ WDT interval init part \
22965 \ ------------------------------\
22966 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
22967 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
22968 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
22969 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
22970 \ ------------------------------\
22972 \ ------------------------------\
22973 BIS.B #RC5,&IR_IE \ enable RC5_Int
22974 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22975 \ ------------------------------\
22976 \ init interrupt vectors
22977 \ ------------------------------\
22978 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
22979 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22980 \ ------------------------------\
22981 \ define LPM mode for ACCEPT \
22982 \ ------------------------------\
22983 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22984 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22985 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22987 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
22989 \ ------------------------------\
22991 \ ------------------------------\
22992 $03E8 20_US \ 1- wait 20 ms
22993 $03 TOP_LCD \ 2- send DB5=DB4=1
22994 $CD 20_US \ 3- wait 4,1 ms
22995 $03 TOP_LCD \ 4- send again DB5=DB4=1
22996 $5 20_US \ 5- wait 0,1 ms
22997 $03 TOP_LCD \ 6- send again again DB5=DB4=1
22998 $2 20_US \ wait 40 us = LCD cycle
22999 $02 TOP_LCD \ 7- send DB5=1 DB4=0
23000 $2 20_US \ wait 40 us = LCD cycle
23001 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23002 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23003 LCD_Clear \ 10- "LCD_Clear"
23004 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23005 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23006 LCD_Clear \ 10- "LCD_Clear"
23007 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23008 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23010 ['] (CR) IS CR \ ' (CR) is CR
23011 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
23013 ." RC5toLCD is running. Type STOP to quit"
23014 \ NOECHO \ uncomment to run this app without terminal connexion
23015 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
23016 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
23020 : STOP \ stops multitasking, must to be used before downloading app
23021 ['] (WARM) IS WARM \ remove START app from FORTH init process
23022 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
23030 CODE MAX \ n1 n2 -- n3 signed maximum
23031 CMP @PSP,TOS \ n2-n1
23032 S< ?GOTO FW1 \ n2<n1
23038 CODE MIN \ n1 n2 -- n3 signed minimum
23039 CMP @PSP,TOS \ n2-n1
23040 S< ?GOTO BW1 \ n2<n1
23046 : U.R \ u n -- display u unsigned in n width (n >= 2)
23048 R> OVER - 0 MAX SPACES TYPE
23052 CODE 20_US \ n -- n * 20 us
23053 BEGIN \ 3 cycles loop + 6~
23054 \ MOV #5,W \ 3 MCLK = 1 MHz
23055 \ MOV #23,W \ 3 MCLK = 4 MHz
23056 MOV #51,W \ 3 MCLK = 8 MHz
23057 \ MOV #104,W \ 3 MCLK = 16 MHz
23058 \ MOV #158,W \ 3 MCLK = 24 MHz
23059 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
23069 CODE TOP_LCD \ LCD Sample
23070 \ \ if write : %xxxxWWWW --
23071 \ \ if read : -- %0000RRRR
23072 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23073 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23074 0= IF \ write LCD bits pattern
23075 AND.B #LCD_DB,TOS \
23076 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23077 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23080 THEN \ read LCD bits pattern
23083 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23084 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23085 AND.B #LCD_DB,TOS \
23090 CODE LCD_W \ byte -- write byte to LCD
23092 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
23093 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
23094 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23095 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23096 COLON \ high level word starts here
23097 TOP_LCD 2 20_US \ write high nibble first
23102 CODE LCD_WrC \ char -- Write Char
23103 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23108 CODE LCD_WrF \ func -- Write Fonction
23109 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23115 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
23120 $02 LCD_WrF 100 20_us
23124 \ : LCD_Entry_set $04 OR LCD_WrF ;
23126 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
23128 \ : LCD_Display_Shift $10 OR LCD_WrF ;
23130 \ : LCD_Fn_Set $20 OR LCD_WrF ;
23132 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
23134 \ : LCD_Goto $80 OR LCD_WrF ;
23136 \ CODE LCD_R \ -- byte read byte from LCD
23137 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23138 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23139 \ COLON \ starts a FORTH word
23140 \ TOP_LCD 2 20_us \ -- %0000HHHH
23141 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
23142 \ HI2LO \ switch from FORTH to assembler
23143 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
23144 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
23145 \ MOV @RSP+,IP \ restore IP saved by COLON
23150 \ CODE LCD_RdS \ -- status Read Status
23151 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23156 \ CODE LCD_RdC \ -- char Read Char
23157 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23162 \ -------------+------+------+------+------++---+---+---+---+---------+
23163 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
23164 \ -------------+------+------+------+------++---+---+---+---+---------+
23165 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
23166 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
23167 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
23168 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
23169 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
23170 \ -------------+------+------+------+------++---+---+---+---+---------+
23173 \ ******************************\
23174 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23175 \ ******************************\
23176 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
23177 \ ------------------------------\
23178 \ define LPM mode for ACCEPT \
23179 \ ------------------------------\
23180 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23181 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23182 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23183 BIT.B #SW2,&SW2_IN \ test switch S2
23184 0= IF \ case of switch S2 pressed
23185 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
23187 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
23190 BIT.B #SW1,&SW1_IN \ test switch S1 input
23191 0= IF \ case of Switch S1 pressed
23192 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
23194 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
23198 RETI \ CPU is ON, GIE is OFF
23203 \ ------------------------------\
23204 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23205 \ ******************************\
23206 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23207 \ ******************************\
23208 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23209 \ \ SMclock = 8|16|24 MHz
23210 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
23211 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
23212 \ \ SR(9)=new Toggle bit memory (ADD on)
23213 \ ------------------------------\
23214 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
23215 \ ------------------------------\
23216 \ define LPM mode for ACCEPT \
23217 \ ------------------------------\
23218 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23219 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23220 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23221 \ ------------------------------\
23222 \ RC5_FirstStartBitHalfCycle: \
23223 \ ------------------------------\
23224 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
23225 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
23226 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
23227 MOV #1778,X \ RC5_Period in us
23228 MOV #14,W \ count of loop
23230 \ ------------------------------\
23231 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
23232 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
23233 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
23234 \ RC5_Compute_3/4_Period: \ |
23235 RRUM #1,X \ X=1/2 cycle |
23239 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
23240 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
23242 \ ------------------------------\
23243 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
23244 \ ------------------------------\
23245 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23246 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
23247 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23248 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23249 SUB #1,W \ decrement count loop
23250 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
23251 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23252 0<> WHILE \ ----> out of loop ----+
23253 \ RC5_compute_7/4_Time_out: \ |
23254 ADD X,Y \ | out of bound = 7/4 period
23255 \ RC5_WaitHalfCycleP1.2_IFG: \ |
23257 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
23258 0>= IF \ | if cycle time out of bound
23259 BIC #$30,&TA0CTL \ | stop timer_A0
23260 RETI \ | then quit to do nothing
23262 \ ------------------------------\ |
23263 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
23265 MOV &TA0R,X \ | | get new RC5_period value
23266 REPEAT \ ----> loop back --+ |
23267 \ ------------------------------\ |
23268 \ RC5_SampleEndOf: \ <---------------------+
23269 \ ------------------------------\
23270 BIC #$30,&TA0CTL \ stop timer_A0
23271 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
23272 \ ******************************\
23273 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23274 \ ******************************\
23275 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
23276 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
23277 XOR IP,X \ (new XOR old) Toggle bit (13)
23278 BIT #BIT13,X \ X(13) = New_RC5_command
23279 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
23281 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
23282 \ ******************************\
23283 \ RC5_ComputeNewRC5word \
23284 \ ******************************\
23286 MOV &BASE,2(PSP) \ save variable BASE before use
23287 MOV TOS,0(PSP) \ save TOS before use
23288 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
23289 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
23290 \ ******************************\
23291 \ RC5_ComputeC6bit \
23292 \ ******************************\
23293 BIT #$4000,IP \ test /C6 bit in IP
23294 0= IF BIS #$40,TOS \ set C6 bit in S
23295 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
23296 \ ******************************\
23297 \ RC5_CommandByteIsDone \ RC5_code --
23298 \ ******************************\
23300 \ ------------------------------\
23301 \ Display IR_RC5 code \
23302 \ ------------------------------\
23303 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
23304 \ ------------------------------\
23305 LO2HI \ switch from assembler to FORTH
23306 ['] LCD_CLEAR IS CR \ redirects CR
23307 ['] LCD_WrC IS EMIT \ redirects EMIT
23308 $10 BASE ! \ change BASE to hexadecimal
23309 CR ." $" 2 U.R \ print IR_RC5 code
23310 ['] (CR) IS CR \ restore CR
23311 ['] (EMIT) IS EMIT \ restore EMIT
23312 HI2LO \ switch from FORTH to assembler
23313 \ ------------------------------\
23314 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
23315 \ ------------------------------\
23316 MOV @PSP+,&BASE \ restore variable BASE
23317 RETI \ CPU is ON, GIE is OFF
23322 \ ------------------------------\
23323 \ TB0CTL = %0000 0010 1001 0100\$3C0
23324 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23325 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23326 \ -- \ID input divider \ 10 = /4
23327 \ -- \MC Mode Control \ 01 = up to TB0CCR0
23328 \ - \TBCLR TimerB Clear
23331 \ --------------------------------\\
23332 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23333 \ -- \CM Capture Mode
23338 \ --- \OUTMOD \ 011 = set/reset
23344 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
23346 \ ------------------------------\
23347 \ set TimerB to make 50kHz PWM \
23348 \ ------------------------------\
23349 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
23350 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
23351 \ ------------------------------\
23352 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
23353 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
23354 \ ------------------------------\
23355 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23356 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
23357 \ ------------------------------\
23358 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23359 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
23360 \ ------------------------------\
23361 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23362 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
23363 \ ------------------------------\
23364 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
23365 \ ------------------------------\
23366 \ set TimerB to generate PWM for LCD_Vo
23367 \ ------------------------------\
23368 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
23369 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
23370 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23371 \ ------------------------------\
23372 BIS.B #LCDVo,&LCDVo_DIR \
23373 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
23374 \ ------------------------------\
23375 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23376 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23377 \ ------------------------------\
23378 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
23379 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
23380 \ ------------------------------\
23381 \ WDT interval init part \
23382 \ ------------------------------\
23383 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
23384 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
23385 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
23386 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
23387 \ ------------------------------\
23389 \ ------------------------------\
23390 BIS.B #RC5,&IR_IE \ enable RC5_Int
23391 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
23392 \ ------------------------------\
23393 \ init interrupt vectors
23394 \ ------------------------------\
23395 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
23396 MOV #RC5_INT,&IR_Vec \ init interrupt vector
23397 \ ------------------------------\
23398 \ define LPM mode for ACCEPT \
23399 \ ------------------------------\
23400 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23401 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23402 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23404 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
23406 \ ------------------------------\
23408 \ ------------------------------\
23409 $03E8 20_US \ 1- wait 20 ms
23410 $03 TOP_LCD \ 2- send DB5=DB4=1
23411 $CD 20_US \ 3- wait 4,1 ms
23412 $03 TOP_LCD \ 4- send again DB5=DB4=1
23413 $5 20_US \ 5- wait 0,1 ms
23414 $03 TOP_LCD \ 6- send again again DB5=DB4=1
23415 $2 20_US \ wait 40 us = LCD cycle
23416 $02 TOP_LCD \ 7- send DB5=1 DB4=0
23417 $2 20_US \ wait 40 us = LCD cycle
23418 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23419 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23420 LCD_Clear \ 10- "LCD_Clear"
23421 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23422 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23423 LCD_Clear \ 10- "LCD_Clear"
23424 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23425 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23427 ['] (CR) IS CR \ ' (CR) is CR
23428 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
23430 ." RC5toLCD is running. Type STOP to quit"
23431 \ NOECHO \ uncomment to run this app without terminal connexion
23432 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
23433 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
23437 : STOP \ stops multitasking, must to be used before downloading app
23438 ['] (WARM) IS WARM \ remove START app from FORTH init process
23439 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
23447 CODE MAX \ n1 n2 -- n3 signed maximum
23448 CMP @PSP,TOS \ n2-n1
23449 S< ?GOTO FW1 \ n2<n1
23455 CODE MIN \ n1 n2 -- n3 signed minimum
23456 CMP @PSP,TOS \ n2-n1
23457 S< ?GOTO BW1 \ n2<n1
23463 : U.R \ u n -- display u unsigned in n width (n >= 2)
23465 R> OVER - 0 MAX SPACES TYPE
23469 CODE 20_US \ n -- n * 20 us
23470 BEGIN \ 3 cycles loop + 6~
23471 \ MOV #5,W \ 3 MCLK = 1 MHz
23472 \ MOV #23,W \ 3 MCLK = 4 MHz
23473 MOV #51,W \ 3 MCLK = 8 MHz
23474 \ MOV #104,W \ 3 MCLK = 16 MHz
23475 \ MOV #158,W \ 3 MCLK = 24 MHz
23476 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
23486 CODE TOP_LCD \ LCD Sample
23487 \ \ if write : %xxxxWWWW --
23488 \ \ if read : -- %0000RRRR
23489 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23490 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23491 0= IF \ write LCD bits pattern
23492 AND.B #LCD_DB,TOS \
23493 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23494 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23497 THEN \ read LCD bits pattern
23500 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23501 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23502 AND.B #LCD_DB,TOS \
23507 CODE LCD_W \ byte -- write byte to LCD
23509 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
23510 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
23511 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23512 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23513 COLON \ high level word starts here
23514 TOP_LCD 2 20_US \ write high nibble first
23519 CODE LCD_WrC \ char -- Write Char
23520 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23525 CODE LCD_WrF \ func -- Write Fonction
23526 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23532 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
23537 $02 LCD_WrF 100 20_us
23541 \ : LCD_Entry_set $04 OR LCD_WrF ;
23543 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
23545 \ : LCD_Display_Shift $10 OR LCD_WrF ;
23547 \ : LCD_Fn_Set $20 OR LCD_WrF ;
23549 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
23551 \ : LCD_Goto $80 OR LCD_WrF ;
23553 \ CODE LCD_R \ -- byte read byte from LCD
23554 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23555 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23556 \ COLON \ starts a FORTH word
23557 \ TOP_LCD 2 20_us \ -- %0000HHHH
23558 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
23559 \ HI2LO \ switch from FORTH to assembler
23560 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
23561 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
23562 \ MOV @RSP+,IP \ restore IP saved by COLON
23567 \ CODE LCD_RdS \ -- status Read Status
23568 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23573 \ CODE LCD_RdC \ -- char Read Char
23574 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23579 \ -------------+------+------+------+------++---+---+---+---+---------+
23580 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
23581 \ -------------+------+------+------+------++---+---+---+---+---------+
23582 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
23583 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
23584 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
23585 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
23586 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
23587 \ -------------+------+------+------+------++---+---+---+---+---------+
23590 \ ******************************\
23591 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23592 \ ******************************\
23593 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
23594 \ ------------------------------\
23595 \ define LPM mode for ACCEPT \
23596 \ ------------------------------\
23597 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23598 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23599 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23600 BIT.B #SW2,&SW2_IN \ test switch S2
23601 0= IF \ case of switch S2 pressed
23602 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
23604 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
23607 BIT.B #SW1,&SW1_IN \ test switch S1 input
23608 0= IF \ case of Switch S1 pressed
23609 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
23611 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
23615 RETI \ CPU is ON, GIE is OFF
23620 \ ------------------------------\
23621 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23622 \ ******************************\
23623 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23624 \ ******************************\
23625 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23626 \ \ SMclock = 8|16|24 MHz
23627 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
23628 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
23629 \ \ SR(9)=new Toggle bit memory (ADD on)
23630 \ ------------------------------\
23631 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
23632 \ ------------------------------\
23633 \ define LPM mode for ACCEPT \
23634 \ ------------------------------\
23635 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23636 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23637 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23638 \ ------------------------------\
23639 \ RC5_FirstStartBitHalfCycle: \
23640 \ ------------------------------\
23641 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
23642 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
23643 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
23644 MOV #1778,X \ RC5_Period in us
23645 MOV #14,W \ count of loop
23647 \ ------------------------------\
23648 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
23649 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
23650 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
23651 \ RC5_Compute_3/4_Period: \ |
23652 RRUM #1,X \ X=1/2 cycle |
23656 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
23657 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
23659 \ ------------------------------\
23660 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
23661 \ ------------------------------\
23662 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23663 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
23664 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23665 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23666 SUB #1,W \ decrement count loop
23667 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
23668 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23669 0<> WHILE \ ----> out of loop ----+
23670 \ RC5_compute_7/4_Time_out: \ |
23671 ADD X,Y \ | out of bound = 7/4 period
23672 \ RC5_WaitHalfCycleP1.2_IFG: \ |
23674 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
23675 0>= IF \ | if cycle time out of bound
23676 BIC #$30,&TA0CTL \ | stop timer_A0
23677 RETI \ | then quit to do nothing
23679 \ ------------------------------\ |
23680 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
23682 MOV &TA0R,X \ | | get new RC5_period value
23683 REPEAT \ ----> loop back --+ |
23684 \ ------------------------------\ |
23685 \ RC5_SampleEndOf: \ <---------------------+
23686 \ ------------------------------\
23687 BIC #$30,&TA0CTL \ stop timer_A0
23688 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
23689 \ ******************************\
23690 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23691 \ ******************************\
23692 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
23693 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
23694 XOR IP,X \ (new XOR old) Toggle bit (13)
23695 BIT #BIT13,X \ X(13) = New_RC5_command
23696 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
23698 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
23699 \ ******************************\
23700 \ RC5_ComputeNewRC5word \
23701 \ ******************************\
23703 MOV &BASE,2(PSP) \ save variable BASE before use
23704 MOV TOS,0(PSP) \ save TOS before use
23705 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
23706 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
23707 \ ******************************\
23708 \ RC5_ComputeC6bit \
23709 \ ******************************\
23710 BIT #$4000,IP \ test /C6 bit in IP
23711 0= IF BIS #$40,TOS \ set C6 bit in S
23712 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
23713 \ ******************************\
23714 \ RC5_CommandByteIsDone \ RC5_code --
23715 \ ******************************\
23717 \ ------------------------------\
23718 \ Display IR_RC5 code \
23719 \ ------------------------------\
23720 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
23721 \ ------------------------------\
23722 LO2HI \ switch from assembler to FORTH
23723 ['] LCD_CLEAR IS CR \ redirects CR
23724 ['] LCD_WrC IS EMIT \ redirects EMIT
23725 $10 BASE ! \ change BASE to hexadecimal
23726 CR ." $" 2 U.R \ print IR_RC5 code
23727 ['] (CR) IS CR \ restore CR
23728 ['] (EMIT) IS EMIT \ restore EMIT
23729 HI2LO \ switch from FORTH to assembler
23730 \ ------------------------------\
23731 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
23732 \ ------------------------------\
23733 MOV @PSP+,&BASE \ restore variable BASE
23734 RETI \ CPU is ON, GIE is OFF
23739 \ ------------------------------\
23740 \ TB0CTL = %0000 0010 1001 0100\$3C0
23741 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23742 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23743 \ -- \ID input divider \ 10 = /4
23744 \ -- \MC Mode Control \ 01 = up to TB0CCR0
23745 \ - \TBCLR TimerB Clear
23748 \ --------------------------------\\
23749 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23750 \ -- \CM Capture Mode
23755 \ --- \OUTMOD \ 011 = set/reset
23761 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
23763 \ ------------------------------\
23764 \ set TimerB to make 50kHz PWM \
23765 \ ------------------------------\
23766 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
23767 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
23768 \ ------------------------------\
23769 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
23770 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
23771 \ ------------------------------\
23772 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23773 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
23774 \ ------------------------------\
23775 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23776 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
23777 \ ------------------------------\
23778 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23779 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
23780 \ ------------------------------\
23781 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
23782 \ ------------------------------\
23783 \ set TimerB to generate PWM for LCD_Vo
23784 \ ------------------------------\
23785 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
23786 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
23787 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23788 \ ------------------------------\
23789 BIS.B #LCDVo,&LCDVo_DIR \
23790 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
23791 \ ------------------------------\
23792 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23793 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23794 \ ------------------------------\
23795 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
23796 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
23797 \ ------------------------------\
23798 \ WDT interval init part \
23799 \ ------------------------------\
23800 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
23801 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
23802 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
23803 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
23804 \ ------------------------------\
23806 \ ------------------------------\
23807 BIS.B #RC5,&IR_IE \ enable RC5_Int
23808 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
23809 \ ------------------------------\
23810 \ init interrupt vectors
23811 \ ------------------------------\
23812 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
23813 MOV #RC5_INT,&IR_Vec \ init interrupt vector
23814 \ ------------------------------\
23815 \ define LPM mode for ACCEPT \
23816 \ ------------------------------\
23817 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23818 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23819 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23821 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
23823 \ ------------------------------\
23825 \ ------------------------------\
23826 $03E8 20_US \ 1- wait 20 ms
23827 $03 TOP_LCD \ 2- send DB5=DB4=1
23828 $CD 20_US \ 3- wait 4,1 ms
23829 $03 TOP_LCD \ 4- send again DB5=DB4=1
23830 $5 20_US \ 5- wait 0,1 ms
23831 $03 TOP_LCD \ 6- send again again DB5=DB4=1
23832 $2 20_US \ wait 40 us = LCD cycle
23833 $02 TOP_LCD \ 7- send DB5=1 DB4=0
23834 $2 20_US \ wait 40 us = LCD cycle
23835 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23836 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23837 LCD_Clear \ 10- "LCD_Clear"
23838 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23839 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23840 LCD_Clear \ 10- "LCD_Clear"
23841 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23842 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23844 ['] (CR) IS CR \ ' (CR) is CR
23845 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
23847 ." RC5toLCD is running. Type STOP to quit"
23848 \ NOECHO \ uncomment to run this app without terminal connexion
23849 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
23850 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
23854 : STOP \ stops multitasking, must to be used before downloading app
23855 ['] (WARM) IS WARM \ remove START app from FORTH init process
23856 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
23864 CODE MAX \ n1 n2 -- n3 signed maximum
23865 CMP @PSP,TOS \ n2-n1
23866 S< ?GOTO FW1 \ n2<n1
23872 CODE MIN \ n1 n2 -- n3 signed minimum
23873 CMP @PSP,TOS \ n2-n1
23874 S< ?GOTO BW1 \ n2<n1
23880 : U.R \ u n -- display u unsigned in n width (n >= 2)
23882 R> OVER - 0 MAX SPACES TYPE
23886 CODE 20_US \ n -- n * 20 us
23887 BEGIN \ 3 cycles loop + 6~
23888 \ MOV #5,W \ 3 MCLK = 1 MHz
23889 \ MOV #23,W \ 3 MCLK = 4 MHz
23890 MOV #51,W \ 3 MCLK = 8 MHz
23891 \ MOV #104,W \ 3 MCLK = 16 MHz
23892 \ MOV #158,W \ 3 MCLK = 24 MHz
23893 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
23903 CODE TOP_LCD \ LCD Sample
23904 \ \ if write : %xxxxWWWW --
23905 \ \ if read : -- %0000RRRR
23906 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23907 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23908 0= IF \ write LCD bits pattern
23909 AND.B #LCD_DB,TOS \
23910 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23911 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23914 THEN \ read LCD bits pattern
23917 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23918 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23919 AND.B #LCD_DB,TOS \
23924 CODE LCD_W \ byte -- write byte to LCD
23926 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
23927 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
23928 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23929 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23930 COLON \ high level word starts here
23931 TOP_LCD 2 20_US \ write high nibble first
23936 CODE LCD_WrC \ char -- Write Char
23937 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23942 CODE LCD_WrF \ func -- Write Fonction
23943 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23949 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
23954 $02 LCD_WrF 100 20_us
23958 \ : LCD_Entry_set $04 OR LCD_WrF ;
23960 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
23962 \ : LCD_Display_Shift $10 OR LCD_WrF ;
23964 \ : LCD_Fn_Set $20 OR LCD_WrF ;
23966 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
23968 \ : LCD_Goto $80 OR LCD_WrF ;
23970 \ CODE LCD_R \ -- byte read byte from LCD
23971 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23972 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23973 \ COLON \ starts a FORTH word
23974 \ TOP_LCD 2 20_us \ -- %0000HHHH
23975 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
23976 \ HI2LO \ switch from FORTH to assembler
23977 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
23978 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
23979 \ MOV @RSP+,IP \ restore IP saved by COLON
23984 \ CODE LCD_RdS \ -- status Read Status
23985 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23990 \ CODE LCD_RdC \ -- char Read Char
23991 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23996 \ -------------+------+------+------+------++---+---+---+---+---------+
23997 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
23998 \ -------------+------+------+------+------++---+---+---+---+---------+
23999 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
24000 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
24001 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
24002 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
24003 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
24004 \ -------------+------+------+------+------++---+---+---+---+---------+
24007 \ ******************************\
24008 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24009 \ ******************************\
24010 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
24011 \ ------------------------------\
24012 \ define LPM mode for ACCEPT \
24013 \ ------------------------------\
24014 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24015 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24016 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24017 BIT.B #SW2,&SW2_IN \ test switch S2
24018 0= IF \ case of switch S2 pressed
24019 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
24021 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
24024 BIT.B #SW1,&SW1_IN \ test switch S1 input
24025 0= IF \ case of Switch S1 pressed
24026 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
24028 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
24032 RETI \ CPU is ON, GIE is OFF
24037 \ ------------------------------\
24038 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24039 \ ******************************\
24040 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24041 \ ******************************\
24042 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24043 \ \ SMclock = 8|16|24 MHz
24044 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
24045 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
24046 \ \ SR(9)=new Toggle bit memory (ADD on)
24047 \ ------------------------------\
24048 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
24049 \ ------------------------------\
24050 \ define LPM mode for ACCEPT \
24051 \ ------------------------------\
24052 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24053 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24054 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24055 \ ------------------------------\
24056 \ RC5_FirstStartBitHalfCycle: \
24057 \ ------------------------------\
24058 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
24059 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
24060 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
24061 MOV #1778,X \ RC5_Period in us
24062 MOV #14,W \ count of loop
24064 \ ------------------------------\
24065 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
24066 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
24067 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
24068 \ RC5_Compute_3/4_Period: \ |
24069 RRUM #1,X \ X=1/2 cycle |
24073 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
24074 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
24076 \ ------------------------------\
24077 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
24078 \ ------------------------------\
24079 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24080 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
24081 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24082 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24083 SUB #1,W \ decrement count loop
24084 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
24085 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24086 0<> WHILE \ ----> out of loop ----+
24087 \ RC5_compute_7/4_Time_out: \ |
24088 ADD X,Y \ | out of bound = 7/4 period
24089 \ RC5_WaitHalfCycleP1.2_IFG: \ |
24091 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
24092 0>= IF \ | if cycle time out of bound
24093 BIC #$30,&TA0CTL \ | stop timer_A0
24094 RETI \ | then quit to do nothing
24096 \ ------------------------------\ |
24097 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
24099 MOV &TA0R,X \ | | get new RC5_period value
24100 REPEAT \ ----> loop back --+ |
24101 \ ------------------------------\ |
24102 \ RC5_SampleEndOf: \ <---------------------+
24103 \ ------------------------------\
24104 BIC #$30,&TA0CTL \ stop timer_A0
24105 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
24106 \ ******************************\
24107 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24108 \ ******************************\
24109 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
24110 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
24111 XOR IP,X \ (new XOR old) Toggle bit (13)
24112 BIT #BIT13,X \ X(13) = New_RC5_command
24113 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
24115 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
24116 \ ******************************\
24117 \ RC5_ComputeNewRC5word \
24118 \ ******************************\
24120 MOV &BASE,2(PSP) \ save variable BASE before use
24121 MOV TOS,0(PSP) \ save TOS before use
24122 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
24123 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
24124 \ ******************************\
24125 \ RC5_ComputeC6bit \
24126 \ ******************************\
24127 BIT #$4000,IP \ test /C6 bit in IP
24128 0= IF BIS #$40,TOS \ set C6 bit in S
24129 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
24130 \ ******************************\
24131 \ RC5_CommandByteIsDone \ RC5_code --
24132 \ ******************************\
24134 \ ------------------------------\
24135 \ Display IR_RC5 code \
24136 \ ------------------------------\
24137 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
24138 \ ------------------------------\
24139 LO2HI \ switch from assembler to FORTH
24140 ['] LCD_CLEAR IS CR \ redirects CR
24141 ['] LCD_WrC IS EMIT \ redirects EMIT
24142 $10 BASE ! \ change BASE to hexadecimal
24143 CR ." $" 2 U.R \ print IR_RC5 code
24144 ['] (CR) IS CR \ restore CR
24145 ['] (EMIT) IS EMIT \ restore EMIT
24146 HI2LO \ switch from FORTH to assembler
24147 \ ------------------------------\
24148 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
24149 \ ------------------------------\
24150 MOV @PSP+,&BASE \ restore variable BASE
24151 RETI \ CPU is ON, GIE is OFF
24156 \ ------------------------------\
24157 \ TB0CTL = %0000 0010 1001 0100\$3C0
24158 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24159 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24160 \ -- \ID input divider \ 10 = /4
24161 \ -- \MC Mode Control \ 01 = up to TB0CCR0
24162 \ - \TBCLR TimerB Clear
24165 \ --------------------------------\\
24166 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24167 \ -- \CM Capture Mode
24172 \ --- \OUTMOD \ 011 = set/reset
24178 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
24180 \ ------------------------------\
24181 \ set TimerB to make 50kHz PWM \
24182 \ ------------------------------\
24183 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
24184 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
24185 \ ------------------------------\
24186 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
24187 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
24188 \ ------------------------------\
24189 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24190 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
24191 \ ------------------------------\
24192 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24193 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
24194 \ ------------------------------\
24195 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24196 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
24197 \ ------------------------------\
24198 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
24199 \ ------------------------------\
24200 \ set TimerB to generate PWM for LCD_Vo
24201 \ ------------------------------\
24202 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
24203 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
24204 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24205 \ ------------------------------\
24206 BIS.B #LCDVo,&LCDVo_DIR \
24207 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
24208 \ ------------------------------\
24209 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24210 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24211 \ ------------------------------\
24212 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24213 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24214 \ ------------------------------\
24215 \ WDT interval init part \
24216 \ ------------------------------\
24217 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
24218 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
24219 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
24220 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
24221 \ ------------------------------\
24223 \ ------------------------------\
24224 BIS.B #RC5,&IR_IE \ enable RC5_Int
24225 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24226 \ ------------------------------\
24227 \ init interrupt vectors
24228 \ ------------------------------\
24229 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
24230 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24231 \ ------------------------------\
24232 \ define LPM mode for ACCEPT \
24233 \ ------------------------------\
24234 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24235 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24236 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24238 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
24240 \ ------------------------------\
24242 \ ------------------------------\
24243 $03E8 20_US \ 1- wait 20 ms
24244 $03 TOP_LCD \ 2- send DB5=DB4=1
24245 $CD 20_US \ 3- wait 4,1 ms
24246 $03 TOP_LCD \ 4- send again DB5=DB4=1
24247 $5 20_US \ 5- wait 0,1 ms
24248 $03 TOP_LCD \ 6- send again again DB5=DB4=1
24249 $2 20_US \ wait 40 us = LCD cycle
24250 $02 TOP_LCD \ 7- send DB5=1 DB4=0
24251 $2 20_US \ wait 40 us = LCD cycle
24252 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24253 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24254 LCD_Clear \ 10- "LCD_Clear"
24255 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24256 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24257 LCD_Clear \ 10- "LCD_Clear"
24258 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24259 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24261 ['] (CR) IS CR \ ' (CR) is CR
24262 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
24264 ." RC5toLCD is running. Type STOP to quit"
24265 \ NOECHO \ uncomment to run this app without terminal connexion
24266 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
24267 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
24271 : STOP \ stops multitasking, must to be used before downloading app
24272 ['] (WARM) IS WARM \ remove START app from FORTH init process
24273 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
24281 CODE MAX \ n1 n2 -- n3 signed maximum
24282 CMP @PSP,TOS \ n2-n1
24283 S< ?GOTO FW1 \ n2<n1
24289 CODE MIN \ n1 n2 -- n3 signed minimum
24290 CMP @PSP,TOS \ n2-n1
24291 S< ?GOTO BW1 \ n2<n1
24297 : U.R \ u n -- display u unsigned in n width (n >= 2)
24299 R> OVER - 0 MAX SPACES TYPE
24303 CODE 20_US \ n -- n * 20 us
24304 BEGIN \ 3 cycles loop + 6~
24305 \ MOV #5,W \ 3 MCLK = 1 MHz
24306 \ MOV #23,W \ 3 MCLK = 4 MHz
24307 MOV #51,W \ 3 MCLK = 8 MHz
24308 \ MOV #104,W \ 3 MCLK = 16 MHz
24309 \ MOV #158,W \ 3 MCLK = 24 MHz
24310 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
24320 CODE TOP_LCD \ LCD Sample
24321 \ \ if write : %xxxxWWWW --
24322 \ \ if read : -- %0000RRRR
24323 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24324 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24325 0= IF \ write LCD bits pattern
24326 AND.B #LCD_DB,TOS \
24327 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24328 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24331 THEN \ read LCD bits pattern
24334 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24335 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24336 AND.B #LCD_DB,TOS \
24341 CODE LCD_W \ byte -- write byte to LCD
24343 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
24344 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
24345 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24346 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24347 COLON \ high level word starts here
24348 TOP_LCD 2 20_US \ write high nibble first
24353 CODE LCD_WrC \ char -- Write Char
24354 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24359 CODE LCD_WrF \ func -- Write Fonction
24360 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24366 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
24371 $02 LCD_WrF 100 20_us
24375 \ : LCD_Entry_set $04 OR LCD_WrF ;
24377 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
24379 \ : LCD_Display_Shift $10 OR LCD_WrF ;
24381 \ : LCD_Fn_Set $20 OR LCD_WrF ;
24383 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
24385 \ : LCD_Goto $80 OR LCD_WrF ;
24387 \ CODE LCD_R \ -- byte read byte from LCD
24388 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24389 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24390 \ COLON \ starts a FORTH word
24391 \ TOP_LCD 2 20_us \ -- %0000HHHH
24392 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
24393 \ HI2LO \ switch from FORTH to assembler
24394 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
24395 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
24396 \ MOV @RSP+,IP \ restore IP saved by COLON
24401 \ CODE LCD_RdS \ -- status Read Status
24402 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24407 \ CODE LCD_RdC \ -- char Read Char
24408 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24413 \ -------------+------+------+------+------++---+---+---+---+---------+
24414 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
24415 \ -------------+------+------+------+------++---+---+---+---+---------+
24416 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
24417 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
24418 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
24419 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
24420 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
24421 \ -------------+------+------+------+------++---+---+---+---+---------+
24424 \ ******************************\
24425 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24426 \ ******************************\
24427 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
24428 \ ------------------------------\
24429 \ define LPM mode for ACCEPT \
24430 \ ------------------------------\
24431 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24432 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24433 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24434 BIT.B #SW2,&SW2_IN \ test switch S2
24435 0= IF \ case of switch S2 pressed
24436 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
24438 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
24441 BIT.B #SW1,&SW1_IN \ test switch S1 input
24442 0= IF \ case of Switch S1 pressed
24443 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
24445 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
24449 RETI \ CPU is ON, GIE is OFF
24454 \ ------------------------------\
24455 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24456 \ ******************************\
24457 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24458 \ ******************************\
24459 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24460 \ \ SMclock = 8|16|24 MHz
24461 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
24462 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
24463 \ \ SR(9)=new Toggle bit memory (ADD on)
24464 \ ------------------------------\
24465 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
24466 \ ------------------------------\
24467 \ define LPM mode for ACCEPT \
24468 \ ------------------------------\
24469 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24470 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24471 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24472 \ ------------------------------\
24473 \ RC5_FirstStartBitHalfCycle: \
24474 \ ------------------------------\
24475 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
24476 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
24477 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
24478 MOV #1778,X \ RC5_Period in us
24479 MOV #14,W \ count of loop
24481 \ ------------------------------\
24482 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
24483 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
24484 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
24485 \ RC5_Compute_3/4_Period: \ |
24486 RRUM #1,X \ X=1/2 cycle |
24490 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
24491 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
24493 \ ------------------------------\
24494 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
24495 \ ------------------------------\
24496 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24497 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
24498 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24499 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24500 SUB #1,W \ decrement count loop
24501 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
24502 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24503 0<> WHILE \ ----> out of loop ----+
24504 \ RC5_compute_7/4_Time_out: \ |
24505 ADD X,Y \ | out of bound = 7/4 period
24506 \ RC5_WaitHalfCycleP1.2_IFG: \ |
24508 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
24509 0>= IF \ | if cycle time out of bound
24510 BIC #$30,&TA0CTL \ | stop timer_A0
24511 RETI \ | then quit to do nothing
24513 \ ------------------------------\ |
24514 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
24516 MOV &TA0R,X \ | | get new RC5_period value
24517 REPEAT \ ----> loop back --+ |
24518 \ ------------------------------\ |
24519 \ RC5_SampleEndOf: \ <---------------------+
24520 \ ------------------------------\
24521 BIC #$30,&TA0CTL \ stop timer_A0
24522 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
24523 \ ******************************\
24524 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24525 \ ******************************\
24526 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
24527 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
24528 XOR IP,X \ (new XOR old) Toggle bit (13)
24529 BIT #BIT13,X \ X(13) = New_RC5_command
24530 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
24532 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
24533 \ ******************************\
24534 \ RC5_ComputeNewRC5word \
24535 \ ******************************\
24537 MOV &BASE,2(PSP) \ save variable BASE before use
24538 MOV TOS,0(PSP) \ save TOS before use
24539 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
24540 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
24541 \ ******************************\
24542 \ RC5_ComputeC6bit \
24543 \ ******************************\
24544 BIT #$4000,IP \ test /C6 bit in IP
24545 0= IF BIS #$40,TOS \ set C6 bit in S
24546 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
24547 \ ******************************\
24548 \ RC5_CommandByteIsDone \ RC5_code --
24549 \ ******************************\
24551 \ ------------------------------\
24552 \ Display IR_RC5 code \
24553 \ ------------------------------\
24554 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
24555 \ ------------------------------\
24556 LO2HI \ switch from assembler to FORTH
24557 ['] LCD_CLEAR IS CR \ redirects CR
24558 ['] LCD_WrC IS EMIT \ redirects EMIT
24559 $10 BASE ! \ change BASE to hexadecimal
24560 CR ." $" 2 U.R \ print IR_RC5 code
24561 ['] (CR) IS CR \ restore CR
24562 ['] (EMIT) IS EMIT \ restore EMIT
24563 HI2LO \ switch from FORTH to assembler
24564 \ ------------------------------\
24565 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
24566 \ ------------------------------\
24567 MOV @PSP+,&BASE \ restore variable BASE
24568 RETI \ CPU is ON, GIE is OFF
24573 \ ------------------------------\
24574 \ TB0CTL = %0000 0010 1001 0100\$3C0
24575 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24576 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24577 \ -- \ID input divider \ 10 = /4
24578 \ -- \MC Mode Control \ 01 = up to TB0CCR0
24579 \ - \TBCLR TimerB Clear
24582 \ --------------------------------\\
24583 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24584 \ -- \CM Capture Mode
24589 \ --- \OUTMOD \ 011 = set/reset
24595 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
24597 \ ------------------------------\
24598 \ set TimerB to make 50kHz PWM \
24599 \ ------------------------------\
24600 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
24601 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
24602 \ ------------------------------\
24603 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
24604 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
24605 \ ------------------------------\
24606 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24607 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
24608 \ ------------------------------\
24609 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24610 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
24611 \ ------------------------------\
24612 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24613 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
24614 \ ------------------------------\
24615 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
24616 \ ------------------------------\
24617 \ set TimerB to generate PWM for LCD_Vo
24618 \ ------------------------------\
24619 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
24620 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
24621 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24622 \ ------------------------------\
24623 BIS.B #LCDVo,&LCDVo_DIR \
24624 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
24625 \ ------------------------------\
24626 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24627 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24628 \ ------------------------------\
24629 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24630 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24631 \ ------------------------------\
24632 \ WDT interval init part \
24633 \ ------------------------------\
24634 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
24635 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
24636 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
24637 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
24638 \ ------------------------------\
24640 \ ------------------------------\
24641 BIS.B #RC5,&IR_IE \ enable RC5_Int
24642 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24643 \ ------------------------------\
24644 \ init interrupt vectors
24645 \ ------------------------------\
24646 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
24647 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24648 \ ------------------------------\
24649 \ define LPM mode for ACCEPT \
24650 \ ------------------------------\
24651 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24652 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24653 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24655 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
24657 \ ------------------------------\
24659 \ ------------------------------\
24660 $03E8 20_US \ 1- wait 20 ms
24661 $03 TOP_LCD \ 2- send DB5=DB4=1
24662 $CD 20_US \ 3- wait 4,1 ms
24663 $03 TOP_LCD \ 4- send again DB5=DB4=1
24664 $5 20_US \ 5- wait 0,1 ms
24665 $03 TOP_LCD \ 6- send again again DB5=DB4=1
24666 $2 20_US \ wait 40 us = LCD cycle
24667 $02 TOP_LCD \ 7- send DB5=1 DB4=0
24668 $2 20_US \ wait 40 us = LCD cycle
24669 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24670 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24671 LCD_Clear \ 10- "LCD_Clear"
24672 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24673 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24674 LCD_Clear \ 10- "LCD_Clear"
24675 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24676 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24678 ['] (CR) IS CR \ ' (CR) is CR
24679 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
24681 ." RC5toLCD is running. Type STOP to quit"
24682 \ NOECHO \ uncomment to run this app without terminal connexion
24683 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
24684 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
24688 : STOP \ stops multitasking, must to be used before downloading app
24689 ['] (WARM) IS WARM \ remove START app from FORTH init process
24690 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
24698 CODE MAX \ n1 n2 -- n3 signed maximum
24699 CMP @PSP,TOS \ n2-n1
24700 S< ?GOTO FW1 \ n2<n1
24706 CODE MIN \ n1 n2 -- n3 signed minimum
24707 CMP @PSP,TOS \ n2-n1
24708 S< ?GOTO BW1 \ n2<n1
24714 : U.R \ u n -- display u unsigned in n width (n >= 2)
24716 R> OVER - 0 MAX SPACES TYPE
24720 CODE 20_US \ n -- n * 20 us
24721 BEGIN \ 3 cycles loop + 6~
24722 \ MOV #5,W \ 3 MCLK = 1 MHz
24723 \ MOV #23,W \ 3 MCLK = 4 MHz
24724 MOV #51,W \ 3 MCLK = 8 MHz
24725 \ MOV #104,W \ 3 MCLK = 16 MHz
24726 \ MOV #158,W \ 3 MCLK = 24 MHz
24727 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
24737 CODE TOP_LCD \ LCD Sample
24738 \ \ if write : %xxxxWWWW --
24739 \ \ if read : -- %0000RRRR
24740 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24741 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24742 0= IF \ write LCD bits pattern
24743 AND.B #LCD_DB,TOS \
24744 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24745 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24748 THEN \ read LCD bits pattern
24751 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24752 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24753 AND.B #LCD_DB,TOS \
24758 CODE LCD_W \ byte -- write byte to LCD
24760 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
24761 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
24762 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24763 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24764 COLON \ high level word starts here
24765 TOP_LCD 2 20_US \ write high nibble first
24770 CODE LCD_WrC \ char -- Write Char
24771 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24776 CODE LCD_WrF \ func -- Write Fonction
24777 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24783 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
24788 $02 LCD_WrF 100 20_us
24792 \ : LCD_Entry_set $04 OR LCD_WrF ;
24794 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
24796 \ : LCD_Display_Shift $10 OR LCD_WrF ;
24798 \ : LCD_Fn_Set $20 OR LCD_WrF ;
24800 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
24802 \ : LCD_Goto $80 OR LCD_WrF ;
24804 \ CODE LCD_R \ -- byte read byte from LCD
24805 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24806 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24807 \ COLON \ starts a FORTH word
24808 \ TOP_LCD 2 20_us \ -- %0000HHHH
24809 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
24810 \ HI2LO \ switch from FORTH to assembler
24811 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
24812 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
24813 \ MOV @RSP+,IP \ restore IP saved by COLON
24818 \ CODE LCD_RdS \ -- status Read Status
24819 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24824 \ CODE LCD_RdC \ -- char Read Char
24825 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24830 \ -------------+------+------+------+------++---+---+---+---+---------+
24831 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
24832 \ -------------+------+------+------+------++---+---+---+---+---------+
24833 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
24834 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
24835 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
24836 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
24837 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
24838 \ -------------+------+------+------+------++---+---+---+---+---------+
24841 \ ******************************\
24842 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24843 \ ******************************\
24844 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
24845 \ ------------------------------\
24846 \ define LPM mode for ACCEPT \
24847 \ ------------------------------\
24848 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24849 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24850 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24851 BIT.B #SW2,&SW2_IN \ test switch S2
24852 0= IF \ case of switch S2 pressed
24853 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
24855 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
24858 BIT.B #SW1,&SW1_IN \ test switch S1 input
24859 0= IF \ case of Switch S1 pressed
24860 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
24862 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
24866 RETI \ CPU is ON, GIE is OFF
24871 \ ------------------------------\
24872 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24873 \ ******************************\
24874 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24875 \ ******************************\
24876 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24877 \ \ SMclock = 8|16|24 MHz
24878 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
24879 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
24880 \ \ SR(9)=new Toggle bit memory (ADD on)
24881 \ ------------------------------\
24882 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
24883 \ ------------------------------\
24884 \ define LPM mode for ACCEPT \
24885 \ ------------------------------\
24886 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24887 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24888 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24889 \ ------------------------------\
24890 \ RC5_FirstStartBitHalfCycle: \
24891 \ ------------------------------\
24892 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
24893 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
24894 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
24895 MOV #1778,X \ RC5_Period in us
24896 MOV #14,W \ count of loop
24898 \ ------------------------------\
24899 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
24900 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
24901 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
24902 \ RC5_Compute_3/4_Period: \ |
24903 RRUM #1,X \ X=1/2 cycle |
24907 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
24908 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
24910 \ ------------------------------\
24911 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
24912 \ ------------------------------\
24913 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24914 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
24915 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24916 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24917 SUB #1,W \ decrement count loop
24918 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
24919 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24920 0<> WHILE \ ----> out of loop ----+
24921 \ RC5_compute_7/4_Time_out: \ |
24922 ADD X,Y \ | out of bound = 7/4 period
24923 \ RC5_WaitHalfCycleP1.2_IFG: \ |
24925 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
24926 0>= IF \ | if cycle time out of bound
24927 BIC #$30,&TA0CTL \ | stop timer_A0
24928 RETI \ | then quit to do nothing
24930 \ ------------------------------\ |
24931 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
24933 MOV &TA0R,X \ | | get new RC5_period value
24934 REPEAT \ ----> loop back --+ |
24935 \ ------------------------------\ |
24936 \ RC5_SampleEndOf: \ <---------------------+
24937 \ ------------------------------\
24938 BIC #$30,&TA0CTL \ stop timer_A0
24939 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
24940 \ ******************************\
24941 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24942 \ ******************************\
24943 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
24944 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
24945 XOR IP,X \ (new XOR old) Toggle bit (13)
24946 BIT #BIT13,X \ X(13) = New_RC5_command
24947 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
24949 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
24950 \ ******************************\
24951 \ RC5_ComputeNewRC5word \
24952 \ ******************************\
24954 MOV &BASE,2(PSP) \ save variable BASE before use
24955 MOV TOS,0(PSP) \ save TOS before use
24956 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
24957 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
24958 \ ******************************\
24959 \ RC5_ComputeC6bit \
24960 \ ******************************\
24961 BIT #$4000,IP \ test /C6 bit in IP
24962 0= IF BIS #$40,TOS \ set C6 bit in S
24963 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
24964 \ ******************************\
24965 \ RC5_CommandByteIsDone \ RC5_code --
24966 \ ******************************\
24968 \ ------------------------------\
24969 \ Display IR_RC5 code \
24970 \ ------------------------------\
24971 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
24972 \ ------------------------------\
24973 LO2HI \ switch from assembler to FORTH
24974 ['] LCD_CLEAR IS CR \ redirects CR
24975 ['] LCD_WrC IS EMIT \ redirects EMIT
24976 $10 BASE ! \ change BASE to hexadecimal
24977 CR ." $" 2 U.R \ print IR_RC5 code
24978 ['] (CR) IS CR \ restore CR
24979 ['] (EMIT) IS EMIT \ restore EMIT
24980 HI2LO \ switch from FORTH to assembler
24981 \ ------------------------------\
24982 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
24983 \ ------------------------------\
24984 MOV @PSP+,&BASE \ restore variable BASE
24985 RETI \ CPU is ON, GIE is OFF
24990 \ ------------------------------\
24991 \ TB0CTL = %0000 0010 1001 0100\$3C0
24992 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24993 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24994 \ -- \ID input divider \ 10 = /4
24995 \ -- \MC Mode Control \ 01 = up to TB0CCR0
24996 \ - \TBCLR TimerB Clear
24999 \ --------------------------------\\
25000 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25001 \ -- \CM Capture Mode
25006 \ --- \OUTMOD \ 011 = set/reset
25012 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
25014 \ ------------------------------\
25015 \ set TimerB to make 50kHz PWM \
25016 \ ------------------------------\
25017 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25018 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
25019 \ ------------------------------\
25020 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25021 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
25022 \ ------------------------------\
25023 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25024 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
25025 \ ------------------------------\
25026 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25027 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
25028 \ ------------------------------\
25029 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25030 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
25031 \ ------------------------------\
25032 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
25033 \ ------------------------------\
25034 \ set TimerB to generate PWM for LCD_Vo
25035 \ ------------------------------\
25036 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
25037 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
25038 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25039 \ ------------------------------\
25040 BIS.B #LCDVo,&LCDVo_DIR \
25041 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
25042 \ ------------------------------\
25043 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25044 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25045 \ ------------------------------\
25046 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25047 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25048 \ ------------------------------\
25049 \ WDT interval init part \
25050 \ ------------------------------\
25051 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
25052 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
25053 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
25054 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
25055 \ ------------------------------\
25057 \ ------------------------------\
25058 BIS.B #RC5,&IR_IE \ enable RC5_Int
25059 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25060 \ ------------------------------\
25061 \ init interrupt vectors
25062 \ ------------------------------\
25063 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
25064 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25065 \ ------------------------------\
25066 \ define LPM mode for ACCEPT \
25067 \ ------------------------------\
25068 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25069 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25070 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25072 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
25074 \ ------------------------------\
25076 \ ------------------------------\
25077 $03E8 20_US \ 1- wait 20 ms
25078 $03 TOP_LCD \ 2- send DB5=DB4=1
25079 $CD 20_US \ 3- wait 4,1 ms
25080 $03 TOP_LCD \ 4- send again DB5=DB4=1
25081 $5 20_US \ 5- wait 0,1 ms
25082 $03 TOP_LCD \ 6- send again again DB5=DB4=1
25083 $2 20_US \ wait 40 us = LCD cycle
25084 $02 TOP_LCD \ 7- send DB5=1 DB4=0
25085 $2 20_US \ wait 40 us = LCD cycle
25086 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25087 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25088 LCD_Clear \ 10- "LCD_Clear"
25089 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25090 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25091 LCD_Clear \ 10- "LCD_Clear"
25092 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25093 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25095 ['] (CR) IS CR \ ' (CR) is CR
25096 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
25098 ." RC5toLCD is running. Type STOP to quit"
25099 \ NOECHO \ uncomment to run this app without terminal connexion
25100 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
25101 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
25105 : STOP \ stops multitasking, must to be used before downloading app
25106 ['] (WARM) IS WARM \ remove START app from FORTH init process
25107 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
25115 CODE MAX \ n1 n2 -- n3 signed maximum
25116 CMP @PSP,TOS \ n2-n1
25117 S< ?GOTO FW1 \ n2<n1
25123 CODE MIN \ n1 n2 -- n3 signed minimum
25124 CMP @PSP,TOS \ n2-n1
25125 S< ?GOTO BW1 \ n2<n1
25131 : U.R \ u n -- display u unsigned in n width (n >= 2)
25133 R> OVER - 0 MAX SPACES TYPE
25137 CODE 20_US \ n -- n * 20 us
25138 BEGIN \ 3 cycles loop + 6~
25139 \ MOV #5,W \ 3 MCLK = 1 MHz
25140 \ MOV #23,W \ 3 MCLK = 4 MHz
25141 MOV #51,W \ 3 MCLK = 8 MHz
25142 \ MOV #104,W \ 3 MCLK = 16 MHz
25143 \ MOV #158,W \ 3 MCLK = 24 MHz
25144 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
25154 CODE TOP_LCD \ LCD Sample
25155 \ \ if write : %xxxxWWWW --
25156 \ \ if read : -- %0000RRRR
25157 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25158 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25159 0= IF \ write LCD bits pattern
25160 AND.B #LCD_DB,TOS \
25161 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25162 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25165 THEN \ read LCD bits pattern
25168 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25169 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25170 AND.B #LCD_DB,TOS \
25175 CODE LCD_W \ byte -- write byte to LCD
25177 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
25178 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
25179 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25180 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25181 COLON \ high level word starts here
25182 TOP_LCD 2 20_US \ write high nibble first
25187 CODE LCD_WrC \ char -- Write Char
25188 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25193 CODE LCD_WrF \ func -- Write Fonction
25194 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25200 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
25205 $02 LCD_WrF 100 20_us
25209 \ : LCD_Entry_set $04 OR LCD_WrF ;
25211 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
25213 \ : LCD_Display_Shift $10 OR LCD_WrF ;
25215 \ : LCD_Fn_Set $20 OR LCD_WrF ;
25217 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
25219 \ : LCD_Goto $80 OR LCD_WrF ;
25221 \ CODE LCD_R \ -- byte read byte from LCD
25222 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25223 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25224 \ COLON \ starts a FORTH word
25225 \ TOP_LCD 2 20_us \ -- %0000HHHH
25226 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
25227 \ HI2LO \ switch from FORTH to assembler
25228 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
25229 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
25230 \ MOV @RSP+,IP \ restore IP saved by COLON
25235 \ CODE LCD_RdS \ -- status Read Status
25236 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25241 \ CODE LCD_RdC \ -- char Read Char
25242 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25247 \ -------------+------+------+------+------++---+---+---+---+---------+
25248 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
25249 \ -------------+------+------+------+------++---+---+---+---+---------+
25250 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
25251 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
25252 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
25253 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
25254 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
25255 \ -------------+------+------+------+------++---+---+---+---+---------+
25258 \ ******************************\
25259 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25260 \ ******************************\
25261 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
25262 \ ------------------------------\
25263 \ define LPM mode for ACCEPT \
25264 \ ------------------------------\
25265 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25266 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25267 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25268 BIT.B #SW2,&SW2_IN \ test switch S2
25269 0= IF \ case of switch S2 pressed
25270 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
25272 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
25275 BIT.B #SW1,&SW1_IN \ test switch S1 input
25276 0= IF \ case of Switch S1 pressed
25277 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
25279 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
25283 RETI \ CPU is ON, GIE is OFF
25288 \ ------------------------------\
25289 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25290 \ ******************************\
25291 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25292 \ ******************************\
25293 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25294 \ \ SMclock = 8|16|24 MHz
25295 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
25296 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
25297 \ \ SR(9)=new Toggle bit memory (ADD on)
25298 \ ------------------------------\
25299 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
25300 \ ------------------------------\
25301 \ define LPM mode for ACCEPT \
25302 \ ------------------------------\
25303 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25304 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25305 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25306 \ ------------------------------\
25307 \ RC5_FirstStartBitHalfCycle: \
25308 \ ------------------------------\
25309 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
25310 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
25311 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
25312 MOV #1778,X \ RC5_Period in us
25313 MOV #14,W \ count of loop
25315 \ ------------------------------\
25316 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
25317 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
25318 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
25319 \ RC5_Compute_3/4_Period: \ |
25320 RRUM #1,X \ X=1/2 cycle |
25324 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
25325 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
25327 \ ------------------------------\
25328 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
25329 \ ------------------------------\
25330 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25331 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
25332 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25333 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25334 SUB #1,W \ decrement count loop
25335 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
25336 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25337 0<> WHILE \ ----> out of loop ----+
25338 \ RC5_compute_7/4_Time_out: \ |
25339 ADD X,Y \ | out of bound = 7/4 period
25340 \ RC5_WaitHalfCycleP1.2_IFG: \ |
25342 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
25343 0>= IF \ | if cycle time out of bound
25344 BIC #$30,&TA0CTL \ | stop timer_A0
25345 RETI \ | then quit to do nothing
25347 \ ------------------------------\ |
25348 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
25350 MOV &TA0R,X \ | | get new RC5_period value
25351 REPEAT \ ----> loop back --+ |
25352 \ ------------------------------\ |
25353 \ RC5_SampleEndOf: \ <---------------------+
25354 \ ------------------------------\
25355 BIC #$30,&TA0CTL \ stop timer_A0
25356 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
25357 \ ******************************\
25358 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25359 \ ******************************\
25360 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
25361 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
25362 XOR IP,X \ (new XOR old) Toggle bit (13)
25363 BIT #BIT13,X \ X(13) = New_RC5_command
25364 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
25366 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
25367 \ ******************************\
25368 \ RC5_ComputeNewRC5word \
25369 \ ******************************\
25371 MOV &BASE,2(PSP) \ save variable BASE before use
25372 MOV TOS,0(PSP) \ save TOS before use
25373 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
25374 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
25375 \ ******************************\
25376 \ RC5_ComputeC6bit \
25377 \ ******************************\
25378 BIT #$4000,IP \ test /C6 bit in IP
25379 0= IF BIS #$40,TOS \ set C6 bit in S
25380 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
25381 \ ******************************\
25382 \ RC5_CommandByteIsDone \ RC5_code --
25383 \ ******************************\
25385 \ ------------------------------\
25386 \ Display IR_RC5 code \
25387 \ ------------------------------\
25388 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
25389 \ ------------------------------\
25390 LO2HI \ switch from assembler to FORTH
25391 ['] LCD_CLEAR IS CR \ redirects CR
25392 ['] LCD_WrC IS EMIT \ redirects EMIT
25393 $10 BASE ! \ change BASE to hexadecimal
25394 CR ." $" 2 U.R \ print IR_RC5 code
25395 ['] (CR) IS CR \ restore CR
25396 ['] (EMIT) IS EMIT \ restore EMIT
25397 HI2LO \ switch from FORTH to assembler
25398 \ ------------------------------\
25399 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
25400 \ ------------------------------\
25401 MOV @PSP+,&BASE \ restore variable BASE
25402 RETI \ CPU is ON, GIE is OFF
25407 \ ------------------------------\
25408 \ TB0CTL = %0000 0010 1001 0100\$3C0
25409 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25410 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25411 \ -- \ID input divider \ 10 = /4
25412 \ -- \MC Mode Control \ 01 = up to TB0CCR0
25413 \ - \TBCLR TimerB Clear
25416 \ --------------------------------\\
25417 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25418 \ -- \CM Capture Mode
25423 \ --- \OUTMOD \ 011 = set/reset
25429 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
25431 \ ------------------------------\
25432 \ set TimerB to make 50kHz PWM \
25433 \ ------------------------------\
25434 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25435 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
25436 \ ------------------------------\
25437 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25438 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
25439 \ ------------------------------\
25440 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25441 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
25442 \ ------------------------------\
25443 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25444 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
25445 \ ------------------------------\
25446 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25447 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
25448 \ ------------------------------\
25449 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
25450 \ ------------------------------\
25451 \ set TimerB to generate PWM for LCD_Vo
25452 \ ------------------------------\
25453 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
25454 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
25455 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25456 \ ------------------------------\
25457 BIS.B #LCDVo,&LCDVo_DIR \
25458 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
25459 \ ------------------------------\
25460 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25461 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25462 \ ------------------------------\
25463 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25464 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25465 \ ------------------------------\
25466 \ WDT interval init part \
25467 \ ------------------------------\
25468 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
25469 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
25470 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
25471 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
25472 \ ------------------------------\
25474 \ ------------------------------\
25475 BIS.B #RC5,&IR_IE \ enable RC5_Int
25476 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25477 \ ------------------------------\
25478 \ init interrupt vectors
25479 \ ------------------------------\
25480 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
25481 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25482 \ ------------------------------\
25483 \ define LPM mode for ACCEPT \
25484 \ ------------------------------\
25485 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25486 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25487 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25489 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
25491 \ ------------------------------\
25493 \ ------------------------------\
25494 $03E8 20_US \ 1- wait 20 ms
25495 $03 TOP_LCD \ 2- send DB5=DB4=1
25496 $CD 20_US \ 3- wait 4,1 ms
25497 $03 TOP_LCD \ 4- send again DB5=DB4=1
25498 $5 20_US \ 5- wait 0,1 ms
25499 $03 TOP_LCD \ 6- send again again DB5=DB4=1
25500 $2 20_US \ wait 40 us = LCD cycle
25501 $02 TOP_LCD \ 7- send DB5=1 DB4=0
25502 $2 20_US \ wait 40 us = LCD cycle
25503 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25504 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25505 LCD_Clear \ 10- "LCD_Clear"
25506 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25507 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25508 LCD_Clear \ 10- "LCD_Clear"
25509 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25510 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25512 ['] (CR) IS CR \ ' (CR) is CR
25513 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
25515 ." RC5toLCD is running. Type STOP to quit"
25516 \ NOECHO \ uncomment to run this app without terminal connexion
25517 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
25518 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
25522 : STOP \ stops multitasking, must to be used before downloading app
25523 ['] (WARM) IS WARM \ remove START app from FORTH init process
25524 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
25532 CODE MAX \ n1 n2 -- n3 signed maximum
25533 CMP @PSP,TOS \ n2-n1
25534 S< ?GOTO FW1 \ n2<n1
25540 CODE MIN \ n1 n2 -- n3 signed minimum
25541 CMP @PSP,TOS \ n2-n1
25542 S< ?GOTO BW1 \ n2<n1
25548 : U.R \ u n -- display u unsigned in n width (n >= 2)
25550 R> OVER - 0 MAX SPACES TYPE
25554 CODE 20_US \ n -- n * 20 us
25555 BEGIN \ 3 cycles loop + 6~
25556 \ MOV #5,W \ 3 MCLK = 1 MHz
25557 \ MOV #23,W \ 3 MCLK = 4 MHz
25558 MOV #51,W \ 3 MCLK = 8 MHz
25559 \ MOV #104,W \ 3 MCLK = 16 MHz
25560 \ MOV #158,W \ 3 MCLK = 24 MHz
25561 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
25571 CODE TOP_LCD \ LCD Sample
25572 \ \ if write : %xxxxWWWW --
25573 \ \ if read : -- %0000RRRR
25574 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25575 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25576 0= IF \ write LCD bits pattern
25577 AND.B #LCD_DB,TOS \
25578 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25579 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25582 THEN \ read LCD bits pattern
25585 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25586 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25587 AND.B #LCD_DB,TOS \
25592 CODE LCD_W \ byte -- write byte to LCD
25594 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
25595 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
25596 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25597 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25598 COLON \ high level word starts here
25599 TOP_LCD 2 20_US \ write high nibble first
25604 CODE LCD_WrC \ char -- Write Char
25605 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25610 CODE LCD_WrF \ func -- Write Fonction
25611 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25617 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
25622 $02 LCD_WrF 100 20_us
25626 \ : LCD_Entry_set $04 OR LCD_WrF ;
25628 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
25630 \ : LCD_Display_Shift $10 OR LCD_WrF ;
25632 \ : LCD_Fn_Set $20 OR LCD_WrF ;
25634 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
25636 \ : LCD_Goto $80 OR LCD_WrF ;
25638 \ CODE LCD_R \ -- byte read byte from LCD
25639 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25640 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25641 \ COLON \ starts a FORTH word
25642 \ TOP_LCD 2 20_us \ -- %0000HHHH
25643 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
25644 \ HI2LO \ switch from FORTH to assembler
25645 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
25646 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
25647 \ MOV @RSP+,IP \ restore IP saved by COLON
25652 \ CODE LCD_RdS \ -- status Read Status
25653 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25658 \ CODE LCD_RdC \ -- char Read Char
25659 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25664 \ -------------+------+------+------+------++---+---+---+---+---------+
25665 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
25666 \ -------------+------+------+------+------++---+---+---+---+---------+
25667 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
25668 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
25669 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
25670 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
25671 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
25672 \ -------------+------+------+------+------++---+---+---+---+---------+
25675 \ ******************************\
25676 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25677 \ ******************************\
25678 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
25679 \ ------------------------------\
25680 \ define LPM mode for ACCEPT \
25681 \ ------------------------------\
25682 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25683 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25684 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25685 BIT.B #SW2,&SW2_IN \ test switch S2
25686 0= IF \ case of switch S2 pressed
25687 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
25689 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
25692 BIT.B #SW1,&SW1_IN \ test switch S1 input
25693 0= IF \ case of Switch S1 pressed
25694 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
25696 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
25700 RETI \ CPU is ON, GIE is OFF
25705 \ ------------------------------\
25706 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25707 \ ******************************\
25708 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25709 \ ******************************\
25710 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25711 \ \ SMclock = 8|16|24 MHz
25712 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
25713 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
25714 \ \ SR(9)=new Toggle bit memory (ADD on)
25715 \ ------------------------------\
25716 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
25717 \ ------------------------------\
25718 \ define LPM mode for ACCEPT \
25719 \ ------------------------------\
25720 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25721 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25722 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25723 \ ------------------------------\
25724 \ RC5_FirstStartBitHalfCycle: \
25725 \ ------------------------------\
25726 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
25727 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
25728 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
25729 MOV #1778,X \ RC5_Period in us
25730 MOV #14,W \ count of loop
25732 \ ------------------------------\
25733 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
25734 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
25735 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
25736 \ RC5_Compute_3/4_Period: \ |
25737 RRUM #1,X \ X=1/2 cycle |
25741 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
25742 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
25744 \ ------------------------------\
25745 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
25746 \ ------------------------------\
25747 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25748 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
25749 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25750 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25751 SUB #1,W \ decrement count loop
25752 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
25753 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25754 0<> WHILE \ ----> out of loop ----+
25755 \ RC5_compute_7/4_Time_out: \ |
25756 ADD X,Y \ | out of bound = 7/4 period
25757 \ RC5_WaitHalfCycleP1.2_IFG: \ |
25759 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
25760 0>= IF \ | if cycle time out of bound
25761 BIC #$30,&TA0CTL \ | stop timer_A0
25762 RETI \ | then quit to do nothing
25764 \ ------------------------------\ |
25765 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
25767 MOV &TA0R,X \ | | get new RC5_period value
25768 REPEAT \ ----> loop back --+ |
25769 \ ------------------------------\ |
25770 \ RC5_SampleEndOf: \ <---------------------+
25771 \ ------------------------------\
25772 BIC #$30,&TA0CTL \ stop timer_A0
25773 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
25774 \ ******************************\
25775 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25776 \ ******************************\
25777 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
25778 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
25779 XOR IP,X \ (new XOR old) Toggle bit (13)
25780 BIT #BIT13,X \ X(13) = New_RC5_command
25781 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
25783 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
25784 \ ******************************\
25785 \ RC5_ComputeNewRC5word \
25786 \ ******************************\
25788 MOV &BASE,2(PSP) \ save variable BASE before use
25789 MOV TOS,0(PSP) \ save TOS before use
25790 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
25791 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
25792 \ ******************************\
25793 \ RC5_ComputeC6bit \
25794 \ ******************************\
25795 BIT #$4000,IP \ test /C6 bit in IP
25796 0= IF BIS #$40,TOS \ set C6 bit in S
25797 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
25798 \ ******************************\
25799 \ RC5_CommandByteIsDone \ RC5_code --
25800 \ ******************************\
25802 \ ------------------------------\
25803 \ Display IR_RC5 code \
25804 \ ------------------------------\
25805 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
25806 \ ------------------------------\
25807 LO2HI \ switch from assembler to FORTH
25808 ['] LCD_CLEAR IS CR \ redirects CR
25809 ['] LCD_WrC IS EMIT \ redirects EMIT
25810 $10 BASE ! \ change BASE to hexadecimal
25811 CR ." $" 2 U.R \ print IR_RC5 code
25812 ['] (CR) IS CR \ restore CR
25813 ['] (EMIT) IS EMIT \ restore EMIT
25814 HI2LO \ switch from FORTH to assembler
25815 \ ------------------------------\
25816 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
25817 \ ------------------------------\
25818 MOV @PSP+,&BASE \ restore variable BASE
25819 RETI \ CPU is ON, GIE is OFF
25824 \ ------------------------------\
25825 \ TB0CTL = %0000 0010 1001 0100\$3C0
25826 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25827 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25828 \ -- \ID input divider \ 10 = /4
25829 \ -- \MC Mode Control \ 01 = up to TB0CCR0
25830 \ - \TBCLR TimerB Clear
25833 \ --------------------------------\\
25834 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25835 \ -- \CM Capture Mode
25840 \ --- \OUTMOD \ 011 = set/reset
25846 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
25848 \ ------------------------------\
25849 \ set TimerB to make 50kHz PWM \
25850 \ ------------------------------\
25851 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25852 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
25853 \ ------------------------------\
25854 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25855 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
25856 \ ------------------------------\
25857 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25858 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
25859 \ ------------------------------\
25860 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25861 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
25862 \ ------------------------------\
25863 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25864 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
25865 \ ------------------------------\
25866 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
25867 \ ------------------------------\
25868 \ set TimerB to generate PWM for LCD_Vo
25869 \ ------------------------------\
25870 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
25871 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
25872 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25873 \ ------------------------------\
25874 BIS.B #LCDVo,&LCDVo_DIR \
25875 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
25876 \ ------------------------------\
25877 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25878 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25879 \ ------------------------------\
25880 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25881 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25882 \ ------------------------------\
25883 \ WDT interval init part \
25884 \ ------------------------------\
25885 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
25886 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
25887 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
25888 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
25889 \ ------------------------------\
25891 \ ------------------------------\
25892 BIS.B #RC5,&IR_IE \ enable RC5_Int
25893 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25894 \ ------------------------------\
25895 \ init interrupt vectors
25896 \ ------------------------------\
25897 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
25898 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25899 \ ------------------------------\
25900 \ define LPM mode for ACCEPT \
25901 \ ------------------------------\
25902 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25903 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25904 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25906 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
25908 \ ------------------------------\
25910 \ ------------------------------\
25911 $03E8 20_US \ 1- wait 20 ms
25912 $03 TOP_LCD \ 2- send DB5=DB4=1
25913 $CD 20_US \ 3- wait 4,1 ms
25914 $03 TOP_LCD \ 4- send again DB5=DB4=1
25915 $5 20_US \ 5- wait 0,1 ms
25916 $03 TOP_LCD \ 6- send again again DB5=DB4=1
25917 $2 20_US \ wait 40 us = LCD cycle
25918 $02 TOP_LCD \ 7- send DB5=1 DB4=0
25919 $2 20_US \ wait 40 us = LCD cycle
25920 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25921 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25922 LCD_Clear \ 10- "LCD_Clear"
25923 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25924 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25925 LCD_Clear \ 10- "LCD_Clear"
25926 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25927 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25929 ['] (CR) IS CR \ ' (CR) is CR
25930 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
25932 ." RC5toLCD is running. Type STOP to quit"
25933 \ NOECHO \ uncomment to run this app without terminal connexion
25934 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
25935 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
25939 : STOP \ stops multitasking, must to be used before downloading app
25940 ['] (WARM) IS WARM \ remove START app from FORTH init process
25941 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
25949 CODE MAX \ n1 n2 -- n3 signed maximum
25950 CMP @PSP,TOS \ n2-n1
25951 S< ?GOTO FW1 \ n2<n1
25957 CODE MIN \ n1 n2 -- n3 signed minimum
25958 CMP @PSP,TOS \ n2-n1
25959 S< ?GOTO BW1 \ n2<n1
25965 : U.R \ u n -- display u unsigned in n width (n >= 2)
25967 R> OVER - 0 MAX SPACES TYPE
25971 CODE 20_US \ n -- n * 20 us
25972 BEGIN \ 3 cycles loop + 6~
25973 \ MOV #5,W \ 3 MCLK = 1 MHz
25974 \ MOV #23,W \ 3 MCLK = 4 MHz
25975 MOV #51,W \ 3 MCLK = 8 MHz
25976 \ MOV #104,W \ 3 MCLK = 16 MHz
25977 \ MOV #158,W \ 3 MCLK = 24 MHz
25978 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
25988 CODE TOP_LCD \ LCD Sample
25989 \ \ if write : %xxxxWWWW --
25990 \ \ if read : -- %0000RRRR
25991 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25992 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25993 0= IF \ write LCD bits pattern
25994 AND.B #LCD_DB,TOS \
25995 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25996 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25999 THEN \ read LCD bits pattern
26002 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26003 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26004 AND.B #LCD_DB,TOS \
26009 CODE LCD_W \ byte -- write byte to LCD
26011 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
26012 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
26013 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26014 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26015 COLON \ high level word starts here
26016 TOP_LCD 2 20_US \ write high nibble first
26021 CODE LCD_WrC \ char -- Write Char
26022 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26027 CODE LCD_WrF \ func -- Write Fonction
26028 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26034 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
26039 $02 LCD_WrF 100 20_us
26043 \ : LCD_Entry_set $04 OR LCD_WrF ;
26045 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
26047 \ : LCD_Display_Shift $10 OR LCD_WrF ;
26049 \ : LCD_Fn_Set $20 OR LCD_WrF ;
26051 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
26053 \ : LCD_Goto $80 OR LCD_WrF ;
26055 \ CODE LCD_R \ -- byte read byte from LCD
26056 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26057 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26058 \ COLON \ starts a FORTH word
26059 \ TOP_LCD 2 20_us \ -- %0000HHHH
26060 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
26061 \ HI2LO \ switch from FORTH to assembler
26062 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
26063 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
26064 \ MOV @RSP+,IP \ restore IP saved by COLON
26069 \ CODE LCD_RdS \ -- status Read Status
26070 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26075 \ CODE LCD_RdC \ -- char Read Char
26076 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26081 \ -------------+------+------+------+------++---+---+---+---+---------+
26082 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
26083 \ -------------+------+------+------+------++---+---+---+---+---------+
26084 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
26085 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
26086 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
26087 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
26088 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
26089 \ -------------+------+------+------+------++---+---+---+---+---------+
26092 \ ******************************\
26093 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26094 \ ******************************\
26095 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
26096 \ ------------------------------\
26097 \ define LPM mode for ACCEPT \
26098 \ ------------------------------\
26099 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26100 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26101 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26102 BIT.B #SW2,&SW2_IN \ test switch S2
26103 0= IF \ case of switch S2 pressed
26104 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
26106 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
26109 BIT.B #SW1,&SW1_IN \ test switch S1 input
26110 0= IF \ case of Switch S1 pressed
26111 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
26113 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
26117 RETI \ CPU is ON, GIE is OFF
26122 \ ------------------------------\
26123 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26124 \ ******************************\
26125 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26126 \ ******************************\
26127 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26128 \ \ SMclock = 8|16|24 MHz
26129 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
26130 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
26131 \ \ SR(9)=new Toggle bit memory (ADD on)
26132 \ ------------------------------\
26133 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
26134 \ ------------------------------\
26135 \ define LPM mode for ACCEPT \
26136 \ ------------------------------\
26137 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26138 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26139 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26140 \ ------------------------------\
26141 \ RC5_FirstStartBitHalfCycle: \
26142 \ ------------------------------\
26143 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
26144 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
26145 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
26146 MOV #1778,X \ RC5_Period in us
26147 MOV #14,W \ count of loop
26149 \ ------------------------------\
26150 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
26151 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
26152 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
26153 \ RC5_Compute_3/4_Period: \ |
26154 RRUM #1,X \ X=1/2 cycle |
26158 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
26159 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
26161 \ ------------------------------\
26162 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
26163 \ ------------------------------\
26164 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26165 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
26166 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26167 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26168 SUB #1,W \ decrement count loop
26169 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
26170 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26171 0<> WHILE \ ----> out of loop ----+
26172 \ RC5_compute_7/4_Time_out: \ |
26173 ADD X,Y \ | out of bound = 7/4 period
26174 \ RC5_WaitHalfCycleP1.2_IFG: \ |
26176 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
26177 0>= IF \ | if cycle time out of bound
26178 BIC #$30,&TA0CTL \ | stop timer_A0
26179 RETI \ | then quit to do nothing
26181 \ ------------------------------\ |
26182 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
26184 MOV &TA0R,X \ | | get new RC5_period value
26185 REPEAT \ ----> loop back --+ |
26186 \ ------------------------------\ |
26187 \ RC5_SampleEndOf: \ <---------------------+
26188 \ ------------------------------\
26189 BIC #$30,&TA0CTL \ stop timer_A0
26190 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
26191 \ ******************************\
26192 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
26193 \ ******************************\
26194 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
26195 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
26196 XOR IP,X \ (new XOR old) Toggle bit (13)
26197 BIT #BIT13,X \ X(13) = New_RC5_command
26198 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
26200 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
26201 \ ******************************\
26202 \ RC5_ComputeNewRC5word \
26203 \ ******************************\
26205 MOV &BASE,2(PSP) \ save variable BASE before use
26206 MOV TOS,0(PSP) \ save TOS before use
26207 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
26208 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
26209 \ ******************************\
26210 \ RC5_ComputeC6bit \
26211 \ ******************************\
26212 BIT #$4000,IP \ test /C6 bit in IP
26213 0= IF BIS #$40,TOS \ set C6 bit in S
26214 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
26215 \ ******************************\
26216 \ RC5_CommandByteIsDone \ RC5_code --
26217 \ ******************************\
26219 \ ------------------------------\
26220 \ Display IR_RC5 code \
26221 \ ------------------------------\
26222 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
26223 \ ------------------------------\
26224 LO2HI \ switch from assembler to FORTH
26225 ['] LCD_CLEAR IS CR \ redirects CR
26226 ['] LCD_WrC IS EMIT \ redirects EMIT
26227 $10 BASE ! \ change BASE to hexadecimal
26228 CR ." $" 2 U.R \ print IR_RC5 code
26229 ['] (CR) IS CR \ restore CR
26230 ['] (EMIT) IS EMIT \ restore EMIT
26231 HI2LO \ switch from FORTH to assembler
26232 \ ------------------------------\
26233 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
26234 \ ------------------------------\
26235 MOV @PSP+,&BASE \ restore variable BASE
26236 RETI \ CPU is ON, GIE is OFF
26241 \ ------------------------------\
26242 \ TB0CTL = %0000 0010 1001 0100\$3C0
26243 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26244 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26245 \ -- \ID input divider \ 10 = /4
26246 \ -- \MC Mode Control \ 01 = up to TB0CCR0
26247 \ - \TBCLR TimerB Clear
26250 \ --------------------------------\\
26251 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26252 \ -- \CM Capture Mode
26257 \ --- \OUTMOD \ 011 = set/reset
26263 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
26265 \ ------------------------------\
26266 \ set TimerB to make 50kHz PWM \
26267 \ ------------------------------\
26268 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
26269 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
26270 \ ------------------------------\
26271 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
26272 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
26273 \ ------------------------------\
26274 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26275 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
26276 \ ------------------------------\
26277 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26278 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
26279 \ ------------------------------\
26280 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26281 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
26282 \ ------------------------------\
26283 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
26284 \ ------------------------------\
26285 \ set TimerB to generate PWM for LCD_Vo
26286 \ ------------------------------\
26287 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
26288 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
26289 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26290 \ ------------------------------\
26291 BIS.B #LCDVo,&LCDVo_DIR \
26292 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
26293 \ ------------------------------\
26294 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26295 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26296 \ ------------------------------\
26297 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26298 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26299 \ ------------------------------\
26300 \ WDT interval init part \
26301 \ ------------------------------\
26302 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
26303 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
26304 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
26305 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
26306 \ ------------------------------\
26308 \ ------------------------------\
26309 BIS.B #RC5,&IR_IE \ enable RC5_Int
26310 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26311 \ ------------------------------\
26312 \ init interrupt vectors
26313 \ ------------------------------\
26314 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
26315 MOV #RC5_INT,&IR_Vec \ init interrupt vector
26316 \ ------------------------------\
26317 \ define LPM mode for ACCEPT \
26318 \ ------------------------------\
26319 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26320 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26321 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26323 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
26325 \ ------------------------------\
26327 \ ------------------------------\
26328 $03E8 20_US \ 1- wait 20 ms
26329 $03 TOP_LCD \ 2- send DB5=DB4=1
26330 $CD 20_US \ 3- wait 4,1 ms
26331 $03 TOP_LCD \ 4- send again DB5=DB4=1
26332 $5 20_US \ 5- wait 0,1 ms
26333 $03 TOP_LCD \ 6- send again again DB5=DB4=1
26334 $2 20_US \ wait 40 us = LCD cycle
26335 $02 TOP_LCD \ 7- send DB5=1 DB4=0
26336 $2 20_US \ wait 40 us = LCD cycle
26337 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26338 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26339 LCD_Clear \ 10- "LCD_Clear"
26340 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26341 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26342 LCD_Clear \ 10- "LCD_Clear"
26343 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26344 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26346 ['] (CR) IS CR \ ' (CR) is CR
26347 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
26349 ." RC5toLCD is running. Type STOP to quit"
26350 \ NOECHO \ uncomment to run this app without terminal connexion
26351 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
26352 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
26356 : STOP \ stops multitasking, must to be used before downloading app
26357 ['] (WARM) IS WARM \ remove START app from FORTH init process
26358 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
26366 CODE MAX \ n1 n2 -- n3 signed maximum
26367 CMP @PSP,TOS \ n2-n1
26368 S< ?GOTO FW1 \ n2<n1
26374 CODE MIN \ n1 n2 -- n3 signed minimum
26375 CMP @PSP,TOS \ n2-n1
26376 S< ?GOTO BW1 \ n2<n1
26382 : U.R \ u n -- display u unsigned in n width (n >= 2)
26384 R> OVER - 0 MAX SPACES TYPE
26388 CODE 20_US \ n -- n * 20 us
26389 BEGIN \ 3 cycles loop + 6~
26390 \ MOV #5,W \ 3 MCLK = 1 MHz
26391 \ MOV #23,W \ 3 MCLK = 4 MHz
26392 MOV #51,W \ 3 MCLK = 8 MHz
26393 \ MOV #104,W \ 3 MCLK = 16 MHz
26394 \ MOV #158,W \ 3 MCLK = 24 MHz
26395 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
26405 CODE TOP_LCD \ LCD Sample
26406 \ \ if write : %xxxxWWWW --
26407 \ \ if read : -- %0000RRRR
26408 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26409 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26410 0= IF \ write LCD bits pattern
26411 AND.B #LCD_DB,TOS \
26412 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26413 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26416 THEN \ read LCD bits pattern
26419 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26420 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26421 AND.B #LCD_DB,TOS \
26426 CODE LCD_W \ byte -- write byte to LCD
26428 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
26429 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
26430 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26431 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26432 COLON \ high level word starts here
26433 TOP_LCD 2 20_US \ write high nibble first
26438 CODE LCD_WrC \ char -- Write Char
26439 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26444 CODE LCD_WrF \ func -- Write Fonction
26445 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26451 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
26456 $02 LCD_WrF 100 20_us
26460 \ : LCD_Entry_set $04 OR LCD_WrF ;
26462 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
26464 \ : LCD_Display_Shift $10 OR LCD_WrF ;
26466 \ : LCD_Fn_Set $20 OR LCD_WrF ;
26468 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
26470 \ : LCD_Goto $80 OR LCD_WrF ;
26472 \ CODE LCD_R \ -- byte read byte from LCD
26473 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26474 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26475 \ COLON \ starts a FORTH word
26476 \ TOP_LCD 2 20_us \ -- %0000HHHH
26477 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
26478 \ HI2LO \ switch from FORTH to assembler
26479 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
26480 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
26481 \ MOV @RSP+,IP \ restore IP saved by COLON
26486 \ CODE LCD_RdS \ -- status Read Status
26487 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26492 \ CODE LCD_RdC \ -- char Read Char
26493 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26498 \ -------------+------+------+------+------++---+---+---+---+---------+
26499 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
26500 \ -------------+------+------+------+------++---+---+---+---+---------+
26501 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
26502 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
26503 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
26504 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
26505 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
26506 \ -------------+------+------+------+------++---+---+---+---+---------+
26509 \ ******************************\
26510 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26511 \ ******************************\
26512 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
26513 \ ------------------------------\
26514 \ define LPM mode for ACCEPT \
26515 \ ------------------------------\
26516 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26517 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26518 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26519 BIT.B #SW2,&SW2_IN \ test switch S2
26520 0= IF \ case of switch S2 pressed
26521 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
26523 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
26526 BIT.B #SW1,&SW1_IN \ test switch S1 input
26527 0= IF \ case of Switch S1 pressed
26528 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
26530 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
26534 RETI \ CPU is ON, GIE is OFF
26539 \ ------------------------------\
26540 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26541 \ ******************************\
26542 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26543 \ ******************************\
26544 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26545 \ \ SMclock = 8|16|24 MHz
26546 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
26547 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
26548 \ \ SR(9)=new Toggle bit memory (ADD on)
26549 \ ------------------------------\
26550 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
26551 \ ------------------------------\
26552 \ define LPM mode for ACCEPT \
26553 \ ------------------------------\
26554 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26555 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26556 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26557 \ ------------------------------\
26558 \ RC5_FirstStartBitHalfCycle: \
26559 \ ------------------------------\
26560 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
26561 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
26562 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
26563 MOV #1778,X \ RC5_Period in us
26564 MOV #14,W \ count of loop
26566 \ ------------------------------\
26567 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
26568 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
26569 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
26570 \ RC5_Compute_3/4_Period: \ |
26571 RRUM #1,X \ X=1/2 cycle |
26575 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
26576 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
26578 \ ------------------------------\
26579 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
26580 \ ------------------------------\
26581 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26582 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
26583 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26584 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26585 SUB #1,W \ decrement count loop
26586 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
26587 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26588 0<> WHILE \ ----> out of loop ----+
26589 \ RC5_compute_7/4_Time_out: \ |
26590 ADD X,Y \ | out of bound = 7/4 period
26591 \ RC5_WaitHalfCycleP1.2_IFG: \ |
26593 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
26594 0>= IF \ | if cycle time out of bound
26595 BIC #$30,&TA0CTL \ | stop timer_A0
26596 RETI \ | then quit to do nothing
26598 \ ------------------------------\ |
26599 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
26601 MOV &TA0R,X \ | | get new RC5_period value
26602 REPEAT \ ----> loop back --+ |
26603 \ ------------------------------\ |
26604 \ RC5_SampleEndOf: \ <---------------------+
26605 \ ------------------------------\
26606 BIC #$30,&TA0CTL \ stop timer_A0
26607 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
26608 \ ******************************\
26609 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
26610 \ ******************************\
26611 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
26612 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
26613 XOR IP,X \ (new XOR old) Toggle bit (13)
26614 BIT #BIT13,X \ X(13) = New_RC5_command
26615 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
26617 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
26618 \ ******************************\
26619 \ RC5_ComputeNewRC5word \
26620 \ ******************************\
26622 MOV &BASE,2(PSP) \ save variable BASE before use
26623 MOV TOS,0(PSP) \ save TOS before use
26624 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
26625 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
26626 \ ******************************\
26627 \ RC5_ComputeC6bit \
26628 \ ******************************\
26629 BIT #$4000,IP \ test /C6 bit in IP
26630 0= IF BIS #$40,TOS \ set C6 bit in S
26631 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
26632 \ ******************************\
26633 \ RC5_CommandByteIsDone \ RC5_code --
26634 \ ******************************\
26636 \ ------------------------------\
26637 \ Display IR_RC5 code \
26638 \ ------------------------------\
26639 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
26640 \ ------------------------------\
26641 LO2HI \ switch from assembler to FORTH
26642 ['] LCD_CLEAR IS CR \ redirects CR
26643 ['] LCD_WrC IS EMIT \ redirects EMIT
26644 $10 BASE ! \ change BASE to hexadecimal
26645 CR ." $" 2 U.R \ print IR_RC5 code
26646 ['] (CR) IS CR \ restore CR
26647 ['] (EMIT) IS EMIT \ restore EMIT
26648 HI2LO \ switch from FORTH to assembler
26649 \ ------------------------------\
26650 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
26651 \ ------------------------------\
26652 MOV @PSP+,&BASE \ restore variable BASE
26653 RETI \ CPU is ON, GIE is OFF
26658 \ ------------------------------\
26659 \ TB0CTL = %0000 0010 1001 0100\$3C0
26660 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26661 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26662 \ -- \ID input divider \ 10 = /4
26663 \ -- \MC Mode Control \ 01 = up to TB0CCR0
26664 \ - \TBCLR TimerB Clear
26667 \ --------------------------------\\
26668 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26669 \ -- \CM Capture Mode
26674 \ --- \OUTMOD \ 011 = set/reset
26680 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
26682 \ ------------------------------\
26683 \ set TimerB to make 50kHz PWM \
26684 \ ------------------------------\
26685 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
26686 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
26687 \ ------------------------------\
26688 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
26689 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
26690 \ ------------------------------\
26691 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26692 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
26693 \ ------------------------------\
26694 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26695 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
26696 \ ------------------------------\
26697 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26698 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
26699 \ ------------------------------\
26700 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
26701 \ ------------------------------\
26702 \ set TimerB to generate PWM for LCD_Vo
26703 \ ------------------------------\
26704 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
26705 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
26706 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26707 \ ------------------------------\
26708 BIS.B #LCDVo,&LCDVo_DIR \
26709 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
26710 \ ------------------------------\
26711 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26712 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26713 \ ------------------------------\
26714 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26715 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26716 \ ------------------------------\
26717 \ WDT interval init part \
26718 \ ------------------------------\
26719 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
26720 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
26721 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
26722 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
26723 \ ------------------------------\
26725 \ ------------------------------\
26726 BIS.B #RC5,&IR_IE \ enable RC5_Int
26727 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26728 \ ------------------------------\
26729 \ init interrupt vectors
26730 \ ------------------------------\
26731 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
26732 MOV #RC5_INT,&IR_Vec \ init interrupt vector
26733 \ ------------------------------\
26734 \ define LPM mode for ACCEPT \
26735 \ ------------------------------\
26736 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26737 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26738 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26740 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
26742 \ ------------------------------\
26744 \ ------------------------------\
26745 $03E8 20_US \ 1- wait 20 ms
26746 $03 TOP_LCD \ 2- send DB5=DB4=1
26747 $CD 20_US \ 3- wait 4,1 ms
26748 $03 TOP_LCD \ 4- send again DB5=DB4=1
26749 $5 20_US \ 5- wait 0,1 ms
26750 $03 TOP_LCD \ 6- send again again DB5=DB4=1
26751 $2 20_US \ wait 40 us = LCD cycle
26752 $02 TOP_LCD \ 7- send DB5=1 DB4=0
26753 $2 20_US \ wait 40 us = LCD cycle
26754 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26755 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26756 LCD_Clear \ 10- "LCD_Clear"
26757 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26758 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26759 LCD_Clear \ 10- "LCD_Clear"
26760 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26761 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26763 ['] (CR) IS CR \ ' (CR) is CR
26764 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
26766 ." RC5toLCD is running. Type STOP to quit"
26767 \ NOECHO \ uncomment to run this app without terminal connexion
26768 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
26769 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
26773 : STOP \ stops multitasking, must to be used before downloading app
26774 ['] (WARM) IS WARM \ remove START app from FORTH init process
26775 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
26783 CODE MAX \ n1 n2 -- n3 signed maximum
26784 CMP @PSP,TOS \ n2-n1
26785 S< ?GOTO FW1 \ n2<n1
26791 CODE MIN \ n1 n2 -- n3 signed minimum
26792 CMP @PSP,TOS \ n2-n1
26793 S< ?GOTO BW1 \ n2<n1
26799 : U.R \ u n -- display u unsigned in n width (n >= 2)
26801 R> OVER - 0 MAX SPACES TYPE
26805 CODE 20_US \ n -- n * 20 us
26806 BEGIN \ 3 cycles loop + 6~
26807 \ MOV #5,W \ 3 MCLK = 1 MHz
26808 \ MOV #23,W \ 3 MCLK = 4 MHz
26809 MOV #51,W \ 3 MCLK = 8 MHz
26810 \ MOV #104,W \ 3 MCLK = 16 MHz
26811 \ MOV #158,W \ 3 MCLK = 24 MHz
26812 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
26822 CODE TOP_LCD \ LCD Sample
26823 \ \ if write : %xxxxWWWW --
26824 \ \ if read : -- %0000RRRR
26825 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26826 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26827 0= IF \ write LCD bits pattern
26828 AND.B #LCD_DB,TOS \
26829 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26830 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26833 THEN \ read LCD bits pattern
26836 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26837 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26838 AND.B #LCD_DB,TOS \
26843 CODE LCD_W \ byte -- write byte to LCD
26845 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
26846 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
26847 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26848 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26849 COLON \ high level word starts here
26850 TOP_LCD 2 20_US \ write high nibble first
26855 CODE LCD_WrC \ char -- Write Char
26856 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26861 CODE LCD_WrF \ func -- Write Fonction
26862 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26868 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
26873 $02 LCD_WrF 100 20_us
26877 \ : LCD_Entry_set $04 OR LCD_WrF ;
26879 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
26881 \ : LCD_Display_Shift $10 OR LCD_WrF ;
26883 \ : LCD_Fn_Set $20 OR LCD_WrF ;
26885 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
26887 \ : LCD_Goto $80 OR LCD_WrF ;
26889 \ CODE LCD_R \ -- byte read byte from LCD
26890 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26891 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26892 \ COLON \ starts a FORTH word
26893 \ TOP_LCD 2 20_us \ -- %0000HHHH
26894 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
26895 \ HI2LO \ switch from FORTH to assembler
26896 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
26897 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
26898 \ MOV @RSP+,IP \ restore IP saved by COLON
26903 \ CODE LCD_RdS \ -- status Read Status
26904 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26909 \ CODE LCD_RdC \ -- char Read Char
26910 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26915 \ -------------+------+------+------+------++---+---+---+---+---------+
26916 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
26917 \ -------------+------+------+------+------++---+---+---+---+---------+
26918 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
26919 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
26920 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
26921 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
26922 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
26923 \ -------------+------+------+------+------++---+---+---+---+---------+
26926 \ ******************************\
26927 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26928 \ ******************************\
26929 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
26930 \ ------------------------------\
26931 \ define LPM mode for ACCEPT \
26932 \ ------------------------------\
26933 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26934 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26935 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26936 BIT.B #SW2,&SW2_IN \ test switch S2
26937 0= IF \ case of switch S2 pressed
26938 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
26940 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
26943 BIT.B #SW1,&SW1_IN \ test switch S1 input
26944 0= IF \ case of Switch S1 pressed
26945 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
26947 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
26951 RETI \ CPU is ON, GIE is OFF
26956 \ ------------------------------\
26957 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26958 \ ******************************\
26959 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26960 \ ******************************\
26961 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26962 \ \ SMclock = 8|16|24 MHz
26963 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
26964 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
26965 \ \ SR(9)=new Toggle bit memory (ADD on)
26966 \ ------------------------------\
26967 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
26968 \ ------------------------------\
26969 \ define LPM mode for ACCEPT \
26970 \ ------------------------------\
26971 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26972 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26973 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26974 \ ------------------------------\
26975 \ RC5_FirstStartBitHalfCycle: \
26976 \ ------------------------------\
26977 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
26978 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
26979 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
26980 MOV #1778,X \ RC5_Period in us
26981 MOV #14,W \ count of loop
26983 \ ------------------------------\
26984 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
26985 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
26986 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
26987 \ RC5_Compute_3/4_Period: \ |
26988 RRUM #1,X \ X=1/2 cycle |
26992 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
26993 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
26995 \ ------------------------------\
26996 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
26997 \ ------------------------------\
26998 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26999 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
27000 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27001 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27002 SUB #1,W \ decrement count loop
27003 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
27004 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27005 0<> WHILE \ ----> out of loop ----+
27006 \ RC5_compute_7/4_Time_out: \ |
27007 ADD X,Y \ | out of bound = 7/4 period
27008 \ RC5_WaitHalfCycleP1.2_IFG: \ |
27010 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
27011 0>= IF \ | if cycle time out of bound
27012 BIC #$30,&TA0CTL \ | stop timer_A0
27013 RETI \ | then quit to do nothing
27015 \ ------------------------------\ |
27016 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
27018 MOV &TA0R,X \ | | get new RC5_period value
27019 REPEAT \ ----> loop back --+ |
27020 \ ------------------------------\ |
27021 \ RC5_SampleEndOf: \ <---------------------+
27022 \ ------------------------------\
27023 BIC #$30,&TA0CTL \ stop timer_A0
27024 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
27025 \ ******************************\
27026 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27027 \ ******************************\
27028 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
27029 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
27030 XOR IP,X \ (new XOR old) Toggle bit (13)
27031 BIT #BIT13,X \ X(13) = New_RC5_command
27032 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
27034 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
27035 \ ******************************\
27036 \ RC5_ComputeNewRC5word \
27037 \ ******************************\
27039 MOV &BASE,2(PSP) \ save variable BASE before use
27040 MOV TOS,0(PSP) \ save TOS before use
27041 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
27042 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
27043 \ ******************************\
27044 \ RC5_ComputeC6bit \
27045 \ ******************************\
27046 BIT #$4000,IP \ test /C6 bit in IP
27047 0= IF BIS #$40,TOS \ set C6 bit in S
27048 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
27049 \ ******************************\
27050 \ RC5_CommandByteIsDone \ RC5_code --
27051 \ ******************************\
27053 \ ------------------------------\
27054 \ Display IR_RC5 code \
27055 \ ------------------------------\
27056 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
27057 \ ------------------------------\
27058 LO2HI \ switch from assembler to FORTH
27059 ['] LCD_CLEAR IS CR \ redirects CR
27060 ['] LCD_WrC IS EMIT \ redirects EMIT
27061 $10 BASE ! \ change BASE to hexadecimal
27062 CR ." $" 2 U.R \ print IR_RC5 code
27063 ['] (CR) IS CR \ restore CR
27064 ['] (EMIT) IS EMIT \ restore EMIT
27065 HI2LO \ switch from FORTH to assembler
27066 \ ------------------------------\
27067 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
27068 \ ------------------------------\
27069 MOV @PSP+,&BASE \ restore variable BASE
27070 RETI \ CPU is ON, GIE is OFF
27075 \ ------------------------------\
27076 \ TB0CTL = %0000 0010 1001 0100\$3C0
27077 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27078 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27079 \ -- \ID input divider \ 10 = /4
27080 \ -- \MC Mode Control \ 01 = up to TB0CCR0
27081 \ - \TBCLR TimerB Clear
27084 \ --------------------------------\\
27085 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27086 \ -- \CM Capture Mode
27091 \ --- \OUTMOD \ 011 = set/reset
27097 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
27099 \ ------------------------------\
27100 \ set TimerB to make 50kHz PWM \
27101 \ ------------------------------\
27102 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27103 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
27104 \ ------------------------------\
27105 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27106 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
27107 \ ------------------------------\
27108 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27109 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
27110 \ ------------------------------\
27111 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27112 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
27113 \ ------------------------------\
27114 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27115 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
27116 \ ------------------------------\
27117 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
27118 \ ------------------------------\
27119 \ set TimerB to generate PWM for LCD_Vo
27120 \ ------------------------------\
27121 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
27122 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
27123 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27124 \ ------------------------------\
27125 BIS.B #LCDVo,&LCDVo_DIR \
27126 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
27127 \ ------------------------------\
27128 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27129 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27130 \ ------------------------------\
27131 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27132 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27133 \ ------------------------------\
27134 \ WDT interval init part \
27135 \ ------------------------------\
27136 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
27137 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
27138 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
27139 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
27140 \ ------------------------------\
27142 \ ------------------------------\
27143 BIS.B #RC5,&IR_IE \ enable RC5_Int
27144 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27145 \ ------------------------------\
27146 \ init interrupt vectors
27147 \ ------------------------------\
27148 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
27149 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27150 \ ------------------------------\
27151 \ define LPM mode for ACCEPT \
27152 \ ------------------------------\
27153 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27154 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27155 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27157 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
27159 \ ------------------------------\
27161 \ ------------------------------\
27162 $03E8 20_US \ 1- wait 20 ms
27163 $03 TOP_LCD \ 2- send DB5=DB4=1
27164 $CD 20_US \ 3- wait 4,1 ms
27165 $03 TOP_LCD \ 4- send again DB5=DB4=1
27166 $5 20_US \ 5- wait 0,1 ms
27167 $03 TOP_LCD \ 6- send again again DB5=DB4=1
27168 $2 20_US \ wait 40 us = LCD cycle
27169 $02 TOP_LCD \ 7- send DB5=1 DB4=0
27170 $2 20_US \ wait 40 us = LCD cycle
27171 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27172 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27173 LCD_Clear \ 10- "LCD_Clear"
27174 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27175 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27176 LCD_Clear \ 10- "LCD_Clear"
27177 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27178 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27180 ['] (CR) IS CR \ ' (CR) is CR
27181 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
27183 ." RC5toLCD is running. Type STOP to quit"
27184 \ NOECHO \ uncomment to run this app without terminal connexion
27185 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
27186 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
27190 : STOP \ stops multitasking, must to be used before downloading app
27191 ['] (WARM) IS WARM \ remove START app from FORTH init process
27192 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
27200 CODE MAX \ n1 n2 -- n3 signed maximum
27201 CMP @PSP,TOS \ n2-n1
27202 S< ?GOTO FW1 \ n2<n1
27208 CODE MIN \ n1 n2 -- n3 signed minimum
27209 CMP @PSP,TOS \ n2-n1
27210 S< ?GOTO BW1 \ n2<n1
27216 : U.R \ u n -- display u unsigned in n width (n >= 2)
27218 R> OVER - 0 MAX SPACES TYPE
27222 CODE 20_US \ n -- n * 20 us
27223 BEGIN \ 3 cycles loop + 6~
27224 \ MOV #5,W \ 3 MCLK = 1 MHz
27225 \ MOV #23,W \ 3 MCLK = 4 MHz
27226 MOV #51,W \ 3 MCLK = 8 MHz
27227 \ MOV #104,W \ 3 MCLK = 16 MHz
27228 \ MOV #158,W \ 3 MCLK = 24 MHz
27229 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
27239 CODE TOP_LCD \ LCD Sample
27240 \ \ if write : %xxxxWWWW --
27241 \ \ if read : -- %0000RRRR
27242 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27243 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27244 0= IF \ write LCD bits pattern
27245 AND.B #LCD_DB,TOS \
27246 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27247 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27250 THEN \ read LCD bits pattern
27253 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27254 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27255 AND.B #LCD_DB,TOS \
27260 CODE LCD_W \ byte -- write byte to LCD
27262 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
27263 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
27264 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27265 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27266 COLON \ high level word starts here
27267 TOP_LCD 2 20_US \ write high nibble first
27272 CODE LCD_WrC \ char -- Write Char
27273 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27278 CODE LCD_WrF \ func -- Write Fonction
27279 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27285 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
27290 $02 LCD_WrF 100 20_us
27294 \ : LCD_Entry_set $04 OR LCD_WrF ;
27296 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
27298 \ : LCD_Display_Shift $10 OR LCD_WrF ;
27300 \ : LCD_Fn_Set $20 OR LCD_WrF ;
27302 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
27304 \ : LCD_Goto $80 OR LCD_WrF ;
27306 \ CODE LCD_R \ -- byte read byte from LCD
27307 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27308 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27309 \ COLON \ starts a FORTH word
27310 \ TOP_LCD 2 20_us \ -- %0000HHHH
27311 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
27312 \ HI2LO \ switch from FORTH to assembler
27313 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
27314 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
27315 \ MOV @RSP+,IP \ restore IP saved by COLON
27320 \ CODE LCD_RdS \ -- status Read Status
27321 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27326 \ CODE LCD_RdC \ -- char Read Char
27327 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27332 \ -------------+------+------+------+------++---+---+---+---+---------+
27333 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
27334 \ -------------+------+------+------+------++---+---+---+---+---------+
27335 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
27336 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
27337 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
27338 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
27339 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
27340 \ -------------+------+------+------+------++---+---+---+---+---------+
27343 \ ******************************\
27344 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27345 \ ******************************\
27346 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
27347 \ ------------------------------\
27348 \ define LPM mode for ACCEPT \
27349 \ ------------------------------\
27350 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27351 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27352 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27353 BIT.B #SW2,&SW2_IN \ test switch S2
27354 0= IF \ case of switch S2 pressed
27355 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
27357 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
27360 BIT.B #SW1,&SW1_IN \ test switch S1 input
27361 0= IF \ case of Switch S1 pressed
27362 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
27364 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
27368 RETI \ CPU is ON, GIE is OFF
27373 \ ------------------------------\
27374 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27375 \ ******************************\
27376 ASM RC5_INT \ wake up on Px.RC5 change interrupt
27377 \ ******************************\
27378 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27379 \ \ SMclock = 8|16|24 MHz
27380 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
27381 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
27382 \ \ SR(9)=new Toggle bit memory (ADD on)
27383 \ ------------------------------\
27384 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
27385 \ ------------------------------\
27386 \ define LPM mode for ACCEPT \
27387 \ ------------------------------\
27388 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27389 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27390 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27391 \ ------------------------------\
27392 \ RC5_FirstStartBitHalfCycle: \
27393 \ ------------------------------\
27394 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
27395 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
27396 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
27397 MOV #1778,X \ RC5_Period in us
27398 MOV #14,W \ count of loop
27400 \ ------------------------------\
27401 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
27402 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
27403 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
27404 \ RC5_Compute_3/4_Period: \ |
27405 RRUM #1,X \ X=1/2 cycle |
27409 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
27410 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
27412 \ ------------------------------\
27413 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
27414 \ ------------------------------\
27415 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27416 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
27417 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27418 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27419 SUB #1,W \ decrement count loop
27420 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
27421 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27422 0<> WHILE \ ----> out of loop ----+
27423 \ RC5_compute_7/4_Time_out: \ |
27424 ADD X,Y \ | out of bound = 7/4 period
27425 \ RC5_WaitHalfCycleP1.2_IFG: \ |
27427 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
27428 0>= IF \ | if cycle time out of bound
27429 BIC #$30,&TA0CTL \ | stop timer_A0
27430 RETI \ | then quit to do nothing
27432 \ ------------------------------\ |
27433 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
27435 MOV &TA0R,X \ | | get new RC5_period value
27436 REPEAT \ ----> loop back --+ |
27437 \ ------------------------------\ |
27438 \ RC5_SampleEndOf: \ <---------------------+
27439 \ ------------------------------\
27440 BIC #$30,&TA0CTL \ stop timer_A0
27441 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
27442 \ ******************************\
27443 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27444 \ ******************************\
27445 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
27446 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
27447 XOR IP,X \ (new XOR old) Toggle bit (13)
27448 BIT #BIT13,X \ X(13) = New_RC5_command
27449 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
27451 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
27452 \ ******************************\
27453 \ RC5_ComputeNewRC5word \
27454 \ ******************************\
27456 MOV &BASE,2(PSP) \ save variable BASE before use
27457 MOV TOS,0(PSP) \ save TOS before use
27458 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
27459 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
27460 \ ******************************\
27461 \ RC5_ComputeC6bit \
27462 \ ******************************\
27463 BIT #$4000,IP \ test /C6 bit in IP
27464 0= IF BIS #$40,TOS \ set C6 bit in S
27465 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
27466 \ ******************************\
27467 \ RC5_CommandByteIsDone \ RC5_code --
27468 \ ******************************\
27470 \ ------------------------------\
27471 \ Display IR_RC5 code \
27472 \ ------------------------------\
27473 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
27474 \ ------------------------------\
27475 LO2HI \ switch from assembler to FORTH
27476 ['] LCD_CLEAR IS CR \ redirects CR
27477 ['] LCD_WrC IS EMIT \ redirects EMIT
27478 $10 BASE ! \ change BASE to hexadecimal
27479 CR ." $" 2 U.R \ print IR_RC5 code
27480 ['] (CR) IS CR \ restore CR
27481 ['] (EMIT) IS EMIT \ restore EMIT
27482 HI2LO \ switch from FORTH to assembler
27483 \ ------------------------------\
27484 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
27485 \ ------------------------------\
27486 MOV @PSP+,&BASE \ restore variable BASE
27487 RETI \ CPU is ON, GIE is OFF
27492 \ ------------------------------\
27493 \ TB0CTL = %0000 0010 1001 0100\$3C0
27494 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27495 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27496 \ -- \ID input divider \ 10 = /4
27497 \ -- \MC Mode Control \ 01 = up to TB0CCR0
27498 \ - \TBCLR TimerB Clear
27501 \ --------------------------------\\
27502 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27503 \ -- \CM Capture Mode
27508 \ --- \OUTMOD \ 011 = set/reset
27514 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
27516 \ ------------------------------\
27517 \ set TimerB to make 50kHz PWM \
27518 \ ------------------------------\
27519 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27520 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
27521 \ ------------------------------\
27522 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27523 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
27524 \ ------------------------------\
27525 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27526 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
27527 \ ------------------------------\
27528 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27529 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
27530 \ ------------------------------\
27531 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27532 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
27533 \ ------------------------------\
27534 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
27535 \ ------------------------------\
27536 \ set TimerB to generate PWM for LCD_Vo
27537 \ ------------------------------\
27538 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
27539 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
27540 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27541 \ ------------------------------\
27542 BIS.B #LCDVo,&LCDVo_DIR \
27543 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
27544 \ ------------------------------\
27545 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27546 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27547 \ ------------------------------\
27548 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27549 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27550 \ ------------------------------\
27551 \ WDT interval init part \
27552 \ ------------------------------\
27553 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
27554 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
27555 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
27556 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
27557 \ ------------------------------\
27559 \ ------------------------------\
27560 BIS.B #RC5,&IR_IE \ enable RC5_Int
27561 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27562 \ ------------------------------\
27563 \ init interrupt vectors
27564 \ ------------------------------\
27565 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
27566 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27567 \ ------------------------------\
27568 \ define LPM mode for ACCEPT \
27569 \ ------------------------------\
27570 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27571 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27572 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27574 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
27576 \ ------------------------------\
27578 \ ------------------------------\
27579 $03E8 20_US \ 1- wait 20 ms
27580 $03 TOP_LCD \ 2- send DB5=DB4=1
27581 $CD 20_US \ 3- wait 4,1 ms
27582 $03 TOP_LCD \ 4- send again DB5=DB4=1
27583 $5 20_US \ 5- wait 0,1 ms
27584 $03 TOP_LCD \ 6- send again again DB5=DB4=1
27585 $2 20_US \ wait 40 us = LCD cycle
27586 $02 TOP_LCD \ 7- send DB5=1 DB4=0
27587 $2 20_US \ wait 40 us = LCD cycle
27588 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27589 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27590 LCD_Clear \ 10- "LCD_Clear"
27591 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27592 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27593 LCD_Clear \ 10- "LCD_Clear"
27594 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27595 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27597 ['] (CR) IS CR \ ' (CR) is CR
27598 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
27600 ." RC5toLCD is running. Type STOP to quit"
27601 \ NOECHO \ uncomment to run this app without terminal connexion
27602 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
27603 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
27607 : STOP \ stops multitasking, must to be used before downloading app
27608 ['] (WARM) IS WARM \ remove START app from FORTH init process
27609 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
27617 CODE MAX \ n1 n2 -- n3 signed maximum
27618 CMP @PSP,TOS \ n2-n1
27619 S< ?GOTO FW1 \ n2<n1
27625 CODE MIN \ n1 n2 -- n3 signed minimum
27626 CMP @PSP,TOS \ n2-n1
27627 S< ?GOTO BW1 \ n2<n1
27633 : U.R \ u n -- display u unsigned in n width (n >= 2)
27635 R> OVER - 0 MAX SPACES TYPE
27639 CODE 20_US \ n -- n * 20 us
27640 BEGIN \ 3 cycles loop + 6~
27641 \ MOV #5,W \ 3 MCLK = 1 MHz
27642 \ MOV #23,W \ 3 MCLK = 4 MHz
27643 MOV #51,W \ 3 MCLK = 8 MHz
27644 \ MOV #104,W \ 3 MCLK = 16 MHz
27645 \ MOV #158,W \ 3 MCLK = 24 MHz
27646 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
27656 CODE TOP_LCD \ LCD Sample
27657 \ \ if write : %xxxxWWWW --
27658 \ \ if read : -- %0000RRRR
27659 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27660 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27661 0= IF \ write LCD bits pattern
27662 AND.B #LCD_DB,TOS \
27663 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27664 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27667 THEN \ read LCD bits pattern
27670 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27671 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27672 AND.B #LCD_DB,TOS \
27677 CODE LCD_W \ byte -- write byte to LCD
27679 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
27680 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
27681 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27682 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27683 COLON \ high level word starts here
27684 TOP_LCD 2 20_US \ write high nibble first
27689 CODE LCD_WrC \ char -- Write Char
27690 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27695 CODE LCD_WrF \ func -- Write Fonction
27696 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27702 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
27707 $02 LCD_WrF 100 20_us
27711 \ : LCD_Entry_set $04 OR LCD_WrF ;
27713 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
27715 \ : LCD_Display_Shift $10 OR LCD_WrF ;
27717 \ : LCD_Fn_Set $20 OR LCD_WrF ;
27719 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
27721 \ : LCD_Goto $80 OR LCD_WrF ;
27723 \ CODE LCD_R \ -- byte read byte from LCD
27724 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27725 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27726 \ COLON \ starts a FORTH word
27727 \ TOP_LCD 2 20_us \ -- %0000HHHH
27728 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
27729 \ HI2LO \ switch from FORTH to assembler
27730 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
27731 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
27732 \ MOV @RSP+,IP \ restore IP saved by COLON
27737 \ CODE LCD_RdS \ -- status Read Status
27738 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27743 \ CODE LCD_RdC \ -- char Read Char
27744 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27749 \ -------------+------+------+------+------++---+---+---+---+---------+
27750 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
27751 \ -------------+------+------+------+------++---+---+---+---+---------+
27752 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
27753 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
27754 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
27755 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
27756 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
27757 \ -------------+------+------+------+------++---+---+---+---+---------+
27760 \ ******************************\
27761 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27762 \ ******************************\
27763 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
27764 \ ------------------------------\
27765 \ define LPM mode for ACCEPT \
27766 \ ------------------------------\
27767 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27768 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27769 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27770 BIT.B #SW2,&SW2_IN \ test switch S2
27771 0= IF \ case of switch S2 pressed
27772 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
27774 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
27777 BIT.B #SW1,&SW1_IN \ test switch S1 input
27778 0= IF \ case of Switch S1 pressed
27779 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
27781 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
27785 RETI \ CPU is ON, GIE is OFF
27790 \ ------------------------------\
27791 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27792 \ ******************************\
27793 ASM RC5_INT \ wake up on Px.RC5 change interrupt
27794 \ ******************************\
27795 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27796 \ \ SMclock = 8|16|24 MHz
27797 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
27798 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
27799 \ \ SR(9)=new Toggle bit memory (ADD on)
27800 \ ------------------------------\
27801 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
27802 \ ------------------------------\
27803 \ define LPM mode for ACCEPT \
27804 \ ------------------------------\
27805 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27806 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27807 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27808 \ ------------------------------\
27809 \ RC5_FirstStartBitHalfCycle: \
27810 \ ------------------------------\
27811 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
27812 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
27813 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
27814 MOV #1778,X \ RC5_Period in us
27815 MOV #14,W \ count of loop
27817 \ ------------------------------\
27818 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
27819 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
27820 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
27821 \ RC5_Compute_3/4_Period: \ |
27822 RRUM #1,X \ X=1/2 cycle |
27826 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
27827 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
27829 \ ------------------------------\
27830 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
27831 \ ------------------------------\
27832 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27833 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
27834 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27835 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27836 SUB #1,W \ decrement count loop
27837 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
27838 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27839 0<> WHILE \ ----> out of loop ----+
27840 \ RC5_compute_7/4_Time_out: \ |
27841 ADD X,Y \ | out of bound = 7/4 period
27842 \ RC5_WaitHalfCycleP1.2_IFG: \ |
27844 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
27845 0>= IF \ | if cycle time out of bound
27846 BIC #$30,&TA0CTL \ | stop timer_A0
27847 RETI \ | then quit to do nothing
27849 \ ------------------------------\ |
27850 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
27852 MOV &TA0R,X \ | | get new RC5_period value
27853 REPEAT \ ----> loop back --+ |
27854 \ ------------------------------\ |
27855 \ RC5_SampleEndOf: \ <---------------------+
27856 \ ------------------------------\
27857 BIC #$30,&TA0CTL \ stop timer_A0
27858 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
27859 \ ******************************\
27860 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27861 \ ******************************\
27862 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
27863 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
27864 XOR IP,X \ (new XOR old) Toggle bit (13)
27865 BIT #BIT13,X \ X(13) = New_RC5_command
27866 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
27868 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
27869 \ ******************************\
27870 \ RC5_ComputeNewRC5word \
27871 \ ******************************\
27873 MOV &BASE,2(PSP) \ save variable BASE before use
27874 MOV TOS,0(PSP) \ save TOS before use
27875 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
27876 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
27877 \ ******************************\
27878 \ RC5_ComputeC6bit \
27879 \ ******************************\
27880 BIT #$4000,IP \ test /C6 bit in IP
27881 0= IF BIS #$40,TOS \ set C6 bit in S
27882 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
27883 \ ******************************\
27884 \ RC5_CommandByteIsDone \ RC5_code --
27885 \ ******************************\
27887 \ ------------------------------\
27888 \ Display IR_RC5 code \
27889 \ ------------------------------\
27890 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
27891 \ ------------------------------\
27892 LO2HI \ switch from assembler to FORTH
27893 ['] LCD_CLEAR IS CR \ redirects CR
27894 ['] LCD_WrC IS EMIT \ redirects EMIT
27895 $10 BASE ! \ change BASE to hexadecimal
27896 CR ." $" 2 U.R \ print IR_RC5 code
27897 ['] (CR) IS CR \ restore CR
27898 ['] (EMIT) IS EMIT \ restore EMIT
27899 HI2LO \ switch from FORTH to assembler
27900 \ ------------------------------\
27901 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
27902 \ ------------------------------\
27903 MOV @PSP+,&BASE \ restore variable BASE
27904 RETI \ CPU is ON, GIE is OFF
27909 \ ------------------------------\
27910 \ TB0CTL = %0000 0010 1001 0100\$3C0
27911 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27912 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27913 \ -- \ID input divider \ 10 = /4
27914 \ -- \MC Mode Control \ 01 = up to TB0CCR0
27915 \ - \TBCLR TimerB Clear
27918 \ --------------------------------\\
27919 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27920 \ -- \CM Capture Mode
27925 \ --- \OUTMOD \ 011 = set/reset
27931 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
27933 \ ------------------------------\
27934 \ set TimerB to make 50kHz PWM \
27935 \ ------------------------------\
27936 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27937 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
27938 \ ------------------------------\
27939 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27940 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
27941 \ ------------------------------\
27942 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27943 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
27944 \ ------------------------------\
27945 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27946 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
27947 \ ------------------------------\
27948 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27949 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
27950 \ ------------------------------\
27951 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
27952 \ ------------------------------\
27953 \ set TimerB to generate PWM for LCD_Vo
27954 \ ------------------------------\
27955 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
27956 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
27957 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27958 \ ------------------------------\
27959 BIS.B #LCDVo,&LCDVo_DIR \
27960 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
27961 \ ------------------------------\
27962 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27963 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27964 \ ------------------------------\
27965 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27966 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27967 \ ------------------------------\
27968 \ WDT interval init part \
27969 \ ------------------------------\
27970 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
27971 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
27972 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
27973 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
27974 \ ------------------------------\
27976 \ ------------------------------\
27977 BIS.B #RC5,&IR_IE \ enable RC5_Int
27978 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27979 \ ------------------------------\
27980 \ init interrupt vectors
27981 \ ------------------------------\
27982 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
27983 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27984 \ ------------------------------\
27985 \ define LPM mode for ACCEPT \
27986 \ ------------------------------\
27987 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27988 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27989 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27991 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
27993 \ ------------------------------\
27995 \ ------------------------------\
27996 $03E8 20_US \ 1- wait 20 ms
27997 $03 TOP_LCD \ 2- send DB5=DB4=1
27998 $CD 20_US \ 3- wait 4,1 ms
27999 $03 TOP_LCD \ 4- send again DB5=DB4=1
28000 $5 20_US \ 5- wait 0,1 ms
28001 $03 TOP_LCD \ 6- send again again DB5=DB4=1
28002 $2 20_US \ wait 40 us = LCD cycle
28003 $02 TOP_LCD \ 7- send DB5=1 DB4=0
28004 $2 20_US \ wait 40 us = LCD cycle
28005 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28006 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28007 LCD_Clear \ 10- "LCD_Clear"
28008 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28009 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28010 LCD_Clear \ 10- "LCD_Clear"
28011 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28012 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28014 ['] (CR) IS CR \ ' (CR) is CR
28015 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
28017 ." RC5toLCD is running. Type STOP to quit"
28018 \ NOECHO \ uncomment to run this app without terminal connexion
28019 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
28020 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
28024 : STOP \ stops multitasking, must to be used before downloading app
28025 ['] (WARM) IS WARM \ remove START app from FORTH init process
28026 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
28034 CODE MAX \ n1 n2 -- n3 signed maximum
28035 CMP @PSP,TOS \ n2-n1
28036 S< ?GOTO FW1 \ n2<n1
28042 CODE MIN \ n1 n2 -- n3 signed minimum
28043 CMP @PSP,TOS \ n2-n1
28044 S< ?GOTO BW1 \ n2<n1
28050 : U.R \ u n -- display u unsigned in n width (n >= 2)
28052 R> OVER - 0 MAX SPACES TYPE
28056 CODE 20_US \ n -- n * 20 us
28057 BEGIN \ 3 cycles loop + 6~
28058 \ MOV #5,W \ 3 MCLK = 1 MHz
28059 \ MOV #23,W \ 3 MCLK = 4 MHz
28060 MOV #51,W \ 3 MCLK = 8 MHz
28061 \ MOV #104,W \ 3 MCLK = 16 MHz
28062 \ MOV #158,W \ 3 MCLK = 24 MHz
28063 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
28073 CODE TOP_LCD \ LCD Sample
28074 \ \ if write : %xxxxWWWW --
28075 \ \ if read : -- %0000RRRR
28076 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28077 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28078 0= IF \ write LCD bits pattern
28079 AND.B #LCD_DB,TOS \
28080 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28081 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28084 THEN \ read LCD bits pattern
28087 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28088 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28089 AND.B #LCD_DB,TOS \
28094 CODE LCD_W \ byte -- write byte to LCD
28096 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
28097 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
28098 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28099 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28100 COLON \ high level word starts here
28101 TOP_LCD 2 20_US \ write high nibble first
28106 CODE LCD_WrC \ char -- Write Char
28107 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28112 CODE LCD_WrF \ func -- Write Fonction
28113 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28119 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
28124 $02 LCD_WrF 100 20_us
28128 \ : LCD_Entry_set $04 OR LCD_WrF ;
28130 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
28132 \ : LCD_Display_Shift $10 OR LCD_WrF ;
28134 \ : LCD_Fn_Set $20 OR LCD_WrF ;
28136 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
28138 \ : LCD_Goto $80 OR LCD_WrF ;
28140 \ CODE LCD_R \ -- byte read byte from LCD
28141 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28142 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28143 \ COLON \ starts a FORTH word
28144 \ TOP_LCD 2 20_us \ -- %0000HHHH
28145 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
28146 \ HI2LO \ switch from FORTH to assembler
28147 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
28148 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
28149 \ MOV @RSP+,IP \ restore IP saved by COLON
28154 \ CODE LCD_RdS \ -- status Read Status
28155 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28160 \ CODE LCD_RdC \ -- char Read Char
28161 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28166 \ -------------+------+------+------+------++---+---+---+---+---------+
28167 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
28168 \ -------------+------+------+------+------++---+---+---+---+---------+
28169 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
28170 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
28171 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
28172 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
28173 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
28174 \ -------------+------+------+------+------++---+---+---+---+---------+
28177 \ ******************************\
28178 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28179 \ ******************************\
28180 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
28181 \ ------------------------------\
28182 \ define LPM mode for ACCEPT \
28183 \ ------------------------------\
28184 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28185 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28186 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28187 BIT.B #SW2,&SW2_IN \ test switch S2
28188 0= IF \ case of switch S2 pressed
28189 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
28191 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
28194 BIT.B #SW1,&SW1_IN \ test switch S1 input
28195 0= IF \ case of Switch S1 pressed
28196 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
28198 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
28202 RETI \ CPU is ON, GIE is OFF
28207 \ ------------------------------\
28208 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28209 \ ******************************\
28210 ASM RC5_INT \ wake up on Px.RC5 change interrupt
28211 \ ******************************\
28212 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28213 \ \ SMclock = 8|16|24 MHz
28214 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
28215 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
28216 \ \ SR(9)=new Toggle bit memory (ADD on)
28217 \ ------------------------------\
28218 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
28219 \ ------------------------------\
28220 \ define LPM mode for ACCEPT \
28221 \ ------------------------------\
28222 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28223 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28224 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28225 \ ------------------------------\
28226 \ RC5_FirstStartBitHalfCycle: \
28227 \ ------------------------------\
28228 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
28229 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
28230 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
28231 MOV #1778,X \ RC5_Period in us
28232 MOV #14,W \ count of loop
28234 \ ------------------------------\
28235 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
28236 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
28237 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
28238 \ RC5_Compute_3/4_Period: \ |
28239 RRUM #1,X \ X=1/2 cycle |
28243 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
28244 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
28246 \ ------------------------------\
28247 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
28248 \ ------------------------------\
28249 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28250 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
28251 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28252 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28253 SUB #1,W \ decrement count loop
28254 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
28255 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28256 0<> WHILE \ ----> out of loop ----+
28257 \ RC5_compute_7/4_Time_out: \ |
28258 ADD X,Y \ | out of bound = 7/4 period
28259 \ RC5_WaitHalfCycleP1.2_IFG: \ |
28261 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
28262 0>= IF \ | if cycle time out of bound
28263 BIC #$30,&TA0CTL \ | stop timer_A0
28264 RETI \ | then quit to do nothing
28266 \ ------------------------------\ |
28267 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
28269 MOV &TA0R,X \ | | get new RC5_period value
28270 REPEAT \ ----> loop back --+ |
28271 \ ------------------------------\ |
28272 \ RC5_SampleEndOf: \ <---------------------+
28273 \ ------------------------------\
28274 BIC #$30,&TA0CTL \ stop timer_A0
28275 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
28276 \ ******************************\
28277 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
28278 \ ******************************\
28279 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
28280 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
28281 XOR IP,X \ (new XOR old) Toggle bit (13)
28282 BIT #BIT13,X \ X(13) = New_RC5_command
28283 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
28285 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
28286 \ ******************************\
28287 \ RC5_ComputeNewRC5word \
28288 \ ******************************\
28290 MOV &BASE,2(PSP) \ save variable BASE before use
28291 MOV TOS,0(PSP) \ save TOS before use
28292 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
28293 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
28294 \ ******************************\
28295 \ RC5_ComputeC6bit \
28296 \ ******************************\
28297 BIT #$4000,IP \ test /C6 bit in IP
28298 0= IF BIS #$40,TOS \ set C6 bit in S
28299 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
28300 \ ******************************\
28301 \ RC5_CommandByteIsDone \ RC5_code --
28302 \ ******************************\
28304 \ ------------------------------\
28305 \ Display IR_RC5 code \
28306 \ ------------------------------\
28307 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
28308 \ ------------------------------\
28309 LO2HI \ switch from assembler to FORTH
28310 ['] LCD_CLEAR IS CR \ redirects CR
28311 ['] LCD_WrC IS EMIT \ redirects EMIT
28312 $10 BASE ! \ change BASE to hexadecimal
28313 CR ." $" 2 U.R \ print IR_RC5 code
28314 ['] (CR) IS CR \ restore CR
28315 ['] (EMIT) IS EMIT \ restore EMIT
28316 HI2LO \ switch from FORTH to assembler
28317 \ ------------------------------\
28318 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
28319 \ ------------------------------\
28320 MOV @PSP+,&BASE \ restore variable BASE
28321 RETI \ CPU is ON, GIE is OFF
28326 \ ------------------------------\
28327 \ TB0CTL = %0000 0010 1001 0100\$3C0
28328 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28329 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28330 \ -- \ID input divider \ 10 = /4
28331 \ -- \MC Mode Control \ 01 = up to TB0CCR0
28332 \ - \TBCLR TimerB Clear
28335 \ --------------------------------\\
28336 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28337 \ -- \CM Capture Mode
28342 \ --- \OUTMOD \ 011 = set/reset
28348 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
28350 \ ------------------------------\
28351 \ set TimerB to make 50kHz PWM \
28352 \ ------------------------------\
28353 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
28354 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
28355 \ ------------------------------\
28356 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
28357 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
28358 \ ------------------------------\
28359 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28360 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
28361 \ ------------------------------\
28362 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28363 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
28364 \ ------------------------------\
28365 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28366 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
28367 \ ------------------------------\
28368 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
28369 \ ------------------------------\
28370 \ set TimerB to generate PWM for LCD_Vo
28371 \ ------------------------------\
28372 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
28373 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
28374 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28375 \ ------------------------------\
28376 BIS.B #LCDVo,&LCDVo_DIR \
28377 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
28378 \ ------------------------------\
28379 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28380 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28381 \ ------------------------------\
28382 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28383 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28384 \ ------------------------------\
28385 \ WDT interval init part \
28386 \ ------------------------------\
28387 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
28388 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
28389 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
28390 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
28391 \ ------------------------------\
28393 \ ------------------------------\
28394 BIS.B #RC5,&IR_IE \ enable RC5_Int
28395 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28396 \ ------------------------------\
28397 \ init interrupt vectors
28398 \ ------------------------------\
28399 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
28400 MOV #RC5_INT,&IR_Vec \ init interrupt vector
28401 \ ------------------------------\
28402 \ define LPM mode for ACCEPT \
28403 \ ------------------------------\
28404 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28405 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28406 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28408 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
28410 \ ------------------------------\
28412 \ ------------------------------\
28413 $03E8 20_US \ 1- wait 20 ms
28414 $03 TOP_LCD \ 2- send DB5=DB4=1
28415 $CD 20_US \ 3- wait 4,1 ms
28416 $03 TOP_LCD \ 4- send again DB5=DB4=1
28417 $5 20_US \ 5- wait 0,1 ms
28418 $03 TOP_LCD \ 6- send again again DB5=DB4=1
28419 $2 20_US \ wait 40 us = LCD cycle
28420 $02 TOP_LCD \ 7- send DB5=1 DB4=0
28421 $2 20_US \ wait 40 us = LCD cycle
28422 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28423 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28424 LCD_Clear \ 10- "LCD_Clear"
28425 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28426 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28427 LCD_Clear \ 10- "LCD_Clear"
28428 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28429 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28431 ['] (CR) IS CR \ ' (CR) is CR
28432 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
28434 ." RC5toLCD is running. Type STOP to quit"
28435 \ NOECHO \ uncomment to run this app without terminal connexion
28436 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
28437 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
28441 : STOP \ stops multitasking, must to be used before downloading app
28442 ['] (WARM) IS WARM \ remove START app from FORTH init process
28443 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
28451 CODE MAX \ n1 n2 -- n3 signed maximum
28452 CMP @PSP,TOS \ n2-n1
28453 S< ?GOTO FW1 \ n2<n1
28459 CODE MIN \ n1 n2 -- n3 signed minimum
28460 CMP @PSP,TOS \ n2-n1
28461 S< ?GOTO BW1 \ n2<n1
28467 : U.R \ u n -- display u unsigned in n width (n >= 2)
28469 R> OVER - 0 MAX SPACES TYPE
28473 CODE 20_US \ n -- n * 20 us
28474 BEGIN \ 3 cycles loop + 6~
28475 \ MOV #5,W \ 3 MCLK = 1 MHz
28476 \ MOV #23,W \ 3 MCLK = 4 MHz
28477 MOV #51,W \ 3 MCLK = 8 MHz
28478 \ MOV #104,W \ 3 MCLK = 16 MHz
28479 \ MOV #158,W \ 3 MCLK = 24 MHz
28480 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
28490 CODE TOP_LCD \ LCD Sample
28491 \ \ if write : %xxxxWWWW --
28492 \ \ if read : -- %0000RRRR
28493 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28494 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28495 0= IF \ write LCD bits pattern
28496 AND.B #LCD_DB,TOS \
28497 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28498 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28501 THEN \ read LCD bits pattern
28504 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28505 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28506 AND.B #LCD_DB,TOS \
28511 CODE LCD_W \ byte -- write byte to LCD
28513 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
28514 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
28515 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28516 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28517 COLON \ high level word starts here
28518 TOP_LCD 2 20_US \ write high nibble first
28523 CODE LCD_WrC \ char -- Write Char
28524 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28529 CODE LCD_WrF \ func -- Write Fonction
28530 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28536 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
28541 $02 LCD_WrF 100 20_us
28545 \ : LCD_Entry_set $04 OR LCD_WrF ;
28547 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
28549 \ : LCD_Display_Shift $10 OR LCD_WrF ;
28551 \ : LCD_Fn_Set $20 OR LCD_WrF ;
28553 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
28555 \ : LCD_Goto $80 OR LCD_WrF ;
28557 \ CODE LCD_R \ -- byte read byte from LCD
28558 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28559 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28560 \ COLON \ starts a FORTH word
28561 \ TOP_LCD 2 20_us \ -- %0000HHHH
28562 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
28563 \ HI2LO \ switch from FORTH to assembler
28564 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
28565 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
28566 \ MOV @RSP+,IP \ restore IP saved by COLON
28571 \ CODE LCD_RdS \ -- status Read Status
28572 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28577 \ CODE LCD_RdC \ -- char Read Char
28578 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28583 \ -------------+------+------+------+------++---+---+---+---+---------+
28584 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
28585 \ -------------+------+------+------+------++---+---+---+---+---------+
28586 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
28587 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
28588 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
28589 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
28590 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
28591 \ -------------+------+------+------+------++---+---+---+---+---------+
28594 \ ******************************\
28595 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28596 \ ******************************\
28597 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
28598 \ ------------------------------\
28599 \ define LPM mode for ACCEPT \
28600 \ ------------------------------\
28601 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28602 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28603 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28604 BIT.B #SW2,&SW2_IN \ test switch S2
28605 0= IF \ case of switch S2 pressed
28606 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
28608 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
28611 BIT.B #SW1,&SW1_IN \ test switch S1 input
28612 0= IF \ case of Switch S1 pressed
28613 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
28615 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
28619 RETI \ CPU is ON, GIE is OFF
28624 \ ------------------------------\
28625 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28626 \ ******************************\
28627 ASM RC5_INT \ wake up on Px.RC5 change interrupt
28628 \ ******************************\
28629 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28630 \ \ SMclock = 8|16|24 MHz
28631 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
28632 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
28633 \ \ SR(9)=new Toggle bit memory (ADD on)
28634 \ ------------------------------\
28635 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
28636 \ ------------------------------\
28637 \ define LPM mode for ACCEPT \
28638 \ ------------------------------\
28639 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28640 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28641 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28642 \ ------------------------------\
28643 \ RC5_FirstStartBitHalfCycle: \
28644 \ ------------------------------\
28645 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
28646 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
28647 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
28648 MOV #1778,X \ RC5_Period in us
28649 MOV #14,W \ count of loop
28651 \ ------------------------------\
28652 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
28653 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
28654 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
28655 \ RC5_Compute_3/4_Period: \ |
28656 RRUM #1,X \ X=1/2 cycle |
28660 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
28661 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
28663 \ ------------------------------\
28664 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
28665 \ ------------------------------\
28666 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28667 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
28668 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28669 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28670 SUB #1,W \ decrement count loop
28671 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
28672 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28673 0<> WHILE \ ----> out of loop ----+
28674 \ RC5_compute_7/4_Time_out: \ |
28675 ADD X,Y \ | out of bound = 7/4 period
28676 \ RC5_WaitHalfCycleP1.2_IFG: \ |
28678 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
28679 0>= IF \ | if cycle time out of bound
28680 BIC #$30,&TA0CTL \ | stop timer_A0
28681 RETI \ | then quit to do nothing
28683 \ ------------------------------\ |
28684 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
28686 MOV &TA0R,X \ | | get new RC5_period value
28687 REPEAT \ ----> loop back --+ |
28688 \ ------------------------------\ |
28689 \ RC5_SampleEndOf: \ <---------------------+
28690 \ ------------------------------\
28691 BIC #$30,&TA0CTL \ stop timer_A0
28692 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
28693 \ ******************************\
28694 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
28695 \ ******************************\
28696 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
28697 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
28698 XOR IP,X \ (new XOR old) Toggle bit (13)
28699 BIT #BIT13,X \ X(13) = New_RC5_command
28700 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
28702 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
28703 \ ******************************\
28704 \ RC5_ComputeNewRC5word \
28705 \ ******************************\
28707 MOV &BASE,2(PSP) \ save variable BASE before use
28708 MOV TOS,0(PSP) \ save TOS before use
28709 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
28710 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
28711 \ ******************************\
28712 \ RC5_ComputeC6bit \
28713 \ ******************************\
28714 BIT #$4000,IP \ test /C6 bit in IP
28715 0= IF BIS #$40,TOS \ set C6 bit in S
28716 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
28717 \ ******************************\
28718 \ RC5_CommandByteIsDone \ RC5_code --
28719 \ ******************************\
28721 \ ------------------------------\
28722 \ Display IR_RC5 code \
28723 \ ------------------------------\
28724 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
28725 \ ------------------------------\
28726 LO2HI \ switch from assembler to FORTH
28727 ['] LCD_CLEAR IS CR \ redirects CR
28728 ['] LCD_WrC IS EMIT \ redirects EMIT
28729 $10 BASE ! \ change BASE to hexadecimal
28730 CR ." $" 2 U.R \ print IR_RC5 code
28731 ['] (CR) IS CR \ restore CR
28732 ['] (EMIT) IS EMIT \ restore EMIT
28733 HI2LO \ switch from FORTH to assembler
28734 \ ------------------------------\
28735 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
28736 \ ------------------------------\
28737 MOV @PSP+,&BASE \ restore variable BASE
28738 RETI \ CPU is ON, GIE is OFF
28743 \ ------------------------------\
28744 \ TB0CTL = %0000 0010 1001 0100\$3C0
28745 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28746 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28747 \ -- \ID input divider \ 10 = /4
28748 \ -- \MC Mode Control \ 01 = up to TB0CCR0
28749 \ - \TBCLR TimerB Clear
28752 \ --------------------------------\\
28753 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28754 \ -- \CM Capture Mode
28759 \ --- \OUTMOD \ 011 = set/reset
28765 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
28767 \ ------------------------------\
28768 \ set TimerB to make 50kHz PWM \
28769 \ ------------------------------\
28770 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
28771 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
28772 \ ------------------------------\
28773 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
28774 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
28775 \ ------------------------------\
28776 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28777 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
28778 \ ------------------------------\
28779 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28780 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
28781 \ ------------------------------\
28782 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28783 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
28784 \ ------------------------------\
28785 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
28786 \ ------------------------------\
28787 \ set TimerB to generate PWM for LCD_Vo
28788 \ ------------------------------\
28789 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
28790 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
28791 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28792 \ ------------------------------\
28793 BIS.B #LCDVo,&LCDVo_DIR \
28794 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
28795 \ ------------------------------\
28796 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28797 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28798 \ ------------------------------\
28799 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28800 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28801 \ ------------------------------\
28802 \ WDT interval init part \
28803 \ ------------------------------\
28804 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
28805 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
28806 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
28807 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
28808 \ ------------------------------\
28810 \ ------------------------------\
28811 BIS.B #RC5,&IR_IE \ enable RC5_Int
28812 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28813 \ ------------------------------\
28814 \ init interrupt vectors
28815 \ ------------------------------\
28816 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
28817 MOV #RC5_INT,&IR_Vec \ init interrupt vector
28818 \ ------------------------------\
28819 \ define LPM mode for ACCEPT \
28820 \ ------------------------------\
28821 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28822 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28823 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28825 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
28827 \ ------------------------------\
28829 \ ------------------------------\
28830 $03E8 20_US \ 1- wait 20 ms
28831 $03 TOP_LCD \ 2- send DB5=DB4=1
28832 $CD 20_US \ 3- wait 4,1 ms
28833 $03 TOP_LCD \ 4- send again DB5=DB4=1
28834 $5 20_US \ 5- wait 0,1 ms
28835 $03 TOP_LCD \ 6- send again again DB5=DB4=1
28836 $2 20_US \ wait 40 us = LCD cycle
28837 $02 TOP_LCD \ 7- send DB5=1 DB4=0
28838 $2 20_US \ wait 40 us = LCD cycle
28839 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28840 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28841 LCD_Clear \ 10- "LCD_Clear"
28842 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28843 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28844 LCD_Clear \ 10- "LCD_Clear"
28845 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28846 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28848 ['] (CR) IS CR \ ' (CR) is CR
28849 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
28851 ." RC5toLCD is running. Type STOP to quit"
28852 \ NOECHO \ uncomment to run this app without terminal connexion
28853 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
28854 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
28858 : STOP \ stops multitasking, must to be used before downloading app
28859 ['] (WARM) IS WARM \ remove START app from FORTH init process
28860 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
28868 CODE MAX \ n1 n2 -- n3 signed maximum
28869 CMP @PSP,TOS \ n2-n1
28870 S< ?GOTO FW1 \ n2<n1
28876 CODE MIN \ n1 n2 -- n3 signed minimum
28877 CMP @PSP,TOS \ n2-n1
28878 S< ?GOTO BW1 \ n2<n1
28884 : U.R \ u n -- display u unsigned in n width (n >= 2)
28886 R> OVER - 0 MAX SPACES TYPE
28890 CODE 20_US \ n -- n * 20 us
28891 BEGIN \ 3 cycles loop + 6~
28892 \ MOV #5,W \ 3 MCLK = 1 MHz
28893 \ MOV #23,W \ 3 MCLK = 4 MHz
28894 MOV #51,W \ 3 MCLK = 8 MHz
28895 \ MOV #104,W \ 3 MCLK = 16 MHz
28896 \ MOV #158,W \ 3 MCLK = 24 MHz
28897 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
28907 CODE TOP_LCD \ LCD Sample
28908 \ \ if write : %xxxxWWWW --
28909 \ \ if read : -- %0000RRRR
28910 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28911 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28912 0= IF \ write LCD bits pattern
28913 AND.B #LCD_DB,TOS \
28914 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28915 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28918 THEN \ read LCD bits pattern
28921 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28922 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28923 AND.B #LCD_DB,TOS \
28928 CODE LCD_W \ byte -- write byte to LCD
28930 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
28931 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
28932 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28933 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28934 COLON \ high level word starts here
28935 TOP_LCD 2 20_US \ write high nibble first
28940 CODE LCD_WrC \ char -- Write Char
28941 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28946 CODE LCD_WrF \ func -- Write Fonction
28947 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28953 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
28958 $02 LCD_WrF 100 20_us
28962 \ : LCD_Entry_set $04 OR LCD_WrF ;
28964 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
28966 \ : LCD_Display_Shift $10 OR LCD_WrF ;
28968 \ : LCD_Fn_Set $20 OR LCD_WrF ;
28970 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
28972 \ : LCD_Goto $80 OR LCD_WrF ;
28974 \ CODE LCD_R \ -- byte read byte from LCD
28975 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28976 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28977 \ COLON \ starts a FORTH word
28978 \ TOP_LCD 2 20_us \ -- %0000HHHH
28979 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
28980 \ HI2LO \ switch from FORTH to assembler
28981 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
28982 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
28983 \ MOV @RSP+,IP \ restore IP saved by COLON
28988 \ CODE LCD_RdS \ -- status Read Status
28989 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28994 \ CODE LCD_RdC \ -- char Read Char
28995 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29000 \ -------------+------+------+------+------++---+---+---+---+---------+
29001 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
29002 \ -------------+------+------+------+------++---+---+---+---+---------+
29003 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
29004 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
29005 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
29006 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
29007 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
29008 \ -------------+------+------+------+------++---+---+---+---+---------+
29011 \ ******************************\
29012 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29013 \ ******************************\
29014 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
29015 \ ------------------------------\
29016 \ define LPM mode for ACCEPT \
29017 \ ------------------------------\
29018 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29019 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29020 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29021 BIT.B #SW2,&SW2_IN \ test switch S2
29022 0= IF \ case of switch S2 pressed
29023 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
29025 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
29028 BIT.B #SW1,&SW1_IN \ test switch S1 input
29029 0= IF \ case of Switch S1 pressed
29030 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
29032 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
29036 RETI \ CPU is ON, GIE is OFF
29041 \ ------------------------------\
29042 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29043 \ ******************************\
29044 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29045 \ ******************************\
29046 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29047 \ \ SMclock = 8|16|24 MHz
29048 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
29049 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
29050 \ \ SR(9)=new Toggle bit memory (ADD on)
29051 \ ------------------------------\
29052 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
29053 \ ------------------------------\
29054 \ define LPM mode for ACCEPT \
29055 \ ------------------------------\
29056 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29057 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29058 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29059 \ ------------------------------\
29060 \ RC5_FirstStartBitHalfCycle: \
29061 \ ------------------------------\
29062 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
29063 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
29064 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
29065 MOV #1778,X \ RC5_Period in us
29066 MOV #14,W \ count of loop
29068 \ ------------------------------\
29069 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
29070 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
29071 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
29072 \ RC5_Compute_3/4_Period: \ |
29073 RRUM #1,X \ X=1/2 cycle |
29077 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
29078 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
29080 \ ------------------------------\
29081 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
29082 \ ------------------------------\
29083 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29084 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
29085 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29086 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29087 SUB #1,W \ decrement count loop
29088 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
29089 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29090 0<> WHILE \ ----> out of loop ----+
29091 \ RC5_compute_7/4_Time_out: \ |
29092 ADD X,Y \ | out of bound = 7/4 period
29093 \ RC5_WaitHalfCycleP1.2_IFG: \ |
29095 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
29096 0>= IF \ | if cycle time out of bound
29097 BIC #$30,&TA0CTL \ | stop timer_A0
29098 RETI \ | then quit to do nothing
29100 \ ------------------------------\ |
29101 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
29103 MOV &TA0R,X \ | | get new RC5_period value
29104 REPEAT \ ----> loop back --+ |
29105 \ ------------------------------\ |
29106 \ RC5_SampleEndOf: \ <---------------------+
29107 \ ------------------------------\
29108 BIC #$30,&TA0CTL \ stop timer_A0
29109 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
29110 \ ******************************\
29111 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29112 \ ******************************\
29113 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
29114 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
29115 XOR IP,X \ (new XOR old) Toggle bit (13)
29116 BIT #BIT13,X \ X(13) = New_RC5_command
29117 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
29119 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
29120 \ ******************************\
29121 \ RC5_ComputeNewRC5word \
29122 \ ******************************\
29124 MOV &BASE,2(PSP) \ save variable BASE before use
29125 MOV TOS,0(PSP) \ save TOS before use
29126 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
29127 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
29128 \ ******************************\
29129 \ RC5_ComputeC6bit \
29130 \ ******************************\
29131 BIT #$4000,IP \ test /C6 bit in IP
29132 0= IF BIS #$40,TOS \ set C6 bit in S
29133 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
29134 \ ******************************\
29135 \ RC5_CommandByteIsDone \ RC5_code --
29136 \ ******************************\
29138 \ ------------------------------\
29139 \ Display IR_RC5 code \
29140 \ ------------------------------\
29141 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
29142 \ ------------------------------\
29143 LO2HI \ switch from assembler to FORTH
29144 ['] LCD_CLEAR IS CR \ redirects CR
29145 ['] LCD_WrC IS EMIT \ redirects EMIT
29146 $10 BASE ! \ change BASE to hexadecimal
29147 CR ." $" 2 U.R \ print IR_RC5 code
29148 ['] (CR) IS CR \ restore CR
29149 ['] (EMIT) IS EMIT \ restore EMIT
29150 HI2LO \ switch from FORTH to assembler
29151 \ ------------------------------\
29152 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
29153 \ ------------------------------\
29154 MOV @PSP+,&BASE \ restore variable BASE
29155 RETI \ CPU is ON, GIE is OFF
29160 \ ------------------------------\
29161 \ TB0CTL = %0000 0010 1001 0100\$3C0
29162 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29163 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29164 \ -- \ID input divider \ 10 = /4
29165 \ -- \MC Mode Control \ 01 = up to TB0CCR0
29166 \ - \TBCLR TimerB Clear
29169 \ --------------------------------\\
29170 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29171 \ -- \CM Capture Mode
29176 \ --- \OUTMOD \ 011 = set/reset
29182 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
29184 \ ------------------------------\
29185 \ set TimerB to make 50kHz PWM \
29186 \ ------------------------------\
29187 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
29188 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
29189 \ ------------------------------\
29190 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
29191 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
29192 \ ------------------------------\
29193 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29194 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
29195 \ ------------------------------\
29196 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29197 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
29198 \ ------------------------------\
29199 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29200 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
29201 \ ------------------------------\
29202 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
29203 \ ------------------------------\
29204 \ set TimerB to generate PWM for LCD_Vo
29205 \ ------------------------------\
29206 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
29207 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
29208 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29209 \ ------------------------------\
29210 BIS.B #LCDVo,&LCDVo_DIR \
29211 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
29212 \ ------------------------------\
29213 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29214 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29215 \ ------------------------------\
29216 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29217 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29218 \ ------------------------------\
29219 \ WDT interval init part \
29220 \ ------------------------------\
29221 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
29222 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
29223 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
29224 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
29225 \ ------------------------------\
29227 \ ------------------------------\
29228 BIS.B #RC5,&IR_IE \ enable RC5_Int
29229 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29230 \ ------------------------------\
29231 \ init interrupt vectors
29232 \ ------------------------------\
29233 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
29234 MOV #RC5_INT,&IR_Vec \ init interrupt vector
29235 \ ------------------------------\
29236 \ define LPM mode for ACCEPT \
29237 \ ------------------------------\
29238 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29239 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29240 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29242 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
29244 \ ------------------------------\
29246 \ ------------------------------\
29247 $03E8 20_US \ 1- wait 20 ms
29248 $03 TOP_LCD \ 2- send DB5=DB4=1
29249 $CD 20_US \ 3- wait 4,1 ms
29250 $03 TOP_LCD \ 4- send again DB5=DB4=1
29251 $5 20_US \ 5- wait 0,1 ms
29252 $03 TOP_LCD \ 6- send again again DB5=DB4=1
29253 $2 20_US \ wait 40 us = LCD cycle
29254 $02 TOP_LCD \ 7- send DB5=1 DB4=0
29255 $2 20_US \ wait 40 us = LCD cycle
29256 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29257 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29258 LCD_Clear \ 10- "LCD_Clear"
29259 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29260 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29261 LCD_Clear \ 10- "LCD_Clear"
29262 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29263 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29265 ['] (CR) IS CR \ ' (CR) is CR
29266 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
29268 ." RC5toLCD is running. Type STOP to quit"
29269 \ NOECHO \ uncomment to run this app without terminal connexion
29270 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
29271 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
29275 : STOP \ stops multitasking, must to be used before downloading app
29276 ['] (WARM) IS WARM \ remove START app from FORTH init process
29277 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
29285 CODE MAX \ n1 n2 -- n3 signed maximum
29286 CMP @PSP,TOS \ n2-n1
29287 S< ?GOTO FW1 \ n2<n1
29293 CODE MIN \ n1 n2 -- n3 signed minimum
29294 CMP @PSP,TOS \ n2-n1
29295 S< ?GOTO BW1 \ n2<n1
29301 : U.R \ u n -- display u unsigned in n width (n >= 2)
29303 R> OVER - 0 MAX SPACES TYPE
29307 CODE 20_US \ n -- n * 20 us
29308 BEGIN \ 3 cycles loop + 6~
29309 \ MOV #5,W \ 3 MCLK = 1 MHz
29310 \ MOV #23,W \ 3 MCLK = 4 MHz
29311 MOV #51,W \ 3 MCLK = 8 MHz
29312 \ MOV #104,W \ 3 MCLK = 16 MHz
29313 \ MOV #158,W \ 3 MCLK = 24 MHz
29314 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
29324 CODE TOP_LCD \ LCD Sample
29325 \ \ if write : %xxxxWWWW --
29326 \ \ if read : -- %0000RRRR
29327 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29328 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29329 0= IF \ write LCD bits pattern
29330 AND.B #LCD_DB,TOS \
29331 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29332 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29335 THEN \ read LCD bits pattern
29338 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29339 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29340 AND.B #LCD_DB,TOS \
29345 CODE LCD_W \ byte -- write byte to LCD
29347 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
29348 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
29349 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29350 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29351 COLON \ high level word starts here
29352 TOP_LCD 2 20_US \ write high nibble first
29357 CODE LCD_WrC \ char -- Write Char
29358 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29363 CODE LCD_WrF \ func -- Write Fonction
29364 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29370 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
29375 $02 LCD_WrF 100 20_us
29379 \ : LCD_Entry_set $04 OR LCD_WrF ;
29381 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
29383 \ : LCD_Display_Shift $10 OR LCD_WrF ;
29385 \ : LCD_Fn_Set $20 OR LCD_WrF ;
29387 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
29389 \ : LCD_Goto $80 OR LCD_WrF ;
29391 \ CODE LCD_R \ -- byte read byte from LCD
29392 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29393 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29394 \ COLON \ starts a FORTH word
29395 \ TOP_LCD 2 20_us \ -- %0000HHHH
29396 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
29397 \ HI2LO \ switch from FORTH to assembler
29398 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
29399 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
29400 \ MOV @RSP+,IP \ restore IP saved by COLON
29405 \ CODE LCD_RdS \ -- status Read Status
29406 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29411 \ CODE LCD_RdC \ -- char Read Char
29412 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29417 \ -------------+------+------+------+------++---+---+---+---+---------+
29418 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
29419 \ -------------+------+------+------+------++---+---+---+---+---------+
29420 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
29421 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
29422 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
29423 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
29424 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
29425 \ -------------+------+------+------+------++---+---+---+---+---------+
29428 \ ******************************\
29429 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29430 \ ******************************\
29431 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
29432 \ ------------------------------\
29433 \ define LPM mode for ACCEPT \
29434 \ ------------------------------\
29435 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29436 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29437 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29438 BIT.B #SW2,&SW2_IN \ test switch S2
29439 0= IF \ case of switch S2 pressed
29440 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
29442 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
29445 BIT.B #SW1,&SW1_IN \ test switch S1 input
29446 0= IF \ case of Switch S1 pressed
29447 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
29449 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
29453 RETI \ CPU is ON, GIE is OFF
29458 \ ------------------------------\
29459 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29460 \ ******************************\
29461 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29462 \ ******************************\
29463 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29464 \ \ SMclock = 8|16|24 MHz
29465 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
29466 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
29467 \ \ SR(9)=new Toggle bit memory (ADD on)
29468 \ ------------------------------\
29469 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
29470 \ ------------------------------\
29471 \ define LPM mode for ACCEPT \
29472 \ ------------------------------\
29473 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29474 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29475 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29476 \ ------------------------------\
29477 \ RC5_FirstStartBitHalfCycle: \
29478 \ ------------------------------\
29479 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
29480 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
29481 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
29482 MOV #1778,X \ RC5_Period in us
29483 MOV #14,W \ count of loop
29485 \ ------------------------------\
29486 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
29487 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
29488 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
29489 \ RC5_Compute_3/4_Period: \ |
29490 RRUM #1,X \ X=1/2 cycle |
29494 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
29495 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
29497 \ ------------------------------\
29498 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
29499 \ ------------------------------\
29500 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29501 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
29502 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29503 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29504 SUB #1,W \ decrement count loop
29505 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
29506 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29507 0<> WHILE \ ----> out of loop ----+
29508 \ RC5_compute_7/4_Time_out: \ |
29509 ADD X,Y \ | out of bound = 7/4 period
29510 \ RC5_WaitHalfCycleP1.2_IFG: \ |
29512 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
29513 0>= IF \ | if cycle time out of bound
29514 BIC #$30,&TA0CTL \ | stop timer_A0
29515 RETI \ | then quit to do nothing
29517 \ ------------------------------\ |
29518 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
29520 MOV &TA0R,X \ | | get new RC5_period value
29521 REPEAT \ ----> loop back --+ |
29522 \ ------------------------------\ |
29523 \ RC5_SampleEndOf: \ <---------------------+
29524 \ ------------------------------\
29525 BIC #$30,&TA0CTL \ stop timer_A0
29526 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
29527 \ ******************************\
29528 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29529 \ ******************************\
29530 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
29531 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
29532 XOR IP,X \ (new XOR old) Toggle bit (13)
29533 BIT #BIT13,X \ X(13) = New_RC5_command
29534 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
29536 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
29537 \ ******************************\
29538 \ RC5_ComputeNewRC5word \
29539 \ ******************************\
29541 MOV &BASE,2(PSP) \ save variable BASE before use
29542 MOV TOS,0(PSP) \ save TOS before use
29543 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
29544 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
29545 \ ******************************\
29546 \ RC5_ComputeC6bit \
29547 \ ******************************\
29548 BIT #$4000,IP \ test /C6 bit in IP
29549 0= IF BIS #$40,TOS \ set C6 bit in S
29550 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
29551 \ ******************************\
29552 \ RC5_CommandByteIsDone \ RC5_code --
29553 \ ******************************\
29555 \ ------------------------------\
29556 \ Display IR_RC5 code \
29557 \ ------------------------------\
29558 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
29559 \ ------------------------------\
29560 LO2HI \ switch from assembler to FORTH
29561 ['] LCD_CLEAR IS CR \ redirects CR
29562 ['] LCD_WrC IS EMIT \ redirects EMIT
29563 $10 BASE ! \ change BASE to hexadecimal
29564 CR ." $" 2 U.R \ print IR_RC5 code
29565 ['] (CR) IS CR \ restore CR
29566 ['] (EMIT) IS EMIT \ restore EMIT
29567 HI2LO \ switch from FORTH to assembler
29568 \ ------------------------------\
29569 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
29570 \ ------------------------------\
29571 MOV @PSP+,&BASE \ restore variable BASE
29572 RETI \ CPU is ON, GIE is OFF
29577 \ ------------------------------\
29578 \ TB0CTL = %0000 0010 1001 0100\$3C0
29579 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29580 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29581 \ -- \ID input divider \ 10 = /4
29582 \ -- \MC Mode Control \ 01 = up to TB0CCR0
29583 \ - \TBCLR TimerB Clear
29586 \ --------------------------------\\
29587 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29588 \ -- \CM Capture Mode
29593 \ --- \OUTMOD \ 011 = set/reset
29599 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
29601 \ ------------------------------\
29602 \ set TimerB to make 50kHz PWM \
29603 \ ------------------------------\
29604 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
29605 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
29606 \ ------------------------------\
29607 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
29608 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
29609 \ ------------------------------\
29610 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29611 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
29612 \ ------------------------------\
29613 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29614 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
29615 \ ------------------------------\
29616 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29617 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
29618 \ ------------------------------\
29619 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
29620 \ ------------------------------\
29621 \ set TimerB to generate PWM for LCD_Vo
29622 \ ------------------------------\
29623 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
29624 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
29625 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29626 \ ------------------------------\
29627 BIS.B #LCDVo,&LCDVo_DIR \
29628 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
29629 \ ------------------------------\
29630 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29631 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29632 \ ------------------------------\
29633 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29634 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29635 \ ------------------------------\
29636 \ WDT interval init part \
29637 \ ------------------------------\
29638 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
29639 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
29640 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
29641 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
29642 \ ------------------------------\
29644 \ ------------------------------\
29645 BIS.B #RC5,&IR_IE \ enable RC5_Int
29646 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29647 \ ------------------------------\
29648 \ init interrupt vectors
29649 \ ------------------------------\
29650 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
29651 MOV #RC5_INT,&IR_Vec \ init interrupt vector
29652 \ ------------------------------\
29653 \ define LPM mode for ACCEPT \
29654 \ ------------------------------\
29655 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29656 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29657 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29659 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
29661 \ ------------------------------\
29663 \ ------------------------------\
29664 $03E8 20_US \ 1- wait 20 ms
29665 $03 TOP_LCD \ 2- send DB5=DB4=1
29666 $CD 20_US \ 3- wait 4,1 ms
29667 $03 TOP_LCD \ 4- send again DB5=DB4=1
29668 $5 20_US \ 5- wait 0,1 ms
29669 $03 TOP_LCD \ 6- send again again DB5=DB4=1
29670 $2 20_US \ wait 40 us = LCD cycle
29671 $02 TOP_LCD \ 7- send DB5=1 DB4=0
29672 $2 20_US \ wait 40 us = LCD cycle
29673 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29674 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29675 LCD_Clear \ 10- "LCD_Clear"
29676 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29677 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29678 LCD_Clear \ 10- "LCD_Clear"
29679 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29680 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29682 ['] (CR) IS CR \ ' (CR) is CR
29683 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
29685 ." RC5toLCD is running. Type STOP to quit"
29686 \ NOECHO \ uncomment to run this app without terminal connexion
29687 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
29688 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
29692 : STOP \ stops multitasking, must to be used before downloading app
29693 ['] (WARM) IS WARM \ remove START app from FORTH init process
29694 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
29702 CODE MAX \ n1 n2 -- n3 signed maximum
29703 CMP @PSP,TOS \ n2-n1
29704 S< ?GOTO FW1 \ n2<n1
29710 CODE MIN \ n1 n2 -- n3 signed minimum
29711 CMP @PSP,TOS \ n2-n1
29712 S< ?GOTO BW1 \ n2<n1
29718 : U.R \ u n -- display u unsigned in n width (n >= 2)
29720 R> OVER - 0 MAX SPACES TYPE
29724 CODE 20_US \ n -- n * 20 us
29725 BEGIN \ 3 cycles loop + 6~
29726 \ MOV #5,W \ 3 MCLK = 1 MHz
29727 \ MOV #23,W \ 3 MCLK = 4 MHz
29728 MOV #51,W \ 3 MCLK = 8 MHz
29729 \ MOV #104,W \ 3 MCLK = 16 MHz
29730 \ MOV #158,W \ 3 MCLK = 24 MHz
29731 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
29741 CODE TOP_LCD \ LCD Sample
29742 \ \ if write : %xxxxWWWW --
29743 \ \ if read : -- %0000RRRR
29744 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29745 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29746 0= IF \ write LCD bits pattern
29747 AND.B #LCD_DB,TOS \
29748 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29749 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29752 THEN \ read LCD bits pattern
29755 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29756 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29757 AND.B #LCD_DB,TOS \
29762 CODE LCD_W \ byte -- write byte to LCD
29764 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
29765 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
29766 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29767 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29768 COLON \ high level word starts here
29769 TOP_LCD 2 20_US \ write high nibble first
29774 CODE LCD_WrC \ char -- Write Char
29775 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29780 CODE LCD_WrF \ func -- Write Fonction
29781 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29787 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
29792 $02 LCD_WrF 100 20_us
29796 \ : LCD_Entry_set $04 OR LCD_WrF ;
29798 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
29800 \ : LCD_Display_Shift $10 OR LCD_WrF ;
29802 \ : LCD_Fn_Set $20 OR LCD_WrF ;
29804 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
29806 \ : LCD_Goto $80 OR LCD_WrF ;
29808 \ CODE LCD_R \ -- byte read byte from LCD
29809 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29810 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29811 \ COLON \ starts a FORTH word
29812 \ TOP_LCD 2 20_us \ -- %0000HHHH
29813 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
29814 \ HI2LO \ switch from FORTH to assembler
29815 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
29816 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
29817 \ MOV @RSP+,IP \ restore IP saved by COLON
29822 \ CODE LCD_RdS \ -- status Read Status
29823 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29828 \ CODE LCD_RdC \ -- char Read Char
29829 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29834 \ -------------+------+------+------+------++---+---+---+---+---------+
29835 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
29836 \ -------------+------+------+------+------++---+---+---+---+---------+
29837 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
29838 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
29839 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
29840 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
29841 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
29842 \ -------------+------+------+------+------++---+---+---+---+---------+
29845 \ ******************************\
29846 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29847 \ ******************************\
29848 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
29849 \ ------------------------------\
29850 \ define LPM mode for ACCEPT \
29851 \ ------------------------------\
29852 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29853 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29854 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29855 BIT.B #SW2,&SW2_IN \ test switch S2
29856 0= IF \ case of switch S2 pressed
29857 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
29859 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
29862 BIT.B #SW1,&SW1_IN \ test switch S1 input
29863 0= IF \ case of Switch S1 pressed
29864 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
29866 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
29870 RETI \ CPU is ON, GIE is OFF
29875 \ ------------------------------\
29876 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29877 \ ******************************\
29878 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29879 \ ******************************\
29880 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29881 \ \ SMclock = 8|16|24 MHz
29882 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
29883 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
29884 \ \ SR(9)=new Toggle bit memory (ADD on)
29885 \ ------------------------------\
29886 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
29887 \ ------------------------------\
29888 \ define LPM mode for ACCEPT \
29889 \ ------------------------------\
29890 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29891 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29892 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29893 \ ------------------------------\
29894 \ RC5_FirstStartBitHalfCycle: \
29895 \ ------------------------------\
29896 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
29897 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
29898 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
29899 MOV #1778,X \ RC5_Period in us
29900 MOV #14,W \ count of loop
29902 \ ------------------------------\
29903 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
29904 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
29905 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
29906 \ RC5_Compute_3/4_Period: \ |
29907 RRUM #1,X \ X=1/2 cycle |
29911 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
29912 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
29914 \ ------------------------------\
29915 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
29916 \ ------------------------------\
29917 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29918 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
29919 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29920 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29921 SUB #1,W \ decrement count loop
29922 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
29923 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29924 0<> WHILE \ ----> out of loop ----+
29925 \ RC5_compute_7/4_Time_out: \ |
29926 ADD X,Y \ | out of bound = 7/4 period
29927 \ RC5_WaitHalfCycleP1.2_IFG: \ |
29929 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
29930 0>= IF \ | if cycle time out of bound
29931 BIC #$30,&TA0CTL \ | stop timer_A0
29932 RETI \ | then quit to do nothing
29934 \ ------------------------------\ |
29935 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
29937 MOV &TA0R,X \ | | get new RC5_period value
29938 REPEAT \ ----> loop back --+ |
29939 \ ------------------------------\ |
29940 \ RC5_SampleEndOf: \ <---------------------+
29941 \ ------------------------------\
29942 BIC #$30,&TA0CTL \ stop timer_A0
29943 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
29944 \ ******************************\
29945 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29946 \ ******************************\
29947 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
29948 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
29949 XOR IP,X \ (new XOR old) Toggle bit (13)
29950 BIT #BIT13,X \ X(13) = New_RC5_command
29951 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
29953 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
29954 \ ******************************\
29955 \ RC5_ComputeNewRC5word \
29956 \ ******************************\
29958 MOV &BASE,2(PSP) \ save variable BASE before use
29959 MOV TOS,0(PSP) \ save TOS before use
29960 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
29961 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
29962 \ ******************************\
29963 \ RC5_ComputeC6bit \
29964 \ ******************************\
29965 BIT #$4000,IP \ test /C6 bit in IP
29966 0= IF BIS #$40,TOS \ set C6 bit in S
29967 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
29968 \ ******************************\
29969 \ RC5_CommandByteIsDone \ RC5_code --
29970 \ ******************************\
29972 \ ------------------------------\
29973 \ Display IR_RC5 code \
29974 \ ------------------------------\
29975 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
29976 \ ------------------------------\
29977 LO2HI \ switch from assembler to FORTH
29978 ['] LCD_CLEAR IS CR \ redirects CR
29979 ['] LCD_WrC IS EMIT \ redirects EMIT
29980 $10 BASE ! \ change BASE to hexadecimal
29981 CR ." $" 2 U.R \ print IR_RC5 code
29982 ['] (CR) IS CR \ restore CR
29983 ['] (EMIT) IS EMIT \ restore EMIT
29984 HI2LO \ switch from FORTH to assembler
29985 \ ------------------------------\
29986 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
29987 \ ------------------------------\
29988 MOV @PSP+,&BASE \ restore variable BASE
29989 RETI \ CPU is ON, GIE is OFF
29994 \ ------------------------------\
29995 \ TB0CTL = %0000 0010 1001 0100\$3C0
29996 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29997 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29998 \ -- \ID input divider \ 10 = /4
29999 \ -- \MC Mode Control \ 01 = up to TB0CCR0
30000 \ - \TBCLR TimerB Clear
30003 \ --------------------------------\\
30004 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30005 \ -- \CM Capture Mode
30010 \ --- \OUTMOD \ 011 = set/reset
30016 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
30018 \ ------------------------------\
30019 \ set TimerB to make 50kHz PWM \
30020 \ ------------------------------\
30021 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30022 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
30023 \ ------------------------------\
30024 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30025 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
30026 \ ------------------------------\
30027 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30028 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
30029 \ ------------------------------\
30030 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30031 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
30032 \ ------------------------------\
30033 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30034 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
30035 \ ------------------------------\
30036 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
30037 \ ------------------------------\
30038 \ set TimerB to generate PWM for LCD_Vo
30039 \ ------------------------------\
30040 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
30041 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
30042 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30043 \ ------------------------------\
30044 BIS.B #LCDVo,&LCDVo_DIR \
30045 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
30046 \ ------------------------------\
30047 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30048 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30049 \ ------------------------------\
30050 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30051 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30052 \ ------------------------------\
30053 \ WDT interval init part \
30054 \ ------------------------------\
30055 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
30056 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
30057 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
30058 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
30059 \ ------------------------------\
30061 \ ------------------------------\
30062 BIS.B #RC5,&IR_IE \ enable RC5_Int
30063 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30064 \ ------------------------------\
30065 \ init interrupt vectors
30066 \ ------------------------------\
30067 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
30068 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30069 \ ------------------------------\
30070 \ define LPM mode for ACCEPT \
30071 \ ------------------------------\
30072 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30073 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30074 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30076 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
30078 \ ------------------------------\
30080 \ ------------------------------\
30081 $03E8 20_US \ 1- wait 20 ms
30082 $03 TOP_LCD \ 2- send DB5=DB4=1
30083 $CD 20_US \ 3- wait 4,1 ms
30084 $03 TOP_LCD \ 4- send again DB5=DB4=1
30085 $5 20_US \ 5- wait 0,1 ms
30086 $03 TOP_LCD \ 6- send again again DB5=DB4=1
30087 $2 20_US \ wait 40 us = LCD cycle
30088 $02 TOP_LCD \ 7- send DB5=1 DB4=0
30089 $2 20_US \ wait 40 us = LCD cycle
30090 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30091 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30092 LCD_Clear \ 10- "LCD_Clear"
30093 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30094 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30095 LCD_Clear \ 10- "LCD_Clear"
30096 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30097 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30099 ['] (CR) IS CR \ ' (CR) is CR
30100 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
30102 ." RC5toLCD is running. Type STOP to quit"
30103 \ NOECHO \ uncomment to run this app without terminal connexion
30104 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
30105 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
30109 : STOP \ stops multitasking, must to be used before downloading app
30110 ['] (WARM) IS WARM \ remove START app from FORTH init process
30111 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
30119 CODE MAX \ n1 n2 -- n3 signed maximum
30120 CMP @PSP,TOS \ n2-n1
30121 S< ?GOTO FW1 \ n2<n1
30127 CODE MIN \ n1 n2 -- n3 signed minimum
30128 CMP @PSP,TOS \ n2-n1
30129 S< ?GOTO BW1 \ n2<n1
30135 : U.R \ u n -- display u unsigned in n width (n >= 2)
30137 R> OVER - 0 MAX SPACES TYPE
30141 CODE 20_US \ n -- n * 20 us
30142 BEGIN \ 3 cycles loop + 6~
30143 \ MOV #5,W \ 3 MCLK = 1 MHz
30144 \ MOV #23,W \ 3 MCLK = 4 MHz
30145 MOV #51,W \ 3 MCLK = 8 MHz
30146 \ MOV #104,W \ 3 MCLK = 16 MHz
30147 \ MOV #158,W \ 3 MCLK = 24 MHz
30148 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
30158 CODE TOP_LCD \ LCD Sample
30159 \ \ if write : %xxxxWWWW --
30160 \ \ if read : -- %0000RRRR
30161 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30162 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30163 0= IF \ write LCD bits pattern
30164 AND.B #LCD_DB,TOS \
30165 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30166 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30169 THEN \ read LCD bits pattern
30172 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30173 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30174 AND.B #LCD_DB,TOS \
30179 CODE LCD_W \ byte -- write byte to LCD
30181 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
30182 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
30183 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30184 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30185 COLON \ high level word starts here
30186 TOP_LCD 2 20_US \ write high nibble first
30191 CODE LCD_WrC \ char -- Write Char
30192 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30197 CODE LCD_WrF \ func -- Write Fonction
30198 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30204 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
30209 $02 LCD_WrF 100 20_us
30213 \ : LCD_Entry_set $04 OR LCD_WrF ;
30215 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
30217 \ : LCD_Display_Shift $10 OR LCD_WrF ;
30219 \ : LCD_Fn_Set $20 OR LCD_WrF ;
30221 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
30223 \ : LCD_Goto $80 OR LCD_WrF ;
30225 \ CODE LCD_R \ -- byte read byte from LCD
30226 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30227 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30228 \ COLON \ starts a FORTH word
30229 \ TOP_LCD 2 20_us \ -- %0000HHHH
30230 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
30231 \ HI2LO \ switch from FORTH to assembler
30232 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
30233 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
30234 \ MOV @RSP+,IP \ restore IP saved by COLON
30239 \ CODE LCD_RdS \ -- status Read Status
30240 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30245 \ CODE LCD_RdC \ -- char Read Char
30246 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30251 \ -------------+------+------+------+------++---+---+---+---+---------+
30252 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
30253 \ -------------+------+------+------+------++---+---+---+---+---------+
30254 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
30255 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
30256 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
30257 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
30258 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
30259 \ -------------+------+------+------+------++---+---+---+---+---------+
30262 \ ******************************\
30263 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30264 \ ******************************\
30265 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
30266 \ ------------------------------\
30267 \ define LPM mode for ACCEPT \
30268 \ ------------------------------\
30269 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30270 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30271 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30272 BIT.B #SW2,&SW2_IN \ test switch S2
30273 0= IF \ case of switch S2 pressed
30274 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
30276 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
30279 BIT.B #SW1,&SW1_IN \ test switch S1 input
30280 0= IF \ case of Switch S1 pressed
30281 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
30283 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
30287 RETI \ CPU is ON, GIE is OFF
30292 \ ------------------------------\
30293 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30294 \ ******************************\
30295 ASM RC5_INT \ wake up on Px.RC5 change interrupt
30296 \ ******************************\
30297 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30298 \ \ SMclock = 8|16|24 MHz
30299 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
30300 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
30301 \ \ SR(9)=new Toggle bit memory (ADD on)
30302 \ ------------------------------\
30303 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
30304 \ ------------------------------\
30305 \ define LPM mode for ACCEPT \
30306 \ ------------------------------\
30307 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30308 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30309 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30310 \ ------------------------------\
30311 \ RC5_FirstStartBitHalfCycle: \
30312 \ ------------------------------\
30313 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
30314 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
30315 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
30316 MOV #1778,X \ RC5_Period in us
30317 MOV #14,W \ count of loop
30319 \ ------------------------------\
30320 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
30321 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
30322 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
30323 \ RC5_Compute_3/4_Period: \ |
30324 RRUM #1,X \ X=1/2 cycle |
30328 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
30329 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
30331 \ ------------------------------\
30332 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
30333 \ ------------------------------\
30334 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30335 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
30336 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30337 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30338 SUB #1,W \ decrement count loop
30339 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
30340 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30341 0<> WHILE \ ----> out of loop ----+
30342 \ RC5_compute_7/4_Time_out: \ |
30343 ADD X,Y \ | out of bound = 7/4 period
30344 \ RC5_WaitHalfCycleP1.2_IFG: \ |
30346 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
30347 0>= IF \ | if cycle time out of bound
30348 BIC #$30,&TA0CTL \ | stop timer_A0
30349 RETI \ | then quit to do nothing
30351 \ ------------------------------\ |
30352 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
30354 MOV &TA0R,X \ | | get new RC5_period value
30355 REPEAT \ ----> loop back --+ |
30356 \ ------------------------------\ |
30357 \ RC5_SampleEndOf: \ <---------------------+
30358 \ ------------------------------\
30359 BIC #$30,&TA0CTL \ stop timer_A0
30360 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
30361 \ ******************************\
30362 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30363 \ ******************************\
30364 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
30365 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
30366 XOR IP,X \ (new XOR old) Toggle bit (13)
30367 BIT #BIT13,X \ X(13) = New_RC5_command
30368 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
30370 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
30371 \ ******************************\
30372 \ RC5_ComputeNewRC5word \
30373 \ ******************************\
30375 MOV &BASE,2(PSP) \ save variable BASE before use
30376 MOV TOS,0(PSP) \ save TOS before use
30377 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
30378 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
30379 \ ******************************\
30380 \ RC5_ComputeC6bit \
30381 \ ******************************\
30382 BIT #$4000,IP \ test /C6 bit in IP
30383 0= IF BIS #$40,TOS \ set C6 bit in S
30384 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
30385 \ ******************************\
30386 \ RC5_CommandByteIsDone \ RC5_code --
30387 \ ******************************\
30389 \ ------------------------------\
30390 \ Display IR_RC5 code \
30391 \ ------------------------------\
30392 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
30393 \ ------------------------------\
30394 LO2HI \ switch from assembler to FORTH
30395 ['] LCD_CLEAR IS CR \ redirects CR
30396 ['] LCD_WrC IS EMIT \ redirects EMIT
30397 $10 BASE ! \ change BASE to hexadecimal
30398 CR ." $" 2 U.R \ print IR_RC5 code
30399 ['] (CR) IS CR \ restore CR
30400 ['] (EMIT) IS EMIT \ restore EMIT
30401 HI2LO \ switch from FORTH to assembler
30402 \ ------------------------------\
30403 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
30404 \ ------------------------------\
30405 MOV @PSP+,&BASE \ restore variable BASE
30406 RETI \ CPU is ON, GIE is OFF
30411 \ ------------------------------\
30412 \ TB0CTL = %0000 0010 1001 0100\$3C0
30413 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30414 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30415 \ -- \ID input divider \ 10 = /4
30416 \ -- \MC Mode Control \ 01 = up to TB0CCR0
30417 \ - \TBCLR TimerB Clear
30420 \ --------------------------------\\
30421 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30422 \ -- \CM Capture Mode
30427 \ --- \OUTMOD \ 011 = set/reset
30433 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
30435 \ ------------------------------\
30436 \ set TimerB to make 50kHz PWM \
30437 \ ------------------------------\
30438 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30439 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
30440 \ ------------------------------\
30441 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30442 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
30443 \ ------------------------------\
30444 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30445 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
30446 \ ------------------------------\
30447 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30448 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
30449 \ ------------------------------\
30450 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30451 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
30452 \ ------------------------------\
30453 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
30454 \ ------------------------------\
30455 \ set TimerB to generate PWM for LCD_Vo
30456 \ ------------------------------\
30457 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
30458 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
30459 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30460 \ ------------------------------\
30461 BIS.B #LCDVo,&LCDVo_DIR \
30462 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
30463 \ ------------------------------\
30464 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30465 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30466 \ ------------------------------\
30467 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30468 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30469 \ ------------------------------\
30470 \ WDT interval init part \
30471 \ ------------------------------\
30472 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
30473 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
30474 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
30475 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
30476 \ ------------------------------\
30478 \ ------------------------------\
30479 BIS.B #RC5,&IR_IE \ enable RC5_Int
30480 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30481 \ ------------------------------\
30482 \ init interrupt vectors
30483 \ ------------------------------\
30484 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
30485 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30486 \ ------------------------------\
30487 \ define LPM mode for ACCEPT \
30488 \ ------------------------------\
30489 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30490 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30491 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30493 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
30495 \ ------------------------------\
30497 \ ------------------------------\
30498 $03E8 20_US \ 1- wait 20 ms
30499 $03 TOP_LCD \ 2- send DB5=DB4=1
30500 $CD 20_US \ 3- wait 4,1 ms
30501 $03 TOP_LCD \ 4- send again DB5=DB4=1
30502 $5 20_US \ 5- wait 0,1 ms
30503 $03 TOP_LCD \ 6- send again again DB5=DB4=1
30504 $2 20_US \ wait 40 us = LCD cycle
30505 $02 TOP_LCD \ 7- send DB5=1 DB4=0
30506 $2 20_US \ wait 40 us = LCD cycle
30507 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30508 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30509 LCD_Clear \ 10- "LCD_Clear"
30510 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30511 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30512 LCD_Clear \ 10- "LCD_Clear"
30513 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30514 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30516 ['] (CR) IS CR \ ' (CR) is CR
30517 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
30519 ." RC5toLCD is running. Type STOP to quit"
30520 \ NOECHO \ uncomment to run this app without terminal connexion
30521 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
30522 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
30526 : STOP \ stops multitasking, must to be used before downloading app
30527 ['] (WARM) IS WARM \ remove START app from FORTH init process
30528 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
30536 CODE MAX \ n1 n2 -- n3 signed maximum
30537 CMP @PSP,TOS \ n2-n1
30538 S< ?GOTO FW1 \ n2<n1
30544 CODE MIN \ n1 n2 -- n3 signed minimum
30545 CMP @PSP,TOS \ n2-n1
30546 S< ?GOTO BW1 \ n2<n1
30552 : U.R \ u n -- display u unsigned in n width (n >= 2)
30554 R> OVER - 0 MAX SPACES TYPE
30558 CODE 20_US \ n -- n * 20 us
30559 BEGIN \ 3 cycles loop + 6~
30560 \ MOV #5,W \ 3 MCLK = 1 MHz
30561 \ MOV #23,W \ 3 MCLK = 4 MHz
30562 MOV #51,W \ 3 MCLK = 8 MHz
30563 \ MOV #104,W \ 3 MCLK = 16 MHz
30564 \ MOV #158,W \ 3 MCLK = 24 MHz
30565 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
30575 CODE TOP_LCD \ LCD Sample
30576 \ \ if write : %xxxxWWWW --
30577 \ \ if read : -- %0000RRRR
30578 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30579 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30580 0= IF \ write LCD bits pattern
30581 AND.B #LCD_DB,TOS \
30582 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30583 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30586 THEN \ read LCD bits pattern
30589 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30590 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30591 AND.B #LCD_DB,TOS \
30596 CODE LCD_W \ byte -- write byte to LCD
30598 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
30599 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
30600 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30601 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30602 COLON \ high level word starts here
30603 TOP_LCD 2 20_US \ write high nibble first
30608 CODE LCD_WrC \ char -- Write Char
30609 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30614 CODE LCD_WrF \ func -- Write Fonction
30615 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30621 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
30626 $02 LCD_WrF 100 20_us
30630 \ : LCD_Entry_set $04 OR LCD_WrF ;
30632 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
30634 \ : LCD_Display_Shift $10 OR LCD_WrF ;
30636 \ : LCD_Fn_Set $20 OR LCD_WrF ;
30638 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
30640 \ : LCD_Goto $80 OR LCD_WrF ;
30642 \ CODE LCD_R \ -- byte read byte from LCD
30643 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30644 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30645 \ COLON \ starts a FORTH word
30646 \ TOP_LCD 2 20_us \ -- %0000HHHH
30647 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
30648 \ HI2LO \ switch from FORTH to assembler
30649 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
30650 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
30651 \ MOV @RSP+,IP \ restore IP saved by COLON
30656 \ CODE LCD_RdS \ -- status Read Status
30657 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30662 \ CODE LCD_RdC \ -- char Read Char
30663 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30668 \ -------------+------+------+------+------++---+---+---+---+---------+
30669 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
30670 \ -------------+------+------+------+------++---+---+---+---+---------+
30671 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
30672 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
30673 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
30674 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
30675 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
30676 \ -------------+------+------+------+------++---+---+---+---+---------+
30679 \ ******************************\
30680 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30681 \ ******************************\
30682 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
30683 \ ------------------------------\
30684 \ define LPM mode for ACCEPT \
30685 \ ------------------------------\
30686 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30687 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30688 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30689 BIT.B #SW2,&SW2_IN \ test switch S2
30690 0= IF \ case of switch S2 pressed
30691 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
30693 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
30696 BIT.B #SW1,&SW1_IN \ test switch S1 input
30697 0= IF \ case of Switch S1 pressed
30698 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
30700 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
30704 RETI \ CPU is ON, GIE is OFF
30709 \ ------------------------------\
30710 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30711 \ ******************************\
30712 ASM RC5_INT \ wake up on Px.RC5 change interrupt
30713 \ ******************************\
30714 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30715 \ \ SMclock = 8|16|24 MHz
30716 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
30717 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
30718 \ \ SR(9)=new Toggle bit memory (ADD on)
30719 \ ------------------------------\
30720 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
30721 \ ------------------------------\
30722 \ define LPM mode for ACCEPT \
30723 \ ------------------------------\
30724 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30725 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30726 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30727 \ ------------------------------\
30728 \ RC5_FirstStartBitHalfCycle: \
30729 \ ------------------------------\
30730 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
30731 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
30732 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
30733 MOV #1778,X \ RC5_Period in us
30734 MOV #14,W \ count of loop
30736 \ ------------------------------\
30737 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
30738 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
30739 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
30740 \ RC5_Compute_3/4_Period: \ |
30741 RRUM #1,X \ X=1/2 cycle |
30745 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
30746 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
30748 \ ------------------------------\
30749 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
30750 \ ------------------------------\
30751 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30752 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
30753 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30754 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30755 SUB #1,W \ decrement count loop
30756 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
30757 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30758 0<> WHILE \ ----> out of loop ----+
30759 \ RC5_compute_7/4_Time_out: \ |
30760 ADD X,Y \ | out of bound = 7/4 period
30761 \ RC5_WaitHalfCycleP1.2_IFG: \ |
30763 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
30764 0>= IF \ | if cycle time out of bound
30765 BIC #$30,&TA0CTL \ | stop timer_A0
30766 RETI \ | then quit to do nothing
30768 \ ------------------------------\ |
30769 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
30771 MOV &TA0R,X \ | | get new RC5_period value
30772 REPEAT \ ----> loop back --+ |
30773 \ ------------------------------\ |
30774 \ RC5_SampleEndOf: \ <---------------------+
30775 \ ------------------------------\
30776 BIC #$30,&TA0CTL \ stop timer_A0
30777 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
30778 \ ******************************\
30779 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30780 \ ******************************\
30781 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
30782 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
30783 XOR IP,X \ (new XOR old) Toggle bit (13)
30784 BIT #BIT13,X \ X(13) = New_RC5_command
30785 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
30787 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
30788 \ ******************************\
30789 \ RC5_ComputeNewRC5word \
30790 \ ******************************\
30792 MOV &BASE,2(PSP) \ save variable BASE before use
30793 MOV TOS,0(PSP) \ save TOS before use
30794 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
30795 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
30796 \ ******************************\
30797 \ RC5_ComputeC6bit \
30798 \ ******************************\
30799 BIT #$4000,IP \ test /C6 bit in IP
30800 0= IF BIS #$40,TOS \ set C6 bit in S
30801 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
30802 \ ******************************\
30803 \ RC5_CommandByteIsDone \ RC5_code --
30804 \ ******************************\
30806 \ ------------------------------\
30807 \ Display IR_RC5 code \
30808 \ ------------------------------\
30809 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
30810 \ ------------------------------\
30811 LO2HI \ switch from assembler to FORTH
30812 ['] LCD_CLEAR IS CR \ redirects CR
30813 ['] LCD_WrC IS EMIT \ redirects EMIT
30814 $10 BASE ! \ change BASE to hexadecimal
30815 CR ." $" 2 U.R \ print IR_RC5 code
30816 ['] (CR) IS CR \ restore CR
30817 ['] (EMIT) IS EMIT \ restore EMIT
30818 HI2LO \ switch from FORTH to assembler
30819 \ ------------------------------\
30820 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
30821 \ ------------------------------\
30822 MOV @PSP+,&BASE \ restore variable BASE
30823 RETI \ CPU is ON, GIE is OFF
30828 \ ------------------------------\
30829 \ TB0CTL = %0000 0010 1001 0100\$3C0
30830 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30831 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30832 \ -- \ID input divider \ 10 = /4
30833 \ -- \MC Mode Control \ 01 = up to TB0CCR0
30834 \ - \TBCLR TimerB Clear
30837 \ --------------------------------\\
30838 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30839 \ -- \CM Capture Mode
30844 \ --- \OUTMOD \ 011 = set/reset
30850 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
30852 \ ------------------------------\
30853 \ set TimerB to make 50kHz PWM \
30854 \ ------------------------------\
30855 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30856 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
30857 \ ------------------------------\
30858 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30859 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
30860 \ ------------------------------\
30861 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30862 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
30863 \ ------------------------------\
30864 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30865 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
30866 \ ------------------------------\
30867 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30868 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
30869 \ ------------------------------\
30870 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
30871 \ ------------------------------\
30872 \ set TimerB to generate PWM for LCD_Vo
30873 \ ------------------------------\
30874 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
30875 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
30876 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30877 \ ------------------------------\
30878 BIS.B #LCDVo,&LCDVo_DIR \
30879 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
30880 \ ------------------------------\
30881 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30882 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30883 \ ------------------------------\
30884 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30885 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30886 \ ------------------------------\
30887 \ WDT interval init part \
30888 \ ------------------------------\
30889 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
30890 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
30891 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
30892 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
30893 \ ------------------------------\
30895 \ ------------------------------\
30896 BIS.B #RC5,&IR_IE \ enable RC5_Int
30897 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30898 \ ------------------------------\
30899 \ init interrupt vectors
30900 \ ------------------------------\
30901 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
30902 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30903 \ ------------------------------\
30904 \ define LPM mode for ACCEPT \
30905 \ ------------------------------\
30906 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30907 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30908 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30910 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
30912 \ ------------------------------\
30914 \ ------------------------------\
30915 $03E8 20_US \ 1- wait 20 ms
30916 $03 TOP_LCD \ 2- send DB5=DB4=1
30917 $CD 20_US \ 3- wait 4,1 ms
30918 $03 TOP_LCD \ 4- send again DB5=DB4=1
30919 $5 20_US \ 5- wait 0,1 ms
30920 $03 TOP_LCD \ 6- send again again DB5=DB4=1
30921 $2 20_US \ wait 40 us = LCD cycle
30922 $02 TOP_LCD \ 7- send DB5=1 DB4=0
30923 $2 20_US \ wait 40 us = LCD cycle
30924 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30925 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30926 LCD_Clear \ 10- "LCD_Clear"
30927 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30928 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30929 LCD_Clear \ 10- "LCD_Clear"
30930 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30931 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30933 ['] (CR) IS CR \ ' (CR) is CR
30934 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
30936 ." RC5toLCD is running. Type STOP to quit"
30937 \ NOECHO \ uncomment to run this app without terminal connexion
30938 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
30939 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
30943 : STOP \ stops multitasking, must to be used before downloading app
30944 ['] (WARM) IS WARM \ remove START app from FORTH init process
30945 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
30953 CODE MAX \ n1 n2 -- n3 signed maximum
30954 CMP @PSP,TOS \ n2-n1
30955 S< ?GOTO FW1 \ n2<n1
30961 CODE MIN \ n1 n2 -- n3 signed minimum
30962 CMP @PSP,TOS \ n2-n1
30963 S< ?GOTO BW1 \ n2<n1
30969 : U.R \ u n -- display u unsigned in n width (n >= 2)
30971 R> OVER - 0 MAX SPACES TYPE
30975 CODE 20_US \ n -- n * 20 us
30976 BEGIN \ 3 cycles loop + 6~
30977 \ MOV #5,W \ 3 MCLK = 1 MHz
30978 \ MOV #23,W \ 3 MCLK = 4 MHz
30979 MOV #51,W \ 3 MCLK = 8 MHz
30980 \ MOV #104,W \ 3 MCLK = 16 MHz
30981 \ MOV #158,W \ 3 MCLK = 24 MHz
30982 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
30992 CODE TOP_LCD \ LCD Sample
30993 \ \ if write : %xxxxWWWW --
30994 \ \ if read : -- %0000RRRR
30995 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30996 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30997 0= IF \ write LCD bits pattern
30998 AND.B #LCD_DB,TOS \
30999 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31000 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31003 THEN \ read LCD bits pattern
31006 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31007 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31008 AND.B #LCD_DB,TOS \
31013 CODE LCD_W \ byte -- write byte to LCD
31015 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
31016 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
31017 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31018 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31019 COLON \ high level word starts here
31020 TOP_LCD 2 20_US \ write high nibble first
31025 CODE LCD_WrC \ char -- Write Char
31026 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31031 CODE LCD_WrF \ func -- Write Fonction
31032 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31038 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
31043 $02 LCD_WrF 100 20_us
31047 \ : LCD_Entry_set $04 OR LCD_WrF ;
31049 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
31051 \ : LCD_Display_Shift $10 OR LCD_WrF ;
31053 \ : LCD_Fn_Set $20 OR LCD_WrF ;
31055 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
31057 \ : LCD_Goto $80 OR LCD_WrF ;
31059 \ CODE LCD_R \ -- byte read byte from LCD
31060 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31061 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31062 \ COLON \ starts a FORTH word
31063 \ TOP_LCD 2 20_us \ -- %0000HHHH
31064 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
31065 \ HI2LO \ switch from FORTH to assembler
31066 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
31067 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
31068 \ MOV @RSP+,IP \ restore IP saved by COLON
31073 \ CODE LCD_RdS \ -- status Read Status
31074 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31079 \ CODE LCD_RdC \ -- char Read Char
31080 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31085 \ -------------+------+------+------+------++---+---+---+---+---------+
31086 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
31087 \ -------------+------+------+------+------++---+---+---+---+---------+
31088 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
31089 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
31090 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
31091 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
31092 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
31093 \ -------------+------+------+------+------++---+---+---+---+---------+
31096 \ ******************************\
31097 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31098 \ ******************************\
31099 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
31100 \ ------------------------------\
31101 \ define LPM mode for ACCEPT \
31102 \ ------------------------------\
31103 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31104 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31105 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31106 BIT.B #SW2,&SW2_IN \ test switch S2
31107 0= IF \ case of switch S2 pressed
31108 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
31110 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
31113 BIT.B #SW1,&SW1_IN \ test switch S1 input
31114 0= IF \ case of Switch S1 pressed
31115 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
31117 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
31121 RETI \ CPU is ON, GIE is OFF
31126 \ ------------------------------\
31127 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31128 \ ******************************\
31129 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31130 \ ******************************\
31131 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31132 \ \ SMclock = 8|16|24 MHz
31133 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
31134 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
31135 \ \ SR(9)=new Toggle bit memory (ADD on)
31136 \ ------------------------------\
31137 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
31138 \ ------------------------------\
31139 \ define LPM mode for ACCEPT \
31140 \ ------------------------------\
31141 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31142 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31143 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31144 \ ------------------------------\
31145 \ RC5_FirstStartBitHalfCycle: \
31146 \ ------------------------------\
31147 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
31148 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
31149 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
31150 MOV #1778,X \ RC5_Period in us
31151 MOV #14,W \ count of loop
31153 \ ------------------------------\
31154 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
31155 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
31156 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
31157 \ RC5_Compute_3/4_Period: \ |
31158 RRUM #1,X \ X=1/2 cycle |
31162 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
31163 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
31165 \ ------------------------------\
31166 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
31167 \ ------------------------------\
31168 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31169 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
31170 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31171 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31172 SUB #1,W \ decrement count loop
31173 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
31174 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31175 0<> WHILE \ ----> out of loop ----+
31176 \ RC5_compute_7/4_Time_out: \ |
31177 ADD X,Y \ | out of bound = 7/4 period
31178 \ RC5_WaitHalfCycleP1.2_IFG: \ |
31180 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
31181 0>= IF \ | if cycle time out of bound
31182 BIC #$30,&TA0CTL \ | stop timer_A0
31183 RETI \ | then quit to do nothing
31185 \ ------------------------------\ |
31186 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
31188 MOV &TA0R,X \ | | get new RC5_period value
31189 REPEAT \ ----> loop back --+ |
31190 \ ------------------------------\ |
31191 \ RC5_SampleEndOf: \ <---------------------+
31192 \ ------------------------------\
31193 BIC #$30,&TA0CTL \ stop timer_A0
31194 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
31195 \ ******************************\
31196 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
31197 \ ******************************\
31198 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
31199 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
31200 XOR IP,X \ (new XOR old) Toggle bit (13)
31201 BIT #BIT13,X \ X(13) = New_RC5_command
31202 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
31204 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
31205 \ ******************************\
31206 \ RC5_ComputeNewRC5word \
31207 \ ******************************\
31209 MOV &BASE,2(PSP) \ save variable BASE before use
31210 MOV TOS,0(PSP) \ save TOS before use
31211 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
31212 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
31213 \ ******************************\
31214 \ RC5_ComputeC6bit \
31215 \ ******************************\
31216 BIT #$4000,IP \ test /C6 bit in IP
31217 0= IF BIS #$40,TOS \ set C6 bit in S
31218 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
31219 \ ******************************\
31220 \ RC5_CommandByteIsDone \ RC5_code --
31221 \ ******************************\
31223 \ ------------------------------\
31224 \ Display IR_RC5 code \
31225 \ ------------------------------\
31226 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
31227 \ ------------------------------\
31228 LO2HI \ switch from assembler to FORTH
31229 ['] LCD_CLEAR IS CR \ redirects CR
31230 ['] LCD_WrC IS EMIT \ redirects EMIT
31231 $10 BASE ! \ change BASE to hexadecimal
31232 CR ." $" 2 U.R \ print IR_RC5 code
31233 ['] (CR) IS CR \ restore CR
31234 ['] (EMIT) IS EMIT \ restore EMIT
31235 HI2LO \ switch from FORTH to assembler
31236 \ ------------------------------\
31237 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
31238 \ ------------------------------\
31239 MOV @PSP+,&BASE \ restore variable BASE
31240 RETI \ CPU is ON, GIE is OFF
31245 \ ------------------------------\
31246 \ TB0CTL = %0000 0010 1001 0100\$3C0
31247 \ - - \CNTL Counter lentgh \ 00 = 16 bits
31248 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
31249 \ -- \ID input divider \ 10 = /4
31250 \ -- \MC Mode Control \ 01 = up to TB0CCR0
31251 \ - \TBCLR TimerB Clear
31254 \ --------------------------------\\
31255 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31256 \ -- \CM Capture Mode
31261 \ --- \OUTMOD \ 011 = set/reset
31267 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
31269 \ ------------------------------\
31270 \ set TimerB to make 50kHz PWM \
31271 \ ------------------------------\
31272 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
31273 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
31274 \ ------------------------------\
31275 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
31276 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
31277 \ ------------------------------\
31278 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31279 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
31280 \ ------------------------------\
31281 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31282 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
31283 \ ------------------------------\
31284 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31285 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
31286 \ ------------------------------\
31287 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
31288 \ ------------------------------\
31289 \ set TimerB to generate PWM for LCD_Vo
31290 \ ------------------------------\
31291 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
31292 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
31293 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31294 \ ------------------------------\
31295 BIS.B #LCDVo,&LCDVo_DIR \
31296 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
31297 \ ------------------------------\
31298 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31299 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31300 \ ------------------------------\
31301 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
31302 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
31303 \ ------------------------------\
31304 \ WDT interval init part \
31305 \ ------------------------------\
31306 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
31307 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
31308 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
31309 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
31310 \ ------------------------------\
31312 \ ------------------------------\
31313 BIS.B #RC5,&IR_IE \ enable RC5_Int
31314 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
31315 \ ------------------------------\
31316 \ init interrupt vectors
31317 \ ------------------------------\
31318 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
31319 MOV #RC5_INT,&IR_Vec \ init interrupt vector
31320 \ ------------------------------\
31321 \ define LPM mode for ACCEPT \
31322 \ ------------------------------\
31323 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31324 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31325 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31327 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
31329 \ ------------------------------\
31331 \ ------------------------------\
31332 $03E8 20_US \ 1- wait 20 ms
31333 $03 TOP_LCD \ 2- send DB5=DB4=1
31334 $CD 20_US \ 3- wait 4,1 ms
31335 $03 TOP_LCD \ 4- send again DB5=DB4=1
31336 $5 20_US \ 5- wait 0,1 ms
31337 $03 TOP_LCD \ 6- send again again DB5=DB4=1
31338 $2 20_US \ wait 40 us = LCD cycle
31339 $02 TOP_LCD \ 7- send DB5=1 DB4=0
31340 $2 20_US \ wait 40 us = LCD cycle
31341 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31342 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31343 LCD_Clear \ 10- "LCD_Clear"
31344 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31345 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31346 LCD_Clear \ 10- "LCD_Clear"
31347 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31348 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31350 ['] (CR) IS CR \ ' (CR) is CR
31351 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
31353 ." RC5toLCD is running. Type STOP to quit"
31354 \ NOECHO \ uncomment to run this app without terminal connexion
31355 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
31356 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
31360 : STOP \ stops multitasking, must to be used before downloading app
31361 ['] (WARM) IS WARM \ remove START app from FORTH init process
31362 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
31370 CODE MAX \ n1 n2 -- n3 signed maximum
31371 CMP @PSP,TOS \ n2-n1
31372 S< ?GOTO FW1 \ n2<n1
31378 CODE MIN \ n1 n2 -- n3 signed minimum
31379 CMP @PSP,TOS \ n2-n1
31380 S< ?GOTO BW1 \ n2<n1
31386 : U.R \ u n -- display u unsigned in n width (n >= 2)
31388 R> OVER - 0 MAX SPACES TYPE
31392 CODE 20_US \ n -- n * 20 us
31393 BEGIN \ 3 cycles loop + 6~
31394 \ MOV #5,W \ 3 MCLK = 1 MHz
31395 \ MOV #23,W \ 3 MCLK = 4 MHz
31396 MOV #51,W \ 3 MCLK = 8 MHz
31397 \ MOV #104,W \ 3 MCLK = 16 MHz
31398 \ MOV #158,W \ 3 MCLK = 24 MHz
31399 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
31409 CODE TOP_LCD \ LCD Sample
31410 \ \ if write : %xxxxWWWW --
31411 \ \ if read : -- %0000RRRR
31412 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31413 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31414 0= IF \ write LCD bits pattern
31415 AND.B #LCD_DB,TOS \
31416 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31417 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31420 THEN \ read LCD bits pattern
31423 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31424 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31425 AND.B #LCD_DB,TOS \
31430 CODE LCD_W \ byte -- write byte to LCD
31432 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
31433 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
31434 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31435 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31436 COLON \ high level word starts here
31437 TOP_LCD 2 20_US \ write high nibble first
31442 CODE LCD_WrC \ char -- Write Char
31443 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31448 CODE LCD_WrF \ func -- Write Fonction
31449 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31455 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
31460 $02 LCD_WrF 100 20_us
31464 \ : LCD_Entry_set $04 OR LCD_WrF ;
31466 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
31468 \ : LCD_Display_Shift $10 OR LCD_WrF ;
31470 \ : LCD_Fn_Set $20 OR LCD_WrF ;
31472 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
31474 \ : LCD_Goto $80 OR LCD_WrF ;
31476 \ CODE LCD_R \ -- byte read byte from LCD
31477 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31478 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31479 \ COLON \ starts a FORTH word
31480 \ TOP_LCD 2 20_us \ -- %0000HHHH
31481 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
31482 \ HI2LO \ switch from FORTH to assembler
31483 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
31484 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
31485 \ MOV @RSP+,IP \ restore IP saved by COLON
31490 \ CODE LCD_RdS \ -- status Read Status
31491 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31496 \ CODE LCD_RdC \ -- char Read Char
31497 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31502 \ -------------+------+------+------+------++---+---+---+---+---------+
31503 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
31504 \ -------------+------+------+------+------++---+---+---+---+---------+
31505 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
31506 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
31507 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
31508 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
31509 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
31510 \ -------------+------+------+------+------++---+---+---+---+---------+
31513 \ ******************************\
31514 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31515 \ ******************************\
31516 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
31517 \ ------------------------------\
31518 \ define LPM mode for ACCEPT \
31519 \ ------------------------------\
31520 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31521 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31522 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31523 BIT.B #SW2,&SW2_IN \ test switch S2
31524 0= IF \ case of switch S2 pressed
31525 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
31527 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
31530 BIT.B #SW1,&SW1_IN \ test switch S1 input
31531 0= IF \ case of Switch S1 pressed
31532 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
31534 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
31538 RETI \ CPU is ON, GIE is OFF
31543 \ ------------------------------\
31544 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31545 \ ******************************\
31546 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31547 \ ******************************\
31548 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31549 \ \ SMclock = 8|16|24 MHz
31550 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
31551 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
31552 \ \ SR(9)=new Toggle bit memory (ADD on)
31553 \ ------------------------------\
31554 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
31555 \ ------------------------------\
31556 \ define LPM mode for ACCEPT \
31557 \ ------------------------------\
31558 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31559 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31560 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31561 \ ------------------------------\
31562 \ RC5_FirstStartBitHalfCycle: \
31563 \ ------------------------------\
31564 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
31565 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
31566 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
31567 MOV #1778,X \ RC5_Period in us
31568 MOV #14,W \ count of loop
31570 \ ------------------------------\
31571 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
31572 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
31573 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
31574 \ RC5_Compute_3/4_Period: \ |
31575 RRUM #1,X \ X=1/2 cycle |
31579 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
31580 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
31582 \ ------------------------------\
31583 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
31584 \ ------------------------------\
31585 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31586 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
31587 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31588 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31589 SUB #1,W \ decrement count loop
31590 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
31591 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31592 0<> WHILE \ ----> out of loop ----+
31593 \ RC5_compute_7/4_Time_out: \ |
31594 ADD X,Y \ | out of bound = 7/4 period
31595 \ RC5_WaitHalfCycleP1.2_IFG: \ |
31597 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
31598 0>= IF \ | if cycle time out of bound
31599 BIC #$30,&TA0CTL \ | stop timer_A0
31600 RETI \ | then quit to do nothing
31602 \ ------------------------------\ |
31603 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
31605 MOV &TA0R,X \ | | get new RC5_period value
31606 REPEAT \ ----> loop back --+ |
31607 \ ------------------------------\ |
31608 \ RC5_SampleEndOf: \ <---------------------+
31609 \ ------------------------------\
31610 BIC #$30,&TA0CTL \ stop timer_A0
31611 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
31612 \ ******************************\
31613 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
31614 \ ******************************\
31615 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
31616 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
31617 XOR IP,X \ (new XOR old) Toggle bit (13)
31618 BIT #BIT13,X \ X(13) = New_RC5_command
31619 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
31621 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
31622 \ ******************************\
31623 \ RC5_ComputeNewRC5word \
31624 \ ******************************\
31626 MOV &BASE,2(PSP) \ save variable BASE before use
31627 MOV TOS,0(PSP) \ save TOS before use
31628 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
31629 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
31630 \ ******************************\
31631 \ RC5_ComputeC6bit \
31632 \ ******************************\
31633 BIT #$4000,IP \ test /C6 bit in IP
31634 0= IF BIS #$40,TOS \ set C6 bit in S
31635 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
31636 \ ******************************\
31637 \ RC5_CommandByteIsDone \ RC5_code --
31638 \ ******************************\
31640 \ ------------------------------\
31641 \ Display IR_RC5 code \
31642 \ ------------------------------\
31643 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
31644 \ ------------------------------\
31645 LO2HI \ switch from assembler to FORTH
31646 ['] LCD_CLEAR IS CR \ redirects CR
31647 ['] LCD_WrC IS EMIT \ redirects EMIT
31648 $10 BASE ! \ change BASE to hexadecimal
31649 CR ." $" 2 U.R \ print IR_RC5 code
31650 ['] (CR) IS CR \ restore CR
31651 ['] (EMIT) IS EMIT \ restore EMIT
31652 HI2LO \ switch from FORTH to assembler
31653 \ ------------------------------\
31654 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
31655 \ ------------------------------\
31656 MOV @PSP+,&BASE \ restore variable BASE
31657 RETI \ CPU is ON, GIE is OFF
31662 \ ------------------------------\
31663 \ TB0CTL = %0000 0010 1001 0100\$3C0
31664 \ - - \CNTL Counter lentgh \ 00 = 16 bits
31665 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
31666 \ -- \ID input divider \ 10 = /4
31667 \ -- \MC Mode Control \ 01 = up to TB0CCR0
31668 \ - \TBCLR TimerB Clear
31671 \ --------------------------------\\
31672 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31673 \ -- \CM Capture Mode
31678 \ --- \OUTMOD \ 011 = set/reset
31684 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
31686 \ ------------------------------\
31687 \ set TimerB to make 50kHz PWM \
31688 \ ------------------------------\
31689 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
31690 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
31691 \ ------------------------------\
31692 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
31693 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
31694 \ ------------------------------\
31695 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31696 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
31697 \ ------------------------------\
31698 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31699 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
31700 \ ------------------------------\
31701 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31702 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
31703 \ ------------------------------\
31704 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
31705 \ ------------------------------\
31706 \ set TimerB to generate PWM for LCD_Vo
31707 \ ------------------------------\
31708 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
31709 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
31710 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31711 \ ------------------------------\
31712 BIS.B #LCDVo,&LCDVo_DIR \
31713 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
31714 \ ------------------------------\
31715 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31716 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31717 \ ------------------------------\
31718 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
31719 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
31720 \ ------------------------------\
31721 \ WDT interval init part \
31722 \ ------------------------------\
31723 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
31724 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
31725 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
31726 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
31727 \ ------------------------------\
31729 \ ------------------------------\
31730 BIS.B #RC5,&IR_IE \ enable RC5_Int
31731 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
31732 \ ------------------------------\
31733 \ init interrupt vectors
31734 \ ------------------------------\
31735 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
31736 MOV #RC5_INT,&IR_Vec \ init interrupt vector
31737 \ ------------------------------\
31738 \ define LPM mode for ACCEPT \
31739 \ ------------------------------\
31740 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31741 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31742 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31744 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
31746 \ ------------------------------\
31748 \ ------------------------------\
31749 $03E8 20_US \ 1- wait 20 ms
31750 $03 TOP_LCD \ 2- send DB5=DB4=1
31751 $CD 20_US \ 3- wait 4,1 ms
31752 $03 TOP_LCD \ 4- send again DB5=DB4=1
31753 $5 20_US \ 5- wait 0,1 ms
31754 $03 TOP_LCD \ 6- send again again DB5=DB4=1
31755 $2 20_US \ wait 40 us = LCD cycle
31756 $02 TOP_LCD \ 7- send DB5=1 DB4=0
31757 $2 20_US \ wait 40 us = LCD cycle
31758 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31759 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31760 LCD_Clear \ 10- "LCD_Clear"
31761 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31762 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31763 LCD_Clear \ 10- "LCD_Clear"
31764 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31765 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31767 ['] (CR) IS CR \ ' (CR) is CR
31768 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
31770 ." RC5toLCD is running. Type STOP to quit"
31771 \ NOECHO \ uncomment to run this app without terminal connexion
31772 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
31773 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
31777 : STOP \ stops multitasking, must to be used before downloading app
31778 ['] (WARM) IS WARM \ remove START app from FORTH init process
31779 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
31787 CODE MAX \ n1 n2 -- n3 signed maximum
31788 CMP @PSP,TOS \ n2-n1
31789 S< ?GOTO FW1 \ n2<n1
31795 CODE MIN \ n1 n2 -- n3 signed minimum
31796 CMP @PSP,TOS \ n2-n1
31797 S< ?GOTO BW1 \ n2<n1
31803 : U.R \ u n -- display u unsigned in n width (n >= 2)
31805 R> OVER - 0 MAX SPACES TYPE
31809 CODE 20_US \ n -- n * 20 us
31810 BEGIN \ 3 cycles loop + 6~
31811 \ MOV #5,W \ 3 MCLK = 1 MHz
31812 \ MOV #23,W \ 3 MCLK = 4 MHz
31813 MOV #51,W \ 3 MCLK = 8 MHz
31814 \ MOV #104,W \ 3 MCLK = 16 MHz
31815 \ MOV #158,W \ 3 MCLK = 24 MHz
31816 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
31826 CODE TOP_LCD \ LCD Sample
31827 \ \ if write : %xxxxWWWW --
31828 \ \ if read : -- %0000RRRR
31829 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31830 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31831 0= IF \ write LCD bits pattern
31832 AND.B #LCD_DB,TOS \
31833 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31834 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31837 THEN \ read LCD bits pattern
31840 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31841 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31842 AND.B #LCD_DB,TOS \
31847 CODE LCD_W \ byte -- write byte to LCD
31849 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
31850 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
31851 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31852 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31853 COLON \ high level word starts here
31854 TOP_LCD 2 20_US \ write high nibble first
31859 CODE LCD_WrC \ char -- Write Char
31860 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31865 CODE LCD_WrF \ func -- Write Fonction
31866 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31872 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
31877 $02 LCD_WrF 100 20_us
31881 \ : LCD_Entry_set $04 OR LCD_WrF ;
31883 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
31885 \ : LCD_Display_Shift $10 OR LCD_WrF ;
31887 \ : LCD_Fn_Set $20 OR LCD_WrF ;
31889 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
31891 \ : LCD_Goto $80 OR LCD_WrF ;
31893 \ CODE LCD_R \ -- byte read byte from LCD
31894 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31895 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31896 \ COLON \ starts a FORTH word
31897 \ TOP_LCD 2 20_us \ -- %0000HHHH
31898 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
31899 \ HI2LO \ switch from FORTH to assembler
31900 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
31901 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
31902 \ MOV @RSP+,IP \ restore IP saved by COLON
31907 \ CODE LCD_RdS \ -- status Read Status
31908 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31913 \ CODE LCD_RdC \ -- char Read Char
31914 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31919 \ -------------+------+------+------+------++---+---+---+---+---------+
31920 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
31921 \ -------------+------+------+------+------++---+---+---+---+---------+
31922 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
31923 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
31924 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
31925 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
31926 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
31927 \ -------------+------+------+------+------++---+---+---+---+---------+
31930 \ ******************************\
31931 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31932 \ ******************************\
31933 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
31934 \ ------------------------------\
31935 \ define LPM mode for ACCEPT \
31936 \ ------------------------------\
31937 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31938 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31939 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31940 BIT.B #SW2,&SW2_IN \ test switch S2
31941 0= IF \ case of switch S2 pressed
31942 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
31944 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
31947 BIT.B #SW1,&SW1_IN \ test switch S1 input
31948 0= IF \ case of Switch S1 pressed
31949 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
31951 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
31955 RETI \ CPU is ON, GIE is OFF
31960 \ ------------------------------\
31961 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31962 \ ******************************\
31963 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31964 \ ******************************\
31965 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31966 \ \ SMclock = 8|16|24 MHz
31967 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
31968 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
31969 \ \ SR(9)=new Toggle bit memory (ADD on)
31970 \ ------------------------------\
31971 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
31972 \ ------------------------------\
31973 \ define LPM mode for ACCEPT \
31974 \ ------------------------------\
31975 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31976 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31977 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31978 \ ------------------------------\
31979 \ RC5_FirstStartBitHalfCycle: \
31980 \ ------------------------------\
31981 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
31982 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
31983 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
31984 MOV #1778,X \ RC5_Period in us
31985 MOV #14,W \ count of loop
31987 \ ------------------------------\
31988 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
31989 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
31990 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
31991 \ RC5_Compute_3/4_Period: \ |
31992 RRUM #1,X \ X=1/2 cycle |
31996 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
31997 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
31999 \ ------------------------------\
32000 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
32001 \ ------------------------------\
32002 BIT.B #RC5,&IR_IN \ C_flag = IR bit
32003 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
32004 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
32005 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
32006 SUB #1,W \ decrement count loop
32007 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
32008 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32009 0<> WHILE \ ----> out of loop ----+
32010 \ RC5_compute_7/4_Time_out: \ |
32011 ADD X,Y \ | out of bound = 7/4 period
32012 \ RC5_WaitHalfCycleP1.2_IFG: \ |
32014 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
32015 0>= IF \ | if cycle time out of bound
32016 BIC #$30,&TA0CTL \ | stop timer_A0
32017 RETI \ | then quit to do nothing
32019 \ ------------------------------\ |
32020 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
32022 MOV &TA0R,X \ | | get new RC5_period value
32023 REPEAT \ ----> loop back --+ |
32024 \ ------------------------------\ |
32025 \ RC5_SampleEndOf: \ <---------------------+
32026 \ ------------------------------\
32027 BIC #$30,&TA0CTL \ stop timer_A0
32028 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
32029 \ ******************************\
32030 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
32031 \ ******************************\
32032 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
32033 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
32034 XOR IP,X \ (new XOR old) Toggle bit (13)
32035 BIT #BIT13,X \ X(13) = New_RC5_command
32036 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
32038 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
32039 \ ******************************\
32040 \ RC5_ComputeNewRC5word \
32041 \ ******************************\
32043 MOV &BASE,2(PSP) \ save variable BASE before use
32044 MOV TOS,0(PSP) \ save TOS before use
32045 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
32046 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
32047 \ ******************************\
32048 \ RC5_ComputeC6bit \
32049 \ ******************************\
32050 BIT #$4000,IP \ test /C6 bit in IP
32051 0= IF BIS #$40,TOS \ set C6 bit in S
32052 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
32053 \ ******************************\
32054 \ RC5_CommandByteIsDone \ RC5_code --
32055 \ ******************************\
32057 \ ------------------------------\
32058 \ Display IR_RC5 code \
32059 \ ------------------------------\
32060 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
32061 \ ------------------------------\
32062 LO2HI \ switch from assembler to FORTH
32063 ['] LCD_CLEAR IS CR \ redirects CR
32064 ['] LCD_WrC IS EMIT \ redirects EMIT
32065 $10 BASE ! \ change BASE to hexadecimal
32066 CR ." $" 2 U.R \ print IR_RC5 code
32067 ['] (CR) IS CR \ restore CR
32068 ['] (EMIT) IS EMIT \ restore EMIT
32069 HI2LO \ switch from FORTH to assembler
32070 \ ------------------------------\
32071 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
32072 \ ------------------------------\
32073 MOV @PSP+,&BASE \ restore variable BASE
32074 RETI \ CPU is ON, GIE is OFF
32079 \ ------------------------------\
32080 \ TB0CTL = %0000 0010 1001 0100\$3C0
32081 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32082 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32083 \ -- \ID input divider \ 10 = /4
32084 \ -- \MC Mode Control \ 01 = up to TB0CCR0
32085 \ - \TBCLR TimerB Clear
32088 \ --------------------------------\\
32089 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32090 \ -- \CM Capture Mode
32095 \ --- \OUTMOD \ 011 = set/reset
32101 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
32103 \ ------------------------------\
32104 \ set TimerB to make 50kHz PWM \
32105 \ ------------------------------\
32106 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32107 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
32108 \ ------------------------------\
32109 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32110 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
32111 \ ------------------------------\
32112 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32113 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
32114 \ ------------------------------\
32115 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32116 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
32117 \ ------------------------------\
32118 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32119 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
32120 \ ------------------------------\
32121 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
32122 \ ------------------------------\
32123 \ set TimerB to generate PWM for LCD_Vo
32124 \ ------------------------------\
32125 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
32126 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
32127 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32128 \ ------------------------------\
32129 BIS.B #LCDVo,&LCDVo_DIR \
32130 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
32131 \ ------------------------------\
32132 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32133 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32134 \ ------------------------------\
32135 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32136 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32137 \ ------------------------------\
32138 \ WDT interval init part \
32139 \ ------------------------------\
32140 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
32141 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
32142 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
32143 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
32144 \ ------------------------------\
32146 \ ------------------------------\
32147 BIS.B #RC5,&IR_IE \ enable RC5_Int
32148 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32149 \ ------------------------------\
32150 \ init interrupt vectors
32151 \ ------------------------------\
32152 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
32153 MOV #RC5_INT,&IR_Vec \ init interrupt vector
32154 \ ------------------------------\
32155 \ define LPM mode for ACCEPT \
32156 \ ------------------------------\
32157 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32158 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32159 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32161 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
32163 \ ------------------------------\
32165 \ ------------------------------\
32166 $03E8 20_US \ 1- wait 20 ms
32167 $03 TOP_LCD \ 2- send DB5=DB4=1
32168 $CD 20_US \ 3- wait 4,1 ms
32169 $03 TOP_LCD \ 4- send again DB5=DB4=1
32170 $5 20_US \ 5- wait 0,1 ms
32171 $03 TOP_LCD \ 6- send again again DB5=DB4=1
32172 $2 20_US \ wait 40 us = LCD cycle
32173 $02 TOP_LCD \ 7- send DB5=1 DB4=0
32174 $2 20_US \ wait 40 us = LCD cycle
32175 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32176 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
32177 LCD_Clear \ 10- "LCD_Clear"
32178 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
32179 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
32180 LCD_Clear \ 10- "LCD_Clear"
32181 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
32182 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
32184 ['] (CR) IS CR \ ' (CR) is CR
32185 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
32187 ." RC5toLCD is running. Type STOP to quit"
32188 \ NOECHO \ uncomment to run this app without terminal connexion
32189 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
32190 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
32194 : STOP \ stops multitasking, must to be used before downloading app
32195 ['] (WARM) IS WARM \ remove START app from FORTH init process
32196 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
32204 CODE MAX \ n1 n2 -- n3 signed maximum
32205 CMP @PSP,TOS \ n2-n1
32206 S< ?GOTO FW1 \ n2<n1
32212 CODE MIN \ n1 n2 -- n3 signed minimum
32213 CMP @PSP,TOS \ n2-n1
32214 S< ?GOTO BW1 \ n2<n1
32220 : U.R \ u n -- display u unsigned in n width (n >= 2)
32222 R> OVER - 0 MAX SPACES TYPE
32226 CODE 20_US \ n -- n * 20 us
32227 BEGIN \ 3 cycles loop + 6~
32228 \ MOV #5,W \ 3 MCLK = 1 MHz
32229 \ MOV #23,W \ 3 MCLK = 4 MHz
32230 MOV #51,W \ 3 MCLK = 8 MHz
32231 \ MOV #104,W \ 3 MCLK = 16 MHz
32232 \ MOV #158,W \ 3 MCLK = 24 MHz
32233 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
32243 CODE TOP_LCD \ LCD Sample
32244 \ \ if write : %xxxxWWWW --
32245 \ \ if read : -- %0000RRRR
32246 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
32247 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
32248 0= IF \ write LCD bits pattern
32249 AND.B #LCD_DB,TOS \
32250 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
32251 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32254 THEN \ read LCD bits pattern
32257 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32258 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
32259 AND.B #LCD_DB,TOS \
32264 CODE LCD_W \ byte -- write byte to LCD
32266 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
32267 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
32268 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
32269 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
32270 COLON \ high level word starts here
32271 TOP_LCD 2 20_US \ write high nibble first
32276 CODE LCD_WrC \ char -- Write Char
32277 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32282 CODE LCD_WrF \ func -- Write Fonction
32283 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32289 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
32294 $02 LCD_WrF 100 20_us
32298 \ : LCD_Entry_set $04 OR LCD_WrF ;
32300 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
32302 \ : LCD_Display_Shift $10 OR LCD_WrF ;
32304 \ : LCD_Fn_Set $20 OR LCD_WrF ;
32306 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
32308 \ : LCD_Goto $80 OR LCD_WrF ;
32310 \ CODE LCD_R \ -- byte read byte from LCD
32311 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
32312 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
32313 \ COLON \ starts a FORTH word
32314 \ TOP_LCD 2 20_us \ -- %0000HHHH
32315 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
32316 \ HI2LO \ switch from FORTH to assembler
32317 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
32318 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
32319 \ MOV @RSP+,IP \ restore IP saved by COLON
32324 \ CODE LCD_RdS \ -- status Read Status
32325 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32330 \ CODE LCD_RdC \ -- char Read Char
32331 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32336 \ -------------+------+------+------+------++---+---+---+---+---------+
32337 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
32338 \ -------------+------+------+------+------++---+---+---+---+---------+
32339 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
32340 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
32341 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
32342 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
32343 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
32344 \ -------------+------+------+------+------++---+---+---+---+---------+
32347 \ ******************************\
32348 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
32349 \ ******************************\
32350 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
32351 \ ------------------------------\
32352 \ define LPM mode for ACCEPT \
32353 \ ------------------------------\
32354 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32355 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32356 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32357 BIT.B #SW2,&SW2_IN \ test switch S2
32358 0= IF \ case of switch S2 pressed
32359 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
32361 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
32364 BIT.B #SW1,&SW1_IN \ test switch S1 input
32365 0= IF \ case of Switch S1 pressed
32366 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
32368 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
32372 RETI \ CPU is ON, GIE is OFF
32377 \ ------------------------------\
32378 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
32379 \ ******************************\
32380 ASM RC5_INT \ wake up on Px.RC5 change interrupt
32381 \ ******************************\
32382 \ \ in : SR(9)=old Toggle bit memory (ADD on)
32383 \ \ SMclock = 8|16|24 MHz
32384 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
32385 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
32386 \ \ SR(9)=new Toggle bit memory (ADD on)
32387 \ ------------------------------\
32388 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
32389 \ ------------------------------\
32390 \ define LPM mode for ACCEPT \
32391 \ ------------------------------\
32392 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32393 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32394 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32395 \ ------------------------------\
32396 \ RC5_FirstStartBitHalfCycle: \
32397 \ ------------------------------\
32398 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
32399 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
32400 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
32401 MOV #1778,X \ RC5_Period in us
32402 MOV #14,W \ count of loop
32404 \ ------------------------------\
32405 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
32406 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
32407 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
32408 \ RC5_Compute_3/4_Period: \ |
32409 RRUM #1,X \ X=1/2 cycle |
32413 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
32414 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
32416 \ ------------------------------\
32417 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
32418 \ ------------------------------\
32419 BIT.B #RC5,&IR_IN \ C_flag = IR bit
32420 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
32421 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
32422 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
32423 SUB #1,W \ decrement count loop
32424 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
32425 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32426 0<> WHILE \ ----> out of loop ----+
32427 \ RC5_compute_7/4_Time_out: \ |
32428 ADD X,Y \ | out of bound = 7/4 period
32429 \ RC5_WaitHalfCycleP1.2_IFG: \ |
32431 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
32432 0>= IF \ | if cycle time out of bound
32433 BIC #$30,&TA0CTL \ | stop timer_A0
32434 RETI \ | then quit to do nothing
32436 \ ------------------------------\ |
32437 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
32439 MOV &TA0R,X \ | | get new RC5_period value
32440 REPEAT \ ----> loop back --+ |
32441 \ ------------------------------\ |
32442 \ RC5_SampleEndOf: \ <---------------------+
32443 \ ------------------------------\
32444 BIC #$30,&TA0CTL \ stop timer_A0
32445 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
32446 \ ******************************\
32447 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
32448 \ ******************************\
32449 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
32450 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
32451 XOR IP,X \ (new XOR old) Toggle bit (13)
32452 BIT #BIT13,X \ X(13) = New_RC5_command
32453 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
32455 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
32456 \ ******************************\
32457 \ RC5_ComputeNewRC5word \
32458 \ ******************************\
32460 MOV &BASE,2(PSP) \ save variable BASE before use
32461 MOV TOS,0(PSP) \ save TOS before use
32462 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
32463 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
32464 \ ******************************\
32465 \ RC5_ComputeC6bit \
32466 \ ******************************\
32467 BIT #$4000,IP \ test /C6 bit in IP
32468 0= IF BIS #$40,TOS \ set C6 bit in S
32469 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
32470 \ ******************************\
32471 \ RC5_CommandByteIsDone \ RC5_code --
32472 \ ******************************\
32474 \ ------------------------------\
32475 \ Display IR_RC5 code \
32476 \ ------------------------------\
32477 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
32478 \ ------------------------------\
32479 LO2HI \ switch from assembler to FORTH
32480 ['] LCD_CLEAR IS CR \ redirects CR
32481 ['] LCD_WrC IS EMIT \ redirects EMIT
32482 $10 BASE ! \ change BASE to hexadecimal
32483 CR ." $" 2 U.R \ print IR_RC5 code
32484 ['] (CR) IS CR \ restore CR
32485 ['] (EMIT) IS EMIT \ restore EMIT
32486 HI2LO \ switch from FORTH to assembler
32487 \ ------------------------------\
32488 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
32489 \ ------------------------------\
32490 MOV @PSP+,&BASE \ restore variable BASE
32491 RETI \ CPU is ON, GIE is OFF
32496 \ ------------------------------\
32497 \ TB0CTL = %0000 0010 1001 0100\$3C0
32498 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32499 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32500 \ -- \ID input divider \ 10 = /4
32501 \ -- \MC Mode Control \ 01 = up to TB0CCR0
32502 \ - \TBCLR TimerB Clear
32505 \ --------------------------------\\
32506 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32507 \ -- \CM Capture Mode
32512 \ --- \OUTMOD \ 011 = set/reset
32518 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
32520 \ ------------------------------\
32521 \ set TimerB to make 50kHz PWM \
32522 \ ------------------------------\
32523 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32524 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
32525 \ ------------------------------\
32526 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32527 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
32528 \ ------------------------------\
32529 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32530 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
32531 \ ------------------------------\
32532 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32533 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
32534 \ ------------------------------\
32535 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32536 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
32537 \ ------------------------------\
32538 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
32539 \ ------------------------------\
32540 \ set TimerB to generate PWM for LCD_Vo
32541 \ ------------------------------\
32542 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
32543 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
32544 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32545 \ ------------------------------\
32546 BIS.B #LCDVo,&LCDVo_DIR \
32547 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
32548 \ ------------------------------\
32549 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32550 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32551 \ ------------------------------\
32552 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32553 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32554 \ ------------------------------\
32555 \ WDT interval init part \
32556 \ ------------------------------\
32557 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
32558 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
32559 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
32560 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
32561 \ ------------------------------\
32563 \ ------------------------------\
32564 BIS.B #RC5,&IR_IE \ enable RC5_Int
32565 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32566 \ ------------------------------\
32567 \ init interrupt vectors
32568 \ ------------------------------\
32569 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
32570 MOV #RC5_INT,&IR_Vec \ init interrupt vector
32571 \ ------------------------------\
32572 \ define LPM mode for ACCEPT \
32573 \ ------------------------------\
32574 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32575 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32576 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32578 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
32580 \ ------------------------------\
32582 \ ------------------------------\
32583 $03E8 20_US \ 1- wait 20 ms
32584 $03 TOP_LCD \ 2- send DB5=DB4=1
32585 $CD 20_US \ 3- wait 4,1 ms
32586 $03 TOP_LCD \ 4- send again DB5=DB4=1
32587 $5 20_US \ 5- wait 0,1 ms
32588 $03 TOP_LCD \ 6- send again again DB5=DB4=1
32589 $2 20_US \ wait 40 us = LCD cycle
32590 $02 TOP_LCD \ 7- send DB5=1 DB4=0
32591 $2 20_US \ wait 40 us = LCD cycle
32592 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32593 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
32594 LCD_Clear \ 10- "LCD_Clear"
32595 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
32596 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
32597 LCD_Clear \ 10- "LCD_Clear"
32598 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
32599 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
32601 ['] (CR) IS CR \ ' (CR) is CR
32602 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
32604 ." RC5toLCD is running. Type STOP to quit"
32605 \ NOECHO \ uncomment to run this app without terminal connexion
32606 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
32607 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
32611 : STOP \ stops multitasking, must to be used before downloading app
32612 ['] (WARM) IS WARM \ remove START app from FORTH init process
32613 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
32621 CODE MAX \ n1 n2 -- n3 signed maximum
32622 CMP @PSP,TOS \ n2-n1
32623 S< ?GOTO FW1 \ n2<n1
32629 CODE MIN \ n1 n2 -- n3 signed minimum
32630 CMP @PSP,TOS \ n2-n1
32631 S< ?GOTO BW1 \ n2<n1
32637 : U.R \ u n -- display u unsigned in n width (n >= 2)
32639 R> OVER - 0 MAX SPACES TYPE
32643 CODE 20_US \ n -- n * 20 us
32644 BEGIN \ 3 cycles loop + 6~
32645 \ MOV #5,W \ 3 MCLK = 1 MHz
32646 \ MOV #23,W \ 3 MCLK = 4 MHz
32647 MOV #51,W \ 3 MCLK = 8 MHz
32648 \ MOV #104,W \ 3 MCLK = 16 MHz
32649 \ MOV #158,W \ 3 MCLK = 24 MHz
32650 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
32660 CODE TOP_LCD \ LCD Sample
32661 \ \ if write : %xxxxWWWW --
32662 \ \ if read : -- %0000RRRR
32663 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
32664 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
32665 0= IF \ write LCD bits pattern
32666 AND.B #LCD_DB,TOS \
32667 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
32668 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32671 THEN \ read LCD bits pattern
32674 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32675 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
32676 AND.B #LCD_DB,TOS \
32681 CODE LCD_W \ byte -- write byte to LCD
32683 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
32684 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
32685 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
32686 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
32687 COLON \ high level word starts here
32688 TOP_LCD 2 20_US \ write high nibble first
32693 CODE LCD_WrC \ char -- Write Char
32694 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32699 CODE LCD_WrF \ func -- Write Fonction
32700 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32706 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
32711 $02 LCD_WrF 100 20_us
32715 \ : LCD_Entry_set $04 OR LCD_WrF ;
32717 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
32719 \ : LCD_Display_Shift $10 OR LCD_WrF ;
32721 \ : LCD_Fn_Set $20 OR LCD_WrF ;
32723 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
32725 \ : LCD_Goto $80 OR LCD_WrF ;
32727 \ CODE LCD_R \ -- byte read byte from LCD
32728 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
32729 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
32730 \ COLON \ starts a FORTH word
32731 \ TOP_LCD 2 20_us \ -- %0000HHHH
32732 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
32733 \ HI2LO \ switch from FORTH to assembler
32734 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
32735 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
32736 \ MOV @RSP+,IP \ restore IP saved by COLON
32741 \ CODE LCD_RdS \ -- status Read Status
32742 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32747 \ CODE LCD_RdC \ -- char Read Char
32748 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32753 \ -------------+------+------+------+------++---+---+---+---+---------+
32754 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
32755 \ -------------+------+------+------+------++---+---+---+---+---------+
32756 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
32757 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
32758 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
32759 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
32760 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
32761 \ -------------+------+------+------+------++---+---+---+---+---------+
32764 \ ******************************\
32765 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
32766 \ ******************************\
32767 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
32768 \ ------------------------------\
32769 \ define LPM mode for ACCEPT \
32770 \ ------------------------------\
32771 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32772 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32773 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32774 BIT.B #SW2,&SW2_IN \ test switch S2
32775 0= IF \ case of switch S2 pressed
32776 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
32778 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
32781 BIT.B #SW1,&SW1_IN \ test switch S1 input
32782 0= IF \ case of Switch S1 pressed
32783 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
32785 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
32789 RETI \ CPU is ON, GIE is OFF
32794 \ ------------------------------\
32795 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
32796 \ ******************************\
32797 ASM RC5_INT \ wake up on Px.RC5 change interrupt
32798 \ ******************************\
32799 \ \ in : SR(9)=old Toggle bit memory (ADD on)
32800 \ \ SMclock = 8|16|24 MHz
32801 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
32802 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
32803 \ \ SR(9)=new Toggle bit memory (ADD on)
32804 \ ------------------------------\
32805 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
32806 \ ------------------------------\
32807 \ define LPM mode for ACCEPT \
32808 \ ------------------------------\
32809 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32810 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32811 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32812 \ ------------------------------\
32813 \ RC5_FirstStartBitHalfCycle: \
32814 \ ------------------------------\
32815 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
32816 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
32817 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
32818 MOV #1778,X \ RC5_Period in us
32819 MOV #14,W \ count of loop
32821 \ ------------------------------\
32822 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
32823 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
32824 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
32825 \ RC5_Compute_3/4_Period: \ |
32826 RRUM #1,X \ X=1/2 cycle |
32830 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
32831 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
32833 \ ------------------------------\
32834 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
32835 \ ------------------------------\
32836 BIT.B #RC5,&IR_IN \ C_flag = IR bit
32837 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
32838 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
32839 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
32840 SUB #1,W \ decrement count loop
32841 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
32842 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32843 0<> WHILE \ ----> out of loop ----+
32844 \ RC5_compute_7/4_Time_out: \ |
32845 ADD X,Y \ | out of bound = 7/4 period
32846 \ RC5_WaitHalfCycleP1.2_IFG: \ |
32848 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
32849 0>= IF \ | if cycle time out of bound
32850 BIC #$30,&TA0CTL \ | stop timer_A0
32851 RETI \ | then quit to do nothing
32853 \ ------------------------------\ |
32854 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
32856 MOV &TA0R,X \ | | get new RC5_period value
32857 REPEAT \ ----> loop back --+ |
32858 \ ------------------------------\ |
32859 \ RC5_SampleEndOf: \ <---------------------+
32860 \ ------------------------------\
32861 BIC #$30,&TA0CTL \ stop timer_A0
32862 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
32863 \ ******************************\
32864 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
32865 \ ******************************\
32866 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
32867 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
32868 XOR IP,X \ (new XOR old) Toggle bit (13)
32869 BIT #BIT13,X \ X(13) = New_RC5_command
32870 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
32872 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
32873 \ ******************************\
32874 \ RC5_ComputeNewRC5word \
32875 \ ******************************\
32877 MOV &BASE,2(PSP) \ save variable BASE before use
32878 MOV TOS,0(PSP) \ save TOS before use
32879 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
32880 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
32881 \ ******************************\
32882 \ RC5_ComputeC6bit \
32883 \ ******************************\
32884 BIT #$4000,IP \ test /C6 bit in IP
32885 0= IF BIS #$40,TOS \ set C6 bit in S
32886 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
32887 \ ******************************\
32888 \ RC5_CommandByteIsDone \ RC5_code --
32889 \ ******************************\
32891 \ ------------------------------\
32892 \ Display IR_RC5 code \
32893 \ ------------------------------\
32894 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
32895 \ ------------------------------\
32896 LO2HI \ switch from assembler to FORTH
32897 ['] LCD_CLEAR IS CR \ redirects CR
32898 ['] LCD_WrC IS EMIT \ redirects EMIT
32899 $10 BASE ! \ change BASE to hexadecimal
32900 CR ." $" 2 U.R \ print IR_RC5 code
32901 ['] (CR) IS CR \ restore CR
32902 ['] (EMIT) IS EMIT \ restore EMIT
32903 HI2LO \ switch from FORTH to assembler
32904 \ ------------------------------\
32905 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
32906 \ ------------------------------\
32907 MOV @PSP+,&BASE \ restore variable BASE
32908 RETI \ CPU is ON, GIE is OFF
32913 \ ------------------------------\
32914 \ TB0CTL = %0000 0010 1001 0100\$3C0
32915 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32916 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32917 \ -- \ID input divider \ 10 = /4
32918 \ -- \MC Mode Control \ 01 = up to TB0CCR0
32919 \ - \TBCLR TimerB Clear
32922 \ --------------------------------\\
32923 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32924 \ -- \CM Capture Mode
32929 \ --- \OUTMOD \ 011 = set/reset
32935 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
32937 \ ------------------------------\
32938 \ set TimerB to make 50kHz PWM \
32939 \ ------------------------------\
32940 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32941 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
32942 \ ------------------------------\
32943 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32944 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
32945 \ ------------------------------\
32946 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32947 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
32948 \ ------------------------------\
32949 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32950 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
32951 \ ------------------------------\
32952 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32953 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
32954 \ ------------------------------\
32955 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
32956 \ ------------------------------\
32957 \ set TimerB to generate PWM for LCD_Vo
32958 \ ------------------------------\
32959 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
32960 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
32961 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32962 \ ------------------------------\
32963 BIS.B #LCDVo,&LCDVo_DIR \
32964 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
32965 \ ------------------------------\
32966 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32967 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32968 \ ------------------------------\
32969 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32970 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32971 \ ------------------------------\
32972 \ WDT interval init part \
32973 \ ------------------------------\
32974 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
32975 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
32976 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
32977 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
32978 \ ------------------------------\
32980 \ ------------------------------\
32981 BIS.B #RC5,&IR_IE \ enable RC5_Int
32982 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32983 \ ------------------------------\
32984 \ init interrupt vectors
32985 \ ------------------------------\
32986 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
32987 MOV #RC5_INT,&IR_Vec \ init interrupt vector
32988 \ ------------------------------\
32989 \ define LPM mode for ACCEPT \
32990 \ ------------------------------\
32991 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32992 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32993 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32995 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
32997 \ ------------------------------\
32999 \ ------------------------------\
33000 $03E8 20_US \ 1- wait 20 ms
33001 $03 TOP_LCD \ 2- send DB5=DB4=1
33002 $CD 20_US \ 3- wait 4,1 ms
33003 $03 TOP_LCD \ 4- send again DB5=DB4=1
33004 $5 20_US \ 5- wait 0,1 ms
33005 $03 TOP_LCD \ 6- send again again DB5=DB4=1
33006 $2 20_US \ wait 40 us = LCD cycle
33007 $02 TOP_LCD \ 7- send DB5=1 DB4=0
33008 $2 20_US \ wait 40 us = LCD cycle
33009 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33010 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33011 LCD_Clear \ 10- "LCD_Clear"
33012 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33013 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33014 LCD_Clear \ 10- "LCD_Clear"
33015 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33016 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33018 ['] (CR) IS CR \ ' (CR) is CR
33019 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
33021 ." RC5toLCD is running. Type STOP to quit"
33022 \ NOECHO \ uncomment to run this app without terminal connexion
33023 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
33024 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
33028 : STOP \ stops multitasking, must to be used before downloading app
33029 ['] (WARM) IS WARM \ remove START app from FORTH init process
33030 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
33038 CODE MAX \ n1 n2 -- n3 signed maximum
33039 CMP @PSP,TOS \ n2-n1
33040 S< ?GOTO FW1 \ n2<n1
33046 CODE MIN \ n1 n2 -- n3 signed minimum
33047 CMP @PSP,TOS \ n2-n1
33048 S< ?GOTO BW1 \ n2<n1
33054 : U.R \ u n -- display u unsigned in n width (n >= 2)
33056 R> OVER - 0 MAX SPACES TYPE
33060 CODE 20_US \ n -- n * 20 us
33061 BEGIN \ 3 cycles loop + 6~
33062 \ MOV #5,W \ 3 MCLK = 1 MHz
33063 \ MOV #23,W \ 3 MCLK = 4 MHz
33064 MOV #51,W \ 3 MCLK = 8 MHz
33065 \ MOV #104,W \ 3 MCLK = 16 MHz
33066 \ MOV #158,W \ 3 MCLK = 24 MHz
33067 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
33077 CODE TOP_LCD \ LCD Sample
33078 \ \ if write : %xxxxWWWW --
33079 \ \ if read : -- %0000RRRR
33080 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33081 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33082 0= IF \ write LCD bits pattern
33083 AND.B #LCD_DB,TOS \
33084 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33085 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33088 THEN \ read LCD bits pattern
33091 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33092 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33093 AND.B #LCD_DB,TOS \
33098 CODE LCD_W \ byte -- write byte to LCD
33100 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
33101 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
33102 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33103 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33104 COLON \ high level word starts here
33105 TOP_LCD 2 20_US \ write high nibble first
33110 CODE LCD_WrC \ char -- Write Char
33111 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33116 CODE LCD_WrF \ func -- Write Fonction
33117 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33123 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
33128 $02 LCD_WrF 100 20_us
33132 \ : LCD_Entry_set $04 OR LCD_WrF ;
33134 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
33136 \ : LCD_Display_Shift $10 OR LCD_WrF ;
33138 \ : LCD_Fn_Set $20 OR LCD_WrF ;
33140 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
33142 \ : LCD_Goto $80 OR LCD_WrF ;
33144 \ CODE LCD_R \ -- byte read byte from LCD
33145 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33146 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33147 \ COLON \ starts a FORTH word
33148 \ TOP_LCD 2 20_us \ -- %0000HHHH
33149 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
33150 \ HI2LO \ switch from FORTH to assembler
33151 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
33152 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
33153 \ MOV @RSP+,IP \ restore IP saved by COLON
33158 \ CODE LCD_RdS \ -- status Read Status
33159 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33164 \ CODE LCD_RdC \ -- char Read Char
33165 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33170 \ -------------+------+------+------+------++---+---+---+---+---------+
33171 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
33172 \ -------------+------+------+------+------++---+---+---+---+---------+
33173 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
33174 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
33175 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
33176 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
33177 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
33178 \ -------------+------+------+------+------++---+---+---+---+---------+
33181 \ ******************************\
33182 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
33183 \ ******************************\
33184 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
33185 \ ------------------------------\
33186 \ define LPM mode for ACCEPT \
33187 \ ------------------------------\
33188 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33189 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33190 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33191 BIT.B #SW2,&SW2_IN \ test switch S2
33192 0= IF \ case of switch S2 pressed
33193 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
33195 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
33198 BIT.B #SW1,&SW1_IN \ test switch S1 input
33199 0= IF \ case of Switch S1 pressed
33200 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
33202 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
33206 RETI \ CPU is ON, GIE is OFF
33211 \ ------------------------------\
33212 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
33213 \ ******************************\
33214 ASM RC5_INT \ wake up on Px.RC5 change interrupt
33215 \ ******************************\
33216 \ \ in : SR(9)=old Toggle bit memory (ADD on)
33217 \ \ SMclock = 8|16|24 MHz
33218 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
33219 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
33220 \ \ SR(9)=new Toggle bit memory (ADD on)
33221 \ ------------------------------\
33222 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
33223 \ ------------------------------\
33224 \ define LPM mode for ACCEPT \
33225 \ ------------------------------\
33226 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33227 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33228 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33229 \ ------------------------------\
33230 \ RC5_FirstStartBitHalfCycle: \
33231 \ ------------------------------\
33232 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
33233 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
33234 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
33235 MOV #1778,X \ RC5_Period in us
33236 MOV #14,W \ count of loop
33238 \ ------------------------------\
33239 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
33240 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
33241 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
33242 \ RC5_Compute_3/4_Period: \ |
33243 RRUM #1,X \ X=1/2 cycle |
33247 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
33248 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
33250 \ ------------------------------\
33251 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
33252 \ ------------------------------\
33253 BIT.B #RC5,&IR_IN \ C_flag = IR bit
33254 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
33255 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
33256 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
33257 SUB #1,W \ decrement count loop
33258 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
33259 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
33260 0<> WHILE \ ----> out of loop ----+
33261 \ RC5_compute_7/4_Time_out: \ |
33262 ADD X,Y \ | out of bound = 7/4 period
33263 \ RC5_WaitHalfCycleP1.2_IFG: \ |
33265 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
33266 0>= IF \ | if cycle time out of bound
33267 BIC #$30,&TA0CTL \ | stop timer_A0
33268 RETI \ | then quit to do nothing
33270 \ ------------------------------\ |
33271 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
33273 MOV &TA0R,X \ | | get new RC5_period value
33274 REPEAT \ ----> loop back --+ |
33275 \ ------------------------------\ |
33276 \ RC5_SampleEndOf: \ <---------------------+
33277 \ ------------------------------\
33278 BIC #$30,&TA0CTL \ stop timer_A0
33279 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
33280 \ ******************************\
33281 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
33282 \ ******************************\
33283 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
33284 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
33285 XOR IP,X \ (new XOR old) Toggle bit (13)
33286 BIT #BIT13,X \ X(13) = New_RC5_command
33287 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
33289 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
33290 \ ******************************\
33291 \ RC5_ComputeNewRC5word \
33292 \ ******************************\
33294 MOV &BASE,2(PSP) \ save variable BASE before use
33295 MOV TOS,0(PSP) \ save TOS before use
33296 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
33297 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
33298 \ ******************************\
33299 \ RC5_ComputeC6bit \
33300 \ ******************************\
33301 BIT #$4000,IP \ test /C6 bit in IP
33302 0= IF BIS #$40,TOS \ set C6 bit in S
33303 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
33304 \ ******************************\
33305 \ RC5_CommandByteIsDone \ RC5_code --
33306 \ ******************************\
33308 \ ------------------------------\
33309 \ Display IR_RC5 code \
33310 \ ------------------------------\
33311 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
33312 \ ------------------------------\
33313 LO2HI \ switch from assembler to FORTH
33314 ['] LCD_CLEAR IS CR \ redirects CR
33315 ['] LCD_WrC IS EMIT \ redirects EMIT
33316 $10 BASE ! \ change BASE to hexadecimal
33317 CR ." $" 2 U.R \ print IR_RC5 code
33318 ['] (CR) IS CR \ restore CR
33319 ['] (EMIT) IS EMIT \ restore EMIT
33320 HI2LO \ switch from FORTH to assembler
33321 \ ------------------------------\
33322 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
33323 \ ------------------------------\
33324 MOV @PSP+,&BASE \ restore variable BASE
33325 RETI \ CPU is ON, GIE is OFF
33330 \ ------------------------------\
33331 \ TB0CTL = %0000 0010 1001 0100\$3C0
33332 \ - - \CNTL Counter lentgh \ 00 = 16 bits
33333 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
33334 \ -- \ID input divider \ 10 = /4
33335 \ -- \MC Mode Control \ 01 = up to TB0CCR0
33336 \ - \TBCLR TimerB Clear
33339 \ --------------------------------\\
33340 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33341 \ -- \CM Capture Mode
33346 \ --- \OUTMOD \ 011 = set/reset
33352 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
33354 \ ------------------------------\
33355 \ set TimerB to make 50kHz PWM \
33356 \ ------------------------------\
33357 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
33358 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
33359 \ ------------------------------\
33360 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
33361 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
33362 \ ------------------------------\
33363 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33364 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
33365 \ ------------------------------\
33366 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33367 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
33368 \ ------------------------------\
33369 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33370 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
33371 \ ------------------------------\
33372 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
33373 \ ------------------------------\
33374 \ set TimerB to generate PWM for LCD_Vo
33375 \ ------------------------------\
33376 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
33377 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
33378 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33379 \ ------------------------------\
33380 BIS.B #LCDVo,&LCDVo_DIR \
33381 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
33382 \ ------------------------------\
33383 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33384 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33385 \ ------------------------------\
33386 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
33387 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
33388 \ ------------------------------\
33389 \ WDT interval init part \
33390 \ ------------------------------\
33391 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
33392 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
33393 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
33394 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
33395 \ ------------------------------\
33397 \ ------------------------------\
33398 BIS.B #RC5,&IR_IE \ enable RC5_Int
33399 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
33400 \ ------------------------------\
33401 \ init interrupt vectors
33402 \ ------------------------------\
33403 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
33404 MOV #RC5_INT,&IR_Vec \ init interrupt vector
33405 \ ------------------------------\
33406 \ define LPM mode for ACCEPT \
33407 \ ------------------------------\
33408 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33409 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33410 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33412 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
33414 \ ------------------------------\
33416 \ ------------------------------\
33417 $03E8 20_US \ 1- wait 20 ms
33418 $03 TOP_LCD \ 2- send DB5=DB4=1
33419 $CD 20_US \ 3- wait 4,1 ms
33420 $03 TOP_LCD \ 4- send again DB5=DB4=1
33421 $5 20_US \ 5- wait 0,1 ms
33422 $03 TOP_LCD \ 6- send again again DB5=DB4=1
33423 $2 20_US \ wait 40 us = LCD cycle
33424 $02 TOP_LCD \ 7- send DB5=1 DB4=0
33425 $2 20_US \ wait 40 us = LCD cycle
33426 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33427 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33428 LCD_Clear \ 10- "LCD_Clear"
33429 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33430 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33431 LCD_Clear \ 10- "LCD_Clear"
33432 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33433 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33435 ['] (CR) IS CR \ ' (CR) is CR
33436 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
33438 ." RC5toLCD is running. Type STOP to quit"
33439 \ NOECHO \ uncomment to run this app without terminal connexion
33440 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
33441 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
33445 : STOP \ stops multitasking, must to be used before downloading app
33446 ['] (WARM) IS WARM \ remove START app from FORTH init process
33447 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
33455 CODE MAX \ n1 n2 -- n3 signed maximum
33456 CMP @PSP,TOS \ n2-n1
33457 S< ?GOTO FW1 \ n2<n1
33463 CODE MIN \ n1 n2 -- n3 signed minimum
33464 CMP @PSP,TOS \ n2-n1
33465 S< ?GOTO BW1 \ n2<n1
33471 : U.R \ u n -- display u unsigned in n width (n >= 2)
33473 R> OVER - 0 MAX SPACES TYPE
33477 CODE 20_US \ n -- n * 20 us
33478 BEGIN \ 3 cycles loop + 6~
33479 \ MOV #5,W \ 3 MCLK = 1 MHz
33480 \ MOV #23,W \ 3 MCLK = 4 MHz
33481 MOV #51,W \ 3 MCLK = 8 MHz
33482 \ MOV #104,W \ 3 MCLK = 16 MHz
33483 \ MOV #158,W \ 3 MCLK = 24 MHz
33484 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
33494 CODE TOP_LCD \ LCD Sample
33495 \ \ if write : %xxxxWWWW --
33496 \ \ if read : -- %0000RRRR
33497 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33498 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33499 0= IF \ write LCD bits pattern
33500 AND.B #LCD_DB,TOS \
33501 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33502 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33505 THEN \ read LCD bits pattern
33508 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33509 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33510 AND.B #LCD_DB,TOS \
33515 CODE LCD_W \ byte -- write byte to LCD
33517 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
33518 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
33519 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33520 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33521 COLON \ high level word starts here
33522 TOP_LCD 2 20_US \ write high nibble first
33527 CODE LCD_WrC \ char -- Write Char
33528 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33533 CODE LCD_WrF \ func -- Write Fonction
33534 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33540 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
33545 $02 LCD_WrF 100 20_us
33549 \ : LCD_Entry_set $04 OR LCD_WrF ;
33551 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
33553 \ : LCD_Display_Shift $10 OR LCD_WrF ;
33555 \ : LCD_Fn_Set $20 OR LCD_WrF ;
33557 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
33559 \ : LCD_Goto $80 OR LCD_WrF ;
33561 \ CODE LCD_R \ -- byte read byte from LCD
33562 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33563 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33564 \ COLON \ starts a FORTH word
33565 \ TOP_LCD 2 20_us \ -- %0000HHHH
33566 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
33567 \ HI2LO \ switch from FORTH to assembler
33568 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
33569 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
33570 \ MOV @RSP+,IP \ restore IP saved by COLON
33575 \ CODE LCD_RdS \ -- status Read Status
33576 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33581 \ CODE LCD_RdC \ -- char Read Char
33582 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33587 \ -------------+------+------+------+------++---+---+---+---+---------+
33588 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
33589 \ -------------+------+------+------+------++---+---+---+---+---------+
33590 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
33591 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
33592 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
33593 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
33594 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
33595 \ -------------+------+------+------+------++---+---+---+---+---------+
33598 \ ******************************\
33599 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
33600 \ ******************************\
33601 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
33602 \ ------------------------------\
33603 \ define LPM mode for ACCEPT \
33604 \ ------------------------------\
33605 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33606 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33607 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33608 BIT.B #SW2,&SW2_IN \ test switch S2
33609 0= IF \ case of switch S2 pressed
33610 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
33612 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
33615 BIT.B #SW1,&SW1_IN \ test switch S1 input
33616 0= IF \ case of Switch S1 pressed
33617 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
33619 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
33623 RETI \ CPU is ON, GIE is OFF
33628 \ ------------------------------\
33629 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
33630 \ ******************************\
33631 ASM RC5_INT \ wake up on Px.RC5 change interrupt
33632 \ ******************************\
33633 \ \ in : SR(9)=old Toggle bit memory (ADD on)
33634 \ \ SMclock = 8|16|24 MHz
33635 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
33636 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
33637 \ \ SR(9)=new Toggle bit memory (ADD on)
33638 \ ------------------------------\
33639 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
33640 \ ------------------------------\
33641 \ define LPM mode for ACCEPT \
33642 \ ------------------------------\
33643 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33644 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33645 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33646 \ ------------------------------\
33647 \ RC5_FirstStartBitHalfCycle: \
33648 \ ------------------------------\
33649 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
33650 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
33651 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
33652 MOV #1778,X \ RC5_Period in us
33653 MOV #14,W \ count of loop
33655 \ ------------------------------\
33656 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
33657 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
33658 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
33659 \ RC5_Compute_3/4_Period: \ |
33660 RRUM #1,X \ X=1/2 cycle |
33664 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
33665 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
33667 \ ------------------------------\
33668 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
33669 \ ------------------------------\
33670 BIT.B #RC5,&IR_IN \ C_flag = IR bit
33671 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
33672 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
33673 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
33674 SUB #1,W \ decrement count loop
33675 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
33676 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
33677 0<> WHILE \ ----> out of loop ----+
33678 \ RC5_compute_7/4_Time_out: \ |
33679 ADD X,Y \ | out of bound = 7/4 period
33680 \ RC5_WaitHalfCycleP1.2_IFG: \ |
33682 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
33683 0>= IF \ | if cycle time out of bound
33684 BIC #$30,&TA0CTL \ | stop timer_A0
33685 RETI \ | then quit to do nothing
33687 \ ------------------------------\ |
33688 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
33690 MOV &TA0R,X \ | | get new RC5_period value
33691 REPEAT \ ----> loop back --+ |
33692 \ ------------------------------\ |
33693 \ RC5_SampleEndOf: \ <---------------------+
33694 \ ------------------------------\
33695 BIC #$30,&TA0CTL \ stop timer_A0
33696 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
33697 \ ******************************\
33698 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
33699 \ ******************************\
33700 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
33701 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
33702 XOR IP,X \ (new XOR old) Toggle bit (13)
33703 BIT #BIT13,X \ X(13) = New_RC5_command
33704 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
33706 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
33707 \ ******************************\
33708 \ RC5_ComputeNewRC5word \
33709 \ ******************************\
33711 MOV &BASE,2(PSP) \ save variable BASE before use
33712 MOV TOS,0(PSP) \ save TOS before use
33713 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
33714 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
33715 \ ******************************\
33716 \ RC5_ComputeC6bit \
33717 \ ******************************\
33718 BIT #$4000,IP \ test /C6 bit in IP
33719 0= IF BIS #$40,TOS \ set C6 bit in S
33720 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
33721 \ ******************************\
33722 \ RC5_CommandByteIsDone \ RC5_code --
33723 \ ******************************\
33725 \ ------------------------------\
33726 \ Display IR_RC5 code \
33727 \ ------------------------------\
33728 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
33729 \ ------------------------------\
33730 LO2HI \ switch from assembler to FORTH
33731 ['] LCD_CLEAR IS CR \ redirects CR
33732 ['] LCD_WrC IS EMIT \ redirects EMIT
33733 $10 BASE ! \ change BASE to hexadecimal
33734 CR ." $" 2 U.R \ print IR_RC5 code
33735 ['] (CR) IS CR \ restore CR
33736 ['] (EMIT) IS EMIT \ restore EMIT
33737 HI2LO \ switch from FORTH to assembler
33738 \ ------------------------------\
33739 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
33740 \ ------------------------------\
33741 MOV @PSP+,&BASE \ restore variable BASE
33742 RETI \ CPU is ON, GIE is OFF
33747 \ ------------------------------\
33748 \ TB0CTL = %0000 0010 1001 0100\$3C0
33749 \ - - \CNTL Counter lentgh \ 00 = 16 bits
33750 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
33751 \ -- \ID input divider \ 10 = /4
33752 \ -- \MC Mode Control \ 01 = up to TB0CCR0
33753 \ - \TBCLR TimerB Clear
33756 \ --------------------------------\\
33757 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33758 \ -- \CM Capture Mode
33763 \ --- \OUTMOD \ 011 = set/reset
33769 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
33771 \ ------------------------------\
33772 \ set TimerB to make 50kHz PWM \
33773 \ ------------------------------\
33774 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
33775 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
33776 \ ------------------------------\
33777 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
33778 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
33779 \ ------------------------------\
33780 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33781 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
33782 \ ------------------------------\
33783 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33784 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
33785 \ ------------------------------\
33786 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33787 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
33788 \ ------------------------------\
33789 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
33790 \ ------------------------------\
33791 \ set TimerB to generate PWM for LCD_Vo
33792 \ ------------------------------\
33793 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
33794 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
33795 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33796 \ ------------------------------\
33797 BIS.B #LCDVo,&LCDVo_DIR \
33798 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
33799 \ ------------------------------\
33800 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33801 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33802 \ ------------------------------\
33803 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
33804 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
33805 \ ------------------------------\
33806 \ WDT interval init part \
33807 \ ------------------------------\
33808 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
33809 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
33810 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
33811 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
33812 \ ------------------------------\
33814 \ ------------------------------\
33815 BIS.B #RC5,&IR_IE \ enable RC5_Int
33816 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
33817 \ ------------------------------\
33818 \ init interrupt vectors
33819 \ ------------------------------\
33820 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
33821 MOV #RC5_INT,&IR_Vec \ init interrupt vector
33822 \ ------------------------------\
33823 \ define LPM mode for ACCEPT \
33824 \ ------------------------------\
33825 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33826 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33827 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33829 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
33831 \ ------------------------------\
33833 \ ------------------------------\
33834 $03E8 20_US \ 1- wait 20 ms
33835 $03 TOP_LCD \ 2- send DB5=DB4=1
33836 $CD 20_US \ 3- wait 4,1 ms
33837 $03 TOP_LCD \ 4- send again DB5=DB4=1
33838 $5 20_US \ 5- wait 0,1 ms
33839 $03 TOP_LCD \ 6- send again again DB5=DB4=1
33840 $2 20_US \ wait 40 us = LCD cycle
33841 $02 TOP_LCD \ 7- send DB5=1 DB4=0
33842 $2 20_US \ wait 40 us = LCD cycle
33843 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33844 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33845 LCD_Clear \ 10- "LCD_Clear"
33846 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33847 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33848 LCD_Clear \ 10- "LCD_Clear"
33849 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33850 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33852 ['] (CR) IS CR \ ' (CR) is CR
33853 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
33855 ." RC5toLCD is running. Type STOP to quit"
33856 \ NOECHO \ uncomment to run this app without terminal connexion
33857 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
33858 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
33862 : STOP \ stops multitasking, must to be used before downloading app
33863 ['] (WARM) IS WARM \ remove START app from FORTH init process
33864 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
33872 CODE MAX \ n1 n2 -- n3 signed maximum
33873 CMP @PSP,TOS \ n2-n1
33874 S< ?GOTO FW1 \ n2<n1
33880 CODE MIN \ n1 n2 -- n3 signed minimum
33881 CMP @PSP,TOS \ n2-n1
33882 S< ?GOTO BW1 \ n2<n1
33888 : U.R \ u n -- display u unsigned in n width (n >= 2)
33890 R> OVER - 0 MAX SPACES TYPE
33894 CODE 20_US \ n -- n * 20 us
33895 BEGIN \ 3 cycles loop + 6~
33896 \ MOV #5,W \ 3 MCLK = 1 MHz
33897 \ MOV #23,W \ 3 MCLK = 4 MHz
33898 MOV #51,W \ 3 MCLK = 8 MHz
33899 \ MOV #104,W \ 3 MCLK = 16 MHz
33900 \ MOV #158,W \ 3 MCLK = 24 MHz
33901 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
33911 CODE TOP_LCD \ LCD Sample
33912 \ \ if write : %xxxxWWWW --
33913 \ \ if read : -- %0000RRRR
33914 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33915 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33916 0= IF \ write LCD bits pattern
33917 AND.B #LCD_DB,TOS \
33918 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33919 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33922 THEN \ read LCD bits pattern
33925 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33926 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33927 AND.B #LCD_DB,TOS \
33932 CODE LCD_W \ byte -- write byte to LCD
33934 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
33935 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
33936 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33937 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33938 COLON \ high level word starts here
33939 TOP_LCD 2 20_US \ write high nibble first
33944 CODE LCD_WrC \ char -- Write Char
33945 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33950 CODE LCD_WrF \ func -- Write Fonction
33951 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33957 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
33962 $02 LCD_WrF 100 20_us
33966 \ : LCD_Entry_set $04 OR LCD_WrF ;
33968 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
33970 \ : LCD_Display_Shift $10 OR LCD_WrF ;
33972 \ : LCD_Fn_Set $20 OR LCD_WrF ;
33974 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
33976 \ : LCD_Goto $80 OR LCD_WrF ;
33978 \ CODE LCD_R \ -- byte read byte from LCD
33979 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33980 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33981 \ COLON \ starts a FORTH word
33982 \ TOP_LCD 2 20_us \ -- %0000HHHH
33983 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
33984 \ HI2LO \ switch from FORTH to assembler
33985 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
33986 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
33987 \ MOV @RSP+,IP \ restore IP saved by COLON
33992 \ CODE LCD_RdS \ -- status Read Status
33993 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33998 \ CODE LCD_RdC \ -- char Read Char
33999 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34004 \ -------------+------+------+------+------++---+---+---+---+---------+
34005 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
34006 \ -------------+------+------+------+------++---+---+---+---+---------+
34007 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
34008 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
34009 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
34010 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
34011 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
34012 \ -------------+------+------+------+------++---+---+---+---+---------+
34015 \ ******************************\
34016 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34017 \ ******************************\
34018 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
34019 \ ------------------------------\
34020 \ define LPM mode for ACCEPT \
34021 \ ------------------------------\
34022 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34023 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34024 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34025 BIT.B #SW2,&SW2_IN \ test switch S2
34026 0= IF \ case of switch S2 pressed
34027 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
34029 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
34032 BIT.B #SW1,&SW1_IN \ test switch S1 input
34033 0= IF \ case of Switch S1 pressed
34034 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
34036 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
34040 RETI \ CPU is ON, GIE is OFF
34045 \ ------------------------------\
34046 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34047 \ ******************************\
34048 ASM RC5_INT \ wake up on Px.RC5 change interrupt
34049 \ ******************************\
34050 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34051 \ \ SMclock = 8|16|24 MHz
34052 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
34053 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
34054 \ \ SR(9)=new Toggle bit memory (ADD on)
34055 \ ------------------------------\
34056 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
34057 \ ------------------------------\
34058 \ define LPM mode for ACCEPT \
34059 \ ------------------------------\
34060 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34061 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34062 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34063 \ ------------------------------\
34064 \ RC5_FirstStartBitHalfCycle: \
34065 \ ------------------------------\
34066 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
34067 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
34068 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
34069 MOV #1778,X \ RC5_Period in us
34070 MOV #14,W \ count of loop
34072 \ ------------------------------\
34073 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
34074 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
34075 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
34076 \ RC5_Compute_3/4_Period: \ |
34077 RRUM #1,X \ X=1/2 cycle |
34081 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
34082 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
34084 \ ------------------------------\
34085 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
34086 \ ------------------------------\
34087 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34088 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
34089 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34090 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34091 SUB #1,W \ decrement count loop
34092 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
34093 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34094 0<> WHILE \ ----> out of loop ----+
34095 \ RC5_compute_7/4_Time_out: \ |
34096 ADD X,Y \ | out of bound = 7/4 period
34097 \ RC5_WaitHalfCycleP1.2_IFG: \ |
34099 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
34100 0>= IF \ | if cycle time out of bound
34101 BIC #$30,&TA0CTL \ | stop timer_A0
34102 RETI \ | then quit to do nothing
34104 \ ------------------------------\ |
34105 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
34107 MOV &TA0R,X \ | | get new RC5_period value
34108 REPEAT \ ----> loop back --+ |
34109 \ ------------------------------\ |
34110 \ RC5_SampleEndOf: \ <---------------------+
34111 \ ------------------------------\
34112 BIC #$30,&TA0CTL \ stop timer_A0
34113 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
34114 \ ******************************\
34115 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
34116 \ ******************************\
34117 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
34118 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
34119 XOR IP,X \ (new XOR old) Toggle bit (13)
34120 BIT #BIT13,X \ X(13) = New_RC5_command
34121 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
34123 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
34124 \ ******************************\
34125 \ RC5_ComputeNewRC5word \
34126 \ ******************************\
34128 MOV &BASE,2(PSP) \ save variable BASE before use
34129 MOV TOS,0(PSP) \ save TOS before use
34130 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
34131 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
34132 \ ******************************\
34133 \ RC5_ComputeC6bit \
34134 \ ******************************\
34135 BIT #$4000,IP \ test /C6 bit in IP
34136 0= IF BIS #$40,TOS \ set C6 bit in S
34137 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
34138 \ ******************************\
34139 \ RC5_CommandByteIsDone \ RC5_code --
34140 \ ******************************\
34142 \ ------------------------------\
34143 \ Display IR_RC5 code \
34144 \ ------------------------------\
34145 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
34146 \ ------------------------------\
34147 LO2HI \ switch from assembler to FORTH
34148 ['] LCD_CLEAR IS CR \ redirects CR
34149 ['] LCD_WrC IS EMIT \ redirects EMIT
34150 $10 BASE ! \ change BASE to hexadecimal
34151 CR ." $" 2 U.R \ print IR_RC5 code
34152 ['] (CR) IS CR \ restore CR
34153 ['] (EMIT) IS EMIT \ restore EMIT
34154 HI2LO \ switch from FORTH to assembler
34155 \ ------------------------------\
34156 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
34157 \ ------------------------------\
34158 MOV @PSP+,&BASE \ restore variable BASE
34159 RETI \ CPU is ON, GIE is OFF
34164 \ ------------------------------\
34165 \ TB0CTL = %0000 0010 1001 0100\$3C0
34166 \ - - \CNTL Counter lentgh \ 00 = 16 bits
34167 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
34168 \ -- \ID input divider \ 10 = /4
34169 \ -- \MC Mode Control \ 01 = up to TB0CCR0
34170 \ - \TBCLR TimerB Clear
34173 \ --------------------------------\\
34174 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
34175 \ -- \CM Capture Mode
34180 \ --- \OUTMOD \ 011 = set/reset
34186 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
34188 \ ------------------------------\
34189 \ set TimerB to make 50kHz PWM \
34190 \ ------------------------------\
34191 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
34192 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
34193 \ ------------------------------\
34194 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
34195 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
34196 \ ------------------------------\
34197 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34198 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
34199 \ ------------------------------\
34200 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34201 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
34202 \ ------------------------------\
34203 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34204 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
34205 \ ------------------------------\
34206 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
34207 \ ------------------------------\
34208 \ set TimerB to generate PWM for LCD_Vo
34209 \ ------------------------------\
34210 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
34211 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
34212 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
34213 \ ------------------------------\
34214 BIS.B #LCDVo,&LCDVo_DIR \
34215 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
34216 \ ------------------------------\
34217 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
34218 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
34219 \ ------------------------------\
34220 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
34221 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
34222 \ ------------------------------\
34223 \ WDT interval init part \
34224 \ ------------------------------\
34225 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
34226 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
34227 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
34228 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
34229 \ ------------------------------\
34231 \ ------------------------------\
34232 BIS.B #RC5,&IR_IE \ enable RC5_Int
34233 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
34234 \ ------------------------------\
34235 \ init interrupt vectors
34236 \ ------------------------------\
34237 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
34238 MOV #RC5_INT,&IR_Vec \ init interrupt vector
34239 \ ------------------------------\
34240 \ define LPM mode for ACCEPT \
34241 \ ------------------------------\
34242 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34243 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34244 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34246 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
34248 \ ------------------------------\
34250 \ ------------------------------\
34251 $03E8 20_US \ 1- wait 20 ms
34252 $03 TOP_LCD \ 2- send DB5=DB4=1
34253 $CD 20_US \ 3- wait 4,1 ms
34254 $03 TOP_LCD \ 4- send again DB5=DB4=1
34255 $5 20_US \ 5- wait 0,1 ms
34256 $03 TOP_LCD \ 6- send again again DB5=DB4=1
34257 $2 20_US \ wait 40 us = LCD cycle
34258 $02 TOP_LCD \ 7- send DB5=1 DB4=0
34259 $2 20_US \ wait 40 us = LCD cycle
34260 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34261 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
34262 LCD_Clear \ 10- "LCD_Clear"
34263 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
34264 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
34265 LCD_Clear \ 10- "LCD_Clear"
34266 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
34267 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
34269 ['] (CR) IS CR \ ' (CR) is CR
34270 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
34272 ." RC5toLCD is running. Type STOP to quit"
34273 \ NOECHO \ uncomment to run this app without terminal connexion
34274 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
34275 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
34279 : STOP \ stops multitasking, must to be used before downloading app
34280 ['] (WARM) IS WARM \ remove START app from FORTH init process
34281 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
34289 CODE MAX \ n1 n2 -- n3 signed maximum
34290 CMP @PSP,TOS \ n2-n1
34291 S< ?GOTO FW1 \ n2<n1
34297 CODE MIN \ n1 n2 -- n3 signed minimum
34298 CMP @PSP,TOS \ n2-n1
34299 S< ?GOTO BW1 \ n2<n1
34305 : U.R \ u n -- display u unsigned in n width (n >= 2)
34307 R> OVER - 0 MAX SPACES TYPE
34311 CODE 20_US \ n -- n * 20 us
34312 BEGIN \ 3 cycles loop + 6~
34313 \ MOV #5,W \ 3 MCLK = 1 MHz
34314 \ MOV #23,W \ 3 MCLK = 4 MHz
34315 MOV #51,W \ 3 MCLK = 8 MHz
34316 \ MOV #104,W \ 3 MCLK = 16 MHz
34317 \ MOV #158,W \ 3 MCLK = 24 MHz
34318 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
34328 CODE TOP_LCD \ LCD Sample
34329 \ \ if write : %xxxxWWWW --
34330 \ \ if read : -- %0000RRRR
34331 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
34332 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
34333 0= IF \ write LCD bits pattern
34334 AND.B #LCD_DB,TOS \
34335 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
34336 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34339 THEN \ read LCD bits pattern
34342 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34343 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
34344 AND.B #LCD_DB,TOS \
34349 CODE LCD_W \ byte -- write byte to LCD
34351 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
34352 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
34353 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
34354 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
34355 COLON \ high level word starts here
34356 TOP_LCD 2 20_US \ write high nibble first
34361 CODE LCD_WrC \ char -- Write Char
34362 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34367 CODE LCD_WrF \ func -- Write Fonction
34368 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34374 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
34379 $02 LCD_WrF 100 20_us
34383 \ : LCD_Entry_set $04 OR LCD_WrF ;
34385 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
34387 \ : LCD_Display_Shift $10 OR LCD_WrF ;
34389 \ : LCD_Fn_Set $20 OR LCD_WrF ;
34391 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
34393 \ : LCD_Goto $80 OR LCD_WrF ;
34395 \ CODE LCD_R \ -- byte read byte from LCD
34396 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
34397 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
34398 \ COLON \ starts a FORTH word
34399 \ TOP_LCD 2 20_us \ -- %0000HHHH
34400 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
34401 \ HI2LO \ switch from FORTH to assembler
34402 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
34403 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
34404 \ MOV @RSP+,IP \ restore IP saved by COLON
34409 \ CODE LCD_RdS \ -- status Read Status
34410 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34415 \ CODE LCD_RdC \ -- char Read Char
34416 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34421 \ -------------+------+------+------+------++---+---+---+---+---------+
34422 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
34423 \ -------------+------+------+------+------++---+---+---+---+---------+
34424 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
34425 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
34426 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
34427 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
34428 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
34429 \ -------------+------+------+------+------++---+---+---+---+---------+
34432 \ ******************************\
34433 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34434 \ ******************************\
34435 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
34436 \ ------------------------------\
34437 \ define LPM mode for ACCEPT \
34438 \ ------------------------------\
34439 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34440 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34441 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34442 BIT.B #SW2,&SW2_IN \ test switch S2
34443 0= IF \ case of switch S2 pressed
34444 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
34446 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
34449 BIT.B #SW1,&SW1_IN \ test switch S1 input
34450 0= IF \ case of Switch S1 pressed
34451 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
34453 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
34457 RETI \ CPU is ON, GIE is OFF
34462 \ ------------------------------\
34463 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34464 \ ******************************\
34465 ASM RC5_INT \ wake up on Px.RC5 change interrupt
34466 \ ******************************\
34467 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34468 \ \ SMclock = 8|16|24 MHz
34469 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
34470 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
34471 \ \ SR(9)=new Toggle bit memory (ADD on)
34472 \ ------------------------------\
34473 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
34474 \ ------------------------------\
34475 \ define LPM mode for ACCEPT \
34476 \ ------------------------------\
34477 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34478 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34479 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34480 \ ------------------------------\
34481 \ RC5_FirstStartBitHalfCycle: \
34482 \ ------------------------------\
34483 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
34484 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
34485 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
34486 MOV #1778,X \ RC5_Period in us
34487 MOV #14,W \ count of loop
34489 \ ------------------------------\
34490 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
34491 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
34492 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
34493 \ RC5_Compute_3/4_Period: \ |
34494 RRUM #1,X \ X=1/2 cycle |
34498 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
34499 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
34501 \ ------------------------------\
34502 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
34503 \ ------------------------------\
34504 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34505 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
34506 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34507 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34508 SUB #1,W \ decrement count loop
34509 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
34510 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34511 0<> WHILE \ ----> out of loop ----+
34512 \ RC5_compute_7/4_Time_out: \ |
34513 ADD X,Y \ | out of bound = 7/4 period
34514 \ RC5_WaitHalfCycleP1.2_IFG: \ |
34516 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
34517 0>= IF \ | if cycle time out of bound
34518 BIC #$30,&TA0CTL \ | stop timer_A0
34519 RETI \ | then quit to do nothing
34521 \ ------------------------------\ |
34522 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
34524 MOV &TA0R,X \ | | get new RC5_period value
34525 REPEAT \ ----> loop back --+ |
34526 \ ------------------------------\ |
34527 \ RC5_SampleEndOf: \ <---------------------+
34528 \ ------------------------------\
34529 BIC #$30,&TA0CTL \ stop timer_A0
34530 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
34531 \ ******************************\
34532 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
34533 \ ******************************\
34534 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
34535 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
34536 XOR IP,X \ (new XOR old) Toggle bit (13)
34537 BIT #BIT13,X \ X(13) = New_RC5_command
34538 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
34540 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
34541 \ ******************************\
34542 \ RC5_ComputeNewRC5word \
34543 \ ******************************\
34545 MOV &BASE,2(PSP) \ save variable BASE before use
34546 MOV TOS,0(PSP) \ save TOS before use
34547 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
34548 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
34549 \ ******************************\
34550 \ RC5_ComputeC6bit \
34551 \ ******************************\
34552 BIT #$4000,IP \ test /C6 bit in IP
34553 0= IF BIS #$40,TOS \ set C6 bit in S
34554 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
34555 \ ******************************\
34556 \ RC5_CommandByteIsDone \ RC5_code --
34557 \ ******************************\
34559 \ ------------------------------\
34560 \ Display IR_RC5 code \
34561 \ ------------------------------\
34562 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
34563 \ ------------------------------\
34564 LO2HI \ switch from assembler to FORTH
34565 ['] LCD_CLEAR IS CR \ redirects CR
34566 ['] LCD_WrC IS EMIT \ redirects EMIT
34567 $10 BASE ! \ change BASE to hexadecimal
34568 CR ." $" 2 U.R \ print IR_RC5 code
34569 ['] (CR) IS CR \ restore CR
34570 ['] (EMIT) IS EMIT \ restore EMIT
34571 HI2LO \ switch from FORTH to assembler
34572 \ ------------------------------\
34573 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
34574 \ ------------------------------\
34575 MOV @PSP+,&BASE \ restore variable BASE
34576 RETI \ CPU is ON, GIE is OFF
34581 \ ------------------------------\
34582 \ TB0CTL = %0000 0010 1001 0100\$3C0
34583 \ - - \CNTL Counter lentgh \ 00 = 16 bits
34584 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
34585 \ -- \ID input divider \ 10 = /4
34586 \ -- \MC Mode Control \ 01 = up to TB0CCR0
34587 \ - \TBCLR TimerB Clear
34590 \ --------------------------------\\
34591 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
34592 \ -- \CM Capture Mode
34597 \ --- \OUTMOD \ 011 = set/reset
34603 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
34605 \ ------------------------------\
34606 \ set TimerB to make 50kHz PWM \
34607 \ ------------------------------\
34608 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
34609 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
34610 \ ------------------------------\
34611 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
34612 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
34613 \ ------------------------------\
34614 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34615 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
34616 \ ------------------------------\
34617 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34618 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
34619 \ ------------------------------\
34620 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34621 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
34622 \ ------------------------------\
34623 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
34624 \ ------------------------------\
34625 \ set TimerB to generate PWM for LCD_Vo
34626 \ ------------------------------\
34627 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
34628 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
34629 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
34630 \ ------------------------------\
34631 BIS.B #LCDVo,&LCDVo_DIR \
34632 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
34633 \ ------------------------------\
34634 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
34635 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
34636 \ ------------------------------\
34637 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
34638 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
34639 \ ------------------------------\
34640 \ WDT interval init part \
34641 \ ------------------------------\
34642 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
34643 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
34644 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
34645 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
34646 \ ------------------------------\
34648 \ ------------------------------\
34649 BIS.B #RC5,&IR_IE \ enable RC5_Int
34650 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
34651 \ ------------------------------\
34652 \ init interrupt vectors
34653 \ ------------------------------\
34654 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
34655 MOV #RC5_INT,&IR_Vec \ init interrupt vector
34656 \ ------------------------------\
34657 \ define LPM mode for ACCEPT \
34658 \ ------------------------------\
34659 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34660 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34661 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34663 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
34665 \ ------------------------------\
34667 \ ------------------------------\
34668 $03E8 20_US \ 1- wait 20 ms
34669 $03 TOP_LCD \ 2- send DB5=DB4=1
34670 $CD 20_US \ 3- wait 4,1 ms
34671 $03 TOP_LCD \ 4- send again DB5=DB4=1
34672 $5 20_US \ 5- wait 0,1 ms
34673 $03 TOP_LCD \ 6- send again again DB5=DB4=1
34674 $2 20_US \ wait 40 us = LCD cycle
34675 $02 TOP_LCD \ 7- send DB5=1 DB4=0
34676 $2 20_US \ wait 40 us = LCD cycle
34677 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34678 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
34679 LCD_Clear \ 10- "LCD_Clear"
34680 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
34681 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
34682 LCD_Clear \ 10- "LCD_Clear"
34683 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
34684 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
34686 ['] (CR) IS CR \ ' (CR) is CR
34687 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
34689 ." RC5toLCD is running. Type STOP to quit"
34690 \ NOECHO \ uncomment to run this app without terminal connexion
34691 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
34692 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
34696 : STOP \ stops multitasking, must to be used before downloading app
34697 ['] (WARM) IS WARM \ remove START app from FORTH init process
34698 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
34706 CODE MAX \ n1 n2 -- n3 signed maximum
34707 CMP @PSP,TOS \ n2-n1
34708 S< ?GOTO FW1 \ n2<n1
34714 CODE MIN \ n1 n2 -- n3 signed minimum
34715 CMP @PSP,TOS \ n2-n1
34716 S< ?GOTO BW1 \ n2<n1
34722 : U.R \ u n -- display u unsigned in n width (n >= 2)
34724 R> OVER - 0 MAX SPACES TYPE
34728 CODE 20_US \ n -- n * 20 us
34729 BEGIN \ 3 cycles loop + 6~
34730 \ MOV #5,W \ 3 MCLK = 1 MHz
34731 \ MOV #23,W \ 3 MCLK = 4 MHz
34732 MOV #51,W \ 3 MCLK = 8 MHz
34733 \ MOV #104,W \ 3 MCLK = 16 MHz
34734 \ MOV #158,W \ 3 MCLK = 24 MHz
34735 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
34745 CODE TOP_LCD \ LCD Sample
34746 \ \ if write : %xxxxWWWW --
34747 \ \ if read : -- %0000RRRR
34748 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
34749 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
34750 0= IF \ write LCD bits pattern
34751 AND.B #LCD_DB,TOS \
34752 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
34753 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34756 THEN \ read LCD bits pattern
34759 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34760 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
34761 AND.B #LCD_DB,TOS \
34766 CODE LCD_W \ byte -- write byte to LCD
34768 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
34769 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
34770 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
34771 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
34772 COLON \ high level word starts here
34773 TOP_LCD 2 20_US \ write high nibble first
34778 CODE LCD_WrC \ char -- Write Char
34779 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34784 CODE LCD_WrF \ func -- Write Fonction
34785 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34791 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
34796 $02 LCD_WrF 100 20_us
34800 \ : LCD_Entry_set $04 OR LCD_WrF ;
34802 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
34804 \ : LCD_Display_Shift $10 OR LCD_WrF ;
34806 \ : LCD_Fn_Set $20 OR LCD_WrF ;
34808 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
34810 \ : LCD_Goto $80 OR LCD_WrF ;
34812 \ CODE LCD_R \ -- byte read byte from LCD
34813 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
34814 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
34815 \ COLON \ starts a FORTH word
34816 \ TOP_LCD 2 20_us \ -- %0000HHHH
34817 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
34818 \ HI2LO \ switch from FORTH to assembler
34819 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
34820 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
34821 \ MOV @RSP+,IP \ restore IP saved by COLON
34826 \ CODE LCD_RdS \ -- status Read Status
34827 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34832 \ CODE LCD_RdC \ -- char Read Char
34833 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34838 \ -------------+------+------+------+------++---+---+---+---+---------+
34839 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
34840 \ -------------+------+------+------+------++---+---+---+---+---------+
34841 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
34842 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
34843 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
34844 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
34845 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
34846 \ -------------+------+------+------+------++---+---+---+---+---------+
34849 \ ******************************\
34850 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34851 \ ******************************\
34852 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
34853 \ ------------------------------\
34854 \ define LPM mode for ACCEPT \
34855 \ ------------------------------\
34856 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34857 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34858 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34859 BIT.B #SW2,&SW2_IN \ test switch S2
34860 0= IF \ case of switch S2 pressed
34861 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
34863 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
34866 BIT.B #SW1,&SW1_IN \ test switch S1 input
34867 0= IF \ case of Switch S1 pressed
34868 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
34870 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
34874 RETI \ CPU is ON, GIE is OFF
34879 \ ------------------------------\
34880 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34881 \ ******************************\
34882 ASM RC5_INT \ wake up on Px.RC5 change interrupt
34883 \ ******************************\
34884 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34885 \ \ SMclock = 8|16|24 MHz
34886 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
34887 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
34888 \ \ SR(9)=new Toggle bit memory (ADD on)
34889 \ ------------------------------\
34890 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
34891 \ ------------------------------\
34892 \ define LPM mode for ACCEPT \
34893 \ ------------------------------\
34894 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34895 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34896 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34897 \ ------------------------------\
34898 \ RC5_FirstStartBitHalfCycle: \
34899 \ ------------------------------\
34900 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
34901 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
34902 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
34903 MOV #1778,X \ RC5_Period in us
34904 MOV #14,W \ count of loop
34906 \ ------------------------------\
34907 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
34908 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
34909 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
34910 \ RC5_Compute_3/4_Period: \ |
34911 RRUM #1,X \ X=1/2 cycle |
34915 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
34916 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
34918 \ ------------------------------\
34919 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
34920 \ ------------------------------\
34921 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34922 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
34923 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34924 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34925 SUB #1,W \ decrement count loop
34926 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
34927 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34928 0<> WHILE \ ----> out of loop ----+
34929 \ RC5_compute_7/4_Time_out: \ |
34930 ADD X,Y \ | out of bound = 7/4 period
34931 \ RC5_WaitHalfCycleP1.2_IFG: \ |
34933 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
34934 0>= IF \ | if cycle time out of bound
34935 BIC #$30,&TA0CTL \ | stop timer_A0
34936 RETI \ | then quit to do nothing
34938 \ ------------------------------\ |
34939 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
34941 MOV &TA0R,X \ | | get new RC5_period value
34942 REPEAT \ ----> loop back --+ |
34943 \ ------------------------------\ |
34944 \ RC5_SampleEndOf: \ <---------------------+
34945 \ ------------------------------\
34946 BIC #$30,&TA0CTL \ stop timer_A0
34947 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
34948 \ ******************************\
34949 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
34950 \ ******************************\
34951 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
34952 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
34953 XOR IP,X \ (new XOR old) Toggle bit (13)
34954 BIT #BIT13,X \ X(13) = New_RC5_command
34955 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
34957 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
34958 \ ******************************\
34959 \ RC5_ComputeNewRC5word \
34960 \ ******************************\
34962 MOV &BASE,2(PSP) \ save variable BASE before use
34963 MOV TOS,0(PSP) \ save TOS before use
34964 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
34965 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
34966 \ ******************************\
34967 \ RC5_ComputeC6bit \
34968 \ ******************************\
34969 BIT #$4000,IP \ test /C6 bit in IP
34970 0= IF BIS #$40,TOS \ set C6 bit in S
34971 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
34972 \ ******************************\
34973 \ RC5_CommandByteIsDone \ RC5_code --
34974 \ ******************************\
34976 \ ------------------------------\
34977 \ Display IR_RC5 code \
34978 \ ------------------------------\
34979 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
34980 \ ------------------------------\
34981 LO2HI \ switch from assembler to FORTH
34982 ['] LCD_CLEAR IS CR \ redirects CR
34983 ['] LCD_WrC IS EMIT \ redirects EMIT
34984 $10 BASE ! \ change BASE to hexadecimal
34985 CR ." $" 2 U.R \ print IR_RC5 code
34986 ['] (CR) IS CR \ restore CR
34987 ['] (EMIT) IS EMIT \ restore EMIT
34988 HI2LO \ switch from FORTH to assembler
34989 \ ------------------------------\
34990 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
34991 \ ------------------------------\
34992 MOV @PSP+,&BASE \ restore variable BASE
34993 RETI \ CPU is ON, GIE is OFF
34998 \ ------------------------------\
34999 \ TB0CTL = %0000 0010 1001 0100\$3C0
35000 \ - - \CNTL Counter lentgh \ 00 = 16 bits
35001 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
35002 \ -- \ID input divider \ 10 = /4
35003 \ -- \MC Mode Control \ 01 = up to TB0CCR0
35004 \ - \TBCLR TimerB Clear
35007 \ --------------------------------\\
35008 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35009 \ -- \CM Capture Mode
35014 \ --- \OUTMOD \ 011 = set/reset
35020 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
35022 \ ------------------------------\
35023 \ set TimerB to make 50kHz PWM \
35024 \ ------------------------------\
35025 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35026 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
35027 \ ------------------------------\
35028 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35029 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
35030 \ ------------------------------\
35031 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35032 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
35033 \ ------------------------------\
35034 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35035 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
35036 \ ------------------------------\
35037 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35038 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
35039 \ ------------------------------\
35040 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
35041 \ ------------------------------\
35042 \ set TimerB to generate PWM for LCD_Vo
35043 \ ------------------------------\
35044 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
35045 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
35046 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35047 \ ------------------------------\
35048 BIS.B #LCDVo,&LCDVo_DIR \
35049 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
35050 \ ------------------------------\
35051 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35052 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35053 \ ------------------------------\
35054 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35055 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35056 \ ------------------------------\
35057 \ WDT interval init part \
35058 \ ------------------------------\
35059 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
35060 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
35061 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
35062 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
35063 \ ------------------------------\
35065 \ ------------------------------\
35066 BIS.B #RC5,&IR_IE \ enable RC5_Int
35067 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35068 \ ------------------------------\
35069 \ init interrupt vectors
35070 \ ------------------------------\
35071 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
35072 MOV #RC5_INT,&IR_Vec \ init interrupt vector
35073 \ ------------------------------\
35074 \ define LPM mode for ACCEPT \
35075 \ ------------------------------\
35076 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35077 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35078 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35080 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
35082 \ ------------------------------\
35084 \ ------------------------------\
35085 $03E8 20_US \ 1- wait 20 ms
35086 $03 TOP_LCD \ 2- send DB5=DB4=1
35087 $CD 20_US \ 3- wait 4,1 ms
35088 $03 TOP_LCD \ 4- send again DB5=DB4=1
35089 $5 20_US \ 5- wait 0,1 ms
35090 $03 TOP_LCD \ 6- send again again DB5=DB4=1
35091 $2 20_US \ wait 40 us = LCD cycle
35092 $02 TOP_LCD \ 7- send DB5=1 DB4=0
35093 $2 20_US \ wait 40 us = LCD cycle
35094 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35095 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35096 LCD_Clear \ 10- "LCD_Clear"
35097 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35098 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35099 LCD_Clear \ 10- "LCD_Clear"
35100 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35101 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35103 ['] (CR) IS CR \ ' (CR) is CR
35104 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
35106 ." RC5toLCD is running. Type STOP to quit"
35107 \ NOECHO \ uncomment to run this app without terminal connexion
35108 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
35109 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
35113 : STOP \ stops multitasking, must to be used before downloading app
35114 ['] (WARM) IS WARM \ remove START app from FORTH init process
35115 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
35123 CODE MAX \ n1 n2 -- n3 signed maximum
35124 CMP @PSP,TOS \ n2-n1
35125 S< ?GOTO FW1 \ n2<n1
35131 CODE MIN \ n1 n2 -- n3 signed minimum
35132 CMP @PSP,TOS \ n2-n1
35133 S< ?GOTO BW1 \ n2<n1
35139 : U.R \ u n -- display u unsigned in n width (n >= 2)
35141 R> OVER - 0 MAX SPACES TYPE
35145 CODE 20_US \ n -- n * 20 us
35146 BEGIN \ 3 cycles loop + 6~
35147 \ MOV #5,W \ 3 MCLK = 1 MHz
35148 \ MOV #23,W \ 3 MCLK = 4 MHz
35149 MOV #51,W \ 3 MCLK = 8 MHz
35150 \ MOV #104,W \ 3 MCLK = 16 MHz
35151 \ MOV #158,W \ 3 MCLK = 24 MHz
35152 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
35162 CODE TOP_LCD \ LCD Sample
35163 \ \ if write : %xxxxWWWW --
35164 \ \ if read : -- %0000RRRR
35165 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
35166 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
35167 0= IF \ write LCD bits pattern
35168 AND.B #LCD_DB,TOS \
35169 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
35170 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35173 THEN \ read LCD bits pattern
35176 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35177 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
35178 AND.B #LCD_DB,TOS \
35183 CODE LCD_W \ byte -- write byte to LCD
35185 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
35186 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
35187 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
35188 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
35189 COLON \ high level word starts here
35190 TOP_LCD 2 20_US \ write high nibble first
35195 CODE LCD_WrC \ char -- Write Char
35196 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35201 CODE LCD_WrF \ func -- Write Fonction
35202 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35208 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
35213 $02 LCD_WrF 100 20_us
35217 \ : LCD_Entry_set $04 OR LCD_WrF ;
35219 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
35221 \ : LCD_Display_Shift $10 OR LCD_WrF ;
35223 \ : LCD_Fn_Set $20 OR LCD_WrF ;
35225 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
35227 \ : LCD_Goto $80 OR LCD_WrF ;
35229 \ CODE LCD_R \ -- byte read byte from LCD
35230 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
35231 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
35232 \ COLON \ starts a FORTH word
35233 \ TOP_LCD 2 20_us \ -- %0000HHHH
35234 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
35235 \ HI2LO \ switch from FORTH to assembler
35236 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
35237 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
35238 \ MOV @RSP+,IP \ restore IP saved by COLON
35243 \ CODE LCD_RdS \ -- status Read Status
35244 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35249 \ CODE LCD_RdC \ -- char Read Char
35250 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35255 \ -------------+------+------+------+------++---+---+---+---+---------+
35256 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
35257 \ -------------+------+------+------+------++---+---+---+---+---------+
35258 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
35259 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
35260 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
35261 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
35262 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
35263 \ -------------+------+------+------+------++---+---+---+---+---------+
35266 \ ******************************\
35267 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
35268 \ ******************************\
35269 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
35270 \ ------------------------------\
35271 \ define LPM mode for ACCEPT \
35272 \ ------------------------------\
35273 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35274 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35275 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35276 BIT.B #SW2,&SW2_IN \ test switch S2
35277 0= IF \ case of switch S2 pressed
35278 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
35280 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
35283 BIT.B #SW1,&SW1_IN \ test switch S1 input
35284 0= IF \ case of Switch S1 pressed
35285 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
35287 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
35291 RETI \ CPU is ON, GIE is OFF
35296 \ ------------------------------\
35297 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
35298 \ ******************************\
35299 ASM RC5_INT \ wake up on Px.RC5 change interrupt
35300 \ ******************************\
35301 \ \ in : SR(9)=old Toggle bit memory (ADD on)
35302 \ \ SMclock = 8|16|24 MHz
35303 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
35304 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
35305 \ \ SR(9)=new Toggle bit memory (ADD on)
35306 \ ------------------------------\
35307 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
35308 \ ------------------------------\
35309 \ define LPM mode for ACCEPT \
35310 \ ------------------------------\
35311 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35312 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35313 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35314 \ ------------------------------\
35315 \ RC5_FirstStartBitHalfCycle: \
35316 \ ------------------------------\
35317 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
35318 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
35319 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
35320 MOV #1778,X \ RC5_Period in us
35321 MOV #14,W \ count of loop
35323 \ ------------------------------\
35324 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
35325 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
35326 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
35327 \ RC5_Compute_3/4_Period: \ |
35328 RRUM #1,X \ X=1/2 cycle |
35332 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
35333 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
35335 \ ------------------------------\
35336 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
35337 \ ------------------------------\
35338 BIT.B #RC5,&IR_IN \ C_flag = IR bit
35339 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
35340 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
35341 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
35342 SUB #1,W \ decrement count loop
35343 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
35344 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
35345 0<> WHILE \ ----> out of loop ----+
35346 \ RC5_compute_7/4_Time_out: \ |
35347 ADD X,Y \ | out of bound = 7/4 period
35348 \ RC5_WaitHalfCycleP1.2_IFG: \ |
35350 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
35351 0>= IF \ | if cycle time out of bound
35352 BIC #$30,&TA0CTL \ | stop timer_A0
35353 RETI \ | then quit to do nothing
35355 \ ------------------------------\ |
35356 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
35358 MOV &TA0R,X \ | | get new RC5_period value
35359 REPEAT \ ----> loop back --+ |
35360 \ ------------------------------\ |
35361 \ RC5_SampleEndOf: \ <---------------------+
35362 \ ------------------------------\
35363 BIC #$30,&TA0CTL \ stop timer_A0
35364 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
35365 \ ******************************\
35366 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
35367 \ ******************************\
35368 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
35369 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
35370 XOR IP,X \ (new XOR old) Toggle bit (13)
35371 BIT #BIT13,X \ X(13) = New_RC5_command
35372 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
35374 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
35375 \ ******************************\
35376 \ RC5_ComputeNewRC5word \
35377 \ ******************************\
35379 MOV &BASE,2(PSP) \ save variable BASE before use
35380 MOV TOS,0(PSP) \ save TOS before use
35381 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
35382 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
35383 \ ******************************\
35384 \ RC5_ComputeC6bit \
35385 \ ******************************\
35386 BIT #$4000,IP \ test /C6 bit in IP
35387 0= IF BIS #$40,TOS \ set C6 bit in S
35388 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
35389 \ ******************************\
35390 \ RC5_CommandByteIsDone \ RC5_code --
35391 \ ******************************\
35393 \ ------------------------------\
35394 \ Display IR_RC5 code \
35395 \ ------------------------------\
35396 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
35397 \ ------------------------------\
35398 LO2HI \ switch from assembler to FORTH
35399 ['] LCD_CLEAR IS CR \ redirects CR
35400 ['] LCD_WrC IS EMIT \ redirects EMIT
35401 $10 BASE ! \ change BASE to hexadecimal
35402 CR ." $" 2 U.R \ print IR_RC5 code
35403 ['] (CR) IS CR \ restore CR
35404 ['] (EMIT) IS EMIT \ restore EMIT
35405 HI2LO \ switch from FORTH to assembler
35406 \ ------------------------------\
35407 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
35408 \ ------------------------------\
35409 MOV @PSP+,&BASE \ restore variable BASE
35410 RETI \ CPU is ON, GIE is OFF
35415 \ ------------------------------\
35416 \ TB0CTL = %0000 0010 1001 0100\$3C0
35417 \ - - \CNTL Counter lentgh \ 00 = 16 bits
35418 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
35419 \ -- \ID input divider \ 10 = /4
35420 \ -- \MC Mode Control \ 01 = up to TB0CCR0
35421 \ - \TBCLR TimerB Clear
35424 \ --------------------------------\\
35425 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35426 \ -- \CM Capture Mode
35431 \ --- \OUTMOD \ 011 = set/reset
35437 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
35439 \ ------------------------------\
35440 \ set TimerB to make 50kHz PWM \
35441 \ ------------------------------\
35442 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35443 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
35444 \ ------------------------------\
35445 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35446 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
35447 \ ------------------------------\
35448 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35449 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
35450 \ ------------------------------\
35451 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35452 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
35453 \ ------------------------------\
35454 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35455 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
35456 \ ------------------------------\
35457 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
35458 \ ------------------------------\
35459 \ set TimerB to generate PWM for LCD_Vo
35460 \ ------------------------------\
35461 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
35462 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
35463 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35464 \ ------------------------------\
35465 BIS.B #LCDVo,&LCDVo_DIR \
35466 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
35467 \ ------------------------------\
35468 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35469 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35470 \ ------------------------------\
35471 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35472 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35473 \ ------------------------------\
35474 \ WDT interval init part \
35475 \ ------------------------------\
35476 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
35477 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
35478 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
35479 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
35480 \ ------------------------------\
35482 \ ------------------------------\
35483 BIS.B #RC5,&IR_IE \ enable RC5_Int
35484 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35485 \ ------------------------------\
35486 \ init interrupt vectors
35487 \ ------------------------------\
35488 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
35489 MOV #RC5_INT,&IR_Vec \ init interrupt vector
35490 \ ------------------------------\
35491 \ define LPM mode for ACCEPT \
35492 \ ------------------------------\
35493 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35494 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35495 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35497 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
35499 \ ------------------------------\
35501 \ ------------------------------\
35502 $03E8 20_US \ 1- wait 20 ms
35503 $03 TOP_LCD \ 2- send DB5=DB4=1
35504 $CD 20_US \ 3- wait 4,1 ms
35505 $03 TOP_LCD \ 4- send again DB5=DB4=1
35506 $5 20_US \ 5- wait 0,1 ms
35507 $03 TOP_LCD \ 6- send again again DB5=DB4=1
35508 $2 20_US \ wait 40 us = LCD cycle
35509 $02 TOP_LCD \ 7- send DB5=1 DB4=0
35510 $2 20_US \ wait 40 us = LCD cycle
35511 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35512 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35513 LCD_Clear \ 10- "LCD_Clear"
35514 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35515 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35516 LCD_Clear \ 10- "LCD_Clear"
35517 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35518 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35520 ['] (CR) IS CR \ ' (CR) is CR
35521 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
35523 ." RC5toLCD is running. Type STOP to quit"
35524 \ NOECHO \ uncomment to run this app without terminal connexion
35525 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
35526 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
35530 : STOP \ stops multitasking, must to be used before downloading app
35531 ['] (WARM) IS WARM \ remove START app from FORTH init process
35532 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
35540 CODE MAX \ n1 n2 -- n3 signed maximum
35541 CMP @PSP,TOS \ n2-n1
35542 S< ?GOTO FW1 \ n2<n1
35548 CODE MIN \ n1 n2 -- n3 signed minimum
35549 CMP @PSP,TOS \ n2-n1
35550 S< ?GOTO BW1 \ n2<n1
35556 : U.R \ u n -- display u unsigned in n width (n >= 2)
35558 R> OVER - 0 MAX SPACES TYPE
35562 CODE 20_US \ n -- n * 20 us
35563 BEGIN \ 3 cycles loop + 6~
35564 \ MOV #5,W \ 3 MCLK = 1 MHz
35565 \ MOV #23,W \ 3 MCLK = 4 MHz
35566 MOV #51,W \ 3 MCLK = 8 MHz
35567 \ MOV #104,W \ 3 MCLK = 16 MHz
35568 \ MOV #158,W \ 3 MCLK = 24 MHz
35569 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
35579 CODE TOP_LCD \ LCD Sample
35580 \ \ if write : %xxxxWWWW --
35581 \ \ if read : -- %0000RRRR
35582 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
35583 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
35584 0= IF \ write LCD bits pattern
35585 AND.B #LCD_DB,TOS \
35586 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
35587 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35590 THEN \ read LCD bits pattern
35593 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35594 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
35595 AND.B #LCD_DB,TOS \
35600 CODE LCD_W \ byte -- write byte to LCD
35602 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
35603 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
35604 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
35605 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
35606 COLON \ high level word starts here
35607 TOP_LCD 2 20_US \ write high nibble first
35612 CODE LCD_WrC \ char -- Write Char
35613 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35618 CODE LCD_WrF \ func -- Write Fonction
35619 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35625 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
35630 $02 LCD_WrF 100 20_us
35634 \ : LCD_Entry_set $04 OR LCD_WrF ;
35636 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
35638 \ : LCD_Display_Shift $10 OR LCD_WrF ;
35640 \ : LCD_Fn_Set $20 OR LCD_WrF ;
35642 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
35644 \ : LCD_Goto $80 OR LCD_WrF ;
35646 \ CODE LCD_R \ -- byte read byte from LCD
35647 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
35648 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
35649 \ COLON \ starts a FORTH word
35650 \ TOP_LCD 2 20_us \ -- %0000HHHH
35651 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
35652 \ HI2LO \ switch from FORTH to assembler
35653 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
35654 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
35655 \ MOV @RSP+,IP \ restore IP saved by COLON
35660 \ CODE LCD_RdS \ -- status Read Status
35661 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35666 \ CODE LCD_RdC \ -- char Read Char
35667 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35672 \ -------------+------+------+------+------++---+---+---+---+---------+
35673 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
35674 \ -------------+------+------+------+------++---+---+---+---+---------+
35675 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
35676 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
35677 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
35678 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
35679 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
35680 \ -------------+------+------+------+------++---+---+---+---+---------+
35683 \ ******************************\
35684 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
35685 \ ******************************\
35686 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
35687 \ ------------------------------\
35688 \ define LPM mode for ACCEPT \
35689 \ ------------------------------\
35690 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35691 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35692 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35693 BIT.B #SW2,&SW2_IN \ test switch S2
35694 0= IF \ case of switch S2 pressed
35695 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
35697 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
35700 BIT.B #SW1,&SW1_IN \ test switch S1 input
35701 0= IF \ case of Switch S1 pressed
35702 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
35704 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
35708 RETI \ CPU is ON, GIE is OFF
35713 \ ------------------------------\
35714 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
35715 \ ******************************\
35716 ASM RC5_INT \ wake up on Px.RC5 change interrupt
35717 \ ******************************\
35718 \ \ in : SR(9)=old Toggle bit memory (ADD on)
35719 \ \ SMclock = 8|16|24 MHz
35720 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
35721 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
35722 \ \ SR(9)=new Toggle bit memory (ADD on)
35723 \ ------------------------------\
35724 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
35725 \ ------------------------------\
35726 \ define LPM mode for ACCEPT \
35727 \ ------------------------------\
35728 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35729 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35730 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35731 \ ------------------------------\
35732 \ RC5_FirstStartBitHalfCycle: \
35733 \ ------------------------------\
35734 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
35735 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
35736 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
35737 MOV #1778,X \ RC5_Period in us
35738 MOV #14,W \ count of loop
35740 \ ------------------------------\
35741 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
35742 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
35743 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
35744 \ RC5_Compute_3/4_Period: \ |
35745 RRUM #1,X \ X=1/2 cycle |
35749 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
35750 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
35752 \ ------------------------------\
35753 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
35754 \ ------------------------------\
35755 BIT.B #RC5,&IR_IN \ C_flag = IR bit
35756 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
35757 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
35758 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
35759 SUB #1,W \ decrement count loop
35760 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
35761 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
35762 0<> WHILE \ ----> out of loop ----+
35763 \ RC5_compute_7/4_Time_out: \ |
35764 ADD X,Y \ | out of bound = 7/4 period
35765 \ RC5_WaitHalfCycleP1.2_IFG: \ |
35767 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
35768 0>= IF \ | if cycle time out of bound
35769 BIC #$30,&TA0CTL \ | stop timer_A0
35770 RETI \ | then quit to do nothing
35772 \ ------------------------------\ |
35773 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
35775 MOV &TA0R,X \ | | get new RC5_period value
35776 REPEAT \ ----> loop back --+ |
35777 \ ------------------------------\ |
35778 \ RC5_SampleEndOf: \ <---------------------+
35779 \ ------------------------------\
35780 BIC #$30,&TA0CTL \ stop timer_A0
35781 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
35782 \ ******************************\
35783 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
35784 \ ******************************\
35785 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
35786 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
35787 XOR IP,X \ (new XOR old) Toggle bit (13)
35788 BIT #BIT13,X \ X(13) = New_RC5_command
35789 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
35791 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
35792 \ ******************************\
35793 \ RC5_ComputeNewRC5word \
35794 \ ******************************\
35796 MOV &BASE,2(PSP) \ save variable BASE before use
35797 MOV TOS,0(PSP) \ save TOS before use
35798 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
35799 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
35800 \ ******************************\
35801 \ RC5_ComputeC6bit \
35802 \ ******************************\
35803 BIT #$4000,IP \ test /C6 bit in IP
35804 0= IF BIS #$40,TOS \ set C6 bit in S
35805 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
35806 \ ******************************\
35807 \ RC5_CommandByteIsDone \ RC5_code --
35808 \ ******************************\
35810 \ ------------------------------\
35811 \ Display IR_RC5 code \
35812 \ ------------------------------\
35813 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
35814 \ ------------------------------\
35815 LO2HI \ switch from assembler to FORTH
35816 ['] LCD_CLEAR IS CR \ redirects CR
35817 ['] LCD_WrC IS EMIT \ redirects EMIT
35818 $10 BASE ! \ change BASE to hexadecimal
35819 CR ." $" 2 U.R \ print IR_RC5 code
35820 ['] (CR) IS CR \ restore CR
35821 ['] (EMIT) IS EMIT \ restore EMIT
35822 HI2LO \ switch from FORTH to assembler
35823 \ ------------------------------\
35824 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
35825 \ ------------------------------\
35826 MOV @PSP+,&BASE \ restore variable BASE
35827 RETI \ CPU is ON, GIE is OFF
35832 \ ------------------------------\
35833 \ TB0CTL = %0000 0010 1001 0100\$3C0
35834 \ - - \CNTL Counter lentgh \ 00 = 16 bits
35835 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
35836 \ -- \ID input divider \ 10 = /4
35837 \ -- \MC Mode Control \ 01 = up to TB0CCR0
35838 \ - \TBCLR TimerB Clear
35841 \ --------------------------------\\
35842 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35843 \ -- \CM Capture Mode
35848 \ --- \OUTMOD \ 011 = set/reset
35854 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
35856 \ ------------------------------\
35857 \ set TimerB to make 50kHz PWM \
35858 \ ------------------------------\
35859 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35860 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
35861 \ ------------------------------\
35862 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35863 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
35864 \ ------------------------------\
35865 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35866 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
35867 \ ------------------------------\
35868 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35869 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
35870 \ ------------------------------\
35871 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35872 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
35873 \ ------------------------------\
35874 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
35875 \ ------------------------------\
35876 \ set TimerB to generate PWM for LCD_Vo
35877 \ ------------------------------\
35878 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
35879 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
35880 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35881 \ ------------------------------\
35882 BIS.B #LCDVo,&LCDVo_DIR \
35883 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
35884 \ ------------------------------\
35885 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35886 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35887 \ ------------------------------\
35888 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35889 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35890 \ ------------------------------\
35891 \ WDT interval init part \
35892 \ ------------------------------\
35893 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
35894 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
35895 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
35896 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
35897 \ ------------------------------\
35899 \ ------------------------------\
35900 BIS.B #RC5,&IR_IE \ enable RC5_Int
35901 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35902 \ ------------------------------\
35903 \ init interrupt vectors
35904 \ ------------------------------\
35905 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
35906 MOV #RC5_INT,&IR_Vec \ init interrupt vector
35907 \ ------------------------------\
35908 \ define LPM mode for ACCEPT \
35909 \ ------------------------------\
35910 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35911 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35912 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35914 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
35916 \ ------------------------------\
35918 \ ------------------------------\
35919 $03E8 20_US \ 1- wait 20 ms
35920 $03 TOP_LCD \ 2- send DB5=DB4=1
35921 $CD 20_US \ 3- wait 4,1 ms
35922 $03 TOP_LCD \ 4- send again DB5=DB4=1
35923 $5 20_US \ 5- wait 0,1 ms
35924 $03 TOP_LCD \ 6- send again again DB5=DB4=1
35925 $2 20_US \ wait 40 us = LCD cycle
35926 $02 TOP_LCD \ 7- send DB5=1 DB4=0
35927 $2 20_US \ wait 40 us = LCD cycle
35928 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35929 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35930 LCD_Clear \ 10- "LCD_Clear"
35931 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35932 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35933 LCD_Clear \ 10- "LCD_Clear"
35934 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35935 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35937 ['] (CR) IS CR \ ' (CR) is CR
35938 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
35940 ." RC5toLCD is running. Type STOP to quit"
35941 \ NOECHO \ uncomment to run this app without terminal connexion
35942 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
35943 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
35947 : STOP \ stops multitasking, must to be used before downloading app
35948 ['] (WARM) IS WARM \ remove START app from FORTH init process
35949 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
35957 CODE MAX \ n1 n2 -- n3 signed maximum
35958 CMP @PSP,TOS \ n2-n1
35959 S< ?GOTO FW1 \ n2<n1
35965 CODE MIN \ n1 n2 -- n3 signed minimum
35966 CMP @PSP,TOS \ n2-n1
35967 S< ?GOTO BW1 \ n2<n1
35973 : U.R \ u n -- display u unsigned in n width (n >= 2)
35975 R> OVER - 0 MAX SPACES TYPE
35979 CODE 20_US \ n -- n * 20 us
35980 BEGIN \ 3 cycles loop + 6~
35981 \ MOV #5,W \ 3 MCLK = 1 MHz
35982 \ MOV #23,W \ 3 MCLK = 4 MHz
35983 MOV #51,W \ 3 MCLK = 8 MHz
35984 \ MOV #104,W \ 3 MCLK = 16 MHz
35985 \ MOV #158,W \ 3 MCLK = 24 MHz
35986 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
35996 CODE TOP_LCD \ LCD Sample
35997 \ \ if write : %xxxxWWWW --
35998 \ \ if read : -- %0000RRRR
35999 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36000 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36001 0= IF \ write LCD bits pattern
36002 AND.B #LCD_DB,TOS \
36003 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36004 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36007 THEN \ read LCD bits pattern
36010 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36011 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36012 AND.B #LCD_DB,TOS \
36017 CODE LCD_W \ byte -- write byte to LCD
36019 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
36020 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
36021 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36022 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36023 COLON \ high level word starts here
36024 TOP_LCD 2 20_US \ write high nibble first
36029 CODE LCD_WrC \ char -- Write Char
36030 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36035 CODE LCD_WrF \ func -- Write Fonction
36036 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36042 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
36047 $02 LCD_WrF 100 20_us
36051 \ : LCD_Entry_set $04 OR LCD_WrF ;
36053 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
36055 \ : LCD_Display_Shift $10 OR LCD_WrF ;
36057 \ : LCD_Fn_Set $20 OR LCD_WrF ;
36059 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
36061 \ : LCD_Goto $80 OR LCD_WrF ;
36063 \ CODE LCD_R \ -- byte read byte from LCD
36064 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36065 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36066 \ COLON \ starts a FORTH word
36067 \ TOP_LCD 2 20_us \ -- %0000HHHH
36068 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
36069 \ HI2LO \ switch from FORTH to assembler
36070 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
36071 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
36072 \ MOV @RSP+,IP \ restore IP saved by COLON
36077 \ CODE LCD_RdS \ -- status Read Status
36078 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36083 \ CODE LCD_RdC \ -- char Read Char
36084 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36089 \ -------------+------+------+------+------++---+---+---+---+---------+
36090 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
36091 \ -------------+------+------+------+------++---+---+---+---+---------+
36092 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
36093 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
36094 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
36095 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
36096 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
36097 \ -------------+------+------+------+------++---+---+---+---+---------+
36100 \ ******************************\
36101 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36102 \ ******************************\
36103 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
36104 \ ------------------------------\
36105 \ define LPM mode for ACCEPT \
36106 \ ------------------------------\
36107 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36108 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36109 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36110 BIT.B #SW2,&SW2_IN \ test switch S2
36111 0= IF \ case of switch S2 pressed
36112 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
36114 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
36117 BIT.B #SW1,&SW1_IN \ test switch S1 input
36118 0= IF \ case of Switch S1 pressed
36119 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
36121 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
36125 RETI \ CPU is ON, GIE is OFF
36130 \ ------------------------------\
36131 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36132 \ ******************************\
36133 ASM RC5_INT \ wake up on Px.RC5 change interrupt
36134 \ ******************************\
36135 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36136 \ \ SMclock = 8|16|24 MHz
36137 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
36138 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
36139 \ \ SR(9)=new Toggle bit memory (ADD on)
36140 \ ------------------------------\
36141 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
36142 \ ------------------------------\
36143 \ define LPM mode for ACCEPT \
36144 \ ------------------------------\
36145 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36146 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36147 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36148 \ ------------------------------\
36149 \ RC5_FirstStartBitHalfCycle: \
36150 \ ------------------------------\
36151 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
36152 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
36153 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
36154 MOV #1778,X \ RC5_Period in us
36155 MOV #14,W \ count of loop
36157 \ ------------------------------\
36158 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
36159 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
36160 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
36161 \ RC5_Compute_3/4_Period: \ |
36162 RRUM #1,X \ X=1/2 cycle |
36166 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
36167 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
36169 \ ------------------------------\
36170 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
36171 \ ------------------------------\
36172 BIT.B #RC5,&IR_IN \ C_flag = IR bit
36173 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
36174 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
36175 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
36176 SUB #1,W \ decrement count loop
36177 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
36178 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
36179 0<> WHILE \ ----> out of loop ----+
36180 \ RC5_compute_7/4_Time_out: \ |
36181 ADD X,Y \ | out of bound = 7/4 period
36182 \ RC5_WaitHalfCycleP1.2_IFG: \ |
36184 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
36185 0>= IF \ | if cycle time out of bound
36186 BIC #$30,&TA0CTL \ | stop timer_A0
36187 RETI \ | then quit to do nothing
36189 \ ------------------------------\ |
36190 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
36192 MOV &TA0R,X \ | | get new RC5_period value
36193 REPEAT \ ----> loop back --+ |
36194 \ ------------------------------\ |
36195 \ RC5_SampleEndOf: \ <---------------------+
36196 \ ------------------------------\
36197 BIC #$30,&TA0CTL \ stop timer_A0
36198 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
36199 \ ******************************\
36200 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
36201 \ ******************************\
36202 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
36203 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
36204 XOR IP,X \ (new XOR old) Toggle bit (13)
36205 BIT #BIT13,X \ X(13) = New_RC5_command
36206 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
36208 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
36209 \ ******************************\
36210 \ RC5_ComputeNewRC5word \
36211 \ ******************************\
36213 MOV &BASE,2(PSP) \ save variable BASE before use
36214 MOV TOS,0(PSP) \ save TOS before use
36215 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
36216 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
36217 \ ******************************\
36218 \ RC5_ComputeC6bit \
36219 \ ******************************\
36220 BIT #$4000,IP \ test /C6 bit in IP
36221 0= IF BIS #$40,TOS \ set C6 bit in S
36222 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
36223 \ ******************************\
36224 \ RC5_CommandByteIsDone \ RC5_code --
36225 \ ******************************\
36227 \ ------------------------------\
36228 \ Display IR_RC5 code \
36229 \ ------------------------------\
36230 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
36231 \ ------------------------------\
36232 LO2HI \ switch from assembler to FORTH
36233 ['] LCD_CLEAR IS CR \ redirects CR
36234 ['] LCD_WrC IS EMIT \ redirects EMIT
36235 $10 BASE ! \ change BASE to hexadecimal
36236 CR ." $" 2 U.R \ print IR_RC5 code
36237 ['] (CR) IS CR \ restore CR
36238 ['] (EMIT) IS EMIT \ restore EMIT
36239 HI2LO \ switch from FORTH to assembler
36240 \ ------------------------------\
36241 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
36242 \ ------------------------------\
36243 MOV @PSP+,&BASE \ restore variable BASE
36244 RETI \ CPU is ON, GIE is OFF
36249 \ ------------------------------\
36250 \ TB0CTL = %0000 0010 1001 0100\$3C0
36251 \ - - \CNTL Counter lentgh \ 00 = 16 bits
36252 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
36253 \ -- \ID input divider \ 10 = /4
36254 \ -- \MC Mode Control \ 01 = up to TB0CCR0
36255 \ - \TBCLR TimerB Clear
36258 \ --------------------------------\\
36259 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36260 \ -- \CM Capture Mode
36265 \ --- \OUTMOD \ 011 = set/reset
36271 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
36273 \ ------------------------------\
36274 \ set TimerB to make 50kHz PWM \
36275 \ ------------------------------\
36276 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
36277 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
36278 \ ------------------------------\
36279 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
36280 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
36281 \ ------------------------------\
36282 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36283 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
36284 \ ------------------------------\
36285 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36286 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
36287 \ ------------------------------\
36288 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36289 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
36290 \ ------------------------------\
36291 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
36292 \ ------------------------------\
36293 \ set TimerB to generate PWM for LCD_Vo
36294 \ ------------------------------\
36295 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
36296 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
36297 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
36298 \ ------------------------------\
36299 BIS.B #LCDVo,&LCDVo_DIR \
36300 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
36301 \ ------------------------------\
36302 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
36303 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
36304 \ ------------------------------\
36305 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
36306 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
36307 \ ------------------------------\
36308 \ WDT interval init part \
36309 \ ------------------------------\
36310 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
36311 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
36312 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
36313 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
36314 \ ------------------------------\
36316 \ ------------------------------\
36317 BIS.B #RC5,&IR_IE \ enable RC5_Int
36318 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
36319 \ ------------------------------\
36320 \ init interrupt vectors
36321 \ ------------------------------\
36322 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
36323 MOV #RC5_INT,&IR_Vec \ init interrupt vector
36324 \ ------------------------------\
36325 \ define LPM mode for ACCEPT \
36326 \ ------------------------------\
36327 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36328 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36329 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36331 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
36333 \ ------------------------------\
36335 \ ------------------------------\
36336 $03E8 20_US \ 1- wait 20 ms
36337 $03 TOP_LCD \ 2- send DB5=DB4=1
36338 $CD 20_US \ 3- wait 4,1 ms
36339 $03 TOP_LCD \ 4- send again DB5=DB4=1
36340 $5 20_US \ 5- wait 0,1 ms
36341 $03 TOP_LCD \ 6- send again again DB5=DB4=1
36342 $2 20_US \ wait 40 us = LCD cycle
36343 $02 TOP_LCD \ 7- send DB5=1 DB4=0
36344 $2 20_US \ wait 40 us = LCD cycle
36345 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
36346 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
36347 LCD_Clear \ 10- "LCD_Clear"
36348 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
36349 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
36350 LCD_Clear \ 10- "LCD_Clear"
36351 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
36352 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
36354 ['] (CR) IS CR \ ' (CR) is CR
36355 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
36357 ." RC5toLCD is running. Type STOP to quit"
36358 \ NOECHO \ uncomment to run this app without terminal connexion
36359 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
36360 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
36364 : STOP \ stops multitasking, must to be used before downloading app
36365 ['] (WARM) IS WARM \ remove START app from FORTH init process
36366 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
36374 CODE MAX \ n1 n2 -- n3 signed maximum
36375 CMP @PSP,TOS \ n2-n1
36376 S< ?GOTO FW1 \ n2<n1
36382 CODE MIN \ n1 n2 -- n3 signed minimum
36383 CMP @PSP,TOS \ n2-n1
36384 S< ?GOTO BW1 \ n2<n1
36390 : U.R \ u n -- display u unsigned in n width (n >= 2)
36392 R> OVER - 0 MAX SPACES TYPE
36396 CODE 20_US \ n -- n * 20 us
36397 BEGIN \ 3 cycles loop + 6~
36398 \ MOV #5,W \ 3 MCLK = 1 MHz
36399 \ MOV #23,W \ 3 MCLK = 4 MHz
36400 MOV #51,W \ 3 MCLK = 8 MHz
36401 \ MOV #104,W \ 3 MCLK = 16 MHz
36402 \ MOV #158,W \ 3 MCLK = 24 MHz
36403 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
36413 CODE TOP_LCD \ LCD Sample
36414 \ \ if write : %xxxxWWWW --
36415 \ \ if read : -- %0000RRRR
36416 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36417 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36418 0= IF \ write LCD bits pattern
36419 AND.B #LCD_DB,TOS \
36420 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36421 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36424 THEN \ read LCD bits pattern
36427 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36428 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36429 AND.B #LCD_DB,TOS \
36434 CODE LCD_W \ byte -- write byte to LCD
36436 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
36437 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
36438 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36439 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36440 COLON \ high level word starts here
36441 TOP_LCD 2 20_US \ write high nibble first
36446 CODE LCD_WrC \ char -- Write Char
36447 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36452 CODE LCD_WrF \ func -- Write Fonction
36453 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36459 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
36464 $02 LCD_WrF 100 20_us
36468 \ : LCD_Entry_set $04 OR LCD_WrF ;
36470 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
36472 \ : LCD_Display_Shift $10 OR LCD_WrF ;
36474 \ : LCD_Fn_Set $20 OR LCD_WrF ;
36476 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
36478 \ : LCD_Goto $80 OR LCD_WrF ;
36480 \ CODE LCD_R \ -- byte read byte from LCD
36481 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36482 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36483 \ COLON \ starts a FORTH word
36484 \ TOP_LCD 2 20_us \ -- %0000HHHH
36485 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
36486 \ HI2LO \ switch from FORTH to assembler
36487 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
36488 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
36489 \ MOV @RSP+,IP \ restore IP saved by COLON
36494 \ CODE LCD_RdS \ -- status Read Status
36495 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36500 \ CODE LCD_RdC \ -- char Read Char
36501 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36506 \ -------------+------+------+------+------++---+---+---+---+---------+
36507 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
36508 \ -------------+------+------+------+------++---+---+---+---+---------+
36509 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
36510 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
36511 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
36512 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
36513 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
36514 \ -------------+------+------+------+------++---+---+---+---+---------+
36517 \ ******************************\
36518 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36519 \ ******************************\
36520 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
36521 \ ------------------------------\
36522 \ define LPM mode for ACCEPT \
36523 \ ------------------------------\
36524 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36525 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36526 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36527 BIT.B #SW2,&SW2_IN \ test switch S2
36528 0= IF \ case of switch S2 pressed
36529 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
36531 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
36534 BIT.B #SW1,&SW1_IN \ test switch S1 input
36535 0= IF \ case of Switch S1 pressed
36536 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
36538 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
36542 RETI \ CPU is ON, GIE is OFF
36547 \ ------------------------------\
36548 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36549 \ ******************************\
36550 ASM RC5_INT \ wake up on Px.RC5 change interrupt
36551 \ ******************************\
36552 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36553 \ \ SMclock = 8|16|24 MHz
36554 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
36555 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
36556 \ \ SR(9)=new Toggle bit memory (ADD on)
36557 \ ------------------------------\
36558 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
36559 \ ------------------------------\
36560 \ define LPM mode for ACCEPT \
36561 \ ------------------------------\
36562 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36563 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36564 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36565 \ ------------------------------\
36566 \ RC5_FirstStartBitHalfCycle: \
36567 \ ------------------------------\
36568 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
36569 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
36570 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
36571 MOV #1778,X \ RC5_Period in us
36572 MOV #14,W \ count of loop
36574 \ ------------------------------\
36575 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
36576 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
36577 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
36578 \ RC5_Compute_3/4_Period: \ |
36579 RRUM #1,X \ X=1/2 cycle |
36583 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
36584 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
36586 \ ------------------------------\
36587 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
36588 \ ------------------------------\
36589 BIT.B #RC5,&IR_IN \ C_flag = IR bit
36590 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
36591 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
36592 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
36593 SUB #1,W \ decrement count loop
36594 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
36595 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
36596 0<> WHILE \ ----> out of loop ----+
36597 \ RC5_compute_7/4_Time_out: \ |
36598 ADD X,Y \ | out of bound = 7/4 period
36599 \ RC5_WaitHalfCycleP1.2_IFG: \ |
36601 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
36602 0>= IF \ | if cycle time out of bound
36603 BIC #$30,&TA0CTL \ | stop timer_A0
36604 RETI \ | then quit to do nothing
36606 \ ------------------------------\ |
36607 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
36609 MOV &TA0R,X \ | | get new RC5_period value
36610 REPEAT \ ----> loop back --+ |
36611 \ ------------------------------\ |
36612 \ RC5_SampleEndOf: \ <---------------------+
36613 \ ------------------------------\
36614 BIC #$30,&TA0CTL \ stop timer_A0
36615 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
36616 \ ******************************\
36617 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
36618 \ ******************************\
36619 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
36620 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
36621 XOR IP,X \ (new XOR old) Toggle bit (13)
36622 BIT #BIT13,X \ X(13) = New_RC5_command
36623 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
36625 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
36626 \ ******************************\
36627 \ RC5_ComputeNewRC5word \
36628 \ ******************************\
36630 MOV &BASE,2(PSP) \ save variable BASE before use
36631 MOV TOS,0(PSP) \ save TOS before use
36632 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
36633 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
36634 \ ******************************\
36635 \ RC5_ComputeC6bit \
36636 \ ******************************\
36637 BIT #$4000,IP \ test /C6 bit in IP
36638 0= IF BIS #$40,TOS \ set C6 bit in S
36639 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
36640 \ ******************************\
36641 \ RC5_CommandByteIsDone \ RC5_code --
36642 \ ******************************\
36644 \ ------------------------------\
36645 \ Display IR_RC5 code \
36646 \ ------------------------------\
36647 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
36648 \ ------------------------------\
36649 LO2HI \ switch from assembler to FORTH
36650 ['] LCD_CLEAR IS CR \ redirects CR
36651 ['] LCD_WrC IS EMIT \ redirects EMIT
36652 $10 BASE ! \ change BASE to hexadecimal
36653 CR ." $" 2 U.R \ print IR_RC5 code
36654 ['] (CR) IS CR \ restore CR
36655 ['] (EMIT) IS EMIT \ restore EMIT
36656 HI2LO \ switch from FORTH to assembler
36657 \ ------------------------------\
36658 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
36659 \ ------------------------------\
36660 MOV @PSP+,&BASE \ restore variable BASE
36661 RETI \ CPU is ON, GIE is OFF
36666 \ ------------------------------\
36667 \ TB0CTL = %0000 0010 1001 0100\$3C0
36668 \ - - \CNTL Counter lentgh \ 00 = 16 bits
36669 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
36670 \ -- \ID input divider \ 10 = /4
36671 \ -- \MC Mode Control \ 01 = up to TB0CCR0
36672 \ - \TBCLR TimerB Clear
36675 \ --------------------------------\\
36676 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36677 \ -- \CM Capture Mode
36682 \ --- \OUTMOD \ 011 = set/reset
36688 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
36690 \ ------------------------------\
36691 \ set TimerB to make 50kHz PWM \
36692 \ ------------------------------\
36693 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
36694 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
36695 \ ------------------------------\
36696 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
36697 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
36698 \ ------------------------------\
36699 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36700 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
36701 \ ------------------------------\
36702 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36703 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
36704 \ ------------------------------\
36705 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36706 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
36707 \ ------------------------------\
36708 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
36709 \ ------------------------------\
36710 \ set TimerB to generate PWM for LCD_Vo
36711 \ ------------------------------\
36712 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
36713 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
36714 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
36715 \ ------------------------------\
36716 BIS.B #LCDVo,&LCDVo_DIR \
36717 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
36718 \ ------------------------------\
36719 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
36720 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
36721 \ ------------------------------\
36722 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
36723 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
36724 \ ------------------------------\
36725 \ WDT interval init part \
36726 \ ------------------------------\
36727 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
36728 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
36729 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
36730 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
36731 \ ------------------------------\
36733 \ ------------------------------\
36734 BIS.B #RC5,&IR_IE \ enable RC5_Int
36735 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
36736 \ ------------------------------\
36737 \ init interrupt vectors
36738 \ ------------------------------\
36739 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
36740 MOV #RC5_INT,&IR_Vec \ init interrupt vector
36741 \ ------------------------------\
36742 \ define LPM mode for ACCEPT \
36743 \ ------------------------------\
36744 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36745 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36746 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36748 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
36750 \ ------------------------------\
36752 \ ------------------------------\
36753 $03E8 20_US \ 1- wait 20 ms
36754 $03 TOP_LCD \ 2- send DB5=DB4=1
36755 $CD 20_US \ 3- wait 4,1 ms
36756 $03 TOP_LCD \ 4- send again DB5=DB4=1
36757 $5 20_US \ 5- wait 0,1 ms
36758 $03 TOP_LCD \ 6- send again again DB5=DB4=1
36759 $2 20_US \ wait 40 us = LCD cycle
36760 $02 TOP_LCD \ 7- send DB5=1 DB4=0
36761 $2 20_US \ wait 40 us = LCD cycle
36762 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
36763 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
36764 LCD_Clear \ 10- "LCD_Clear"
36765 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
36766 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
36767 LCD_Clear \ 10- "LCD_Clear"
36768 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
36769 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
36771 ['] (CR) IS CR \ ' (CR) is CR
36772 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
36774 ." RC5toLCD is running. Type STOP to quit"
36775 \ NOECHO \ uncomment to run this app without terminal connexion
36776 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
36777 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
36781 : STOP \ stops multitasking, must to be used before downloading app
36782 ['] (WARM) IS WARM \ remove START app from FORTH init process
36783 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
36791 CODE MAX \ n1 n2 -- n3 signed maximum
36792 CMP @PSP,TOS \ n2-n1
36793 S< ?GOTO FW1 \ n2<n1
36799 CODE MIN \ n1 n2 -- n3 signed minimum
36800 CMP @PSP,TOS \ n2-n1
36801 S< ?GOTO BW1 \ n2<n1
36807 : U.R \ u n -- display u unsigned in n width (n >= 2)
36809 R> OVER - 0 MAX SPACES TYPE
36813 CODE 20_US \ n -- n * 20 us
36814 BEGIN \ 3 cycles loop + 6~
36815 \ MOV #5,W \ 3 MCLK = 1 MHz
36816 \ MOV #23,W \ 3 MCLK = 4 MHz
36817 MOV #51,W \ 3 MCLK = 8 MHz
36818 \ MOV #104,W \ 3 MCLK = 16 MHz
36819 \ MOV #158,W \ 3 MCLK = 24 MHz
36820 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
36830 CODE TOP_LCD \ LCD Sample
36831 \ \ if write : %xxxxWWWW --
36832 \ \ if read : -- %0000RRRR
36833 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36834 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36835 0= IF \ write LCD bits pattern
36836 AND.B #LCD_DB,TOS \
36837 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36838 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36841 THEN \ read LCD bits pattern
36844 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36845 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36846 AND.B #LCD_DB,TOS \
36851 CODE LCD_W \ byte -- write byte to LCD
36853 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
36854 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
36855 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36856 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36857 COLON \ high level word starts here
36858 TOP_LCD 2 20_US \ write high nibble first
36863 CODE LCD_WrC \ char -- Write Char
36864 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36869 CODE LCD_WrF \ func -- Write Fonction
36870 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36876 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
36881 $02 LCD_WrF 100 20_us
36885 \ : LCD_Entry_set $04 OR LCD_WrF ;
36887 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
36889 \ : LCD_Display_Shift $10 OR LCD_WrF ;
36891 \ : LCD_Fn_Set $20 OR LCD_WrF ;
36893 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
36895 \ : LCD_Goto $80 OR LCD_WrF ;
36897 \ CODE LCD_R \ -- byte read byte from LCD
36898 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36899 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36900 \ COLON \ starts a FORTH word
36901 \ TOP_LCD 2 20_us \ -- %0000HHHH
36902 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
36903 \ HI2LO \ switch from FORTH to assembler
36904 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
36905 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
36906 \ MOV @RSP+,IP \ restore IP saved by COLON
36911 \ CODE LCD_RdS \ -- status Read Status
36912 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36917 \ CODE LCD_RdC \ -- char Read Char
36918 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36923 \ -------------+------+------+------+------++---+---+---+---+---------+
36924 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
36925 \ -------------+------+------+------+------++---+---+---+---+---------+
36926 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
36927 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
36928 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
36929 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
36930 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
36931 \ -------------+------+------+------+------++---+---+---+---+---------+
36934 \ ******************************\
36935 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36936 \ ******************************\
36937 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
36938 \ ------------------------------\
36939 \ define LPM mode for ACCEPT \
36940 \ ------------------------------\
36941 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36942 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36943 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36944 BIT.B #SW2,&SW2_IN \ test switch S2
36945 0= IF \ case of switch S2 pressed
36946 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
36948 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
36951 BIT.B #SW1,&SW1_IN \ test switch S1 input
36952 0= IF \ case of Switch S1 pressed
36953 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
36955 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
36959 RETI \ CPU is ON, GIE is OFF
36964 \ ------------------------------\
36965 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36966 \ ******************************\
36967 ASM RC5_INT \ wake up on Px.RC5 change interrupt
36968 \ ******************************\
36969 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36970 \ \ SMclock = 8|16|24 MHz
36971 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
36972 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
36973 \ \ SR(9)=new Toggle bit memory (ADD on)
36974 \ ------------------------------\
36975 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
36976 \ ------------------------------\
36977 \ define LPM mode for ACCEPT \
36978 \ ------------------------------\
36979 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36980 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36981 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36982 \ ------------------------------\
36983 \ RC5_FirstStartBitHalfCycle: \
36984 \ ------------------------------\
36985 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
36986 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
36987 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
36988 MOV #1778,X \ RC5_Period in us
36989 MOV #14,W \ count of loop
36991 \ ------------------------------\
36992 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
36993 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
36994 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
36995 \ RC5_Compute_3/4_Period: \ |
36996 RRUM #1,X \ X=1/2 cycle |
37000 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
37001 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
37003 \ ------------------------------\
37004 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
37005 \ ------------------------------\
37006 BIT.B #RC5,&IR_IN \ C_flag = IR bit
37007 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
37008 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37009 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37010 SUB #1,W \ decrement count loop
37011 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
37012 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37013 0<> WHILE \ ----> out of loop ----+
37014 \ RC5_compute_7/4_Time_out: \ |
37015 ADD X,Y \ | out of bound = 7/4 period
37016 \ RC5_WaitHalfCycleP1.2_IFG: \ |
37018 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
37019 0>= IF \ | if cycle time out of bound
37020 BIC #$30,&TA0CTL \ | stop timer_A0
37021 RETI \ | then quit to do nothing
37023 \ ------------------------------\ |
37024 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
37026 MOV &TA0R,X \ | | get new RC5_period value
37027 REPEAT \ ----> loop back --+ |
37028 \ ------------------------------\ |
37029 \ RC5_SampleEndOf: \ <---------------------+
37030 \ ------------------------------\
37031 BIC #$30,&TA0CTL \ stop timer_A0
37032 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
37033 \ ******************************\
37034 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
37035 \ ******************************\
37036 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
37037 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
37038 XOR IP,X \ (new XOR old) Toggle bit (13)
37039 BIT #BIT13,X \ X(13) = New_RC5_command
37040 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
37042 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
37043 \ ******************************\
37044 \ RC5_ComputeNewRC5word \
37045 \ ******************************\
37047 MOV &BASE,2(PSP) \ save variable BASE before use
37048 MOV TOS,0(PSP) \ save TOS before use
37049 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
37050 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
37051 \ ******************************\
37052 \ RC5_ComputeC6bit \
37053 \ ******************************\
37054 BIT #$4000,IP \ test /C6 bit in IP
37055 0= IF BIS #$40,TOS \ set C6 bit in S
37056 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
37057 \ ******************************\
37058 \ RC5_CommandByteIsDone \ RC5_code --
37059 \ ******************************\
37061 \ ------------------------------\
37062 \ Display IR_RC5 code \
37063 \ ------------------------------\
37064 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
37065 \ ------------------------------\
37066 LO2HI \ switch from assembler to FORTH
37067 ['] LCD_CLEAR IS CR \ redirects CR
37068 ['] LCD_WrC IS EMIT \ redirects EMIT
37069 $10 BASE ! \ change BASE to hexadecimal
37070 CR ." $" 2 U.R \ print IR_RC5 code
37071 ['] (CR) IS CR \ restore CR
37072 ['] (EMIT) IS EMIT \ restore EMIT
37073 HI2LO \ switch from FORTH to assembler
37074 \ ------------------------------\
37075 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
37076 \ ------------------------------\
37077 MOV @PSP+,&BASE \ restore variable BASE
37078 RETI \ CPU is ON, GIE is OFF
37083 \ ------------------------------\
37084 \ TB0CTL = %0000 0010 1001 0100\$3C0
37085 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37086 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37087 \ -- \ID input divider \ 10 = /4
37088 \ -- \MC Mode Control \ 01 = up to TB0CCR0
37089 \ - \TBCLR TimerB Clear
37092 \ --------------------------------\\
37093 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37094 \ -- \CM Capture Mode
37099 \ --- \OUTMOD \ 011 = set/reset
37105 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
37107 \ ------------------------------\
37108 \ set TimerB to make 50kHz PWM \
37109 \ ------------------------------\
37110 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37111 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
37112 \ ------------------------------\
37113 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37114 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
37115 \ ------------------------------\
37116 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37117 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
37118 \ ------------------------------\
37119 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37120 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
37121 \ ------------------------------\
37122 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37123 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
37124 \ ------------------------------\
37125 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
37126 \ ------------------------------\
37127 \ set TimerB to generate PWM for LCD_Vo
37128 \ ------------------------------\
37129 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
37130 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
37131 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37132 \ ------------------------------\
37133 BIS.B #LCDVo,&LCDVo_DIR \
37134 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
37135 \ ------------------------------\
37136 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37137 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37138 \ ------------------------------\
37139 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37140 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37141 \ ------------------------------\
37142 \ WDT interval init part \
37143 \ ------------------------------\
37144 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
37145 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
37146 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
37147 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
37148 \ ------------------------------\
37150 \ ------------------------------\
37151 BIS.B #RC5,&IR_IE \ enable RC5_Int
37152 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37153 \ ------------------------------\
37154 \ init interrupt vectors
37155 \ ------------------------------\
37156 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
37157 MOV #RC5_INT,&IR_Vec \ init interrupt vector
37158 \ ------------------------------\
37159 \ define LPM mode for ACCEPT \
37160 \ ------------------------------\
37161 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37162 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37163 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37165 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
37167 \ ------------------------------\
37169 \ ------------------------------\
37170 $03E8 20_US \ 1- wait 20 ms
37171 $03 TOP_LCD \ 2- send DB5=DB4=1
37172 $CD 20_US \ 3- wait 4,1 ms
37173 $03 TOP_LCD \ 4- send again DB5=DB4=1
37174 $5 20_US \ 5- wait 0,1 ms
37175 $03 TOP_LCD \ 6- send again again DB5=DB4=1
37176 $2 20_US \ wait 40 us = LCD cycle
37177 $02 TOP_LCD \ 7- send DB5=1 DB4=0
37178 $2 20_US \ wait 40 us = LCD cycle
37179 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37180 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
37181 LCD_Clear \ 10- "LCD_Clear"
37182 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
37183 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
37184 LCD_Clear \ 10- "LCD_Clear"
37185 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
37186 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
37188 ['] (CR) IS CR \ ' (CR) is CR
37189 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
37191 ." RC5toLCD is running. Type STOP to quit"
37192 \ NOECHO \ uncomment to run this app without terminal connexion
37193 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
37194 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
37198 : STOP \ stops multitasking, must to be used before downloading app
37199 ['] (WARM) IS WARM \ remove START app from FORTH init process
37200 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
37208 CODE MAX \ n1 n2 -- n3 signed maximum
37209 CMP @PSP,TOS \ n2-n1
37210 S< ?GOTO FW1 \ n2<n1
37216 CODE MIN \ n1 n2 -- n3 signed minimum
37217 CMP @PSP,TOS \ n2-n1
37218 S< ?GOTO BW1 \ n2<n1
37224 : U.R \ u n -- display u unsigned in n width (n >= 2)
37226 R> OVER - 0 MAX SPACES TYPE
37230 CODE 20_US \ n -- n * 20 us
37231 BEGIN \ 3 cycles loop + 6~
37232 \ MOV #5,W \ 3 MCLK = 1 MHz
37233 \ MOV #23,W \ 3 MCLK = 4 MHz
37234 MOV #51,W \ 3 MCLK = 8 MHz
37235 \ MOV #104,W \ 3 MCLK = 16 MHz
37236 \ MOV #158,W \ 3 MCLK = 24 MHz
37237 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
37247 CODE TOP_LCD \ LCD Sample
37248 \ \ if write : %xxxxWWWW --
37249 \ \ if read : -- %0000RRRR
37250 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
37251 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
37252 0= IF \ write LCD bits pattern
37253 AND.B #LCD_DB,TOS \
37254 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
37255 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37258 THEN \ read LCD bits pattern
37261 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37262 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
37263 AND.B #LCD_DB,TOS \
37268 CODE LCD_W \ byte -- write byte to LCD
37270 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
37271 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
37272 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
37273 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
37274 COLON \ high level word starts here
37275 TOP_LCD 2 20_US \ write high nibble first
37280 CODE LCD_WrC \ char -- Write Char
37281 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37286 CODE LCD_WrF \ func -- Write Fonction
37287 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37293 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
37298 $02 LCD_WrF 100 20_us
37302 \ : LCD_Entry_set $04 OR LCD_WrF ;
37304 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
37306 \ : LCD_Display_Shift $10 OR LCD_WrF ;
37308 \ : LCD_Fn_Set $20 OR LCD_WrF ;
37310 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
37312 \ : LCD_Goto $80 OR LCD_WrF ;
37314 \ CODE LCD_R \ -- byte read byte from LCD
37315 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
37316 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
37317 \ COLON \ starts a FORTH word
37318 \ TOP_LCD 2 20_us \ -- %0000HHHH
37319 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
37320 \ HI2LO \ switch from FORTH to assembler
37321 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
37322 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
37323 \ MOV @RSP+,IP \ restore IP saved by COLON
37328 \ CODE LCD_RdS \ -- status Read Status
37329 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37334 \ CODE LCD_RdC \ -- char Read Char
37335 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37340 \ -------------+------+------+------+------++---+---+---+---+---------+
37341 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
37342 \ -------------+------+------+------+------++---+---+---+---+---------+
37343 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
37344 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
37345 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
37346 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
37347 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
37348 \ -------------+------+------+------+------++---+---+---+---+---------+
37351 \ ******************************\
37352 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
37353 \ ******************************\
37354 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
37355 \ ------------------------------\
37356 \ define LPM mode for ACCEPT \
37357 \ ------------------------------\
37358 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37359 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37360 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37361 BIT.B #SW2,&SW2_IN \ test switch S2
37362 0= IF \ case of switch S2 pressed
37363 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
37365 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
37368 BIT.B #SW1,&SW1_IN \ test switch S1 input
37369 0= IF \ case of Switch S1 pressed
37370 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
37372 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
37376 RETI \ CPU is ON, GIE is OFF
37381 \ ------------------------------\
37382 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
37383 \ ******************************\
37384 ASM RC5_INT \ wake up on Px.RC5 change interrupt
37385 \ ******************************\
37386 \ \ in : SR(9)=old Toggle bit memory (ADD on)
37387 \ \ SMclock = 8|16|24 MHz
37388 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
37389 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
37390 \ \ SR(9)=new Toggle bit memory (ADD on)
37391 \ ------------------------------\
37392 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
37393 \ ------------------------------\
37394 \ define LPM mode for ACCEPT \
37395 \ ------------------------------\
37396 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37397 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37398 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37399 \ ------------------------------\
37400 \ RC5_FirstStartBitHalfCycle: \
37401 \ ------------------------------\
37402 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
37403 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
37404 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
37405 MOV #1778,X \ RC5_Period in us
37406 MOV #14,W \ count of loop
37408 \ ------------------------------\
37409 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
37410 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
37411 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
37412 \ RC5_Compute_3/4_Period: \ |
37413 RRUM #1,X \ X=1/2 cycle |
37417 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
37418 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
37420 \ ------------------------------\
37421 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
37422 \ ------------------------------\
37423 BIT.B #RC5,&IR_IN \ C_flag = IR bit
37424 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
37425 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37426 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37427 SUB #1,W \ decrement count loop
37428 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
37429 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37430 0<> WHILE \ ----> out of loop ----+
37431 \ RC5_compute_7/4_Time_out: \ |
37432 ADD X,Y \ | out of bound = 7/4 period
37433 \ RC5_WaitHalfCycleP1.2_IFG: \ |
37435 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
37436 0>= IF \ | if cycle time out of bound
37437 BIC #$30,&TA0CTL \ | stop timer_A0
37438 RETI \ | then quit to do nothing
37440 \ ------------------------------\ |
37441 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
37443 MOV &TA0R,X \ | | get new RC5_period value
37444 REPEAT \ ----> loop back --+ |
37445 \ ------------------------------\ |
37446 \ RC5_SampleEndOf: \ <---------------------+
37447 \ ------------------------------\
37448 BIC #$30,&TA0CTL \ stop timer_A0
37449 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
37450 \ ******************************\
37451 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
37452 \ ******************************\
37453 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
37454 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
37455 XOR IP,X \ (new XOR old) Toggle bit (13)
37456 BIT #BIT13,X \ X(13) = New_RC5_command
37457 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
37459 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
37460 \ ******************************\
37461 \ RC5_ComputeNewRC5word \
37462 \ ******************************\
37464 MOV &BASE,2(PSP) \ save variable BASE before use
37465 MOV TOS,0(PSP) \ save TOS before use
37466 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
37467 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
37468 \ ******************************\
37469 \ RC5_ComputeC6bit \
37470 \ ******************************\
37471 BIT #$4000,IP \ test /C6 bit in IP
37472 0= IF BIS #$40,TOS \ set C6 bit in S
37473 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
37474 \ ******************************\
37475 \ RC5_CommandByteIsDone \ RC5_code --
37476 \ ******************************\
37478 \ ------------------------------\
37479 \ Display IR_RC5 code \
37480 \ ------------------------------\
37481 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
37482 \ ------------------------------\
37483 LO2HI \ switch from assembler to FORTH
37484 ['] LCD_CLEAR IS CR \ redirects CR
37485 ['] LCD_WrC IS EMIT \ redirects EMIT
37486 $10 BASE ! \ change BASE to hexadecimal
37487 CR ." $" 2 U.R \ print IR_RC5 code
37488 ['] (CR) IS CR \ restore CR
37489 ['] (EMIT) IS EMIT \ restore EMIT
37490 HI2LO \ switch from FORTH to assembler
37491 \ ------------------------------\
37492 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
37493 \ ------------------------------\
37494 MOV @PSP+,&BASE \ restore variable BASE
37495 RETI \ CPU is ON, GIE is OFF
37500 \ ------------------------------\
37501 \ TB0CTL = %0000 0010 1001 0100\$3C0
37502 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37503 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37504 \ -- \ID input divider \ 10 = /4
37505 \ -- \MC Mode Control \ 01 = up to TB0CCR0
37506 \ - \TBCLR TimerB Clear
37509 \ --------------------------------\\
37510 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37511 \ -- \CM Capture Mode
37516 \ --- \OUTMOD \ 011 = set/reset
37522 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
37524 \ ------------------------------\
37525 \ set TimerB to make 50kHz PWM \
37526 \ ------------------------------\
37527 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37528 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
37529 \ ------------------------------\
37530 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37531 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
37532 \ ------------------------------\
37533 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37534 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
37535 \ ------------------------------\
37536 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37537 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
37538 \ ------------------------------\
37539 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37540 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
37541 \ ------------------------------\
37542 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
37543 \ ------------------------------\
37544 \ set TimerB to generate PWM for LCD_Vo
37545 \ ------------------------------\
37546 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
37547 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
37548 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37549 \ ------------------------------\
37550 BIS.B #LCDVo,&LCDVo_DIR \
37551 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
37552 \ ------------------------------\
37553 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37554 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37555 \ ------------------------------\
37556 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37557 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37558 \ ------------------------------\
37559 \ WDT interval init part \
37560 \ ------------------------------\
37561 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
37562 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
37563 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
37564 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
37565 \ ------------------------------\
37567 \ ------------------------------\
37568 BIS.B #RC5,&IR_IE \ enable RC5_Int
37569 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37570 \ ------------------------------\
37571 \ init interrupt vectors
37572 \ ------------------------------\
37573 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
37574 MOV #RC5_INT,&IR_Vec \ init interrupt vector
37575 \ ------------------------------\
37576 \ define LPM mode for ACCEPT \
37577 \ ------------------------------\
37578 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37579 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37580 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37582 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
37584 \ ------------------------------\
37586 \ ------------------------------\
37587 $03E8 20_US \ 1- wait 20 ms
37588 $03 TOP_LCD \ 2- send DB5=DB4=1
37589 $CD 20_US \ 3- wait 4,1 ms
37590 $03 TOP_LCD \ 4- send again DB5=DB4=1
37591 $5 20_US \ 5- wait 0,1 ms
37592 $03 TOP_LCD \ 6- send again again DB5=DB4=1
37593 $2 20_US \ wait 40 us = LCD cycle
37594 $02 TOP_LCD \ 7- send DB5=1 DB4=0
37595 $2 20_US \ wait 40 us = LCD cycle
37596 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37597 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
37598 LCD_Clear \ 10- "LCD_Clear"
37599 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
37600 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
37601 LCD_Clear \ 10- "LCD_Clear"
37602 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
37603 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
37605 ['] (CR) IS CR \ ' (CR) is CR
37606 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
37608 ." RC5toLCD is running. Type STOP to quit"
37609 \ NOECHO \ uncomment to run this app without terminal connexion
37610 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
37611 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
37615 : STOP \ stops multitasking, must to be used before downloading app
37616 ['] (WARM) IS WARM \ remove START app from FORTH init process
37617 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
37625 CODE MAX \ n1 n2 -- n3 signed maximum
37626 CMP @PSP,TOS \ n2-n1
37627 S< ?GOTO FW1 \ n2<n1
37633 CODE MIN \ n1 n2 -- n3 signed minimum
37634 CMP @PSP,TOS \ n2-n1
37635 S< ?GOTO BW1 \ n2<n1
37641 : U.R \ u n -- display u unsigned in n width (n >= 2)
37643 R> OVER - 0 MAX SPACES TYPE
37647 CODE 20_US \ n -- n * 20 us
37648 BEGIN \ 3 cycles loop + 6~
37649 \ MOV #5,W \ 3 MCLK = 1 MHz
37650 \ MOV #23,W \ 3 MCLK = 4 MHz
37651 MOV #51,W \ 3 MCLK = 8 MHz
37652 \ MOV #104,W \ 3 MCLK = 16 MHz
37653 \ MOV #158,W \ 3 MCLK = 24 MHz
37654 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
37664 CODE TOP_LCD \ LCD Sample
37665 \ \ if write : %xxxxWWWW --
37666 \ \ if read : -- %0000RRRR
37667 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
37668 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
37669 0= IF \ write LCD bits pattern
37670 AND.B #LCD_DB,TOS \
37671 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
37672 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37675 THEN \ read LCD bits pattern
37678 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37679 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
37680 AND.B #LCD_DB,TOS \
37685 CODE LCD_W \ byte -- write byte to LCD
37687 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
37688 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
37689 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
37690 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
37691 COLON \ high level word starts here
37692 TOP_LCD 2 20_US \ write high nibble first
37697 CODE LCD_WrC \ char -- Write Char
37698 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37703 CODE LCD_WrF \ func -- Write Fonction
37704 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37710 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
37715 $02 LCD_WrF 100 20_us
37719 \ : LCD_Entry_set $04 OR LCD_WrF ;
37721 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
37723 \ : LCD_Display_Shift $10 OR LCD_WrF ;
37725 \ : LCD_Fn_Set $20 OR LCD_WrF ;
37727 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
37729 \ : LCD_Goto $80 OR LCD_WrF ;
37731 \ CODE LCD_R \ -- byte read byte from LCD
37732 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
37733 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
37734 \ COLON \ starts a FORTH word
37735 \ TOP_LCD 2 20_us \ -- %0000HHHH
37736 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
37737 \ HI2LO \ switch from FORTH to assembler
37738 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
37739 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
37740 \ MOV @RSP+,IP \ restore IP saved by COLON
37745 \ CODE LCD_RdS \ -- status Read Status
37746 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37751 \ CODE LCD_RdC \ -- char Read Char
37752 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37757 \ -------------+------+------+------+------++---+---+---+---+---------+
37758 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
37759 \ -------------+------+------+------+------++---+---+---+---+---------+
37760 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
37761 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
37762 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
37763 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
37764 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
37765 \ -------------+------+------+------+------++---+---+---+---+---------+
37768 \ ******************************\
37769 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
37770 \ ******************************\
37771 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
37772 \ ------------------------------\
37773 \ define LPM mode for ACCEPT \
37774 \ ------------------------------\
37775 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37776 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37777 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37778 BIT.B #SW2,&SW2_IN \ test switch S2
37779 0= IF \ case of switch S2 pressed
37780 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
37782 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
37785 BIT.B #SW1,&SW1_IN \ test switch S1 input
37786 0= IF \ case of Switch S1 pressed
37787 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
37789 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
37793 RETI \ CPU is ON, GIE is OFF
37798 \ ------------------------------\
37799 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
37800 \ ******************************\
37801 ASM RC5_INT \ wake up on Px.RC5 change interrupt
37802 \ ******************************\
37803 \ \ in : SR(9)=old Toggle bit memory (ADD on)
37804 \ \ SMclock = 8|16|24 MHz
37805 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
37806 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
37807 \ \ SR(9)=new Toggle bit memory (ADD on)
37808 \ ------------------------------\
37809 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
37810 \ ------------------------------\
37811 \ define LPM mode for ACCEPT \
37812 \ ------------------------------\
37813 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37814 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37815 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37816 \ ------------------------------\
37817 \ RC5_FirstStartBitHalfCycle: \
37818 \ ------------------------------\
37819 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
37820 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
37821 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
37822 MOV #1778,X \ RC5_Period in us
37823 MOV #14,W \ count of loop
37825 \ ------------------------------\
37826 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
37827 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
37828 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
37829 \ RC5_Compute_3/4_Period: \ |
37830 RRUM #1,X \ X=1/2 cycle |
37834 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
37835 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
37837 \ ------------------------------\
37838 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
37839 \ ------------------------------\
37840 BIT.B #RC5,&IR_IN \ C_flag = IR bit
37841 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
37842 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37843 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37844 SUB #1,W \ decrement count loop
37845 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
37846 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37847 0<> WHILE \ ----> out of loop ----+
37848 \ RC5_compute_7/4_Time_out: \ |
37849 ADD X,Y \ | out of bound = 7/4 period
37850 \ RC5_WaitHalfCycleP1.2_IFG: \ |
37852 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
37853 0>= IF \ | if cycle time out of bound
37854 BIC #$30,&TA0CTL \ | stop timer_A0
37855 RETI \ | then quit to do nothing
37857 \ ------------------------------\ |
37858 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
37860 MOV &TA0R,X \ | | get new RC5_period value
37861 REPEAT \ ----> loop back --+ |
37862 \ ------------------------------\ |
37863 \ RC5_SampleEndOf: \ <---------------------+
37864 \ ------------------------------\
37865 BIC #$30,&TA0CTL \ stop timer_A0
37866 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
37867 \ ******************************\
37868 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
37869 \ ******************************\
37870 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
37871 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
37872 XOR IP,X \ (new XOR old) Toggle bit (13)
37873 BIT #BIT13,X \ X(13) = New_RC5_command
37874 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
37876 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
37877 \ ******************************\
37878 \ RC5_ComputeNewRC5word \
37879 \ ******************************\
37881 MOV &BASE,2(PSP) \ save variable BASE before use
37882 MOV TOS,0(PSP) \ save TOS before use
37883 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
37884 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
37885 \ ******************************\
37886 \ RC5_ComputeC6bit \
37887 \ ******************************\
37888 BIT #$4000,IP \ test /C6 bit in IP
37889 0= IF BIS #$40,TOS \ set C6 bit in S
37890 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
37891 \ ******************************\
37892 \ RC5_CommandByteIsDone \ RC5_code --
37893 \ ******************************\
37895 \ ------------------------------\
37896 \ Display IR_RC5 code \
37897 \ ------------------------------\
37898 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
37899 \ ------------------------------\
37900 LO2HI \ switch from assembler to FORTH
37901 ['] LCD_CLEAR IS CR \ redirects CR
37902 ['] LCD_WrC IS EMIT \ redirects EMIT
37903 $10 BASE ! \ change BASE to hexadecimal
37904 CR ." $" 2 U.R \ print IR_RC5 code
37905 ['] (CR) IS CR \ restore CR
37906 ['] (EMIT) IS EMIT \ restore EMIT
37907 HI2LO \ switch from FORTH to assembler
37908 \ ------------------------------\
37909 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
37910 \ ------------------------------\
37911 MOV @PSP+,&BASE \ restore variable BASE
37912 RETI \ CPU is ON, GIE is OFF
37917 \ ------------------------------\
37918 \ TB0CTL = %0000 0010 1001 0100\$3C0
37919 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37920 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37921 \ -- \ID input divider \ 10 = /4
37922 \ -- \MC Mode Control \ 01 = up to TB0CCR0
37923 \ - \TBCLR TimerB Clear
37926 \ --------------------------------\\
37927 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37928 \ -- \CM Capture Mode
37933 \ --- \OUTMOD \ 011 = set/reset
37939 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
37941 \ ------------------------------\
37942 \ set TimerB to make 50kHz PWM \
37943 \ ------------------------------\
37944 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37945 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
37946 \ ------------------------------\
37947 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37948 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
37949 \ ------------------------------\
37950 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37951 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
37952 \ ------------------------------\
37953 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37954 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
37955 \ ------------------------------\
37956 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37957 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
37958 \ ------------------------------\
37959 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
37960 \ ------------------------------\
37961 \ set TimerB to generate PWM for LCD_Vo
37962 \ ------------------------------\
37963 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
37964 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
37965 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37966 \ ------------------------------\
37967 BIS.B #LCDVo,&LCDVo_DIR \
37968 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
37969 \ ------------------------------\
37970 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37971 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37972 \ ------------------------------\
37973 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37974 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37975 \ ------------------------------\
37976 \ WDT interval init part \
37977 \ ------------------------------\
37978 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
37979 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
37980 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
37981 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
37982 \ ------------------------------\
37984 \ ------------------------------\
37985 BIS.B #RC5,&IR_IE \ enable RC5_Int
37986 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37987 \ ------------------------------\
37988 \ init interrupt vectors
37989 \ ------------------------------\
37990 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
37991 MOV #RC5_INT,&IR_Vec \ init interrupt vector
37992 \ ------------------------------\
37993 \ define LPM mode for ACCEPT \
37994 \ ------------------------------\
37995 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37996 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37997 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37999 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
38001 \ ------------------------------\
38003 \ ------------------------------\
38004 $03E8 20_US \ 1- wait 20 ms
38005 $03 TOP_LCD \ 2- send DB5=DB4=1
38006 $CD 20_US \ 3- wait 4,1 ms
38007 $03 TOP_LCD \ 4- send again DB5=DB4=1
38008 $5 20_US \ 5- wait 0,1 ms
38009 $03 TOP_LCD \ 6- send again again DB5=DB4=1
38010 $2 20_US \ wait 40 us = LCD cycle
38011 $02 TOP_LCD \ 7- send DB5=1 DB4=0
38012 $2 20_US \ wait 40 us = LCD cycle
38013 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38014 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38015 LCD_Clear \ 10- "LCD_Clear"
38016 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38017 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38018 LCD_Clear \ 10- "LCD_Clear"
38019 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38020 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38022 ['] (CR) IS CR \ ' (CR) is CR
38023 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
38025 ." RC5toLCD is running. Type STOP to quit"
38026 \ NOECHO \ uncomment to run this app without terminal connexion
38027 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
38028 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
38032 : STOP \ stops multitasking, must to be used before downloading app
38033 ['] (WARM) IS WARM \ remove START app from FORTH init process
38034 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
38042 CODE MAX \ n1 n2 -- n3 signed maximum
38043 CMP @PSP,TOS \ n2-n1
38044 S< ?GOTO FW1 \ n2<n1
38050 CODE MIN \ n1 n2 -- n3 signed minimum
38051 CMP @PSP,TOS \ n2-n1
38052 S< ?GOTO BW1 \ n2<n1
38058 : U.R \ u n -- display u unsigned in n width (n >= 2)
38060 R> OVER - 0 MAX SPACES TYPE
38064 CODE 20_US \ n -- n * 20 us
38065 BEGIN \ 3 cycles loop + 6~
38066 \ MOV #5,W \ 3 MCLK = 1 MHz
38067 \ MOV #23,W \ 3 MCLK = 4 MHz
38068 MOV #51,W \ 3 MCLK = 8 MHz
38069 \ MOV #104,W \ 3 MCLK = 16 MHz
38070 \ MOV #158,W \ 3 MCLK = 24 MHz
38071 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
38081 CODE TOP_LCD \ LCD Sample
38082 \ \ if write : %xxxxWWWW --
38083 \ \ if read : -- %0000RRRR
38084 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
38085 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
38086 0= IF \ write LCD bits pattern
38087 AND.B #LCD_DB,TOS \
38088 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
38089 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38092 THEN \ read LCD bits pattern
38095 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38096 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
38097 AND.B #LCD_DB,TOS \
38102 CODE LCD_W \ byte -- write byte to LCD
38104 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
38105 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
38106 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38107 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38108 COLON \ high level word starts here
38109 TOP_LCD 2 20_US \ write high nibble first
38114 CODE LCD_WrC \ char -- Write Char
38115 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38120 CODE LCD_WrF \ func -- Write Fonction
38121 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38127 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
38132 $02 LCD_WrF 100 20_us
38136 \ : LCD_Entry_set $04 OR LCD_WrF ;
38138 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
38140 \ : LCD_Display_Shift $10 OR LCD_WrF ;
38142 \ : LCD_Fn_Set $20 OR LCD_WrF ;
38144 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
38146 \ : LCD_Goto $80 OR LCD_WrF ;
38148 \ CODE LCD_R \ -- byte read byte from LCD
38149 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38150 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38151 \ COLON \ starts a FORTH word
38152 \ TOP_LCD 2 20_us \ -- %0000HHHH
38153 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
38154 \ HI2LO \ switch from FORTH to assembler
38155 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
38156 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
38157 \ MOV @RSP+,IP \ restore IP saved by COLON
38162 \ CODE LCD_RdS \ -- status Read Status
38163 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38168 \ CODE LCD_RdC \ -- char Read Char
38169 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38174 \ -------------+------+------+------+------++---+---+---+---+---------+
38175 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
38176 \ -------------+------+------+------+------++---+---+---+---+---------+
38177 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
38178 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
38179 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
38180 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
38181 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
38182 \ -------------+------+------+------+------++---+---+---+---+---------+
38185 \ ******************************\
38186 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
38187 \ ******************************\
38188 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
38189 \ ------------------------------\
38190 \ define LPM mode for ACCEPT \
38191 \ ------------------------------\
38192 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38193 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38194 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38195 BIT.B #SW2,&SW2_IN \ test switch S2
38196 0= IF \ case of switch S2 pressed
38197 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
38199 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
38202 BIT.B #SW1,&SW1_IN \ test switch S1 input
38203 0= IF \ case of Switch S1 pressed
38204 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
38206 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
38210 RETI \ CPU is ON, GIE is OFF
38215 \ ------------------------------\
38216 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
38217 \ ******************************\
38218 ASM RC5_INT \ wake up on Px.RC5 change interrupt
38219 \ ******************************\
38220 \ \ in : SR(9)=old Toggle bit memory (ADD on)
38221 \ \ SMclock = 8|16|24 MHz
38222 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
38223 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
38224 \ \ SR(9)=new Toggle bit memory (ADD on)
38225 \ ------------------------------\
38226 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
38227 \ ------------------------------\
38228 \ define LPM mode for ACCEPT \
38229 \ ------------------------------\
38230 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38231 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38232 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38233 \ ------------------------------\
38234 \ RC5_FirstStartBitHalfCycle: \
38235 \ ------------------------------\
38236 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
38237 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
38238 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
38239 MOV #1778,X \ RC5_Period in us
38240 MOV #14,W \ count of loop
38242 \ ------------------------------\
38243 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
38244 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
38245 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
38246 \ RC5_Compute_3/4_Period: \ |
38247 RRUM #1,X \ X=1/2 cycle |
38251 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
38252 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
38254 \ ------------------------------\
38255 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
38256 \ ------------------------------\
38257 BIT.B #RC5,&IR_IN \ C_flag = IR bit
38258 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
38259 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
38260 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
38261 SUB #1,W \ decrement count loop
38262 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
38263 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
38264 0<> WHILE \ ----> out of loop ----+
38265 \ RC5_compute_7/4_Time_out: \ |
38266 ADD X,Y \ | out of bound = 7/4 period
38267 \ RC5_WaitHalfCycleP1.2_IFG: \ |
38269 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
38270 0>= IF \ | if cycle time out of bound
38271 BIC #$30,&TA0CTL \ | stop timer_A0
38272 RETI \ | then quit to do nothing
38274 \ ------------------------------\ |
38275 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
38277 MOV &TA0R,X \ | | get new RC5_period value
38278 REPEAT \ ----> loop back --+ |
38279 \ ------------------------------\ |
38280 \ RC5_SampleEndOf: \ <---------------------+
38281 \ ------------------------------\
38282 BIC #$30,&TA0CTL \ stop timer_A0
38283 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
38284 \ ******************************\
38285 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
38286 \ ******************************\
38287 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
38288 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
38289 XOR IP,X \ (new XOR old) Toggle bit (13)
38290 BIT #BIT13,X \ X(13) = New_RC5_command
38291 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
38293 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
38294 \ ******************************\
38295 \ RC5_ComputeNewRC5word \
38296 \ ******************************\
38298 MOV &BASE,2(PSP) \ save variable BASE before use
38299 MOV TOS,0(PSP) \ save TOS before use
38300 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
38301 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
38302 \ ******************************\
38303 \ RC5_ComputeC6bit \
38304 \ ******************************\
38305 BIT #$4000,IP \ test /C6 bit in IP
38306 0= IF BIS #$40,TOS \ set C6 bit in S
38307 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
38308 \ ******************************\
38309 \ RC5_CommandByteIsDone \ RC5_code --
38310 \ ******************************\
38312 \ ------------------------------\
38313 \ Display IR_RC5 code \
38314 \ ------------------------------\
38315 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
38316 \ ------------------------------\
38317 LO2HI \ switch from assembler to FORTH
38318 ['] LCD_CLEAR IS CR \ redirects CR
38319 ['] LCD_WrC IS EMIT \ redirects EMIT
38320 $10 BASE ! \ change BASE to hexadecimal
38321 CR ." $" 2 U.R \ print IR_RC5 code
38322 ['] (CR) IS CR \ restore CR
38323 ['] (EMIT) IS EMIT \ restore EMIT
38324 HI2LO \ switch from FORTH to assembler
38325 \ ------------------------------\
38326 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
38327 \ ------------------------------\
38328 MOV @PSP+,&BASE \ restore variable BASE
38329 RETI \ CPU is ON, GIE is OFF
38334 \ ------------------------------\
38335 \ TB0CTL = %0000 0010 1001 0100\$3C0
38336 \ - - \CNTL Counter lentgh \ 00 = 16 bits
38337 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
38338 \ -- \ID input divider \ 10 = /4
38339 \ -- \MC Mode Control \ 01 = up to TB0CCR0
38340 \ - \TBCLR TimerB Clear
38343 \ --------------------------------\\
38344 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38345 \ -- \CM Capture Mode
38350 \ --- \OUTMOD \ 011 = set/reset
38356 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
38358 \ ------------------------------\
38359 \ set TimerB to make 50kHz PWM \
38360 \ ------------------------------\
38361 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
38362 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
38363 \ ------------------------------\
38364 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
38365 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
38366 \ ------------------------------\
38367 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38368 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
38369 \ ------------------------------\
38370 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38371 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
38372 \ ------------------------------\
38373 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38374 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
38375 \ ------------------------------\
38376 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
38377 \ ------------------------------\
38378 \ set TimerB to generate PWM for LCD_Vo
38379 \ ------------------------------\
38380 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
38381 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
38382 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38383 \ ------------------------------\
38384 BIS.B #LCDVo,&LCDVo_DIR \
38385 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
38386 \ ------------------------------\
38387 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38388 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38389 \ ------------------------------\
38390 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
38391 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
38392 \ ------------------------------\
38393 \ WDT interval init part \
38394 \ ------------------------------\
38395 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
38396 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
38397 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
38398 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
38399 \ ------------------------------\
38401 \ ------------------------------\
38402 BIS.B #RC5,&IR_IE \ enable RC5_Int
38403 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
38404 \ ------------------------------\
38405 \ init interrupt vectors
38406 \ ------------------------------\
38407 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
38408 MOV #RC5_INT,&IR_Vec \ init interrupt vector
38409 \ ------------------------------\
38410 \ define LPM mode for ACCEPT \
38411 \ ------------------------------\
38412 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38413 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38414 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38416 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
38418 \ ------------------------------\
38420 \ ------------------------------\
38421 $03E8 20_US \ 1- wait 20 ms
38422 $03 TOP_LCD \ 2- send DB5=DB4=1
38423 $CD 20_US \ 3- wait 4,1 ms
38424 $03 TOP_LCD \ 4- send again DB5=DB4=1
38425 $5 20_US \ 5- wait 0,1 ms
38426 $03 TOP_LCD \ 6- send again again DB5=DB4=1
38427 $2 20_US \ wait 40 us = LCD cycle
38428 $02 TOP_LCD \ 7- send DB5=1 DB4=0
38429 $2 20_US \ wait 40 us = LCD cycle
38430 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38431 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38432 LCD_Clear \ 10- "LCD_Clear"
38433 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38434 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38435 LCD_Clear \ 10- "LCD_Clear"
38436 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38437 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38439 ['] (CR) IS CR \ ' (CR) is CR
38440 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
38442 ." RC5toLCD is running. Type STOP to quit"
38443 \ NOECHO \ uncomment to run this app without terminal connexion
38444 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
38445 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
38449 : STOP \ stops multitasking, must to be used before downloading app
38450 ['] (WARM) IS WARM \ remove START app from FORTH init process
38451 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
38459 CODE MAX \ n1 n2 -- n3 signed maximum
38460 CMP @PSP,TOS \ n2-n1
38461 S< ?GOTO FW1 \ n2<n1
38467 CODE MIN \ n1 n2 -- n3 signed minimum
38468 CMP @PSP,TOS \ n2-n1
38469 S< ?GOTO BW1 \ n2<n1
38475 : U.R \ u n -- display u unsigned in n width (n >= 2)
38477 R> OVER - 0 MAX SPACES TYPE
38481 CODE 20_US \ n -- n * 20 us
38482 BEGIN \ 3 cycles loop + 6~
38483 \ MOV #5,W \ 3 MCLK = 1 MHz
38484 \ MOV #23,W \ 3 MCLK = 4 MHz
38485 MOV #51,W \ 3 MCLK = 8 MHz
38486 \ MOV #104,W \ 3 MCLK = 16 MHz
38487 \ MOV #158,W \ 3 MCLK = 24 MHz
38488 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
38498 CODE TOP_LCD \ LCD Sample
38499 \ \ if write : %xxxxWWWW --
38500 \ \ if read : -- %0000RRRR
38501 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
38502 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
38503 0= IF \ write LCD bits pattern
38504 AND.B #LCD_DB,TOS \
38505 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
38506 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38509 THEN \ read LCD bits pattern
38512 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38513 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
38514 AND.B #LCD_DB,TOS \
38519 CODE LCD_W \ byte -- write byte to LCD
38521 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
38522 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
38523 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38524 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38525 COLON \ high level word starts here
38526 TOP_LCD 2 20_US \ write high nibble first
38531 CODE LCD_WrC \ char -- Write Char
38532 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38537 CODE LCD_WrF \ func -- Write Fonction
38538 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38544 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
38549 $02 LCD_WrF 100 20_us
38553 \ : LCD_Entry_set $04 OR LCD_WrF ;
38555 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
38557 \ : LCD_Display_Shift $10 OR LCD_WrF ;
38559 \ : LCD_Fn_Set $20 OR LCD_WrF ;
38561 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
38563 \ : LCD_Goto $80 OR LCD_WrF ;
38565 \ CODE LCD_R \ -- byte read byte from LCD
38566 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38567 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38568 \ COLON \ starts a FORTH word
38569 \ TOP_LCD 2 20_us \ -- %0000HHHH
38570 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
38571 \ HI2LO \ switch from FORTH to assembler
38572 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
38573 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
38574 \ MOV @RSP+,IP \ restore IP saved by COLON
38579 \ CODE LCD_RdS \ -- status Read Status
38580 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38585 \ CODE LCD_RdC \ -- char Read Char
38586 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38591 \ -------------+------+------+------+------++---+---+---+---+---------+
38592 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
38593 \ -------------+------+------+------+------++---+---+---+---+---------+
38594 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
38595 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
38596 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
38597 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
38598 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
38599 \ -------------+------+------+------+------++---+---+---+---+---------+
38602 \ ******************************\
38603 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
38604 \ ******************************\
38605 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
38606 \ ------------------------------\
38607 \ define LPM mode for ACCEPT \
38608 \ ------------------------------\
38609 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38610 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38611 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38612 BIT.B #SW2,&SW2_IN \ test switch S2
38613 0= IF \ case of switch S2 pressed
38614 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
38616 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
38619 BIT.B #SW1,&SW1_IN \ test switch S1 input
38620 0= IF \ case of Switch S1 pressed
38621 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
38623 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
38627 RETI \ CPU is ON, GIE is OFF
38632 \ ------------------------------\
38633 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
38634 \ ******************************\
38635 ASM RC5_INT \ wake up on Px.RC5 change interrupt
38636 \ ******************************\
38637 \ \ in : SR(9)=old Toggle bit memory (ADD on)
38638 \ \ SMclock = 8|16|24 MHz
38639 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
38640 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
38641 \ \ SR(9)=new Toggle bit memory (ADD on)
38642 \ ------------------------------\
38643 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
38644 \ ------------------------------\
38645 \ define LPM mode for ACCEPT \
38646 \ ------------------------------\
38647 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38648 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38649 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38650 \ ------------------------------\
38651 \ RC5_FirstStartBitHalfCycle: \
38652 \ ------------------------------\
38653 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
38654 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
38655 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
38656 MOV #1778,X \ RC5_Period in us
38657 MOV #14,W \ count of loop
38659 \ ------------------------------\
38660 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
38661 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
38662 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
38663 \ RC5_Compute_3/4_Period: \ |
38664 RRUM #1,X \ X=1/2 cycle |
38668 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
38669 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
38671 \ ------------------------------\
38672 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
38673 \ ------------------------------\
38674 BIT.B #RC5,&IR_IN \ C_flag = IR bit
38675 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
38676 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
38677 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
38678 SUB #1,W \ decrement count loop
38679 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
38680 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
38681 0<> WHILE \ ----> out of loop ----+
38682 \ RC5_compute_7/4_Time_out: \ |
38683 ADD X,Y \ | out of bound = 7/4 period
38684 \ RC5_WaitHalfCycleP1.2_IFG: \ |
38686 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
38687 0>= IF \ | if cycle time out of bound
38688 BIC #$30,&TA0CTL \ | stop timer_A0
38689 RETI \ | then quit to do nothing
38691 \ ------------------------------\ |
38692 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
38694 MOV &TA0R,X \ | | get new RC5_period value
38695 REPEAT \ ----> loop back --+ |
38696 \ ------------------------------\ |
38697 \ RC5_SampleEndOf: \ <---------------------+
38698 \ ------------------------------\
38699 BIC #$30,&TA0CTL \ stop timer_A0
38700 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
38701 \ ******************************\
38702 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
38703 \ ******************************\
38704 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
38705 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
38706 XOR IP,X \ (new XOR old) Toggle bit (13)
38707 BIT #BIT13,X \ X(13) = New_RC5_command
38708 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
38710 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
38711 \ ******************************\
38712 \ RC5_ComputeNewRC5word \
38713 \ ******************************\
38715 MOV &BASE,2(PSP) \ save variable BASE before use
38716 MOV TOS,0(PSP) \ save TOS before use
38717 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
38718 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
38719 \ ******************************\
38720 \ RC5_ComputeC6bit \
38721 \ ******************************\
38722 BIT #$4000,IP \ test /C6 bit in IP
38723 0= IF BIS #$40,TOS \ set C6 bit in S
38724 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
38725 \ ******************************\
38726 \ RC5_CommandByteIsDone \ RC5_code --
38727 \ ******************************\
38729 \ ------------------------------\
38730 \ Display IR_RC5 code \
38731 \ ------------------------------\
38732 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
38733 \ ------------------------------\
38734 LO2HI \ switch from assembler to FORTH
38735 ['] LCD_CLEAR IS CR \ redirects CR
38736 ['] LCD_WrC IS EMIT \ redirects EMIT
38737 $10 BASE ! \ change BASE to hexadecimal
38738 CR ." $" 2 U.R \ print IR_RC5 code
38739 ['] (CR) IS CR \ restore CR
38740 ['] (EMIT) IS EMIT \ restore EMIT
38741 HI2LO \ switch from FORTH to assembler
38742 \ ------------------------------\
38743 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
38744 \ ------------------------------\
38745 MOV @PSP+,&BASE \ restore variable BASE
38746 RETI \ CPU is ON, GIE is OFF
38751 \ ------------------------------\
38752 \ TB0CTL = %0000 0010 1001 0100\$3C0
38753 \ - - \CNTL Counter lentgh \ 00 = 16 bits
38754 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
38755 \ -- \ID input divider \ 10 = /4
38756 \ -- \MC Mode Control \ 01 = up to TB0CCR0
38757 \ - \TBCLR TimerB Clear
38760 \ --------------------------------\\
38761 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38762 \ -- \CM Capture Mode
38767 \ --- \OUTMOD \ 011 = set/reset
38773 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
38775 \ ------------------------------\
38776 \ set TimerB to make 50kHz PWM \
38777 \ ------------------------------\
38778 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
38779 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
38780 \ ------------------------------\
38781 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
38782 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
38783 \ ------------------------------\
38784 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38785 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
38786 \ ------------------------------\
38787 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38788 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
38789 \ ------------------------------\
38790 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38791 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
38792 \ ------------------------------\
38793 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
38794 \ ------------------------------\
38795 \ set TimerB to generate PWM for LCD_Vo
38796 \ ------------------------------\
38797 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
38798 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
38799 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38800 \ ------------------------------\
38801 BIS.B #LCDVo,&LCDVo_DIR \
38802 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
38803 \ ------------------------------\
38804 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38805 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38806 \ ------------------------------\
38807 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
38808 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
38809 \ ------------------------------\
38810 \ WDT interval init part \
38811 \ ------------------------------\
38812 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
38813 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
38814 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
38815 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
38816 \ ------------------------------\
38818 \ ------------------------------\
38819 BIS.B #RC5,&IR_IE \ enable RC5_Int
38820 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
38821 \ ------------------------------\
38822 \ init interrupt vectors
38823 \ ------------------------------\
38824 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
38825 MOV #RC5_INT,&IR_Vec \ init interrupt vector
38826 \ ------------------------------\
38827 \ define LPM mode for ACCEPT \
38828 \ ------------------------------\
38829 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38830 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38831 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38833 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
38835 \ ------------------------------\
38837 \ ------------------------------\
38838 $03E8 20_US \ 1- wait 20 ms
38839 $03 TOP_LCD \ 2- send DB5=DB4=1
38840 $CD 20_US \ 3- wait 4,1 ms
38841 $03 TOP_LCD \ 4- send again DB5=DB4=1
38842 $5 20_US \ 5- wait 0,1 ms
38843 $03 TOP_LCD \ 6- send again again DB5=DB4=1
38844 $2 20_US \ wait 40 us = LCD cycle
38845 $02 TOP_LCD \ 7- send DB5=1 DB4=0
38846 $2 20_US \ wait 40 us = LCD cycle
38847 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38848 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38849 LCD_Clear \ 10- "LCD_Clear"
38850 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38851 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38852 LCD_Clear \ 10- "LCD_Clear"
38853 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38854 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38856 ['] (CR) IS CR \ ' (CR) is CR
38857 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
38859 ." RC5toLCD is running. Type STOP to quit"
38860 \ NOECHO \ uncomment to run this app without terminal connexion
38861 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
38862 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
38866 : STOP \ stops multitasking, must to be used before downloading app
38867 ['] (WARM) IS WARM \ remove START app from FORTH init process
38868 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
38876 CODE MAX \ n1 n2 -- n3 signed maximum
38877 CMP @PSP,TOS \ n2-n1
38878 S< ?GOTO FW1 \ n2<n1
38884 CODE MIN \ n1 n2 -- n3 signed minimum
38885 CMP @PSP,TOS \ n2-n1
38886 S< ?GOTO BW1 \ n2<n1
38892 : U.R \ u n -- display u unsigned in n width (n >= 2)
38894 R> OVER - 0 MAX SPACES TYPE
38898 CODE 20_US \ n -- n * 20 us
38899 BEGIN \ 3 cycles loop + 6~
38900 \ MOV #5,W \ 3 MCLK = 1 MHz
38901 \ MOV #23,W \ 3 MCLK = 4 MHz
38902 MOV #51,W \ 3 MCLK = 8 MHz
38903 \ MOV #104,W \ 3 MCLK = 16 MHz
38904 \ MOV #158,W \ 3 MCLK = 24 MHz
38905 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
38915 CODE TOP_LCD \ LCD Sample
38916 \ \ if write : %xxxxWWWW --
38917 \ \ if read : -- %0000RRRR
38918 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
38919 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
38920 0= IF \ write LCD bits pattern
38921 AND.B #LCD_DB,TOS \
38922 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
38923 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38926 THEN \ read LCD bits pattern
38929 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38930 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
38931 AND.B #LCD_DB,TOS \
38936 CODE LCD_W \ byte -- write byte to LCD
38938 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
38939 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
38940 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38941 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38942 COLON \ high level word starts here
38943 TOP_LCD 2 20_US \ write high nibble first
38948 CODE LCD_WrC \ char -- Write Char
38949 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38954 CODE LCD_WrF \ func -- Write Fonction
38955 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38961 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
38966 $02 LCD_WrF 100 20_us
38970 \ : LCD_Entry_set $04 OR LCD_WrF ;
38972 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
38974 \ : LCD_Display_Shift $10 OR LCD_WrF ;
38976 \ : LCD_Fn_Set $20 OR LCD_WrF ;
38978 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
38980 \ : LCD_Goto $80 OR LCD_WrF ;
38982 \ CODE LCD_R \ -- byte read byte from LCD
38983 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38984 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38985 \ COLON \ starts a FORTH word
38986 \ TOP_LCD 2 20_us \ -- %0000HHHH
38987 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
38988 \ HI2LO \ switch from FORTH to assembler
38989 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
38990 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
38991 \ MOV @RSP+,IP \ restore IP saved by COLON
38996 \ CODE LCD_RdS \ -- status Read Status
38997 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39002 \ CODE LCD_RdC \ -- char Read Char
39003 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39008 \ -------------+------+------+------+------++---+---+---+---+---------+
39009 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
39010 \ -------------+------+------+------+------++---+---+---+---+---------+
39011 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
39012 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
39013 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
39014 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
39015 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
39016 \ -------------+------+------+------+------++---+---+---+---+---------+
39019 \ ******************************\
39020 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39021 \ ******************************\
39022 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
39023 \ ------------------------------\
39024 \ define LPM mode for ACCEPT \
39025 \ ------------------------------\
39026 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39027 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39028 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39029 BIT.B #SW2,&SW2_IN \ test switch S2
39030 0= IF \ case of switch S2 pressed
39031 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
39033 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
39036 BIT.B #SW1,&SW1_IN \ test switch S1 input
39037 0= IF \ case of Switch S1 pressed
39038 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
39040 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
39044 RETI \ CPU is ON, GIE is OFF
39049 \ ------------------------------\
39050 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39051 \ ******************************\
39052 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39053 \ ******************************\
39054 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39055 \ \ SMclock = 8|16|24 MHz
39056 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
39057 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
39058 \ \ SR(9)=new Toggle bit memory (ADD on)
39059 \ ------------------------------\
39060 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
39061 \ ------------------------------\
39062 \ define LPM mode for ACCEPT \
39063 \ ------------------------------\
39064 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39065 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39066 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39067 \ ------------------------------\
39068 \ RC5_FirstStartBitHalfCycle: \
39069 \ ------------------------------\
39070 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
39071 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
39072 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
39073 MOV #1778,X \ RC5_Period in us
39074 MOV #14,W \ count of loop
39076 \ ------------------------------\
39077 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
39078 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
39079 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
39080 \ RC5_Compute_3/4_Period: \ |
39081 RRUM #1,X \ X=1/2 cycle |
39085 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
39086 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
39088 \ ------------------------------\
39089 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
39090 \ ------------------------------\
39091 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39092 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
39093 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39094 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39095 SUB #1,W \ decrement count loop
39096 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
39097 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39098 0<> WHILE \ ----> out of loop ----+
39099 \ RC5_compute_7/4_Time_out: \ |
39100 ADD X,Y \ | out of bound = 7/4 period
39101 \ RC5_WaitHalfCycleP1.2_IFG: \ |
39103 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
39104 0>= IF \ | if cycle time out of bound
39105 BIC #$30,&TA0CTL \ | stop timer_A0
39106 RETI \ | then quit to do nothing
39108 \ ------------------------------\ |
39109 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
39111 MOV &TA0R,X \ | | get new RC5_period value
39112 REPEAT \ ----> loop back --+ |
39113 \ ------------------------------\ |
39114 \ RC5_SampleEndOf: \ <---------------------+
39115 \ ------------------------------\
39116 BIC #$30,&TA0CTL \ stop timer_A0
39117 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
39118 \ ******************************\
39119 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
39120 \ ******************************\
39121 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
39122 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
39123 XOR IP,X \ (new XOR old) Toggle bit (13)
39124 BIT #BIT13,X \ X(13) = New_RC5_command
39125 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
39127 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
39128 \ ******************************\
39129 \ RC5_ComputeNewRC5word \
39130 \ ******************************\
39132 MOV &BASE,2(PSP) \ save variable BASE before use
39133 MOV TOS,0(PSP) \ save TOS before use
39134 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
39135 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
39136 \ ******************************\
39137 \ RC5_ComputeC6bit \
39138 \ ******************************\
39139 BIT #$4000,IP \ test /C6 bit in IP
39140 0= IF BIS #$40,TOS \ set C6 bit in S
39141 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
39142 \ ******************************\
39143 \ RC5_CommandByteIsDone \ RC5_code --
39144 \ ******************************\
39146 \ ------------------------------\
39147 \ Display IR_RC5 code \
39148 \ ------------------------------\
39149 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
39150 \ ------------------------------\
39151 LO2HI \ switch from assembler to FORTH
39152 ['] LCD_CLEAR IS CR \ redirects CR
39153 ['] LCD_WrC IS EMIT \ redirects EMIT
39154 $10 BASE ! \ change BASE to hexadecimal
39155 CR ." $" 2 U.R \ print IR_RC5 code
39156 ['] (CR) IS CR \ restore CR
39157 ['] (EMIT) IS EMIT \ restore EMIT
39158 HI2LO \ switch from FORTH to assembler
39159 \ ------------------------------\
39160 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
39161 \ ------------------------------\
39162 MOV @PSP+,&BASE \ restore variable BASE
39163 RETI \ CPU is ON, GIE is OFF
39168 \ ------------------------------\
39169 \ TB0CTL = %0000 0010 1001 0100\$3C0
39170 \ - - \CNTL Counter lentgh \ 00 = 16 bits
39171 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
39172 \ -- \ID input divider \ 10 = /4
39173 \ -- \MC Mode Control \ 01 = up to TB0CCR0
39174 \ - \TBCLR TimerB Clear
39177 \ --------------------------------\\
39178 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
39179 \ -- \CM Capture Mode
39184 \ --- \OUTMOD \ 011 = set/reset
39190 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
39192 \ ------------------------------\
39193 \ set TimerB to make 50kHz PWM \
39194 \ ------------------------------\
39195 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
39196 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
39197 \ ------------------------------\
39198 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
39199 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
39200 \ ------------------------------\
39201 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39202 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
39203 \ ------------------------------\
39204 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39205 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
39206 \ ------------------------------\
39207 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39208 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
39209 \ ------------------------------\
39210 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
39211 \ ------------------------------\
39212 \ set TimerB to generate PWM for LCD_Vo
39213 \ ------------------------------\
39214 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
39215 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
39216 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
39217 \ ------------------------------\
39218 BIS.B #LCDVo,&LCDVo_DIR \
39219 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
39220 \ ------------------------------\
39221 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
39222 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
39223 \ ------------------------------\
39224 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
39225 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
39226 \ ------------------------------\
39227 \ WDT interval init part \
39228 \ ------------------------------\
39229 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
39230 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
39231 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
39232 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
39233 \ ------------------------------\
39235 \ ------------------------------\
39236 BIS.B #RC5,&IR_IE \ enable RC5_Int
39237 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
39238 \ ------------------------------\
39239 \ init interrupt vectors
39240 \ ------------------------------\
39241 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
39242 MOV #RC5_INT,&IR_Vec \ init interrupt vector
39243 \ ------------------------------\
39244 \ define LPM mode for ACCEPT \
39245 \ ------------------------------\
39246 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39247 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39248 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39250 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
39252 \ ------------------------------\
39254 \ ------------------------------\
39255 $03E8 20_US \ 1- wait 20 ms
39256 $03 TOP_LCD \ 2- send DB5=DB4=1
39257 $CD 20_US \ 3- wait 4,1 ms
39258 $03 TOP_LCD \ 4- send again DB5=DB4=1
39259 $5 20_US \ 5- wait 0,1 ms
39260 $03 TOP_LCD \ 6- send again again DB5=DB4=1
39261 $2 20_US \ wait 40 us = LCD cycle
39262 $02 TOP_LCD \ 7- send DB5=1 DB4=0
39263 $2 20_US \ wait 40 us = LCD cycle
39264 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
39265 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
39266 LCD_Clear \ 10- "LCD_Clear"
39267 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
39268 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
39269 LCD_Clear \ 10- "LCD_Clear"
39270 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
39271 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
39273 ['] (CR) IS CR \ ' (CR) is CR
39274 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
39276 ." RC5toLCD is running. Type STOP to quit"
39277 \ NOECHO \ uncomment to run this app without terminal connexion
39278 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
39279 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
39283 : STOP \ stops multitasking, must to be used before downloading app
39284 ['] (WARM) IS WARM \ remove START app from FORTH init process
39285 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
39293 CODE MAX \ n1 n2 -- n3 signed maximum
39294 CMP @PSP,TOS \ n2-n1
39295 S< ?GOTO FW1 \ n2<n1
39301 CODE MIN \ n1 n2 -- n3 signed minimum
39302 CMP @PSP,TOS \ n2-n1
39303 S< ?GOTO BW1 \ n2<n1
39309 : U.R \ u n -- display u unsigned in n width (n >= 2)
39311 R> OVER - 0 MAX SPACES TYPE
39315 CODE 20_US \ n -- n * 20 us
39316 BEGIN \ 3 cycles loop + 6~
39317 \ MOV #5,W \ 3 MCLK = 1 MHz
39318 \ MOV #23,W \ 3 MCLK = 4 MHz
39319 MOV #51,W \ 3 MCLK = 8 MHz
39320 \ MOV #104,W \ 3 MCLK = 16 MHz
39321 \ MOV #158,W \ 3 MCLK = 24 MHz
39322 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
39332 CODE TOP_LCD \ LCD Sample
39333 \ \ if write : %xxxxWWWW --
39334 \ \ if read : -- %0000RRRR
39335 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
39336 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
39337 0= IF \ write LCD bits pattern
39338 AND.B #LCD_DB,TOS \
39339 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
39340 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39343 THEN \ read LCD bits pattern
39346 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39347 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
39348 AND.B #LCD_DB,TOS \
39353 CODE LCD_W \ byte -- write byte to LCD
39355 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
39356 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
39357 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
39358 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
39359 COLON \ high level word starts here
39360 TOP_LCD 2 20_US \ write high nibble first
39365 CODE LCD_WrC \ char -- Write Char
39366 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39371 CODE LCD_WrF \ func -- Write Fonction
39372 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39378 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
39383 $02 LCD_WrF 100 20_us
39387 \ : LCD_Entry_set $04 OR LCD_WrF ;
39389 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
39391 \ : LCD_Display_Shift $10 OR LCD_WrF ;
39393 \ : LCD_Fn_Set $20 OR LCD_WrF ;
39395 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
39397 \ : LCD_Goto $80 OR LCD_WrF ;
39399 \ CODE LCD_R \ -- byte read byte from LCD
39400 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
39401 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
39402 \ COLON \ starts a FORTH word
39403 \ TOP_LCD 2 20_us \ -- %0000HHHH
39404 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
39405 \ HI2LO \ switch from FORTH to assembler
39406 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
39407 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
39408 \ MOV @RSP+,IP \ restore IP saved by COLON
39413 \ CODE LCD_RdS \ -- status Read Status
39414 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39419 \ CODE LCD_RdC \ -- char Read Char
39420 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39425 \ -------------+------+------+------+------++---+---+---+---+---------+
39426 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
39427 \ -------------+------+------+------+------++---+---+---+---+---------+
39428 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
39429 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
39430 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
39431 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
39432 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
39433 \ -------------+------+------+------+------++---+---+---+---+---------+
39436 \ ******************************\
39437 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39438 \ ******************************\
39439 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
39440 \ ------------------------------\
39441 \ define LPM mode for ACCEPT \
39442 \ ------------------------------\
39443 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39444 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39445 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39446 BIT.B #SW2,&SW2_IN \ test switch S2
39447 0= IF \ case of switch S2 pressed
39448 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
39450 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
39453 BIT.B #SW1,&SW1_IN \ test switch S1 input
39454 0= IF \ case of Switch S1 pressed
39455 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
39457 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
39461 RETI \ CPU is ON, GIE is OFF
39466 \ ------------------------------\
39467 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39468 \ ******************************\
39469 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39470 \ ******************************\
39471 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39472 \ \ SMclock = 8|16|24 MHz
39473 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
39474 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
39475 \ \ SR(9)=new Toggle bit memory (ADD on)
39476 \ ------------------------------\
39477 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
39478 \ ------------------------------\
39479 \ define LPM mode for ACCEPT \
39480 \ ------------------------------\
39481 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39482 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39483 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39484 \ ------------------------------\
39485 \ RC5_FirstStartBitHalfCycle: \
39486 \ ------------------------------\
39487 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
39488 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
39489 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
39490 MOV #1778,X \ RC5_Period in us
39491 MOV #14,W \ count of loop
39493 \ ------------------------------\
39494 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
39495 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
39496 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
39497 \ RC5_Compute_3/4_Period: \ |
39498 RRUM #1,X \ X=1/2 cycle |
39502 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
39503 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
39505 \ ------------------------------\
39506 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
39507 \ ------------------------------\
39508 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39509 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
39510 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39511 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39512 SUB #1,W \ decrement count loop
39513 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
39514 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39515 0<> WHILE \ ----> out of loop ----+
39516 \ RC5_compute_7/4_Time_out: \ |
39517 ADD X,Y \ | out of bound = 7/4 period
39518 \ RC5_WaitHalfCycleP1.2_IFG: \ |
39520 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
39521 0>= IF \ | if cycle time out of bound
39522 BIC #$30,&TA0CTL \ | stop timer_A0
39523 RETI \ | then quit to do nothing
39525 \ ------------------------------\ |
39526 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
39528 MOV &TA0R,X \ | | get new RC5_period value
39529 REPEAT \ ----> loop back --+ |
39530 \ ------------------------------\ |
39531 \ RC5_SampleEndOf: \ <---------------------+
39532 \ ------------------------------\
39533 BIC #$30,&TA0CTL \ stop timer_A0
39534 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
39535 \ ******************************\
39536 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
39537 \ ******************************\
39538 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
39539 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
39540 XOR IP,X \ (new XOR old) Toggle bit (13)
39541 BIT #BIT13,X \ X(13) = New_RC5_command
39542 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
39544 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
39545 \ ******************************\
39546 \ RC5_ComputeNewRC5word \
39547 \ ******************************\
39549 MOV &BASE,2(PSP) \ save variable BASE before use
39550 MOV TOS,0(PSP) \ save TOS before use
39551 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
39552 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
39553 \ ******************************\
39554 \ RC5_ComputeC6bit \
39555 \ ******************************\
39556 BIT #$4000,IP \ test /C6 bit in IP
39557 0= IF BIS #$40,TOS \ set C6 bit in S
39558 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
39559 \ ******************************\
39560 \ RC5_CommandByteIsDone \ RC5_code --
39561 \ ******************************\
39563 \ ------------------------------\
39564 \ Display IR_RC5 code \
39565 \ ------------------------------\
39566 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
39567 \ ------------------------------\
39568 LO2HI \ switch from assembler to FORTH
39569 ['] LCD_CLEAR IS CR \ redirects CR
39570 ['] LCD_WrC IS EMIT \ redirects EMIT
39571 $10 BASE ! \ change BASE to hexadecimal
39572 CR ." $" 2 U.R \ print IR_RC5 code
39573 ['] (CR) IS CR \ restore CR
39574 ['] (EMIT) IS EMIT \ restore EMIT
39575 HI2LO \ switch from FORTH to assembler
39576 \ ------------------------------\
39577 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
39578 \ ------------------------------\
39579 MOV @PSP+,&BASE \ restore variable BASE
39580 RETI \ CPU is ON, GIE is OFF
39585 \ ------------------------------\
39586 \ TB0CTL = %0000 0010 1001 0100\$3C0
39587 \ - - \CNTL Counter lentgh \ 00 = 16 bits
39588 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
39589 \ -- \ID input divider \ 10 = /4
39590 \ -- \MC Mode Control \ 01 = up to TB0CCR0
39591 \ - \TBCLR TimerB Clear
39594 \ --------------------------------\\
39595 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
39596 \ -- \CM Capture Mode
39601 \ --- \OUTMOD \ 011 = set/reset
39607 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
39609 \ ------------------------------\
39610 \ set TimerB to make 50kHz PWM \
39611 \ ------------------------------\
39612 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
39613 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
39614 \ ------------------------------\
39615 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
39616 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
39617 \ ------------------------------\
39618 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39619 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
39620 \ ------------------------------\
39621 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39622 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
39623 \ ------------------------------\
39624 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39625 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
39626 \ ------------------------------\
39627 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
39628 \ ------------------------------\
39629 \ set TimerB to generate PWM for LCD_Vo
39630 \ ------------------------------\
39631 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
39632 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
39633 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
39634 \ ------------------------------\
39635 BIS.B #LCDVo,&LCDVo_DIR \
39636 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
39637 \ ------------------------------\
39638 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
39639 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
39640 \ ------------------------------\
39641 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
39642 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
39643 \ ------------------------------\
39644 \ WDT interval init part \
39645 \ ------------------------------\
39646 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
39647 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
39648 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
39649 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
39650 \ ------------------------------\
39652 \ ------------------------------\
39653 BIS.B #RC5,&IR_IE \ enable RC5_Int
39654 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
39655 \ ------------------------------\
39656 \ init interrupt vectors
39657 \ ------------------------------\
39658 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
39659 MOV #RC5_INT,&IR_Vec \ init interrupt vector
39660 \ ------------------------------\
39661 \ define LPM mode for ACCEPT \
39662 \ ------------------------------\
39663 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39664 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39665 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39667 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
39669 \ ------------------------------\
39671 \ ------------------------------\
39672 $03E8 20_US \ 1- wait 20 ms
39673 $03 TOP_LCD \ 2- send DB5=DB4=1
39674 $CD 20_US \ 3- wait 4,1 ms
39675 $03 TOP_LCD \ 4- send again DB5=DB4=1
39676 $5 20_US \ 5- wait 0,1 ms
39677 $03 TOP_LCD \ 6- send again again DB5=DB4=1
39678 $2 20_US \ wait 40 us = LCD cycle
39679 $02 TOP_LCD \ 7- send DB5=1 DB4=0
39680 $2 20_US \ wait 40 us = LCD cycle
39681 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
39682 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
39683 LCD_Clear \ 10- "LCD_Clear"
39684 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
39685 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
39686 LCD_Clear \ 10- "LCD_Clear"
39687 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
39688 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
39690 ['] (CR) IS CR \ ' (CR) is CR
39691 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
39693 ." RC5toLCD is running. Type STOP to quit"
39694 \ NOECHO \ uncomment to run this app without terminal connexion
39695 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
39696 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
39700 : STOP \ stops multitasking, must to be used before downloading app
39701 ['] (WARM) IS WARM \ remove START app from FORTH init process
39702 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
39710 CODE MAX \ n1 n2 -- n3 signed maximum
39711 CMP @PSP,TOS \ n2-n1
39712 S< ?GOTO FW1 \ n2<n1
39718 CODE MIN \ n1 n2 -- n3 signed minimum
39719 CMP @PSP,TOS \ n2-n1
39720 S< ?GOTO BW1 \ n2<n1
39726 : U.R \ u n -- display u unsigned in n width (n >= 2)
39728 R> OVER - 0 MAX SPACES TYPE
39732 CODE 20_US \ n -- n * 20 us
39733 BEGIN \ 3 cycles loop + 6~
39734 \ MOV #5,W \ 3 MCLK = 1 MHz
39735 \ MOV #23,W \ 3 MCLK = 4 MHz
39736 MOV #51,W \ 3 MCLK = 8 MHz
39737 \ MOV #104,W \ 3 MCLK = 16 MHz
39738 \ MOV #158,W \ 3 MCLK = 24 MHz
39739 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
39749 CODE TOP_LCD \ LCD Sample
39750 \ \ if write : %xxxxWWWW --
39751 \ \ if read : -- %0000RRRR
39752 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
39753 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
39754 0= IF \ write LCD bits pattern
39755 AND.B #LCD_DB,TOS \
39756 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
39757 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39760 THEN \ read LCD bits pattern
39763 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39764 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
39765 AND.B #LCD_DB,TOS \
39770 CODE LCD_W \ byte -- write byte to LCD
39772 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
39773 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
39774 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
39775 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
39776 COLON \ high level word starts here
39777 TOP_LCD 2 20_US \ write high nibble first
39782 CODE LCD_WrC \ char -- Write Char
39783 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39788 CODE LCD_WrF \ func -- Write Fonction
39789 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39795 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
39800 $02 LCD_WrF 100 20_us
39804 \ : LCD_Entry_set $04 OR LCD_WrF ;
39806 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
39808 \ : LCD_Display_Shift $10 OR LCD_WrF ;
39810 \ : LCD_Fn_Set $20 OR LCD_WrF ;
39812 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
39814 \ : LCD_Goto $80 OR LCD_WrF ;
39816 \ CODE LCD_R \ -- byte read byte from LCD
39817 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
39818 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
39819 \ COLON \ starts a FORTH word
39820 \ TOP_LCD 2 20_us \ -- %0000HHHH
39821 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
39822 \ HI2LO \ switch from FORTH to assembler
39823 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
39824 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
39825 \ MOV @RSP+,IP \ restore IP saved by COLON
39830 \ CODE LCD_RdS \ -- status Read Status
39831 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39836 \ CODE LCD_RdC \ -- char Read Char
39837 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39842 \ -------------+------+------+------+------++---+---+---+---+---------+
39843 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
39844 \ -------------+------+------+------+------++---+---+---+---+---------+
39845 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
39846 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
39847 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
39848 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
39849 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
39850 \ -------------+------+------+------+------++---+---+---+---+---------+
39853 \ ******************************\
39854 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39855 \ ******************************\
39856 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
39857 \ ------------------------------\
39858 \ define LPM mode for ACCEPT \
39859 \ ------------------------------\
39860 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39861 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39862 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39863 BIT.B #SW2,&SW2_IN \ test switch S2
39864 0= IF \ case of switch S2 pressed
39865 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
39867 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
39870 BIT.B #SW1,&SW1_IN \ test switch S1 input
39871 0= IF \ case of Switch S1 pressed
39872 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
39874 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
39878 RETI \ CPU is ON, GIE is OFF
39883 \ ------------------------------\
39884 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39885 \ ******************************\
39886 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39887 \ ******************************\
39888 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39889 \ \ SMclock = 8|16|24 MHz
39890 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
39891 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
39892 \ \ SR(9)=new Toggle bit memory (ADD on)
39893 \ ------------------------------\
39894 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
39895 \ ------------------------------\
39896 \ define LPM mode for ACCEPT \
39897 \ ------------------------------\
39898 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39899 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39900 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39901 \ ------------------------------\
39902 \ RC5_FirstStartBitHalfCycle: \
39903 \ ------------------------------\
39904 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
39905 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
39906 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
39907 MOV #1778,X \ RC5_Period in us
39908 MOV #14,W \ count of loop
39910 \ ------------------------------\
39911 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
39912 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
39913 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
39914 \ RC5_Compute_3/4_Period: \ |
39915 RRUM #1,X \ X=1/2 cycle |
39919 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
39920 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
39922 \ ------------------------------\
39923 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
39924 \ ------------------------------\
39925 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39926 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
39927 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39928 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39929 SUB #1,W \ decrement count loop
39930 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
39931 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39932 0<> WHILE \ ----> out of loop ----+
39933 \ RC5_compute_7/4_Time_out: \ |
39934 ADD X,Y \ | out of bound = 7/4 period
39935 \ RC5_WaitHalfCycleP1.2_IFG: \ |
39937 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
39938 0>= IF \ | if cycle time out of bound
39939 BIC #$30,&TA0CTL \ | stop timer_A0
39940 RETI \ | then quit to do nothing
39942 \ ------------------------------\ |
39943 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
39945 MOV &TA0R,X \ | | get new RC5_period value
39946 REPEAT \ ----> loop back --+ |
39947 \ ------------------------------\ |
39948 \ RC5_SampleEndOf: \ <---------------------+
39949 \ ------------------------------\
39950 BIC #$30,&TA0CTL \ stop timer_A0
39951 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
39952 \ ******************************\
39953 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
39954 \ ******************************\
39955 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
39956 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
39957 XOR IP,X \ (new XOR old) Toggle bit (13)
39958 BIT #BIT13,X \ X(13) = New_RC5_command
39959 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
39961 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
39962 \ ******************************\
39963 \ RC5_ComputeNewRC5word \
39964 \ ******************************\
39966 MOV &BASE,2(PSP) \ save variable BASE before use
39967 MOV TOS,0(PSP) \ save TOS before use
39968 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
39969 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
39970 \ ******************************\
39971 \ RC5_ComputeC6bit \
39972 \ ******************************\
39973 BIT #$4000,IP \ test /C6 bit in IP
39974 0= IF BIS #$40,TOS \ set C6 bit in S
39975 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
39976 \ ******************************\
39977 \ RC5_CommandByteIsDone \ RC5_code --
39978 \ ******************************\
39980 \ ------------------------------\
39981 \ Display IR_RC5 code \
39982 \ ------------------------------\
39983 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
39984 \ ------------------------------\
39985 LO2HI \ switch from assembler to FORTH
39986 ['] LCD_CLEAR IS CR \ redirects CR
39987 ['] LCD_WrC IS EMIT \ redirects EMIT
39988 $10 BASE ! \ change BASE to hexadecimal
39989 CR ." $" 2 U.R \ print IR_RC5 code
39990 ['] (CR) IS CR \ restore CR
39991 ['] (EMIT) IS EMIT \ restore EMIT
39992 HI2LO \ switch from FORTH to assembler
39993 \ ------------------------------\
39994 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
39995 \ ------------------------------\
39996 MOV @PSP+,&BASE \ restore variable BASE
39997 RETI \ CPU is ON, GIE is OFF
40002 \ ------------------------------\
40003 \ TB0CTL = %0000 0010 1001 0100\$3C0
40004 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40005 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40006 \ -- \ID input divider \ 10 = /4
40007 \ -- \MC Mode Control \ 01 = up to TB0CCR0
40008 \ - \TBCLR TimerB Clear
40011 \ --------------------------------\\
40012 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40013 \ -- \CM Capture Mode
40018 \ --- \OUTMOD \ 011 = set/reset
40024 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
40026 \ ------------------------------\
40027 \ set TimerB to make 50kHz PWM \
40028 \ ------------------------------\
40029 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40030 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
40031 \ ------------------------------\
40032 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40033 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
40034 \ ------------------------------\
40035 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40036 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
40037 \ ------------------------------\
40038 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40039 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
40040 \ ------------------------------\
40041 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40042 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
40043 \ ------------------------------\
40044 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
40045 \ ------------------------------\
40046 \ set TimerB to generate PWM for LCD_Vo
40047 \ ------------------------------\
40048 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
40049 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
40050 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40051 \ ------------------------------\
40052 BIS.B #LCDVo,&LCDVo_DIR \
40053 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
40054 \ ------------------------------\
40055 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40056 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40057 \ ------------------------------\
40058 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40059 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40060 \ ------------------------------\
40061 \ WDT interval init part \
40062 \ ------------------------------\
40063 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
40064 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
40065 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
40066 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
40067 \ ------------------------------\
40069 \ ------------------------------\
40070 BIS.B #RC5,&IR_IE \ enable RC5_Int
40071 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40072 \ ------------------------------\
40073 \ init interrupt vectors
40074 \ ------------------------------\
40075 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
40076 MOV #RC5_INT,&IR_Vec \ init interrupt vector
40077 \ ------------------------------\
40078 \ define LPM mode for ACCEPT \
40079 \ ------------------------------\
40080 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40081 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40082 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40084 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
40086 \ ------------------------------\
40088 \ ------------------------------\
40089 $03E8 20_US \ 1- wait 20 ms
40090 $03 TOP_LCD \ 2- send DB5=DB4=1
40091 $CD 20_US \ 3- wait 4,1 ms
40092 $03 TOP_LCD \ 4- send again DB5=DB4=1
40093 $5 20_US \ 5- wait 0,1 ms
40094 $03 TOP_LCD \ 6- send again again DB5=DB4=1
40095 $2 20_US \ wait 40 us = LCD cycle
40096 $02 TOP_LCD \ 7- send DB5=1 DB4=0
40097 $2 20_US \ wait 40 us = LCD cycle
40098 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40099 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40100 LCD_Clear \ 10- "LCD_Clear"
40101 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40102 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40103 LCD_Clear \ 10- "LCD_Clear"
40104 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40105 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40107 ['] (CR) IS CR \ ' (CR) is CR
40108 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
40110 ." RC5toLCD is running. Type STOP to quit"
40111 \ NOECHO \ uncomment to run this app without terminal connexion
40112 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
40113 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
40117 : STOP \ stops multitasking, must to be used before downloading app
40118 ['] (WARM) IS WARM \ remove START app from FORTH init process
40119 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
40127 CODE MAX \ n1 n2 -- n3 signed maximum
40128 CMP @PSP,TOS \ n2-n1
40129 S< ?GOTO FW1 \ n2<n1
40135 CODE MIN \ n1 n2 -- n3 signed minimum
40136 CMP @PSP,TOS \ n2-n1
40137 S< ?GOTO BW1 \ n2<n1
40143 : U.R \ u n -- display u unsigned in n width (n >= 2)
40145 R> OVER - 0 MAX SPACES TYPE
40149 CODE 20_US \ n -- n * 20 us
40150 BEGIN \ 3 cycles loop + 6~
40151 \ MOV #5,W \ 3 MCLK = 1 MHz
40152 \ MOV #23,W \ 3 MCLK = 4 MHz
40153 MOV #51,W \ 3 MCLK = 8 MHz
40154 \ MOV #104,W \ 3 MCLK = 16 MHz
40155 \ MOV #158,W \ 3 MCLK = 24 MHz
40156 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
40166 CODE TOP_LCD \ LCD Sample
40167 \ \ if write : %xxxxWWWW --
40168 \ \ if read : -- %0000RRRR
40169 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
40170 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
40171 0= IF \ write LCD bits pattern
40172 AND.B #LCD_DB,TOS \
40173 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
40174 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40177 THEN \ read LCD bits pattern
40180 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40181 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
40182 AND.B #LCD_DB,TOS \
40187 CODE LCD_W \ byte -- write byte to LCD
40189 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
40190 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
40191 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
40192 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
40193 COLON \ high level word starts here
40194 TOP_LCD 2 20_US \ write high nibble first
40199 CODE LCD_WrC \ char -- Write Char
40200 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40205 CODE LCD_WrF \ func -- Write Fonction
40206 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40212 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
40217 $02 LCD_WrF 100 20_us
40221 \ : LCD_Entry_set $04 OR LCD_WrF ;
40223 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
40225 \ : LCD_Display_Shift $10 OR LCD_WrF ;
40227 \ : LCD_Fn_Set $20 OR LCD_WrF ;
40229 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
40231 \ : LCD_Goto $80 OR LCD_WrF ;
40233 \ CODE LCD_R \ -- byte read byte from LCD
40234 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
40235 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
40236 \ COLON \ starts a FORTH word
40237 \ TOP_LCD 2 20_us \ -- %0000HHHH
40238 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
40239 \ HI2LO \ switch from FORTH to assembler
40240 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
40241 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
40242 \ MOV @RSP+,IP \ restore IP saved by COLON
40247 \ CODE LCD_RdS \ -- status Read Status
40248 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40253 \ CODE LCD_RdC \ -- char Read Char
40254 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40259 \ -------------+------+------+------+------++---+---+---+---+---------+
40260 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
40261 \ -------------+------+------+------+------++---+---+---+---+---------+
40262 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
40263 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
40264 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
40265 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
40266 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
40267 \ -------------+------+------+------+------++---+---+---+---+---------+
40270 \ ******************************\
40271 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
40272 \ ******************************\
40273 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
40274 \ ------------------------------\
40275 \ define LPM mode for ACCEPT \
40276 \ ------------------------------\
40277 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40278 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40279 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40280 BIT.B #SW2,&SW2_IN \ test switch S2
40281 0= IF \ case of switch S2 pressed
40282 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
40284 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
40287 BIT.B #SW1,&SW1_IN \ test switch S1 input
40288 0= IF \ case of Switch S1 pressed
40289 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
40291 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
40295 RETI \ CPU is ON, GIE is OFF
40300 \ ------------------------------\
40301 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
40302 \ ******************************\
40303 ASM RC5_INT \ wake up on Px.RC5 change interrupt
40304 \ ******************************\
40305 \ \ in : SR(9)=old Toggle bit memory (ADD on)
40306 \ \ SMclock = 8|16|24 MHz
40307 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
40308 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
40309 \ \ SR(9)=new Toggle bit memory (ADD on)
40310 \ ------------------------------\
40311 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
40312 \ ------------------------------\
40313 \ define LPM mode for ACCEPT \
40314 \ ------------------------------\
40315 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40316 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40317 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40318 \ ------------------------------\
40319 \ RC5_FirstStartBitHalfCycle: \
40320 \ ------------------------------\
40321 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
40322 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
40323 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
40324 MOV #1778,X \ RC5_Period in us
40325 MOV #14,W \ count of loop
40327 \ ------------------------------\
40328 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
40329 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
40330 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
40331 \ RC5_Compute_3/4_Period: \ |
40332 RRUM #1,X \ X=1/2 cycle |
40336 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
40337 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
40339 \ ------------------------------\
40340 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
40341 \ ------------------------------\
40342 BIT.B #RC5,&IR_IN \ C_flag = IR bit
40343 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
40344 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
40345 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
40346 SUB #1,W \ decrement count loop
40347 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
40348 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
40349 0<> WHILE \ ----> out of loop ----+
40350 \ RC5_compute_7/4_Time_out: \ |
40351 ADD X,Y \ | out of bound = 7/4 period
40352 \ RC5_WaitHalfCycleP1.2_IFG: \ |
40354 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
40355 0>= IF \ | if cycle time out of bound
40356 BIC #$30,&TA0CTL \ | stop timer_A0
40357 RETI \ | then quit to do nothing
40359 \ ------------------------------\ |
40360 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
40362 MOV &TA0R,X \ | | get new RC5_period value
40363 REPEAT \ ----> loop back --+ |
40364 \ ------------------------------\ |
40365 \ RC5_SampleEndOf: \ <---------------------+
40366 \ ------------------------------\
40367 BIC #$30,&TA0CTL \ stop timer_A0
40368 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
40369 \ ******************************\
40370 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
40371 \ ******************************\
40372 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
40373 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
40374 XOR IP,X \ (new XOR old) Toggle bit (13)
40375 BIT #BIT13,X \ X(13) = New_RC5_command
40376 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
40378 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
40379 \ ******************************\
40380 \ RC5_ComputeNewRC5word \
40381 \ ******************************\
40383 MOV &BASE,2(PSP) \ save variable BASE before use
40384 MOV TOS,0(PSP) \ save TOS before use
40385 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
40386 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
40387 \ ******************************\
40388 \ RC5_ComputeC6bit \
40389 \ ******************************\
40390 BIT #$4000,IP \ test /C6 bit in IP
40391 0= IF BIS #$40,TOS \ set C6 bit in S
40392 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
40393 \ ******************************\
40394 \ RC5_CommandByteIsDone \ RC5_code --
40395 \ ******************************\
40397 \ ------------------------------\
40398 \ Display IR_RC5 code \
40399 \ ------------------------------\
40400 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
40401 \ ------------------------------\
40402 LO2HI \ switch from assembler to FORTH
40403 ['] LCD_CLEAR IS CR \ redirects CR
40404 ['] LCD_WrC IS EMIT \ redirects EMIT
40405 $10 BASE ! \ change BASE to hexadecimal
40406 CR ." $" 2 U.R \ print IR_RC5 code
40407 ['] (CR) IS CR \ restore CR
40408 ['] (EMIT) IS EMIT \ restore EMIT
40409 HI2LO \ switch from FORTH to assembler
40410 \ ------------------------------\
40411 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
40412 \ ------------------------------\
40413 MOV @PSP+,&BASE \ restore variable BASE
40414 RETI \ CPU is ON, GIE is OFF
40419 \ ------------------------------\
40420 \ TB0CTL = %0000 0010 1001 0100\$3C0
40421 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40422 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40423 \ -- \ID input divider \ 10 = /4
40424 \ -- \MC Mode Control \ 01 = up to TB0CCR0
40425 \ - \TBCLR TimerB Clear
40428 \ --------------------------------\\
40429 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40430 \ -- \CM Capture Mode
40435 \ --- \OUTMOD \ 011 = set/reset
40441 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
40443 \ ------------------------------\
40444 \ set TimerB to make 50kHz PWM \
40445 \ ------------------------------\
40446 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40447 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
40448 \ ------------------------------\
40449 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40450 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
40451 \ ------------------------------\
40452 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40453 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
40454 \ ------------------------------\
40455 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40456 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
40457 \ ------------------------------\
40458 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40459 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
40460 \ ------------------------------\
40461 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
40462 \ ------------------------------\
40463 \ set TimerB to generate PWM for LCD_Vo
40464 \ ------------------------------\
40465 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
40466 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
40467 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40468 \ ------------------------------\
40469 BIS.B #LCDVo,&LCDVo_DIR \
40470 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
40471 \ ------------------------------\
40472 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40473 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40474 \ ------------------------------\
40475 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40476 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40477 \ ------------------------------\
40478 \ WDT interval init part \
40479 \ ------------------------------\
40480 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
40481 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
40482 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
40483 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
40484 \ ------------------------------\
40486 \ ------------------------------\
40487 BIS.B #RC5,&IR_IE \ enable RC5_Int
40488 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40489 \ ------------------------------\
40490 \ init interrupt vectors
40491 \ ------------------------------\
40492 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
40493 MOV #RC5_INT,&IR_Vec \ init interrupt vector
40494 \ ------------------------------\
40495 \ define LPM mode for ACCEPT \
40496 \ ------------------------------\
40497 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40498 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40499 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40501 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
40503 \ ------------------------------\
40505 \ ------------------------------\
40506 $03E8 20_US \ 1- wait 20 ms
40507 $03 TOP_LCD \ 2- send DB5=DB4=1
40508 $CD 20_US \ 3- wait 4,1 ms
40509 $03 TOP_LCD \ 4- send again DB5=DB4=1
40510 $5 20_US \ 5- wait 0,1 ms
40511 $03 TOP_LCD \ 6- send again again DB5=DB4=1
40512 $2 20_US \ wait 40 us = LCD cycle
40513 $02 TOP_LCD \ 7- send DB5=1 DB4=0
40514 $2 20_US \ wait 40 us = LCD cycle
40515 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40516 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40517 LCD_Clear \ 10- "LCD_Clear"
40518 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40519 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40520 LCD_Clear \ 10- "LCD_Clear"
40521 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40522 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40524 ['] (CR) IS CR \ ' (CR) is CR
40525 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
40527 ." RC5toLCD is running. Type STOP to quit"
40528 \ NOECHO \ uncomment to run this app without terminal connexion
40529 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
40530 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
40534 : STOP \ stops multitasking, must to be used before downloading app
40535 ['] (WARM) IS WARM \ remove START app from FORTH init process
40536 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
40544 CODE MAX \ n1 n2 -- n3 signed maximum
40545 CMP @PSP,TOS \ n2-n1
40546 S< ?GOTO FW1 \ n2<n1
40552 CODE MIN \ n1 n2 -- n3 signed minimum
40553 CMP @PSP,TOS \ n2-n1
40554 S< ?GOTO BW1 \ n2<n1
40560 : U.R \ u n -- display u unsigned in n width (n >= 2)
40562 R> OVER - 0 MAX SPACES TYPE
40566 CODE 20_US \ n -- n * 20 us
40567 BEGIN \ 3 cycles loop + 6~
40568 \ MOV #5,W \ 3 MCLK = 1 MHz
40569 \ MOV #23,W \ 3 MCLK = 4 MHz
40570 MOV #51,W \ 3 MCLK = 8 MHz
40571 \ MOV #104,W \ 3 MCLK = 16 MHz
40572 \ MOV #158,W \ 3 MCLK = 24 MHz
40573 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
40583 CODE TOP_LCD \ LCD Sample
40584 \ \ if write : %xxxxWWWW --
40585 \ \ if read : -- %0000RRRR
40586 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
40587 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
40588 0= IF \ write LCD bits pattern
40589 AND.B #LCD_DB,TOS \
40590 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
40591 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40594 THEN \ read LCD bits pattern
40597 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40598 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
40599 AND.B #LCD_DB,TOS \
40604 CODE LCD_W \ byte -- write byte to LCD
40606 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
40607 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
40608 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
40609 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
40610 COLON \ high level word starts here
40611 TOP_LCD 2 20_US \ write high nibble first
40616 CODE LCD_WrC \ char -- Write Char
40617 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40622 CODE LCD_WrF \ func -- Write Fonction
40623 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40629 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
40634 $02 LCD_WrF 100 20_us
40638 \ : LCD_Entry_set $04 OR LCD_WrF ;
40640 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
40642 \ : LCD_Display_Shift $10 OR LCD_WrF ;
40644 \ : LCD_Fn_Set $20 OR LCD_WrF ;
40646 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
40648 \ : LCD_Goto $80 OR LCD_WrF ;
40650 \ CODE LCD_R \ -- byte read byte from LCD
40651 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
40652 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
40653 \ COLON \ starts a FORTH word
40654 \ TOP_LCD 2 20_us \ -- %0000HHHH
40655 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
40656 \ HI2LO \ switch from FORTH to assembler
40657 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
40658 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
40659 \ MOV @RSP+,IP \ restore IP saved by COLON
40664 \ CODE LCD_RdS \ -- status Read Status
40665 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40670 \ CODE LCD_RdC \ -- char Read Char
40671 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40676 \ -------------+------+------+------+------++---+---+---+---+---------+
40677 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
40678 \ -------------+------+------+------+------++---+---+---+---+---------+
40679 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
40680 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
40681 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
40682 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
40683 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
40684 \ -------------+------+------+------+------++---+---+---+---+---------+
40687 \ ******************************\
40688 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
40689 \ ******************************\
40690 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
40691 \ ------------------------------\
40692 \ define LPM mode for ACCEPT \
40693 \ ------------------------------\
40694 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40695 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40696 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40697 BIT.B #SW2,&SW2_IN \ test switch S2
40698 0= IF \ case of switch S2 pressed
40699 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
40701 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
40704 BIT.B #SW1,&SW1_IN \ test switch S1 input
40705 0= IF \ case of Switch S1 pressed
40706 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
40708 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
40712 RETI \ CPU is ON, GIE is OFF
40717 \ ------------------------------\
40718 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
40719 \ ******************************\
40720 ASM RC5_INT \ wake up on Px.RC5 change interrupt
40721 \ ******************************\
40722 \ \ in : SR(9)=old Toggle bit memory (ADD on)
40723 \ \ SMclock = 8|16|24 MHz
40724 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
40725 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
40726 \ \ SR(9)=new Toggle bit memory (ADD on)
40727 \ ------------------------------\
40728 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
40729 \ ------------------------------\
40730 \ define LPM mode for ACCEPT \
40731 \ ------------------------------\
40732 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40733 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40734 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40735 \ ------------------------------\
40736 \ RC5_FirstStartBitHalfCycle: \
40737 \ ------------------------------\
40738 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
40739 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
40740 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
40741 MOV #1778,X \ RC5_Period in us
40742 MOV #14,W \ count of loop
40744 \ ------------------------------\
40745 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
40746 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
40747 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
40748 \ RC5_Compute_3/4_Period: \ |
40749 RRUM #1,X \ X=1/2 cycle |
40753 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
40754 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
40756 \ ------------------------------\
40757 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
40758 \ ------------------------------\
40759 BIT.B #RC5,&IR_IN \ C_flag = IR bit
40760 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
40761 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
40762 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
40763 SUB #1,W \ decrement count loop
40764 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
40765 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
40766 0<> WHILE \ ----> out of loop ----+
40767 \ RC5_compute_7/4_Time_out: \ |
40768 ADD X,Y \ | out of bound = 7/4 period
40769 \ RC5_WaitHalfCycleP1.2_IFG: \ |
40771 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
40772 0>= IF \ | if cycle time out of bound
40773 BIC #$30,&TA0CTL \ | stop timer_A0
40774 RETI \ | then quit to do nothing
40776 \ ------------------------------\ |
40777 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
40779 MOV &TA0R,X \ | | get new RC5_period value
40780 REPEAT \ ----> loop back --+ |
40781 \ ------------------------------\ |
40782 \ RC5_SampleEndOf: \ <---------------------+
40783 \ ------------------------------\
40784 BIC #$30,&TA0CTL \ stop timer_A0
40785 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
40786 \ ******************************\
40787 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
40788 \ ******************************\
40789 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
40790 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
40791 XOR IP,X \ (new XOR old) Toggle bit (13)
40792 BIT #BIT13,X \ X(13) = New_RC5_command
40793 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
40795 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
40796 \ ******************************\
40797 \ RC5_ComputeNewRC5word \
40798 \ ******************************\
40800 MOV &BASE,2(PSP) \ save variable BASE before use
40801 MOV TOS,0(PSP) \ save TOS before use
40802 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
40803 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
40804 \ ******************************\
40805 \ RC5_ComputeC6bit \
40806 \ ******************************\
40807 BIT #$4000,IP \ test /C6 bit in IP
40808 0= IF BIS #$40,TOS \ set C6 bit in S
40809 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
40810 \ ******************************\
40811 \ RC5_CommandByteIsDone \ RC5_code --
40812 \ ******************************\
40814 \ ------------------------------\
40815 \ Display IR_RC5 code \
40816 \ ------------------------------\
40817 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
40818 \ ------------------------------\
40819 LO2HI \ switch from assembler to FORTH
40820 ['] LCD_CLEAR IS CR \ redirects CR
40821 ['] LCD_WrC IS EMIT \ redirects EMIT
40822 $10 BASE ! \ change BASE to hexadecimal
40823 CR ." $" 2 U.R \ print IR_RC5 code
40824 ['] (CR) IS CR \ restore CR
40825 ['] (EMIT) IS EMIT \ restore EMIT
40826 HI2LO \ switch from FORTH to assembler
40827 \ ------------------------------\
40828 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
40829 \ ------------------------------\
40830 MOV @PSP+,&BASE \ restore variable BASE
40831 RETI \ CPU is ON, GIE is OFF
40836 \ ------------------------------\
40837 \ TB0CTL = %0000 0010 1001 0100\$3C0
40838 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40839 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40840 \ -- \ID input divider \ 10 = /4
40841 \ -- \MC Mode Control \ 01 = up to TB0CCR0
40842 \ - \TBCLR TimerB Clear
40845 \ --------------------------------\\
40846 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40847 \ -- \CM Capture Mode
40852 \ --- \OUTMOD \ 011 = set/reset
40858 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
40860 \ ------------------------------\
40861 \ set TimerB to make 50kHz PWM \
40862 \ ------------------------------\
40863 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40864 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
40865 \ ------------------------------\
40866 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40867 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
40868 \ ------------------------------\
40869 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40870 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
40871 \ ------------------------------\
40872 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40873 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
40874 \ ------------------------------\
40875 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40876 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
40877 \ ------------------------------\
40878 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
40879 \ ------------------------------\
40880 \ set TimerB to generate PWM for LCD_Vo
40881 \ ------------------------------\
40882 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
40883 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
40884 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40885 \ ------------------------------\
40886 BIS.B #LCDVo,&LCDVo_DIR \
40887 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
40888 \ ------------------------------\
40889 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40890 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40891 \ ------------------------------\
40892 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40893 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40894 \ ------------------------------\
40895 \ WDT interval init part \
40896 \ ------------------------------\
40897 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
40898 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
40899 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
40900 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
40901 \ ------------------------------\
40903 \ ------------------------------\
40904 BIS.B #RC5,&IR_IE \ enable RC5_Int
40905 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40906 \ ------------------------------\
40907 \ init interrupt vectors
40908 \ ------------------------------\
40909 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
40910 MOV #RC5_INT,&IR_Vec \ init interrupt vector
40911 \ ------------------------------\
40912 \ define LPM mode for ACCEPT \
40913 \ ------------------------------\
40914 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40915 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40916 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40918 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
40920 \ ------------------------------\
40922 \ ------------------------------\
40923 $03E8 20_US \ 1- wait 20 ms
40924 $03 TOP_LCD \ 2- send DB5=DB4=1
40925 $CD 20_US \ 3- wait 4,1 ms
40926 $03 TOP_LCD \ 4- send again DB5=DB4=1
40927 $5 20_US \ 5- wait 0,1 ms
40928 $03 TOP_LCD \ 6- send again again DB5=DB4=1
40929 $2 20_US \ wait 40 us = LCD cycle
40930 $02 TOP_LCD \ 7- send DB5=1 DB4=0
40931 $2 20_US \ wait 40 us = LCD cycle
40932 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40933 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40934 LCD_Clear \ 10- "LCD_Clear"
40935 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40936 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40937 LCD_Clear \ 10- "LCD_Clear"
40938 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40939 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40941 ['] (CR) IS CR \ ' (CR) is CR
40942 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
40944 ." RC5toLCD is running. Type STOP to quit"
40945 \ NOECHO \ uncomment to run this app without terminal connexion
40946 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
40947 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
40951 : STOP \ stops multitasking, must to be used before downloading app
40952 ['] (WARM) IS WARM \ remove START app from FORTH init process
40953 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
40961 CODE MAX \ n1 n2 -- n3 signed maximum
40962 CMP @PSP,TOS \ n2-n1
40963 S< ?GOTO FW1 \ n2<n1
40969 CODE MIN \ n1 n2 -- n3 signed minimum
40970 CMP @PSP,TOS \ n2-n1
40971 S< ?GOTO BW1 \ n2<n1
40977 : U.R \ u n -- display u unsigned in n width (n >= 2)
40979 R> OVER - 0 MAX SPACES TYPE
40983 CODE 20_US \ n -- n * 20 us
40984 BEGIN \ 3 cycles loop + 6~
40985 \ MOV #5,W \ 3 MCLK = 1 MHz
40986 \ MOV #23,W \ 3 MCLK = 4 MHz
40987 MOV #51,W \ 3 MCLK = 8 MHz
40988 \ MOV #104,W \ 3 MCLK = 16 MHz
40989 \ MOV #158,W \ 3 MCLK = 24 MHz
40990 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
41000 CODE TOP_LCD \ LCD Sample
41001 \ \ if write : %xxxxWWWW --
41002 \ \ if read : -- %0000RRRR
41003 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
41004 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
41005 0= IF \ write LCD bits pattern
41006 AND.B #LCD_DB,TOS \
41007 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
41008 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41011 THEN \ read LCD bits pattern
41014 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41015 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41016 AND.B #LCD_DB,TOS \
41021 CODE LCD_W \ byte -- write byte to LCD
41023 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
41024 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
41025 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41026 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41027 COLON \ high level word starts here
41028 TOP_LCD 2 20_US \ write high nibble first
41033 CODE LCD_WrC \ char -- Write Char
41034 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41039 CODE LCD_WrF \ func -- Write Fonction
41040 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41046 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
41051 $02 LCD_WrF 100 20_us
41055 \ : LCD_Entry_set $04 OR LCD_WrF ;
41057 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
41059 \ : LCD_Display_Shift $10 OR LCD_WrF ;
41061 \ : LCD_Fn_Set $20 OR LCD_WrF ;
41063 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
41065 \ : LCD_Goto $80 OR LCD_WrF ;
41067 \ CODE LCD_R \ -- byte read byte from LCD
41068 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41069 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41070 \ COLON \ starts a FORTH word
41071 \ TOP_LCD 2 20_us \ -- %0000HHHH
41072 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
41073 \ HI2LO \ switch from FORTH to assembler
41074 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
41075 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
41076 \ MOV @RSP+,IP \ restore IP saved by COLON
41081 \ CODE LCD_RdS \ -- status Read Status
41082 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41087 \ CODE LCD_RdC \ -- char Read Char
41088 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41093 \ -------------+------+------+------+------++---+---+---+---+---------+
41094 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
41095 \ -------------+------+------+------+------++---+---+---+---+---------+
41096 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
41097 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
41098 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
41099 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
41100 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
41101 \ -------------+------+------+------+------++---+---+---+---+---------+
41104 \ ******************************\
41105 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41106 \ ******************************\
41107 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
41108 \ ------------------------------\
41109 \ define LPM mode for ACCEPT \
41110 \ ------------------------------\
41111 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41112 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41113 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41114 BIT.B #SW2,&SW2_IN \ test switch S2
41115 0= IF \ case of switch S2 pressed
41116 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
41118 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
41121 BIT.B #SW1,&SW1_IN \ test switch S1 input
41122 0= IF \ case of Switch S1 pressed
41123 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
41125 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
41129 RETI \ CPU is ON, GIE is OFF
41134 \ ------------------------------\
41135 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41136 \ ******************************\
41137 ASM RC5_INT \ wake up on Px.RC5 change interrupt
41138 \ ******************************\
41139 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41140 \ \ SMclock = 8|16|24 MHz
41141 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
41142 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
41143 \ \ SR(9)=new Toggle bit memory (ADD on)
41144 \ ------------------------------\
41145 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
41146 \ ------------------------------\
41147 \ define LPM mode for ACCEPT \
41148 \ ------------------------------\
41149 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41150 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41151 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41152 \ ------------------------------\
41153 \ RC5_FirstStartBitHalfCycle: \
41154 \ ------------------------------\
41155 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
41156 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
41157 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
41158 MOV #1778,X \ RC5_Period in us
41159 MOV #14,W \ count of loop
41161 \ ------------------------------\
41162 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
41163 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
41164 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
41165 \ RC5_Compute_3/4_Period: \ |
41166 RRUM #1,X \ X=1/2 cycle |
41170 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
41171 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
41173 \ ------------------------------\
41174 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
41175 \ ------------------------------\
41176 BIT.B #RC5,&IR_IN \ C_flag = IR bit
41177 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
41178 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
41179 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
41180 SUB #1,W \ decrement count loop
41181 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
41182 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
41183 0<> WHILE \ ----> out of loop ----+
41184 \ RC5_compute_7/4_Time_out: \ |
41185 ADD X,Y \ | out of bound = 7/4 period
41186 \ RC5_WaitHalfCycleP1.2_IFG: \ |
41188 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
41189 0>= IF \ | if cycle time out of bound
41190 BIC #$30,&TA0CTL \ | stop timer_A0
41191 RETI \ | then quit to do nothing
41193 \ ------------------------------\ |
41194 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
41196 MOV &TA0R,X \ | | get new RC5_period value
41197 REPEAT \ ----> loop back --+ |
41198 \ ------------------------------\ |
41199 \ RC5_SampleEndOf: \ <---------------------+
41200 \ ------------------------------\
41201 BIC #$30,&TA0CTL \ stop timer_A0
41202 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
41203 \ ******************************\
41204 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
41205 \ ******************************\
41206 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
41207 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
41208 XOR IP,X \ (new XOR old) Toggle bit (13)
41209 BIT #BIT13,X \ X(13) = New_RC5_command
41210 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
41212 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
41213 \ ******************************\
41214 \ RC5_ComputeNewRC5word \
41215 \ ******************************\
41217 MOV &BASE,2(PSP) \ save variable BASE before use
41218 MOV TOS,0(PSP) \ save TOS before use
41219 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
41220 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
41221 \ ******************************\
41222 \ RC5_ComputeC6bit \
41223 \ ******************************\
41224 BIT #$4000,IP \ test /C6 bit in IP
41225 0= IF BIS #$40,TOS \ set C6 bit in S
41226 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
41227 \ ******************************\
41228 \ RC5_CommandByteIsDone \ RC5_code --
41229 \ ******************************\
41231 \ ------------------------------\
41232 \ Display IR_RC5 code \
41233 \ ------------------------------\
41234 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
41235 \ ------------------------------\
41236 LO2HI \ switch from assembler to FORTH
41237 ['] LCD_CLEAR IS CR \ redirects CR
41238 ['] LCD_WrC IS EMIT \ redirects EMIT
41239 $10 BASE ! \ change BASE to hexadecimal
41240 CR ." $" 2 U.R \ print IR_RC5 code
41241 ['] (CR) IS CR \ restore CR
41242 ['] (EMIT) IS EMIT \ restore EMIT
41243 HI2LO \ switch from FORTH to assembler
41244 \ ------------------------------\
41245 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
41246 \ ------------------------------\
41247 MOV @PSP+,&BASE \ restore variable BASE
41248 RETI \ CPU is ON, GIE is OFF
41253 \ ------------------------------\
41254 \ TB0CTL = %0000 0010 1001 0100\$3C0
41255 \ - - \CNTL Counter lentgh \ 00 = 16 bits
41256 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
41257 \ -- \ID input divider \ 10 = /4
41258 \ -- \MC Mode Control \ 01 = up to TB0CCR0
41259 \ - \TBCLR TimerB Clear
41262 \ --------------------------------\\
41263 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41264 \ -- \CM Capture Mode
41269 \ --- \OUTMOD \ 011 = set/reset
41275 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
41277 \ ------------------------------\
41278 \ set TimerB to make 50kHz PWM \
41279 \ ------------------------------\
41280 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
41281 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
41282 \ ------------------------------\
41283 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
41284 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
41285 \ ------------------------------\
41286 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41287 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
41288 \ ------------------------------\
41289 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41290 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
41291 \ ------------------------------\
41292 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41293 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
41294 \ ------------------------------\
41295 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
41296 \ ------------------------------\
41297 \ set TimerB to generate PWM for LCD_Vo
41298 \ ------------------------------\
41299 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
41300 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
41301 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41302 \ ------------------------------\
41303 BIS.B #LCDVo,&LCDVo_DIR \
41304 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
41305 \ ------------------------------\
41306 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41307 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41308 \ ------------------------------\
41309 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
41310 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
41311 \ ------------------------------\
41312 \ WDT interval init part \
41313 \ ------------------------------\
41314 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
41315 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
41316 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
41317 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
41318 \ ------------------------------\
41320 \ ------------------------------\
41321 BIS.B #RC5,&IR_IE \ enable RC5_Int
41322 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
41323 \ ------------------------------\
41324 \ init interrupt vectors
41325 \ ------------------------------\
41326 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
41327 MOV #RC5_INT,&IR_Vec \ init interrupt vector
41328 \ ------------------------------\
41329 \ define LPM mode for ACCEPT \
41330 \ ------------------------------\
41331 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41332 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41333 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41335 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
41337 \ ------------------------------\
41339 \ ------------------------------\
41340 $03E8 20_US \ 1- wait 20 ms
41341 $03 TOP_LCD \ 2- send DB5=DB4=1
41342 $CD 20_US \ 3- wait 4,1 ms
41343 $03 TOP_LCD \ 4- send again DB5=DB4=1
41344 $5 20_US \ 5- wait 0,1 ms
41345 $03 TOP_LCD \ 6- send again again DB5=DB4=1
41346 $2 20_US \ wait 40 us = LCD cycle
41347 $02 TOP_LCD \ 7- send DB5=1 DB4=0
41348 $2 20_US \ wait 40 us = LCD cycle
41349 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
41350 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
41351 LCD_Clear \ 10- "LCD_Clear"
41352 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
41353 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
41354 LCD_Clear \ 10- "LCD_Clear"
41355 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
41356 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
41358 ['] (CR) IS CR \ ' (CR) is CR
41359 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
41361 ." RC5toLCD is running. Type STOP to quit"
41362 \ NOECHO \ uncomment to run this app without terminal connexion
41363 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
41364 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
41368 : STOP \ stops multitasking, must to be used before downloading app
41369 ['] (WARM) IS WARM \ remove START app from FORTH init process
41370 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
41378 CODE MAX \ n1 n2 -- n3 signed maximum
41379 CMP @PSP,TOS \ n2-n1
41380 S< ?GOTO FW1 \ n2<n1
41386 CODE MIN \ n1 n2 -- n3 signed minimum
41387 CMP @PSP,TOS \ n2-n1
41388 S< ?GOTO BW1 \ n2<n1
41394 : U.R \ u n -- display u unsigned in n width (n >= 2)
41396 R> OVER - 0 MAX SPACES TYPE
41400 CODE 20_US \ n -- n * 20 us
41401 BEGIN \ 3 cycles loop + 6~
41402 \ MOV #5,W \ 3 MCLK = 1 MHz
41403 \ MOV #23,W \ 3 MCLK = 4 MHz
41404 MOV #51,W \ 3 MCLK = 8 MHz
41405 \ MOV #104,W \ 3 MCLK = 16 MHz
41406 \ MOV #158,W \ 3 MCLK = 24 MHz
41407 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
41417 CODE TOP_LCD \ LCD Sample
41418 \ \ if write : %xxxxWWWW --
41419 \ \ if read : -- %0000RRRR
41420 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
41421 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
41422 0= IF \ write LCD bits pattern
41423 AND.B #LCD_DB,TOS \
41424 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
41425 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41428 THEN \ read LCD bits pattern
41431 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41432 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41433 AND.B #LCD_DB,TOS \
41438 CODE LCD_W \ byte -- write byte to LCD
41440 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
41441 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
41442 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41443 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41444 COLON \ high level word starts here
41445 TOP_LCD 2 20_US \ write high nibble first
41450 CODE LCD_WrC \ char -- Write Char
41451 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41456 CODE LCD_WrF \ func -- Write Fonction
41457 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41463 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
41468 $02 LCD_WrF 100 20_us
41472 \ : LCD_Entry_set $04 OR LCD_WrF ;
41474 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
41476 \ : LCD_Display_Shift $10 OR LCD_WrF ;
41478 \ : LCD_Fn_Set $20 OR LCD_WrF ;
41480 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
41482 \ : LCD_Goto $80 OR LCD_WrF ;
41484 \ CODE LCD_R \ -- byte read byte from LCD
41485 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41486 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41487 \ COLON \ starts a FORTH word
41488 \ TOP_LCD 2 20_us \ -- %0000HHHH
41489 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
41490 \ HI2LO \ switch from FORTH to assembler
41491 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
41492 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
41493 \ MOV @RSP+,IP \ restore IP saved by COLON
41498 \ CODE LCD_RdS \ -- status Read Status
41499 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41504 \ CODE LCD_RdC \ -- char Read Char
41505 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41510 \ -------------+------+------+------+------++---+---+---+---+---------+
41511 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
41512 \ -------------+------+------+------+------++---+---+---+---+---------+
41513 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
41514 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
41515 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
41516 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
41517 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
41518 \ -------------+------+------+------+------++---+---+---+---+---------+
41521 \ ******************************\
41522 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41523 \ ******************************\
41524 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
41525 \ ------------------------------\
41526 \ define LPM mode for ACCEPT \
41527 \ ------------------------------\
41528 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41529 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41530 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41531 BIT.B #SW2,&SW2_IN \ test switch S2
41532 0= IF \ case of switch S2 pressed
41533 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
41535 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
41538 BIT.B #SW1,&SW1_IN \ test switch S1 input
41539 0= IF \ case of Switch S1 pressed
41540 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
41542 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
41546 RETI \ CPU is ON, GIE is OFF
41551 \ ------------------------------\
41552 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41553 \ ******************************\
41554 ASM RC5_INT \ wake up on Px.RC5 change interrupt
41555 \ ******************************\
41556 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41557 \ \ SMclock = 8|16|24 MHz
41558 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
41559 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
41560 \ \ SR(9)=new Toggle bit memory (ADD on)
41561 \ ------------------------------\
41562 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
41563 \ ------------------------------\
41564 \ define LPM mode for ACCEPT \
41565 \ ------------------------------\
41566 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41567 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41568 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41569 \ ------------------------------\
41570 \ RC5_FirstStartBitHalfCycle: \
41571 \ ------------------------------\
41572 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
41573 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
41574 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
41575 MOV #1778,X \ RC5_Period in us
41576 MOV #14,W \ count of loop
41578 \ ------------------------------\
41579 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
41580 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
41581 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
41582 \ RC5_Compute_3/4_Period: \ |
41583 RRUM #1,X \ X=1/2 cycle |
41587 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
41588 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
41590 \ ------------------------------\
41591 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
41592 \ ------------------------------\
41593 BIT.B #RC5,&IR_IN \ C_flag = IR bit
41594 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
41595 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
41596 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
41597 SUB #1,W \ decrement count loop
41598 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
41599 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
41600 0<> WHILE \ ----> out of loop ----+
41601 \ RC5_compute_7/4_Time_out: \ |
41602 ADD X,Y \ | out of bound = 7/4 period
41603 \ RC5_WaitHalfCycleP1.2_IFG: \ |
41605 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
41606 0>= IF \ | if cycle time out of bound
41607 BIC #$30,&TA0CTL \ | stop timer_A0
41608 RETI \ | then quit to do nothing
41610 \ ------------------------------\ |
41611 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
41613 MOV &TA0R,X \ | | get new RC5_period value
41614 REPEAT \ ----> loop back --+ |
41615 \ ------------------------------\ |
41616 \ RC5_SampleEndOf: \ <---------------------+
41617 \ ------------------------------\
41618 BIC #$30,&TA0CTL \ stop timer_A0
41619 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
41620 \ ******************************\
41621 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
41622 \ ******************************\
41623 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
41624 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
41625 XOR IP,X \ (new XOR old) Toggle bit (13)
41626 BIT #BIT13,X \ X(13) = New_RC5_command
41627 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
41629 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
41630 \ ******************************\
41631 \ RC5_ComputeNewRC5word \
41632 \ ******************************\
41634 MOV &BASE,2(PSP) \ save variable BASE before use
41635 MOV TOS,0(PSP) \ save TOS before use
41636 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
41637 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
41638 \ ******************************\
41639 \ RC5_ComputeC6bit \
41640 \ ******************************\
41641 BIT #$4000,IP \ test /C6 bit in IP
41642 0= IF BIS #$40,TOS \ set C6 bit in S
41643 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
41644 \ ******************************\
41645 \ RC5_CommandByteIsDone \ RC5_code --
41646 \ ******************************\
41648 \ ------------------------------\
41649 \ Display IR_RC5 code \
41650 \ ------------------------------\
41651 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
41652 \ ------------------------------\
41653 LO2HI \ switch from assembler to FORTH
41654 ['] LCD_CLEAR IS CR \ redirects CR
41655 ['] LCD_WrC IS EMIT \ redirects EMIT
41656 $10 BASE ! \ change BASE to hexadecimal
41657 CR ." $" 2 U.R \ print IR_RC5 code
41658 ['] (CR) IS CR \ restore CR
41659 ['] (EMIT) IS EMIT \ restore EMIT
41660 HI2LO \ switch from FORTH to assembler
41661 \ ------------------------------\
41662 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
41663 \ ------------------------------\
41664 MOV @PSP+,&BASE \ restore variable BASE
41665 RETI \ CPU is ON, GIE is OFF
41670 \ ------------------------------\
41671 \ TB0CTL = %0000 0010 1001 0100\$3C0
41672 \ - - \CNTL Counter lentgh \ 00 = 16 bits
41673 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
41674 \ -- \ID input divider \ 10 = /4
41675 \ -- \MC Mode Control \ 01 = up to TB0CCR0
41676 \ - \TBCLR TimerB Clear
41679 \ --------------------------------\\
41680 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41681 \ -- \CM Capture Mode
41686 \ --- \OUTMOD \ 011 = set/reset
41692 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
41694 \ ------------------------------\
41695 \ set TimerB to make 50kHz PWM \
41696 \ ------------------------------\
41697 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
41698 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
41699 \ ------------------------------\
41700 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
41701 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
41702 \ ------------------------------\
41703 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41704 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
41705 \ ------------------------------\
41706 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41707 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
41708 \ ------------------------------\
41709 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41710 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
41711 \ ------------------------------\
41712 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
41713 \ ------------------------------\
41714 \ set TimerB to generate PWM for LCD_Vo
41715 \ ------------------------------\
41716 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
41717 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
41718 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41719 \ ------------------------------\
41720 BIS.B #LCDVo,&LCDVo_DIR \
41721 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
41722 \ ------------------------------\
41723 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41724 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41725 \ ------------------------------\
41726 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
41727 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
41728 \ ------------------------------\
41729 \ WDT interval init part \
41730 \ ------------------------------\
41731 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
41732 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
41733 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
41734 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
41735 \ ------------------------------\
41737 \ ------------------------------\
41738 BIS.B #RC5,&IR_IE \ enable RC5_Int
41739 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
41740 \ ------------------------------\
41741 \ init interrupt vectors
41742 \ ------------------------------\
41743 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
41744 MOV #RC5_INT,&IR_Vec \ init interrupt vector
41745 \ ------------------------------\
41746 \ define LPM mode for ACCEPT \
41747 \ ------------------------------\
41748 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41749 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41750 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41752 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
41754 \ ------------------------------\
41756 \ ------------------------------\
41757 $03E8 20_US \ 1- wait 20 ms
41758 $03 TOP_LCD \ 2- send DB5=DB4=1
41759 $CD 20_US \ 3- wait 4,1 ms
41760 $03 TOP_LCD \ 4- send again DB5=DB4=1
41761 $5 20_US \ 5- wait 0,1 ms
41762 $03 TOP_LCD \ 6- send again again DB5=DB4=1
41763 $2 20_US \ wait 40 us = LCD cycle
41764 $02 TOP_LCD \ 7- send DB5=1 DB4=0
41765 $2 20_US \ wait 40 us = LCD cycle
41766 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
41767 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
41768 LCD_Clear \ 10- "LCD_Clear"
41769 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
41770 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
41771 LCD_Clear \ 10- "LCD_Clear"
41772 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
41773 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
41775 ['] (CR) IS CR \ ' (CR) is CR
41776 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
41778 ." RC5toLCD is running. Type STOP to quit"
41779 \ NOECHO \ uncomment to run this app without terminal connexion
41780 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
41781 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
41785 : STOP \ stops multitasking, must to be used before downloading app
41786 ['] (WARM) IS WARM \ remove START app from FORTH init process
41787 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
41795 CODE MAX \ n1 n2 -- n3 signed maximum
41796 CMP @PSP,TOS \ n2-n1
41797 S< ?GOTO FW1 \ n2<n1
41803 CODE MIN \ n1 n2 -- n3 signed minimum
41804 CMP @PSP,TOS \ n2-n1
41805 S< ?GOTO BW1 \ n2<n1
41811 : U.R \ u n -- display u unsigned in n width (n >= 2)
41813 R> OVER - 0 MAX SPACES TYPE
41817 CODE 20_US \ n -- n * 20 us
41818 BEGIN \ 3 cycles loop + 6~
41819 \ MOV #5,W \ 3 MCLK = 1 MHz
41820 \ MOV #23,W \ 3 MCLK = 4 MHz
41821 MOV #51,W \ 3 MCLK = 8 MHz
41822 \ MOV #104,W \ 3 MCLK = 16 MHz
41823 \ MOV #158,W \ 3 MCLK = 24 MHz
41824 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
41834 CODE TOP_LCD \ LCD Sample
41835 \ \ if write : %xxxxWWWW --
41836 \ \ if read : -- %0000RRRR
41837 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
41838 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
41839 0= IF \ write LCD bits pattern
41840 AND.B #LCD_DB,TOS \
41841 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
41842 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41845 THEN \ read LCD bits pattern
41848 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41849 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41850 AND.B #LCD_DB,TOS \
41855 CODE LCD_W \ byte -- write byte to LCD
41857 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
41858 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
41859 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41860 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41861 COLON \ high level word starts here
41862 TOP_LCD 2 20_US \ write high nibble first
41867 CODE LCD_WrC \ char -- Write Char
41868 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41873 CODE LCD_WrF \ func -- Write Fonction
41874 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41880 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
41885 $02 LCD_WrF 100 20_us
41889 \ : LCD_Entry_set $04 OR LCD_WrF ;
41891 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
41893 \ : LCD_Display_Shift $10 OR LCD_WrF ;
41895 \ : LCD_Fn_Set $20 OR LCD_WrF ;
41897 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
41899 \ : LCD_Goto $80 OR LCD_WrF ;
41901 \ CODE LCD_R \ -- byte read byte from LCD
41902 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41903 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41904 \ COLON \ starts a FORTH word
41905 \ TOP_LCD 2 20_us \ -- %0000HHHH
41906 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
41907 \ HI2LO \ switch from FORTH to assembler
41908 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
41909 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
41910 \ MOV @RSP+,IP \ restore IP saved by COLON
41915 \ CODE LCD_RdS \ -- status Read Status
41916 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41921 \ CODE LCD_RdC \ -- char Read Char
41922 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41927 \ -------------+------+------+------+------++---+---+---+---+---------+
41928 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
41929 \ -------------+------+------+------+------++---+---+---+---+---------+
41930 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
41931 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
41932 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
41933 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
41934 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
41935 \ -------------+------+------+------+------++---+---+---+---+---------+
41938 \ ******************************\
41939 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41940 \ ******************************\
41941 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
41942 \ ------------------------------\
41943 \ define LPM mode for ACCEPT \
41944 \ ------------------------------\
41945 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41946 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41947 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41948 BIT.B #SW2,&SW2_IN \ test switch S2
41949 0= IF \ case of switch S2 pressed
41950 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
41952 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
41955 BIT.B #SW1,&SW1_IN \ test switch S1 input
41956 0= IF \ case of Switch S1 pressed
41957 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
41959 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
41963 RETI \ CPU is ON, GIE is OFF
41968 \ ------------------------------\
41969 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41970 \ ******************************\
41971 ASM RC5_INT \ wake up on Px.RC5 change interrupt
41972 \ ******************************\
41973 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41974 \ \ SMclock = 8|16|24 MHz
41975 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
41976 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
41977 \ \ SR(9)=new Toggle bit memory (ADD on)
41978 \ ------------------------------\
41979 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
41980 \ ------------------------------\
41981 \ define LPM mode for ACCEPT \
41982 \ ------------------------------\
41983 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41984 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41985 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41986 \ ------------------------------\
41987 \ RC5_FirstStartBitHalfCycle: \
41988 \ ------------------------------\
41989 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
41990 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
41991 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
41992 MOV #1778,X \ RC5_Period in us
41993 MOV #14,W \ count of loop
41995 \ ------------------------------\
41996 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
41997 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
41998 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
41999 \ RC5_Compute_3/4_Period: \ |
42000 RRUM #1,X \ X=1/2 cycle |
42004 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
42005 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
42007 \ ------------------------------\
42008 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
42009 \ ------------------------------\
42010 BIT.B #RC5,&IR_IN \ C_flag = IR bit
42011 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
42012 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
42013 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
42014 SUB #1,W \ decrement count loop
42015 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
42016 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
42017 0<> WHILE \ ----> out of loop ----+
42018 \ RC5_compute_7/4_Time_out: \ |
42019 ADD X,Y \ | out of bound = 7/4 period
42020 \ RC5_WaitHalfCycleP1.2_IFG: \ |
42022 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
42023 0>= IF \ | if cycle time out of bound
42024 BIC #$30,&TA0CTL \ | stop timer_A0
42025 RETI \ | then quit to do nothing
42027 \ ------------------------------\ |
42028 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
42030 MOV &TA0R,X \ | | get new RC5_period value
42031 REPEAT \ ----> loop back --+ |
42032 \ ------------------------------\ |
42033 \ RC5_SampleEndOf: \ <---------------------+
42034 \ ------------------------------\
42035 BIC #$30,&TA0CTL \ stop timer_A0
42036 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
42037 \ ******************************\
42038 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
42039 \ ******************************\
42040 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
42041 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
42042 XOR IP,X \ (new XOR old) Toggle bit (13)
42043 BIT #BIT13,X \ X(13) = New_RC5_command
42044 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
42046 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
42047 \ ******************************\
42048 \ RC5_ComputeNewRC5word \
42049 \ ******************************\
42051 MOV &BASE,2(PSP) \ save variable BASE before use
42052 MOV TOS,0(PSP) \ save TOS before use
42053 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
42054 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
42055 \ ******************************\
42056 \ RC5_ComputeC6bit \
42057 \ ******************************\
42058 BIT #$4000,IP \ test /C6 bit in IP
42059 0= IF BIS #$40,TOS \ set C6 bit in S
42060 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
42061 \ ******************************\
42062 \ RC5_CommandByteIsDone \ RC5_code --
42063 \ ******************************\
42065 \ ------------------------------\
42066 \ Display IR_RC5 code \
42067 \ ------------------------------\
42068 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
42069 \ ------------------------------\
42070 LO2HI \ switch from assembler to FORTH
42071 ['] LCD_CLEAR IS CR \ redirects CR
42072 ['] LCD_WrC IS EMIT \ redirects EMIT
42073 $10 BASE ! \ change BASE to hexadecimal
42074 CR ." $" 2 U.R \ print IR_RC5 code
42075 ['] (CR) IS CR \ restore CR
42076 ['] (EMIT) IS EMIT \ restore EMIT
42077 HI2LO \ switch from FORTH to assembler
42078 \ ------------------------------\
42079 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
42080 \ ------------------------------\
42081 MOV @PSP+,&BASE \ restore variable BASE
42082 RETI \ CPU is ON, GIE is OFF
42087 \ ------------------------------\
42088 \ TB0CTL = %0000 0010 1001 0100\$3C0
42089 \ - - \CNTL Counter lentgh \ 00 = 16 bits
42090 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
42091 \ -- \ID input divider \ 10 = /4
42092 \ -- \MC Mode Control \ 01 = up to TB0CCR0
42093 \ - \TBCLR TimerB Clear
42096 \ --------------------------------\\
42097 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
42098 \ -- \CM Capture Mode
42103 \ --- \OUTMOD \ 011 = set/reset
42109 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
42111 \ ------------------------------\
42112 \ set TimerB to make 50kHz PWM \
42113 \ ------------------------------\
42114 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42115 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
42116 \ ------------------------------\
42117 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42118 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
42119 \ ------------------------------\
42120 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42121 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
42122 \ ------------------------------\
42123 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42124 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
42125 \ ------------------------------\
42126 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42127 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
42128 \ ------------------------------\
42129 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
42130 \ ------------------------------\
42131 \ set TimerB to generate PWM for LCD_Vo
42132 \ ------------------------------\
42133 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
42134 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
42135 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
42136 \ ------------------------------\
42137 BIS.B #LCDVo,&LCDVo_DIR \
42138 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
42139 \ ------------------------------\
42140 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
42141 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
42142 \ ------------------------------\
42143 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
42144 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
42145 \ ------------------------------\
42146 \ WDT interval init part \
42147 \ ------------------------------\
42148 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
42149 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
42150 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
42151 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
42152 \ ------------------------------\
42154 \ ------------------------------\
42155 BIS.B #RC5,&IR_IE \ enable RC5_Int
42156 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
42157 \ ------------------------------\
42158 \ init interrupt vectors
42159 \ ------------------------------\
42160 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
42161 MOV #RC5_INT,&IR_Vec \ init interrupt vector
42162 \ ------------------------------\
42163 \ define LPM mode for ACCEPT \
42164 \ ------------------------------\
42165 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42166 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42167 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42169 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
42171 \ ------------------------------\
42173 \ ------------------------------\
42174 $03E8 20_US \ 1- wait 20 ms
42175 $03 TOP_LCD \ 2- send DB5=DB4=1
42176 $CD 20_US \ 3- wait 4,1 ms
42177 $03 TOP_LCD \ 4- send again DB5=DB4=1
42178 $5 20_US \ 5- wait 0,1 ms
42179 $03 TOP_LCD \ 6- send again again DB5=DB4=1
42180 $2 20_US \ wait 40 us = LCD cycle
42181 $02 TOP_LCD \ 7- send DB5=1 DB4=0
42182 $2 20_US \ wait 40 us = LCD cycle
42183 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
42184 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
42185 LCD_Clear \ 10- "LCD_Clear"
42186 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
42187 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
42188 LCD_Clear \ 10- "LCD_Clear"
42189 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
42190 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
42192 ['] (CR) IS CR \ ' (CR) is CR
42193 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
42195 ." RC5toLCD is running. Type STOP to quit"
42196 \ NOECHO \ uncomment to run this app without terminal connexion
42197 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
42198 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
42202 : STOP \ stops multitasking, must to be used before downloading app
42203 ['] (WARM) IS WARM \ remove START app from FORTH init process
42204 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
42212 CODE MAX \ n1 n2 -- n3 signed maximum
42213 CMP @PSP,TOS \ n2-n1
42214 S< ?GOTO FW1 \ n2<n1
42220 CODE MIN \ n1 n2 -- n3 signed minimum
42221 CMP @PSP,TOS \ n2-n1
42222 S< ?GOTO BW1 \ n2<n1
42228 : U.R \ u n -- display u unsigned in n width (n >= 2)
42230 R> OVER - 0 MAX SPACES TYPE
42234 CODE 20_US \ n -- n * 20 us
42235 BEGIN \ 3 cycles loop + 6~
42236 \ MOV #5,W \ 3 MCLK = 1 MHz
42237 \ MOV #23,W \ 3 MCLK = 4 MHz
42238 MOV #51,W \ 3 MCLK = 8 MHz
42239 \ MOV #104,W \ 3 MCLK = 16 MHz
42240 \ MOV #158,W \ 3 MCLK = 24 MHz
42241 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
42251 CODE TOP_LCD \ LCD Sample
42252 \ \ if write : %xxxxWWWW --
42253 \ \ if read : -- %0000RRRR
42254 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
42255 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
42256 0= IF \ write LCD bits pattern
42257 AND.B #LCD_DB,TOS \
42258 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
42259 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42262 THEN \ read LCD bits pattern
42265 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42266 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
42267 AND.B #LCD_DB,TOS \
42272 CODE LCD_W \ byte -- write byte to LCD
42274 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
42275 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
42276 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
42277 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
42278 COLON \ high level word starts here
42279 TOP_LCD 2 20_US \ write high nibble first
42284 CODE LCD_WrC \ char -- Write Char
42285 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42290 CODE LCD_WrF \ func -- Write Fonction
42291 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42297 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
42302 $02 LCD_WrF 100 20_us
42306 \ : LCD_Entry_set $04 OR LCD_WrF ;
42308 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
42310 \ : LCD_Display_Shift $10 OR LCD_WrF ;
42312 \ : LCD_Fn_Set $20 OR LCD_WrF ;
42314 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
42316 \ : LCD_Goto $80 OR LCD_WrF ;
42318 \ CODE LCD_R \ -- byte read byte from LCD
42319 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
42320 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
42321 \ COLON \ starts a FORTH word
42322 \ TOP_LCD 2 20_us \ -- %0000HHHH
42323 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
42324 \ HI2LO \ switch from FORTH to assembler
42325 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
42326 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
42327 \ MOV @RSP+,IP \ restore IP saved by COLON
42332 \ CODE LCD_RdS \ -- status Read Status
42333 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42338 \ CODE LCD_RdC \ -- char Read Char
42339 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42344 \ -------------+------+------+------+------++---+---+---+---+---------+
42345 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
42346 \ -------------+------+------+------+------++---+---+---+---+---------+
42347 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
42348 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
42349 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
42350 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
42351 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
42352 \ -------------+------+------+------+------++---+---+---+---+---------+
42355 \ ******************************\
42356 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
42357 \ ******************************\
42358 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
42359 \ ------------------------------\
42360 \ define LPM mode for ACCEPT \
42361 \ ------------------------------\
42362 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42363 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42364 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42365 BIT.B #SW2,&SW2_IN \ test switch S2
42366 0= IF \ case of switch S2 pressed
42367 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
42369 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
42372 BIT.B #SW1,&SW1_IN \ test switch S1 input
42373 0= IF \ case of Switch S1 pressed
42374 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
42376 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
42380 RETI \ CPU is ON, GIE is OFF
42385 \ ------------------------------\
42386 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
42387 \ ******************************\
42388 ASM RC5_INT \ wake up on Px.RC5 change interrupt
42389 \ ******************************\
42390 \ \ in : SR(9)=old Toggle bit memory (ADD on)
42391 \ \ SMclock = 8|16|24 MHz
42392 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
42393 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
42394 \ \ SR(9)=new Toggle bit memory (ADD on)
42395 \ ------------------------------\
42396 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
42397 \ ------------------------------\
42398 \ define LPM mode for ACCEPT \
42399 \ ------------------------------\
42400 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42401 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42402 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42403 \ ------------------------------\
42404 \ RC5_FirstStartBitHalfCycle: \
42405 \ ------------------------------\
42406 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
42407 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
42408 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
42409 MOV #1778,X \ RC5_Period in us
42410 MOV #14,W \ count of loop
42412 \ ------------------------------\
42413 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
42414 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
42415 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
42416 \ RC5_Compute_3/4_Period: \ |
42417 RRUM #1,X \ X=1/2 cycle |
42421 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
42422 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
42424 \ ------------------------------\
42425 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
42426 \ ------------------------------\
42427 BIT.B #RC5,&IR_IN \ C_flag = IR bit
42428 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
42429 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
42430 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
42431 SUB #1,W \ decrement count loop
42432 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
42433 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
42434 0<> WHILE \ ----> out of loop ----+
42435 \ RC5_compute_7/4_Time_out: \ |
42436 ADD X,Y \ | out of bound = 7/4 period
42437 \ RC5_WaitHalfCycleP1.2_IFG: \ |
42439 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
42440 0>= IF \ | if cycle time out of bound
42441 BIC #$30,&TA0CTL \ | stop timer_A0
42442 RETI \ | then quit to do nothing
42444 \ ------------------------------\ |
42445 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
42447 MOV &TA0R,X \ | | get new RC5_period value
42448 REPEAT \ ----> loop back --+ |
42449 \ ------------------------------\ |
42450 \ RC5_SampleEndOf: \ <---------------------+
42451 \ ------------------------------\
42452 BIC #$30,&TA0CTL \ stop timer_A0
42453 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
42454 \ ******************************\
42455 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
42456 \ ******************************\
42457 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
42458 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
42459 XOR IP,X \ (new XOR old) Toggle bit (13)
42460 BIT #BIT13,X \ X(13) = New_RC5_command
42461 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
42463 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
42464 \ ******************************\
42465 \ RC5_ComputeNewRC5word \
42466 \ ******************************\
42468 MOV &BASE,2(PSP) \ save variable BASE before use
42469 MOV TOS,0(PSP) \ save TOS before use
42470 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
42471 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
42472 \ ******************************\
42473 \ RC5_ComputeC6bit \
42474 \ ******************************\
42475 BIT #$4000,IP \ test /C6 bit in IP
42476 0= IF BIS #$40,TOS \ set C6 bit in S
42477 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
42478 \ ******************************\
42479 \ RC5_CommandByteIsDone \ RC5_code --
42480 \ ******************************\
42482 \ ------------------------------\
42483 \ Display IR_RC5 code \
42484 \ ------------------------------\
42485 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
42486 \ ------------------------------\
42487 LO2HI \ switch from assembler to FORTH
42488 ['] LCD_CLEAR IS CR \ redirects CR
42489 ['] LCD_WrC IS EMIT \ redirects EMIT
42490 $10 BASE ! \ change BASE to hexadecimal
42491 CR ." $" 2 U.R \ print IR_RC5 code
42492 ['] (CR) IS CR \ restore CR
42493 ['] (EMIT) IS EMIT \ restore EMIT
42494 HI2LO \ switch from FORTH to assembler
42495 \ ------------------------------\
42496 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
42497 \ ------------------------------\
42498 MOV @PSP+,&BASE \ restore variable BASE
42499 RETI \ CPU is ON, GIE is OFF
42504 \ ------------------------------\
42505 \ TB0CTL = %0000 0010 1001 0100\$3C0
42506 \ - - \CNTL Counter lentgh \ 00 = 16 bits
42507 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
42508 \ -- \ID input divider \ 10 = /4
42509 \ -- \MC Mode Control \ 01 = up to TB0CCR0
42510 \ - \TBCLR TimerB Clear
42513 \ --------------------------------\\
42514 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
42515 \ -- \CM Capture Mode
42520 \ --- \OUTMOD \ 011 = set/reset
42526 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
42528 \ ------------------------------\
42529 \ set TimerB to make 50kHz PWM \
42530 \ ------------------------------\
42531 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42532 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
42533 \ ------------------------------\
42534 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42535 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
42536 \ ------------------------------\
42537 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42538 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
42539 \ ------------------------------\
42540 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42541 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
42542 \ ------------------------------\
42543 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42544 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
42545 \ ------------------------------\
42546 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
42547 \ ------------------------------\
42548 \ set TimerB to generate PWM for LCD_Vo
42549 \ ------------------------------\
42550 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
42551 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
42552 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
42553 \ ------------------------------\
42554 BIS.B #LCDVo,&LCDVo_DIR \
42555 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
42556 \ ------------------------------\
42557 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
42558 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
42559 \ ------------------------------\
42560 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
42561 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
42562 \ ------------------------------\
42563 \ WDT interval init part \
42564 \ ------------------------------\
42565 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
42566 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
42567 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
42568 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
42569 \ ------------------------------\
42571 \ ------------------------------\
42572 BIS.B #RC5,&IR_IE \ enable RC5_Int
42573 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
42574 \ ------------------------------\
42575 \ init interrupt vectors
42576 \ ------------------------------\
42577 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
42578 MOV #RC5_INT,&IR_Vec \ init interrupt vector
42579 \ ------------------------------\
42580 \ define LPM mode for ACCEPT \
42581 \ ------------------------------\
42582 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42583 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42584 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42586 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
42588 \ ------------------------------\
42590 \ ------------------------------\
42591 $03E8 20_US \ 1- wait 20 ms
42592 $03 TOP_LCD \ 2- send DB5=DB4=1
42593 $CD 20_US \ 3- wait 4,1 ms
42594 $03 TOP_LCD \ 4- send again DB5=DB4=1
42595 $5 20_US \ 5- wait 0,1 ms
42596 $03 TOP_LCD \ 6- send again again DB5=DB4=1
42597 $2 20_US \ wait 40 us = LCD cycle
42598 $02 TOP_LCD \ 7- send DB5=1 DB4=0
42599 $2 20_US \ wait 40 us = LCD cycle
42600 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
42601 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
42602 LCD_Clear \ 10- "LCD_Clear"
42603 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
42604 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
42605 LCD_Clear \ 10- "LCD_Clear"
42606 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
42607 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
42609 ['] (CR) IS CR \ ' (CR) is CR
42610 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
42612 ." RC5toLCD is running. Type STOP to quit"
42613 \ NOECHO \ uncomment to run this app without terminal connexion
42614 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
42615 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
42619 : STOP \ stops multitasking, must to be used before downloading app
42620 ['] (WARM) IS WARM \ remove START app from FORTH init process
42621 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
42629 CODE MAX \ n1 n2 -- n3 signed maximum
42630 CMP @PSP,TOS \ n2-n1
42631 S< ?GOTO FW1 \ n2<n1
42637 CODE MIN \ n1 n2 -- n3 signed minimum
42638 CMP @PSP,TOS \ n2-n1
42639 S< ?GOTO BW1 \ n2<n1
42645 : U.R \ u n -- display u unsigned in n width (n >= 2)
42647 R> OVER - 0 MAX SPACES TYPE
42651 CODE 20_US \ n -- n * 20 us
42652 BEGIN \ 3 cycles loop + 6~
42653 \ MOV #5,W \ 3 MCLK = 1 MHz
42654 \ MOV #23,W \ 3 MCLK = 4 MHz
42655 MOV #51,W \ 3 MCLK = 8 MHz
42656 \ MOV #104,W \ 3 MCLK = 16 MHz
42657 \ MOV #158,W \ 3 MCLK = 24 MHz
42658 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
42668 CODE TOP_LCD \ LCD Sample
42669 \ \ if write : %xxxxWWWW --
42670 \ \ if read : -- %0000RRRR
42671 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
42672 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
42673 0= IF \ write LCD bits pattern
42674 AND.B #LCD_DB,TOS \
42675 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
42676 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42679 THEN \ read LCD bits pattern
42682 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42683 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
42684 AND.B #LCD_DB,TOS \
42689 CODE LCD_W \ byte -- write byte to LCD
42691 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
42692 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
42693 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
42694 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
42695 COLON \ high level word starts here
42696 TOP_LCD 2 20_US \ write high nibble first
42701 CODE LCD_WrC \ char -- Write Char
42702 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42707 CODE LCD_WrF \ func -- Write Fonction
42708 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42714 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
42719 $02 LCD_WrF 100 20_us
42723 \ : LCD_Entry_set $04 OR LCD_WrF ;
42725 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
42727 \ : LCD_Display_Shift $10 OR LCD_WrF ;
42729 \ : LCD_Fn_Set $20 OR LCD_WrF ;
42731 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
42733 \ : LCD_Goto $80 OR LCD_WrF ;
42735 \ CODE LCD_R \ -- byte read byte from LCD
42736 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
42737 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
42738 \ COLON \ starts a FORTH word
42739 \ TOP_LCD 2 20_us \ -- %0000HHHH
42740 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
42741 \ HI2LO \ switch from FORTH to assembler
42742 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
42743 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
42744 \ MOV @RSP+,IP \ restore IP saved by COLON
42749 \ CODE LCD_RdS \ -- status Read Status
42750 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42755 \ CODE LCD_RdC \ -- char Read Char
42756 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42761 \ -------------+------+------+------+------++---+---+---+---+---------+
42762 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
42763 \ -------------+------+------+------+------++---+---+---+---+---------+
42764 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
42765 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
42766 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
42767 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
42768 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
42769 \ -------------+------+------+------+------++---+---+---+---+---------+
42772 \ ******************************\
42773 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
42774 \ ******************************\
42775 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
42776 \ ------------------------------\
42777 \ define LPM mode for ACCEPT \
42778 \ ------------------------------\
42779 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42780 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42781 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42782 BIT.B #SW2,&SW2_IN \ test switch S2
42783 0= IF \ case of switch S2 pressed
42784 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
42786 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
42789 BIT.B #SW1,&SW1_IN \ test switch S1 input
42790 0= IF \ case of Switch S1 pressed
42791 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
42793 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
42797 RETI \ CPU is ON, GIE is OFF
42802 \ ------------------------------\
42803 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
42804 \ ******************************\
42805 ASM RC5_INT \ wake up on Px.RC5 change interrupt
42806 \ ******************************\
42807 \ \ in : SR(9)=old Toggle bit memory (ADD on)
42808 \ \ SMclock = 8|16|24 MHz
42809 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
42810 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
42811 \ \ SR(9)=new Toggle bit memory (ADD on)
42812 \ ------------------------------\
42813 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
42814 \ ------------------------------\
42815 \ define LPM mode for ACCEPT \
42816 \ ------------------------------\
42817 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42818 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42819 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42820 \ ------------------------------\
42821 \ RC5_FirstStartBitHalfCycle: \
42822 \ ------------------------------\
42823 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
42824 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
42825 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
42826 MOV #1778,X \ RC5_Period in us
42827 MOV #14,W \ count of loop
42829 \ ------------------------------\
42830 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
42831 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
42832 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
42833 \ RC5_Compute_3/4_Period: \ |
42834 RRUM #1,X \ X=1/2 cycle |
42838 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
42839 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
42841 \ ------------------------------\
42842 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
42843 \ ------------------------------\
42844 BIT.B #RC5,&IR_IN \ C_flag = IR bit
42845 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
42846 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
42847 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
42848 SUB #1,W \ decrement count loop
42849 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
42850 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
42851 0<> WHILE \ ----> out of loop ----+
42852 \ RC5_compute_7/4_Time_out: \ |
42853 ADD X,Y \ | out of bound = 7/4 period
42854 \ RC5_WaitHalfCycleP1.2_IFG: \ |
42856 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
42857 0>= IF \ | if cycle time out of bound
42858 BIC #$30,&TA0CTL \ | stop timer_A0
42859 RETI \ | then quit to do nothing
42861 \ ------------------------------\ |
42862 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
42864 MOV &TA0R,X \ | | get new RC5_period value
42865 REPEAT \ ----> loop back --+ |
42866 \ ------------------------------\ |
42867 \ RC5_SampleEndOf: \ <---------------------+
42868 \ ------------------------------\
42869 BIC #$30,&TA0CTL \ stop timer_A0
42870 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
42871 \ ******************************\
42872 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
42873 \ ******************************\
42874 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
42875 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
42876 XOR IP,X \ (new XOR old) Toggle bit (13)
42877 BIT #BIT13,X \ X(13) = New_RC5_command
42878 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
42880 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
42881 \ ******************************\
42882 \ RC5_ComputeNewRC5word \
42883 \ ******************************\
42885 MOV &BASE,2(PSP) \ save variable BASE before use
42886 MOV TOS,0(PSP) \ save TOS before use
42887 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
42888 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
42889 \ ******************************\
42890 \ RC5_ComputeC6bit \
42891 \ ******************************\
42892 BIT #$4000,IP \ test /C6 bit in IP
42893 0= IF BIS #$40,TOS \ set C6 bit in S
42894 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
42895 \ ******************************\
42896 \ RC5_CommandByteIsDone \ RC5_code --
42897 \ ******************************\
42899 \ ------------------------------\
42900 \ Display IR_RC5 code \
42901 \ ------------------------------\
42902 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
42903 \ ------------------------------\
42904 LO2HI \ switch from assembler to FORTH
42905 ['] LCD_CLEAR IS CR \ redirects CR
42906 ['] LCD_WrC IS EMIT \ redirects EMIT
42907 $10 BASE ! \ change BASE to hexadecimal
42908 CR ." $" 2 U.R \ print IR_RC5 code
42909 ['] (CR) IS CR \ restore CR
42910 ['] (EMIT) IS EMIT \ restore EMIT
42911 HI2LO \ switch from FORTH to assembler
42912 \ ------------------------------\
42913 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
42914 \ ------------------------------\
42915 MOV @PSP+,&BASE \ restore variable BASE
42916 RETI \ CPU is ON, GIE is OFF
42921 \ ------------------------------\
42922 \ TB0CTL = %0000 0010 1001 0100\$3C0
42923 \ - - \CNTL Counter lentgh \ 00 = 16 bits
42924 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
42925 \ -- \ID input divider \ 10 = /4
42926 \ -- \MC Mode Control \ 01 = up to TB0CCR0
42927 \ - \TBCLR TimerB Clear
42930 \ --------------------------------\\
42931 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
42932 \ -- \CM Capture Mode
42937 \ --- \OUTMOD \ 011 = set/reset
42943 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
42945 \ ------------------------------\
42946 \ set TimerB to make 50kHz PWM \
42947 \ ------------------------------\
42948 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42949 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
42950 \ ------------------------------\
42951 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42952 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
42953 \ ------------------------------\
42954 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42955 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
42956 \ ------------------------------\
42957 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42958 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
42959 \ ------------------------------\
42960 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42961 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
42962 \ ------------------------------\
42963 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
42964 \ ------------------------------\
42965 \ set TimerB to generate PWM for LCD_Vo
42966 \ ------------------------------\
42967 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
42968 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
42969 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
42970 \ ------------------------------\
42971 BIS.B #LCDVo,&LCDVo_DIR \
42972 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
42973 \ ------------------------------\
42974 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
42975 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
42976 \ ------------------------------\
42977 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
42978 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
42979 \ ------------------------------\
42980 \ WDT interval init part \
42981 \ ------------------------------\
42982 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
42983 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
42984 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
42985 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
42986 \ ------------------------------\
42988 \ ------------------------------\
42989 BIS.B #RC5,&IR_IE \ enable RC5_Int
42990 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
42991 \ ------------------------------\
42992 \ init interrupt vectors
42993 \ ------------------------------\
42994 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
42995 MOV #RC5_INT,&IR_Vec \ init interrupt vector
42996 \ ------------------------------\
42997 \ define LPM mode for ACCEPT \
42998 \ ------------------------------\
42999 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43000 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43001 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43003 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
43005 \ ------------------------------\
43007 \ ------------------------------\
43008 $03E8 20_US \ 1- wait 20 ms
43009 $03 TOP_LCD \ 2- send DB5=DB4=1
43010 $CD 20_US \ 3- wait 4,1 ms
43011 $03 TOP_LCD \ 4- send again DB5=DB4=1
43012 $5 20_US \ 5- wait 0,1 ms
43013 $03 TOP_LCD \ 6- send again again DB5=DB4=1
43014 $2 20_US \ wait 40 us = LCD cycle
43015 $02 TOP_LCD \ 7- send DB5=1 DB4=0
43016 $2 20_US \ wait 40 us = LCD cycle
43017 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43018 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
43019 LCD_Clear \ 10- "LCD_Clear"
43020 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
43021 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
43022 LCD_Clear \ 10- "LCD_Clear"
43023 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
43024 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
43026 ['] (CR) IS CR \ ' (CR) is CR
43027 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
43029 ." RC5toLCD is running. Type STOP to quit"
43030 \ NOECHO \ uncomment to run this app without terminal connexion
43031 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
43032 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
43036 : STOP \ stops multitasking, must to be used before downloading app
43037 ['] (WARM) IS WARM \ remove START app from FORTH init process
43038 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
43046 CODE MAX \ n1 n2 -- n3 signed maximum
43047 CMP @PSP,TOS \ n2-n1
43048 S< ?GOTO FW1 \ n2<n1
43054 CODE MIN \ n1 n2 -- n3 signed minimum
43055 CMP @PSP,TOS \ n2-n1
43056 S< ?GOTO BW1 \ n2<n1
43062 : U.R \ u n -- display u unsigned in n width (n >= 2)
43064 R> OVER - 0 MAX SPACES TYPE
43068 CODE 20_US \ n -- n * 20 us
43069 BEGIN \ 3 cycles loop + 6~
43070 \ MOV #5,W \ 3 MCLK = 1 MHz
43071 \ MOV #23,W \ 3 MCLK = 4 MHz
43072 MOV #51,W \ 3 MCLK = 8 MHz
43073 \ MOV #104,W \ 3 MCLK = 16 MHz
43074 \ MOV #158,W \ 3 MCLK = 24 MHz
43075 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
43085 CODE TOP_LCD \ LCD Sample
43086 \ \ if write : %xxxxWWWW --
43087 \ \ if read : -- %0000RRRR
43088 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
43089 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
43090 0= IF \ write LCD bits pattern
43091 AND.B #LCD_DB,TOS \
43092 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
43093 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43096 THEN \ read LCD bits pattern
43099 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43100 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
43101 AND.B #LCD_DB,TOS \
43106 CODE LCD_W \ byte -- write byte to LCD
43108 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
43109 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
43110 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
43111 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
43112 COLON \ high level word starts here
43113 TOP_LCD 2 20_US \ write high nibble first
43118 CODE LCD_WrC \ char -- Write Char
43119 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43124 CODE LCD_WrF \ func -- Write Fonction
43125 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43131 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
43136 $02 LCD_WrF 100 20_us
43140 \ : LCD_Entry_set $04 OR LCD_WrF ;
43142 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
43144 \ : LCD_Display_Shift $10 OR LCD_WrF ;
43146 \ : LCD_Fn_Set $20 OR LCD_WrF ;
43148 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
43150 \ : LCD_Goto $80 OR LCD_WrF ;
43152 \ CODE LCD_R \ -- byte read byte from LCD
43153 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
43154 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
43155 \ COLON \ starts a FORTH word
43156 \ TOP_LCD 2 20_us \ -- %0000HHHH
43157 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
43158 \ HI2LO \ switch from FORTH to assembler
43159 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
43160 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
43161 \ MOV @RSP+,IP \ restore IP saved by COLON
43166 \ CODE LCD_RdS \ -- status Read Status
43167 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43172 \ CODE LCD_RdC \ -- char Read Char
43173 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43178 \ -------------+------+------+------+------++---+---+---+---+---------+
43179 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
43180 \ -------------+------+------+------+------++---+---+---+---+---------+
43181 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
43182 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
43183 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
43184 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
43185 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
43186 \ -------------+------+------+------+------++---+---+---+---+---------+
43189 \ ******************************\
43190 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
43191 \ ******************************\
43192 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
43193 \ ------------------------------\
43194 \ define LPM mode for ACCEPT \
43195 \ ------------------------------\
43196 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43197 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43198 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43199 BIT.B #SW2,&SW2_IN \ test switch S2
43200 0= IF \ case of switch S2 pressed
43201 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
43203 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
43206 BIT.B #SW1,&SW1_IN \ test switch S1 input
43207 0= IF \ case of Switch S1 pressed
43208 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
43210 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
43214 RETI \ CPU is ON, GIE is OFF
43219 \ ------------------------------\
43220 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
43221 \ ******************************\
43222 ASM RC5_INT \ wake up on Px.RC5 change interrupt
43223 \ ******************************\
43224 \ \ in : SR(9)=old Toggle bit memory (ADD on)
43225 \ \ SMclock = 8|16|24 MHz
43226 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
43227 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
43228 \ \ SR(9)=new Toggle bit memory (ADD on)
43229 \ ------------------------------\
43230 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
43231 \ ------------------------------\
43232 \ define LPM mode for ACCEPT \
43233 \ ------------------------------\
43234 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43235 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43236 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43237 \ ------------------------------\
43238 \ RC5_FirstStartBitHalfCycle: \
43239 \ ------------------------------\
43240 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
43241 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
43242 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
43243 MOV #1778,X \ RC5_Period in us
43244 MOV #14,W \ count of loop
43246 \ ------------------------------\
43247 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
43248 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
43249 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
43250 \ RC5_Compute_3/4_Period: \ |
43251 RRUM #1,X \ X=1/2 cycle |
43255 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
43256 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
43258 \ ------------------------------\
43259 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
43260 \ ------------------------------\
43261 BIT.B #RC5,&IR_IN \ C_flag = IR bit
43262 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
43263 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
43264 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
43265 SUB #1,W \ decrement count loop
43266 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
43267 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
43268 0<> WHILE \ ----> out of loop ----+
43269 \ RC5_compute_7/4_Time_out: \ |
43270 ADD X,Y \ | out of bound = 7/4 period
43271 \ RC5_WaitHalfCycleP1.2_IFG: \ |
43273 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
43274 0>= IF \ | if cycle time out of bound
43275 BIC #$30,&TA0CTL \ | stop timer_A0
43276 RETI \ | then quit to do nothing
43278 \ ------------------------------\ |
43279 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
43281 MOV &TA0R,X \ | | get new RC5_period value
43282 REPEAT \ ----> loop back --+ |
43283 \ ------------------------------\ |
43284 \ RC5_SampleEndOf: \ <---------------------+
43285 \ ------------------------------\
43286 BIC #$30,&TA0CTL \ stop timer_A0
43287 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
43288 \ ******************************\
43289 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
43290 \ ******************************\
43291 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
43292 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
43293 XOR IP,X \ (new XOR old) Toggle bit (13)
43294 BIT #BIT13,X \ X(13) = New_RC5_command
43295 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
43297 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
43298 \ ******************************\
43299 \ RC5_ComputeNewRC5word \
43300 \ ******************************\
43302 MOV &BASE,2(PSP) \ save variable BASE before use
43303 MOV TOS,0(PSP) \ save TOS before use
43304 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
43305 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
43306 \ ******************************\
43307 \ RC5_ComputeC6bit \
43308 \ ******************************\
43309 BIT #$4000,IP \ test /C6 bit in IP
43310 0= IF BIS #$40,TOS \ set C6 bit in S
43311 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
43312 \ ******************************\
43313 \ RC5_CommandByteIsDone \ RC5_code --
43314 \ ******************************\
43316 \ ------------------------------\
43317 \ Display IR_RC5 code \
43318 \ ------------------------------\
43319 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
43320 \ ------------------------------\
43321 LO2HI \ switch from assembler to FORTH
43322 ['] LCD_CLEAR IS CR \ redirects CR
43323 ['] LCD_WrC IS EMIT \ redirects EMIT
43324 $10 BASE ! \ change BASE to hexadecimal
43325 CR ." $" 2 U.R \ print IR_RC5 code
43326 ['] (CR) IS CR \ restore CR
43327 ['] (EMIT) IS EMIT \ restore EMIT
43328 HI2LO \ switch from FORTH to assembler
43329 \ ------------------------------\
43330 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
43331 \ ------------------------------\
43332 MOV @PSP+,&BASE \ restore variable BASE
43333 RETI \ CPU is ON, GIE is OFF
43338 \ ------------------------------\
43339 \ TB0CTL = %0000 0010 1001 0100\$3C0
43340 \ - - \CNTL Counter lentgh \ 00 = 16 bits
43341 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
43342 \ -- \ID input divider \ 10 = /4
43343 \ -- \MC Mode Control \ 01 = up to TB0CCR0
43344 \ - \TBCLR TimerB Clear
43347 \ --------------------------------\\
43348 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
43349 \ -- \CM Capture Mode
43354 \ --- \OUTMOD \ 011 = set/reset
43360 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
43362 \ ------------------------------\
43363 \ set TimerB to make 50kHz PWM \
43364 \ ------------------------------\
43365 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
43366 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
43367 \ ------------------------------\
43368 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
43369 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
43370 \ ------------------------------\
43371 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43372 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
43373 \ ------------------------------\
43374 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43375 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
43376 \ ------------------------------\
43377 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43378 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
43379 \ ------------------------------\
43380 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
43381 \ ------------------------------\
43382 \ set TimerB to generate PWM for LCD_Vo
43383 \ ------------------------------\
43384 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
43385 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
43386 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
43387 \ ------------------------------\
43388 BIS.B #LCDVo,&LCDVo_DIR \
43389 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
43390 \ ------------------------------\
43391 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
43392 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
43393 \ ------------------------------\
43394 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
43395 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
43396 \ ------------------------------\
43397 \ WDT interval init part \
43398 \ ------------------------------\
43399 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
43400 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
43401 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
43402 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
43403 \ ------------------------------\
43405 \ ------------------------------\
43406 BIS.B #RC5,&IR_IE \ enable RC5_Int
43407 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
43408 \ ------------------------------\
43409 \ init interrupt vectors
43410 \ ------------------------------\
43411 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
43412 MOV #RC5_INT,&IR_Vec \ init interrupt vector
43413 \ ------------------------------\
43414 \ define LPM mode for ACCEPT \
43415 \ ------------------------------\
43416 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43417 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43418 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43420 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
43422 \ ------------------------------\
43424 \ ------------------------------\
43425 $03E8 20_US \ 1- wait 20 ms
43426 $03 TOP_LCD \ 2- send DB5=DB4=1
43427 $CD 20_US \ 3- wait 4,1 ms
43428 $03 TOP_LCD \ 4- send again DB5=DB4=1
43429 $5 20_US \ 5- wait 0,1 ms
43430 $03 TOP_LCD \ 6- send again again DB5=DB4=1
43431 $2 20_US \ wait 40 us = LCD cycle
43432 $02 TOP_LCD \ 7- send DB5=1 DB4=0
43433 $2 20_US \ wait 40 us = LCD cycle
43434 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43435 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
43436 LCD_Clear \ 10- "LCD_Clear"
43437 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
43438 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
43439 LCD_Clear \ 10- "LCD_Clear"
43440 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
43441 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
43443 ['] (CR) IS CR \ ' (CR) is CR
43444 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
43446 ." RC5toLCD is running. Type STOP to quit"
43447 \ NOECHO \ uncomment to run this app without terminal connexion
43448 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
43449 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
43453 : STOP \ stops multitasking, must to be used before downloading app
43454 ['] (WARM) IS WARM \ remove START app from FORTH init process
43455 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
43463 CODE MAX \ n1 n2 -- n3 signed maximum
43464 CMP @PSP,TOS \ n2-n1
43465 S< ?GOTO FW1 \ n2<n1
43471 CODE MIN \ n1 n2 -- n3 signed minimum
43472 CMP @PSP,TOS \ n2-n1
43473 S< ?GOTO BW1 \ n2<n1
43479 : U.R \ u n -- display u unsigned in n width (n >= 2)
43481 R> OVER - 0 MAX SPACES TYPE
43485 CODE 20_US \ n -- n * 20 us
43486 BEGIN \ 3 cycles loop + 6~
43487 \ MOV #5,W \ 3 MCLK = 1 MHz
43488 \ MOV #23,W \ 3 MCLK = 4 MHz
43489 MOV #51,W \ 3 MCLK = 8 MHz
43490 \ MOV #104,W \ 3 MCLK = 16 MHz
43491 \ MOV #158,W \ 3 MCLK = 24 MHz
43492 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
43502 CODE TOP_LCD \ LCD Sample
43503 \ \ if write : %xxxxWWWW --
43504 \ \ if read : -- %0000RRRR
43505 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
43506 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
43507 0= IF \ write LCD bits pattern
43508 AND.B #LCD_DB,TOS \
43509 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
43510 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43513 THEN \ read LCD bits pattern
43516 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43517 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
43518 AND.B #LCD_DB,TOS \
43523 CODE LCD_W \ byte -- write byte to LCD
43525 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
43526 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
43527 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
43528 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
43529 COLON \ high level word starts here
43530 TOP_LCD 2 20_US \ write high nibble first
43535 CODE LCD_WrC \ char -- Write Char
43536 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43541 CODE LCD_WrF \ func -- Write Fonction
43542 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43548 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
43553 $02 LCD_WrF 100 20_us
43557 \ : LCD_Entry_set $04 OR LCD_WrF ;
43559 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
43561 \ : LCD_Display_Shift $10 OR LCD_WrF ;
43563 \ : LCD_Fn_Set $20 OR LCD_WrF ;
43565 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
43567 \ : LCD_Goto $80 OR LCD_WrF ;
43569 \ CODE LCD_R \ -- byte read byte from LCD
43570 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
43571 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
43572 \ COLON \ starts a FORTH word
43573 \ TOP_LCD 2 20_us \ -- %0000HHHH
43574 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
43575 \ HI2LO \ switch from FORTH to assembler
43576 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
43577 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
43578 \ MOV @RSP+,IP \ restore IP saved by COLON
43583 \ CODE LCD_RdS \ -- status Read Status
43584 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43589 \ CODE LCD_RdC \ -- char Read Char
43590 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43595 \ -------------+------+------+------+------++---+---+---+---+---------+
43596 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
43597 \ -------------+------+------+------+------++---+---+---+---+---------+
43598 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
43599 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
43600 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
43601 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
43602 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
43603 \ -------------+------+------+------+------++---+---+---+---+---------+
43606 \ ******************************\
43607 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
43608 \ ******************************\
43609 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
43610 \ ------------------------------\
43611 \ define LPM mode for ACCEPT \
43612 \ ------------------------------\
43613 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43614 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43615 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43616 BIT.B #SW2,&SW2_IN \ test switch S2
43617 0= IF \ case of switch S2 pressed
43618 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
43620 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
43623 BIT.B #SW1,&SW1_IN \ test switch S1 input
43624 0= IF \ case of Switch S1 pressed
43625 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
43627 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
43631 RETI \ CPU is ON, GIE is OFF
43636 \ ------------------------------\
43637 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
43638 \ ******************************\
43639 ASM RC5_INT \ wake up on Px.RC5 change interrupt
43640 \ ******************************\
43641 \ \ in : SR(9)=old Toggle bit memory (ADD on)
43642 \ \ SMclock = 8|16|24 MHz
43643 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
43644 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
43645 \ \ SR(9)=new Toggle bit memory (ADD on)
43646 \ ------------------------------\
43647 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
43648 \ ------------------------------\
43649 \ define LPM mode for ACCEPT \
43650 \ ------------------------------\
43651 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43652 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43653 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43654 \ ------------------------------\
43655 \ RC5_FirstStartBitHalfCycle: \
43656 \ ------------------------------\
43657 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
43658 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
43659 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
43660 MOV #1778,X \ RC5_Period in us
43661 MOV #14,W \ count of loop
43663 \ ------------------------------\
43664 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
43665 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
43666 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
43667 \ RC5_Compute_3/4_Period: \ |
43668 RRUM #1,X \ X=1/2 cycle |
43672 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
43673 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
43675 \ ------------------------------\
43676 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
43677 \ ------------------------------\
43678 BIT.B #RC5,&IR_IN \ C_flag = IR bit
43679 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
43680 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
43681 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
43682 SUB #1,W \ decrement count loop
43683 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
43684 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
43685 0<> WHILE \ ----> out of loop ----+
43686 \ RC5_compute_7/4_Time_out: \ |
43687 ADD X,Y \ | out of bound = 7/4 period
43688 \ RC5_WaitHalfCycleP1.2_IFG: \ |
43690 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
43691 0>= IF \ | if cycle time out of bound
43692 BIC #$30,&TA0CTL \ | stop timer_A0
43693 RETI \ | then quit to do nothing
43695 \ ------------------------------\ |
43696 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
43698 MOV &TA0R,X \ | | get new RC5_period value
43699 REPEAT \ ----> loop back --+ |
43700 \ ------------------------------\ |
43701 \ RC5_SampleEndOf: \ <---------------------+
43702 \ ------------------------------\
43703 BIC #$30,&TA0CTL \ stop timer_A0
43704 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
43705 \ ******************************\
43706 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
43707 \ ******************************\
43708 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
43709 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
43710 XOR IP,X \ (new XOR old) Toggle bit (13)
43711 BIT #BIT13,X \ X(13) = New_RC5_command
43712 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
43714 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
43715 \ ******************************\
43716 \ RC5_ComputeNewRC5word \
43717 \ ******************************\
43719 MOV &BASE,2(PSP) \ save variable BASE before use
43720 MOV TOS,0(PSP) \ save TOS before use
43721 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
43722 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
43723 \ ******************************\
43724 \ RC5_ComputeC6bit \
43725 \ ******************************\
43726 BIT #$4000,IP \ test /C6 bit in IP
43727 0= IF BIS #$40,TOS \ set C6 bit in S
43728 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
43729 \ ******************************\
43730 \ RC5_CommandByteIsDone \ RC5_code --
43731 \ ******************************\
43733 \ ------------------------------\
43734 \ Display IR_RC5 code \
43735 \ ------------------------------\
43736 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
43737 \ ------------------------------\
43738 LO2HI \ switch from assembler to FORTH
43739 ['] LCD_CLEAR IS CR \ redirects CR
43740 ['] LCD_WrC IS EMIT \ redirects EMIT
43741 $10 BASE ! \ change BASE to hexadecimal
43742 CR ." $" 2 U.R \ print IR_RC5 code
43743 ['] (CR) IS CR \ restore CR
43744 ['] (EMIT) IS EMIT \ restore EMIT
43745 HI2LO \ switch from FORTH to assembler
43746 \ ------------------------------\
43747 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
43748 \ ------------------------------\
43749 MOV @PSP+,&BASE \ restore variable BASE
43750 RETI \ CPU is ON, GIE is OFF
43755 \ ------------------------------\
43756 \ TB0CTL = %0000 0010 1001 0100\$3C0
43757 \ - - \CNTL Counter lentgh \ 00 = 16 bits
43758 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
43759 \ -- \ID input divider \ 10 = /4
43760 \ -- \MC Mode Control \ 01 = up to TB0CCR0
43761 \ - \TBCLR TimerB Clear
43764 \ --------------------------------\\
43765 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
43766 \ -- \CM Capture Mode
43771 \ --- \OUTMOD \ 011 = set/reset
43777 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
43779 \ ------------------------------\
43780 \ set TimerB to make 50kHz PWM \
43781 \ ------------------------------\
43782 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
43783 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
43784 \ ------------------------------\
43785 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
43786 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
43787 \ ------------------------------\
43788 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43789 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
43790 \ ------------------------------\
43791 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43792 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
43793 \ ------------------------------\
43794 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43795 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
43796 \ ------------------------------\
43797 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
43798 \ ------------------------------\
43799 \ set TimerB to generate PWM for LCD_Vo
43800 \ ------------------------------\
43801 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
43802 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
43803 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
43804 \ ------------------------------\
43805 BIS.B #LCDVo,&LCDVo_DIR \
43806 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
43807 \ ------------------------------\
43808 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
43809 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
43810 \ ------------------------------\
43811 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
43812 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
43813 \ ------------------------------\
43814 \ WDT interval init part \
43815 \ ------------------------------\
43816 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
43817 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
43818 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
43819 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
43820 \ ------------------------------\
43822 \ ------------------------------\
43823 BIS.B #RC5,&IR_IE \ enable RC5_Int
43824 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
43825 \ ------------------------------\
43826 \ init interrupt vectors
43827 \ ------------------------------\
43828 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
43829 MOV #RC5_INT,&IR_Vec \ init interrupt vector
43830 \ ------------------------------\
43831 \ define LPM mode for ACCEPT \
43832 \ ------------------------------\
43833 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43834 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43835 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43837 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
43839 \ ------------------------------\
43841 \ ------------------------------\
43842 $03E8 20_US \ 1- wait 20 ms
43843 $03 TOP_LCD \ 2- send DB5=DB4=1
43844 $CD 20_US \ 3- wait 4,1 ms
43845 $03 TOP_LCD \ 4- send again DB5=DB4=1
43846 $5 20_US \ 5- wait 0,1 ms
43847 $03 TOP_LCD \ 6- send again again DB5=DB4=1
43848 $2 20_US \ wait 40 us = LCD cycle
43849 $02 TOP_LCD \ 7- send DB5=1 DB4=0
43850 $2 20_US \ wait 40 us = LCD cycle
43851 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43852 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
43853 LCD_Clear \ 10- "LCD_Clear"
43854 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
43855 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
43856 LCD_Clear \ 10- "LCD_Clear"
43857 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
43858 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
43860 ['] (CR) IS CR \ ' (CR) is CR
43861 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
43863 ." RC5toLCD is running. Type STOP to quit"
43864 \ NOECHO \ uncomment to run this app without terminal connexion
43865 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
43866 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
43870 : STOP \ stops multitasking, must to be used before downloading app
43871 ['] (WARM) IS WARM \ remove START app from FORTH init process
43872 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
43880 CODE MAX \ n1 n2 -- n3 signed maximum
43881 CMP @PSP,TOS \ n2-n1
43882 S< ?GOTO FW1 \ n2<n1
43888 CODE MIN \ n1 n2 -- n3 signed minimum
43889 CMP @PSP,TOS \ n2-n1
43890 S< ?GOTO BW1 \ n2<n1
43896 : U.R \ u n -- display u unsigned in n width (n >= 2)
43898 R> OVER - 0 MAX SPACES TYPE
43902 CODE 20_US \ n -- n * 20 us
43903 BEGIN \ 3 cycles loop + 6~
43904 \ MOV #5,W \ 3 MCLK = 1 MHz
43905 \ MOV #23,W \ 3 MCLK = 4 MHz
43906 MOV #51,W \ 3 MCLK = 8 MHz
43907 \ MOV #104,W \ 3 MCLK = 16 MHz
43908 \ MOV #158,W \ 3 MCLK = 24 MHz
43909 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
43919 CODE TOP_LCD \ LCD Sample
43920 \ \ if write : %xxxxWWWW --
43921 \ \ if read : -- %0000RRRR
43922 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
43923 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
43924 0= IF \ write LCD bits pattern
43925 AND.B #LCD_DB,TOS \
43926 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
43927 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43930 THEN \ read LCD bits pattern
43933 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43934 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
43935 AND.B #LCD_DB,TOS \
43940 CODE LCD_W \ byte -- write byte to LCD
43942 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
43943 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
43944 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
43945 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
43946 COLON \ high level word starts here
43947 TOP_LCD 2 20_US \ write high nibble first
43952 CODE LCD_WrC \ char -- Write Char
43953 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43958 CODE LCD_WrF \ func -- Write Fonction
43959 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43965 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
43970 $02 LCD_WrF 100 20_us
43974 \ : LCD_Entry_set $04 OR LCD_WrF ;
43976 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
43978 \ : LCD_Display_Shift $10 OR LCD_WrF ;
43980 \ : LCD_Fn_Set $20 OR LCD_WrF ;
43982 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
43984 \ : LCD_Goto $80 OR LCD_WrF ;
43986 \ CODE LCD_R \ -- byte read byte from LCD
43987 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
43988 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
43989 \ COLON \ starts a FORTH word
43990 \ TOP_LCD 2 20_us \ -- %0000HHHH
43991 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
43992 \ HI2LO \ switch from FORTH to assembler
43993 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
43994 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
43995 \ MOV @RSP+,IP \ restore IP saved by COLON
44000 \ CODE LCD_RdS \ -- status Read Status
44001 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44006 \ CODE LCD_RdC \ -- char Read Char
44007 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44012 \ -------------+------+------+------+------++---+---+---+---+---------+
44013 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
44014 \ -------------+------+------+------+------++---+---+---+---+---------+
44015 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
44016 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
44017 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
44018 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
44019 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
44020 \ -------------+------+------+------+------++---+---+---+---+---------+
44023 \ ******************************\
44024 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
44025 \ ******************************\
44026 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
44027 \ ------------------------------\
44028 \ define LPM mode for ACCEPT \
44029 \ ------------------------------\
44030 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44031 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44032 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44033 BIT.B #SW2,&SW2_IN \ test switch S2
44034 0= IF \ case of switch S2 pressed
44035 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
44037 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
44040 BIT.B #SW1,&SW1_IN \ test switch S1 input
44041 0= IF \ case of Switch S1 pressed
44042 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
44044 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
44048 RETI \ CPU is ON, GIE is OFF
44053 \ ------------------------------\
44054 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
44055 \ ******************************\
44056 ASM RC5_INT \ wake up on Px.RC5 change interrupt
44057 \ ******************************\
44058 \ \ in : SR(9)=old Toggle bit memory (ADD on)
44059 \ \ SMclock = 8|16|24 MHz
44060 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
44061 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
44062 \ \ SR(9)=new Toggle bit memory (ADD on)
44063 \ ------------------------------\
44064 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
44065 \ ------------------------------\
44066 \ define LPM mode for ACCEPT \
44067 \ ------------------------------\
44068 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44069 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44070 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44071 \ ------------------------------\
44072 \ RC5_FirstStartBitHalfCycle: \
44073 \ ------------------------------\
44074 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
44075 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
44076 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
44077 MOV #1778,X \ RC5_Period in us
44078 MOV #14,W \ count of loop
44080 \ ------------------------------\
44081 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
44082 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
44083 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
44084 \ RC5_Compute_3/4_Period: \ |
44085 RRUM #1,X \ X=1/2 cycle |
44089 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
44090 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
44092 \ ------------------------------\
44093 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
44094 \ ------------------------------\
44095 BIT.B #RC5,&IR_IN \ C_flag = IR bit
44096 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
44097 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
44098 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
44099 SUB #1,W \ decrement count loop
44100 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
44101 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
44102 0<> WHILE \ ----> out of loop ----+
44103 \ RC5_compute_7/4_Time_out: \ |
44104 ADD X,Y \ | out of bound = 7/4 period
44105 \ RC5_WaitHalfCycleP1.2_IFG: \ |
44107 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
44108 0>= IF \ | if cycle time out of bound
44109 BIC #$30,&TA0CTL \ | stop timer_A0
44110 RETI \ | then quit to do nothing
44112 \ ------------------------------\ |
44113 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
44115 MOV &TA0R,X \ | | get new RC5_period value
44116 REPEAT \ ----> loop back --+ |
44117 \ ------------------------------\ |
44118 \ RC5_SampleEndOf: \ <---------------------+
44119 \ ------------------------------\
44120 BIC #$30,&TA0CTL \ stop timer_A0
44121 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
44122 \ ******************************\
44123 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
44124 \ ******************************\
44125 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
44126 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
44127 XOR IP,X \ (new XOR old) Toggle bit (13)
44128 BIT #BIT13,X \ X(13) = New_RC5_command
44129 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
44131 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
44132 \ ******************************\
44133 \ RC5_ComputeNewRC5word \
44134 \ ******************************\
44136 MOV &BASE,2(PSP) \ save variable BASE before use
44137 MOV TOS,0(PSP) \ save TOS before use
44138 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
44139 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
44140 \ ******************************\
44141 \ RC5_ComputeC6bit \
44142 \ ******************************\
44143 BIT #$4000,IP \ test /C6 bit in IP
44144 0= IF BIS #$40,TOS \ set C6 bit in S
44145 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
44146 \ ******************************\
44147 \ RC5_CommandByteIsDone \ RC5_code --
44148 \ ******************************\
44150 \ ------------------------------\
44151 \ Display IR_RC5 code \
44152 \ ------------------------------\
44153 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
44154 \ ------------------------------\
44155 LO2HI \ switch from assembler to FORTH
44156 ['] LCD_CLEAR IS CR \ redirects CR
44157 ['] LCD_WrC IS EMIT \ redirects EMIT
44158 $10 BASE ! \ change BASE to hexadecimal
44159 CR ." $" 2 U.R \ print IR_RC5 code
44160 ['] (CR) IS CR \ restore CR
44161 ['] (EMIT) IS EMIT \ restore EMIT
44162 HI2LO \ switch from FORTH to assembler
44163 \ ------------------------------\
44164 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
44165 \ ------------------------------\
44166 MOV @PSP+,&BASE \ restore variable BASE
44167 RETI \ CPU is ON, GIE is OFF
44172 \ ------------------------------\
44173 \ TB0CTL = %0000 0010 1001 0100\$3C0
44174 \ - - \CNTL Counter lentgh \ 00 = 16 bits
44175 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
44176 \ -- \ID input divider \ 10 = /4
44177 \ -- \MC Mode Control \ 01 = up to TB0CCR0
44178 \ - \TBCLR TimerB Clear
44181 \ --------------------------------\\
44182 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
44183 \ -- \CM Capture Mode
44188 \ --- \OUTMOD \ 011 = set/reset
44194 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
44196 \ ------------------------------\
44197 \ set TimerB to make 50kHz PWM \
44198 \ ------------------------------\
44199 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
44200 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
44201 \ ------------------------------\
44202 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
44203 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
44204 \ ------------------------------\
44205 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44206 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
44207 \ ------------------------------\
44208 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44209 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
44210 \ ------------------------------\
44211 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44212 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
44213 \ ------------------------------\
44214 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
44215 \ ------------------------------\
44216 \ set TimerB to generate PWM for LCD_Vo
44217 \ ------------------------------\
44218 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
44219 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
44220 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
44221 \ ------------------------------\
44222 BIS.B #LCDVo,&LCDVo_DIR \
44223 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
44224 \ ------------------------------\
44225 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
44226 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
44227 \ ------------------------------\
44228 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
44229 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
44230 \ ------------------------------\
44231 \ WDT interval init part \
44232 \ ------------------------------\
44233 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
44234 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
44235 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
44236 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
44237 \ ------------------------------\
44239 \ ------------------------------\
44240 BIS.B #RC5,&IR_IE \ enable RC5_Int
44241 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
44242 \ ------------------------------\
44243 \ init interrupt vectors
44244 \ ------------------------------\
44245 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
44246 MOV #RC5_INT,&IR_Vec \ init interrupt vector
44247 \ ------------------------------\
44248 \ define LPM mode for ACCEPT \
44249 \ ------------------------------\
44250 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44251 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44252 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44254 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
44256 \ ------------------------------\
44258 \ ------------------------------\
44259 $03E8 20_US \ 1- wait 20 ms
44260 $03 TOP_LCD \ 2- send DB5=DB4=1
44261 $CD 20_US \ 3- wait 4,1 ms
44262 $03 TOP_LCD \ 4- send again DB5=DB4=1
44263 $5 20_US \ 5- wait 0,1 ms
44264 $03 TOP_LCD \ 6- send again again DB5=DB4=1
44265 $2 20_US \ wait 40 us = LCD cycle
44266 $02 TOP_LCD \ 7- send DB5=1 DB4=0
44267 $2 20_US \ wait 40 us = LCD cycle
44268 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
44269 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
44270 LCD_Clear \ 10- "LCD_Clear"
44271 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
44272 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
44273 LCD_Clear \ 10- "LCD_Clear"
44274 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
44275 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
44277 ['] (CR) IS CR \ ' (CR) is CR
44278 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
44280 ." RC5toLCD is running. Type STOP to quit"
44281 \ NOECHO \ uncomment to run this app without terminal connexion
44282 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
44283 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
44287 : STOP \ stops multitasking, must to be used before downloading app
44288 ['] (WARM) IS WARM \ remove START app from FORTH init process
44289 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
44297 CODE MAX \ n1 n2 -- n3 signed maximum
44298 CMP @PSP,TOS \ n2-n1
44299 S< ?GOTO FW1 \ n2<n1
44305 CODE MIN \ n1 n2 -- n3 signed minimum
44306 CMP @PSP,TOS \ n2-n1
44307 S< ?GOTO BW1 \ n2<n1
44313 : U.R \ u n -- display u unsigned in n width (n >= 2)
44315 R> OVER - 0 MAX SPACES TYPE
44319 CODE 20_US \ n -- n * 20 us
44320 BEGIN \ 3 cycles loop + 6~
44321 \ MOV #5,W \ 3 MCLK = 1 MHz
44322 \ MOV #23,W \ 3 MCLK = 4 MHz
44323 MOV #51,W \ 3 MCLK = 8 MHz
44324 \ MOV #104,W \ 3 MCLK = 16 MHz
44325 \ MOV #158,W \ 3 MCLK = 24 MHz
44326 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
44336 CODE TOP_LCD \ LCD Sample
44337 \ \ if write : %xxxxWWWW --
44338 \ \ if read : -- %0000RRRR
44339 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
44340 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
44341 0= IF \ write LCD bits pattern
44342 AND.B #LCD_DB,TOS \
44343 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
44344 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44347 THEN \ read LCD bits pattern
44350 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44351 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
44352 AND.B #LCD_DB,TOS \
44357 CODE LCD_W \ byte -- write byte to LCD
44359 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
44360 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
44361 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
44362 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
44363 COLON \ high level word starts here
44364 TOP_LCD 2 20_US \ write high nibble first
44369 CODE LCD_WrC \ char -- Write Char
44370 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44375 CODE LCD_WrF \ func -- Write Fonction
44376 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44382 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
44387 $02 LCD_WrF 100 20_us
44391 \ : LCD_Entry_set $04 OR LCD_WrF ;
44393 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
44395 \ : LCD_Display_Shift $10 OR LCD_WrF ;
44397 \ : LCD_Fn_Set $20 OR LCD_WrF ;
44399 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
44401 \ : LCD_Goto $80 OR LCD_WrF ;
44403 \ CODE LCD_R \ -- byte read byte from LCD
44404 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
44405 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
44406 \ COLON \ starts a FORTH word
44407 \ TOP_LCD 2 20_us \ -- %0000HHHH
44408 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
44409 \ HI2LO \ switch from FORTH to assembler
44410 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
44411 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
44412 \ MOV @RSP+,IP \ restore IP saved by COLON
44417 \ CODE LCD_RdS \ -- status Read Status
44418 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44423 \ CODE LCD_RdC \ -- char Read Char
44424 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44429 \ -------------+------+------+------+------++---+---+---+---+---------+
44430 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
44431 \ -------------+------+------+------+------++---+---+---+---+---------+
44432 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
44433 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
44434 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
44435 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
44436 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
44437 \ -------------+------+------+------+------++---+---+---+---+---------+
44440 \ ******************************\
44441 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
44442 \ ******************************\
44443 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
44444 \ ------------------------------\
44445 \ define LPM mode for ACCEPT \
44446 \ ------------------------------\
44447 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44448 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44449 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44450 BIT.B #SW2,&SW2_IN \ test switch S2
44451 0= IF \ case of switch S2 pressed
44452 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
44454 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
44457 BIT.B #SW1,&SW1_IN \ test switch S1 input
44458 0= IF \ case of Switch S1 pressed
44459 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
44461 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
44465 RETI \ CPU is ON, GIE is OFF
44470 \ ------------------------------\
44471 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
44472 \ ******************************\
44473 ASM RC5_INT \ wake up on Px.RC5 change interrupt
44474 \ ******************************\
44475 \ \ in : SR(9)=old Toggle bit memory (ADD on)
44476 \ \ SMclock = 8|16|24 MHz
44477 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
44478 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
44479 \ \ SR(9)=new Toggle bit memory (ADD on)
44480 \ ------------------------------\
44481 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
44482 \ ------------------------------\
44483 \ define LPM mode for ACCEPT \
44484 \ ------------------------------\
44485 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44486 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44487 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44488 \ ------------------------------\
44489 \ RC5_FirstStartBitHalfCycle: \
44490 \ ------------------------------\
44491 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
44492 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
44493 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
44494 MOV #1778,X \ RC5_Period in us
44495 MOV #14,W \ count of loop
44497 \ ------------------------------\
44498 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
44499 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
44500 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
44501 \ RC5_Compute_3/4_Period: \ |
44502 RRUM #1,X \ X=1/2 cycle |
44506 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
44507 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
44509 \ ------------------------------\
44510 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
44511 \ ------------------------------\
44512 BIT.B #RC5,&IR_IN \ C_flag = IR bit
44513 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
44514 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
44515 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
44516 SUB #1,W \ decrement count loop
44517 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
44518 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
44519 0<> WHILE \ ----> out of loop ----+
44520 \ RC5_compute_7/4_Time_out: \ |
44521 ADD X,Y \ | out of bound = 7/4 period
44522 \ RC5_WaitHalfCycleP1.2_IFG: \ |
44524 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
44525 0>= IF \ | if cycle time out of bound
44526 BIC #$30,&TA0CTL \ | stop timer_A0
44527 RETI \ | then quit to do nothing
44529 \ ------------------------------\ |
44530 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
44532 MOV &TA0R,X \ | | get new RC5_period value
44533 REPEAT \ ----> loop back --+ |
44534 \ ------------------------------\ |
44535 \ RC5_SampleEndOf: \ <---------------------+
44536 \ ------------------------------\
44537 BIC #$30,&TA0CTL \ stop timer_A0
44538 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
44539 \ ******************************\
44540 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
44541 \ ******************************\
44542 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
44543 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
44544 XOR IP,X \ (new XOR old) Toggle bit (13)
44545 BIT #BIT13,X \ X(13) = New_RC5_command
44546 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
44548 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
44549 \ ******************************\
44550 \ RC5_ComputeNewRC5word \
44551 \ ******************************\
44553 MOV &BASE,2(PSP) \ save variable BASE before use
44554 MOV TOS,0(PSP) \ save TOS before use
44555 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
44556 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
44557 \ ******************************\
44558 \ RC5_ComputeC6bit \
44559 \ ******************************\
44560 BIT #$4000,IP \ test /C6 bit in IP
44561 0= IF BIS #$40,TOS \ set C6 bit in S
44562 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
44563 \ ******************************\
44564 \ RC5_CommandByteIsDone \ RC5_code --
44565 \ ******************************\
44567 \ ------------------------------\
44568 \ Display IR_RC5 code \
44569 \ ------------------------------\
44570 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
44571 \ ------------------------------\
44572 LO2HI \ switch from assembler to FORTH
44573 ['] LCD_CLEAR IS CR \ redirects CR
44574 ['] LCD_WrC IS EMIT \ redirects EMIT
44575 $10 BASE ! \ change BASE to hexadecimal
44576 CR ." $" 2 U.R \ print IR_RC5 code
44577 ['] (CR) IS CR \ restore CR
44578 ['] (EMIT) IS EMIT \ restore EMIT
44579 HI2LO \ switch from FORTH to assembler
44580 \ ------------------------------\
44581 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
44582 \ ------------------------------\
44583 MOV @PSP+,&BASE \ restore variable BASE
44584 RETI \ CPU is ON, GIE is OFF
44589 \ ------------------------------\
44590 \ TB0CTL = %0000 0010 1001 0100\$3C0
44591 \ - - \CNTL Counter lentgh \ 00 = 16 bits
44592 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
44593 \ -- \ID input divider \ 10 = /4
44594 \ -- \MC Mode Control \ 01 = up to TB0CCR0
44595 \ - \TBCLR TimerB Clear
44598 \ --------------------------------\\
44599 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
44600 \ -- \CM Capture Mode
44605 \ --- \OUTMOD \ 011 = set/reset
44611 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
44613 \ ------------------------------\
44614 \ set TimerB to make 50kHz PWM \
44615 \ ------------------------------\
44616 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
44617 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
44618 \ ------------------------------\
44619 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
44620 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
44621 \ ------------------------------\
44622 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44623 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
44624 \ ------------------------------\
44625 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44626 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
44627 \ ------------------------------\
44628 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44629 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
44630 \ ------------------------------\
44631 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
44632 \ ------------------------------\
44633 \ set TimerB to generate PWM for LCD_Vo
44634 \ ------------------------------\
44635 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
44636 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
44637 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
44638 \ ------------------------------\
44639 BIS.B #LCDVo,&LCDVo_DIR \
44640 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
44641 \ ------------------------------\
44642 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
44643 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
44644 \ ------------------------------\
44645 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
44646 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
44647 \ ------------------------------\
44648 \ WDT interval init part \
44649 \ ------------------------------\
44650 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
44651 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
44652 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
44653 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
44654 \ ------------------------------\
44656 \ ------------------------------\
44657 BIS.B #RC5,&IR_IE \ enable RC5_Int
44658 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
44659 \ ------------------------------\
44660 \ init interrupt vectors
44661 \ ------------------------------\
44662 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
44663 MOV #RC5_INT,&IR_Vec \ init interrupt vector
44664 \ ------------------------------\
44665 \ define LPM mode for ACCEPT \
44666 \ ------------------------------\
44667 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44668 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44669 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44671 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
44673 \ ------------------------------\
44675 \ ------------------------------\
44676 $03E8 20_US \ 1- wait 20 ms
44677 $03 TOP_LCD \ 2- send DB5=DB4=1
44678 $CD 20_US \ 3- wait 4,1 ms
44679 $03 TOP_LCD \ 4- send again DB5=DB4=1
44680 $5 20_US \ 5- wait 0,1 ms
44681 $03 TOP_LCD \ 6- send again again DB5=DB4=1
44682 $2 20_US \ wait 40 us = LCD cycle
44683 $02 TOP_LCD \ 7- send DB5=1 DB4=0
44684 $2 20_US \ wait 40 us = LCD cycle
44685 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
44686 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
44687 LCD_Clear \ 10- "LCD_Clear"
44688 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
44689 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
44690 LCD_Clear \ 10- "LCD_Clear"
44691 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
44692 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
44694 ['] (CR) IS CR \ ' (CR) is CR
44695 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
44697 ." RC5toLCD is running. Type STOP to quit"
44698 \ NOECHO \ uncomment to run this app without terminal connexion
44699 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
44700 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
44704 : STOP \ stops multitasking, must to be used before downloading app
44705 ['] (WARM) IS WARM \ remove START app from FORTH init process
44706 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
44714 CODE MAX \ n1 n2 -- n3 signed maximum
44715 CMP @PSP,TOS \ n2-n1
44716 S< ?GOTO FW1 \ n2<n1
44722 CODE MIN \ n1 n2 -- n3 signed minimum
44723 CMP @PSP,TOS \ n2-n1
44724 S< ?GOTO BW1 \ n2<n1
44730 : U.R \ u n -- display u unsigned in n width (n >= 2)
44732 R> OVER - 0 MAX SPACES TYPE
44736 CODE 20_US \ n -- n * 20 us
44737 BEGIN \ 3 cycles loop + 6~
44738 \ MOV #5,W \ 3 MCLK = 1 MHz
44739 \ MOV #23,W \ 3 MCLK = 4 MHz
44740 MOV #51,W \ 3 MCLK = 8 MHz
44741 \ MOV #104,W \ 3 MCLK = 16 MHz
44742 \ MOV #158,W \ 3 MCLK = 24 MHz
44743 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
44753 CODE TOP_LCD \ LCD Sample
44754 \ \ if write : %xxxxWWWW --
44755 \ \ if read : -- %0000RRRR
44756 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
44757 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
44758 0= IF \ write LCD bits pattern
44759 AND.B #LCD_DB,TOS \
44760 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
44761 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44764 THEN \ read LCD bits pattern
44767 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44768 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
44769 AND.B #LCD_DB,TOS \
44774 CODE LCD_W \ byte -- write byte to LCD
44776 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
44777 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
44778 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
44779 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
44780 COLON \ high level word starts here
44781 TOP_LCD 2 20_US \ write high nibble first
44786 CODE LCD_WrC \ char -- Write Char
44787 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44792 CODE LCD_WrF \ func -- Write Fonction
44793 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44799 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
44804 $02 LCD_WrF 100 20_us
44808 \ : LCD_Entry_set $04 OR LCD_WrF ;
44810 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
44812 \ : LCD_Display_Shift $10 OR LCD_WrF ;
44814 \ : LCD_Fn_Set $20 OR LCD_WrF ;
44816 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
44818 \ : LCD_Goto $80 OR LCD_WrF ;
44820 \ CODE LCD_R \ -- byte read byte from LCD
44821 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
44822 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
44823 \ COLON \ starts a FORTH word
44824 \ TOP_LCD 2 20_us \ -- %0000HHHH
44825 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
44826 \ HI2LO \ switch from FORTH to assembler
44827 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
44828 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
44829 \ MOV @RSP+,IP \ restore IP saved by COLON
44834 \ CODE LCD_RdS \ -- status Read Status
44835 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44840 \ CODE LCD_RdC \ -- char Read Char
44841 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44846 \ -------------+------+------+------+------++---+---+---+---+---------+
44847 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
44848 \ -------------+------+------+------+------++---+---+---+---+---------+
44849 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
44850 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
44851 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
44852 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
44853 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
44854 \ -------------+------+------+------+------++---+---+---+---+---------+
44857 \ ******************************\
44858 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
44859 \ ******************************\
44860 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
44861 \ ------------------------------\
44862 \ define LPM mode for ACCEPT \
44863 \ ------------------------------\
44864 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44865 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44866 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44867 BIT.B #SW2,&SW2_IN \ test switch S2
44868 0= IF \ case of switch S2 pressed
44869 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
44871 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
44874 BIT.B #SW1,&SW1_IN \ test switch S1 input
44875 0= IF \ case of Switch S1 pressed
44876 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
44878 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
44882 RETI \ CPU is ON, GIE is OFF
44887 \ ------------------------------\
44888 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
44889 \ ******************************\
44890 ASM RC5_INT \ wake up on Px.RC5 change interrupt
44891 \ ******************************\
44892 \ \ in : SR(9)=old Toggle bit memory (ADD on)
44893 \ \ SMclock = 8|16|24 MHz
44894 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
44895 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
44896 \ \ SR(9)=new Toggle bit memory (ADD on)
44897 \ ------------------------------\
44898 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
44899 \ ------------------------------\
44900 \ define LPM mode for ACCEPT \
44901 \ ------------------------------\
44902 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44903 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44904 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44905 \ ------------------------------\
44906 \ RC5_FirstStartBitHalfCycle: \
44907 \ ------------------------------\
44908 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
44909 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
44910 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
44911 MOV #1778,X \ RC5_Period in us
44912 MOV #14,W \ count of loop
44914 \ ------------------------------\
44915 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
44916 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
44917 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
44918 \ RC5_Compute_3/4_Period: \ |
44919 RRUM #1,X \ X=1/2 cycle |
44923 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
44924 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
44926 \ ------------------------------\
44927 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
44928 \ ------------------------------\
44929 BIT.B #RC5,&IR_IN \ C_flag = IR bit
44930 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
44931 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
44932 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
44933 SUB #1,W \ decrement count loop
44934 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
44935 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
44936 0<> WHILE \ ----> out of loop ----+
44937 \ RC5_compute_7/4_Time_out: \ |
44938 ADD X,Y \ | out of bound = 7/4 period
44939 \ RC5_WaitHalfCycleP1.2_IFG: \ |
44941 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
44942 0>= IF \ | if cycle time out of bound
44943 BIC #$30,&TA0CTL \ | stop timer_A0
44944 RETI \ | then quit to do nothing
44946 \ ------------------------------\ |
44947 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
44949 MOV &TA0R,X \ | | get new RC5_period value
44950 REPEAT \ ----> loop back --+ |
44951 \ ------------------------------\ |
44952 \ RC5_SampleEndOf: \ <---------------------+
44953 \ ------------------------------\
44954 BIC #$30,&TA0CTL \ stop timer_A0
44955 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
44956 \ ******************************\
44957 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
44958 \ ******************************\
44959 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
44960 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
44961 XOR IP,X \ (new XOR old) Toggle bit (13)
44962 BIT #BIT13,X \ X(13) = New_RC5_command
44963 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
44965 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
44966 \ ******************************\
44967 \ RC5_ComputeNewRC5word \
44968 \ ******************************\
44970 MOV &BASE,2(PSP) \ save variable BASE before use
44971 MOV TOS,0(PSP) \ save TOS before use
44972 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
44973 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
44974 \ ******************************\
44975 \ RC5_ComputeC6bit \
44976 \ ******************************\
44977 BIT #$4000,IP \ test /C6 bit in IP
44978 0= IF BIS #$40,TOS \ set C6 bit in S
44979 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
44980 \ ******************************\
44981 \ RC5_CommandByteIsDone \ RC5_code --
44982 \ ******************************\
44984 \ ------------------------------\
44985 \ Display IR_RC5 code \
44986 \ ------------------------------\
44987 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
44988 \ ------------------------------\
44989 LO2HI \ switch from assembler to FORTH
44990 ['] LCD_CLEAR IS CR \ redirects CR
44991 ['] LCD_WrC IS EMIT \ redirects EMIT
44992 $10 BASE ! \ change BASE to hexadecimal
44993 CR ." $" 2 U.R \ print IR_RC5 code
44994 ['] (CR) IS CR \ restore CR
44995 ['] (EMIT) IS EMIT \ restore EMIT
44996 HI2LO \ switch from FORTH to assembler
44997 \ ------------------------------\
44998 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
44999 \ ------------------------------\
45000 MOV @PSP+,&BASE \ restore variable BASE
45001 RETI \ CPU is ON, GIE is OFF
45006 \ ------------------------------\
45007 \ TB0CTL = %0000 0010 1001 0100\$3C0
45008 \ - - \CNTL Counter lentgh \ 00 = 16 bits
45009 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
45010 \ -- \ID input divider \ 10 = /4
45011 \ -- \MC Mode Control \ 01 = up to TB0CCR0
45012 \ - \TBCLR TimerB Clear
45015 \ --------------------------------\\
45016 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
45017 \ -- \CM Capture Mode
45022 \ --- \OUTMOD \ 011 = set/reset
45028 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
45030 \ ------------------------------\
45031 \ set TimerB to make 50kHz PWM \
45032 \ ------------------------------\
45033 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45034 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
45035 \ ------------------------------\
45036 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45037 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
45038 \ ------------------------------\
45039 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45040 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
45041 \ ------------------------------\
45042 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45043 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
45044 \ ------------------------------\
45045 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45046 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
45047 \ ------------------------------\
45048 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
45049 \ ------------------------------\
45050 \ set TimerB to generate PWM for LCD_Vo
45051 \ ------------------------------\
45052 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
45053 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
45054 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45055 \ ------------------------------\
45056 BIS.B #LCDVo,&LCDVo_DIR \
45057 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
45058 \ ------------------------------\
45059 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45060 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45061 \ ------------------------------\
45062 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
45063 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
45064 \ ------------------------------\
45065 \ WDT interval init part \
45066 \ ------------------------------\
45067 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
45068 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
45069 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
45070 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
45071 \ ------------------------------\
45073 \ ------------------------------\
45074 BIS.B #RC5,&IR_IE \ enable RC5_Int
45075 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
45076 \ ------------------------------\
45077 \ init interrupt vectors
45078 \ ------------------------------\
45079 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
45080 MOV #RC5_INT,&IR_Vec \ init interrupt vector
45081 \ ------------------------------\
45082 \ define LPM mode for ACCEPT \
45083 \ ------------------------------\
45084 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45085 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45086 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45088 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
45090 \ ------------------------------\
45092 \ ------------------------------\
45093 $03E8 20_US \ 1- wait 20 ms
45094 $03 TOP_LCD \ 2- send DB5=DB4=1
45095 $CD 20_US \ 3- wait 4,1 ms
45096 $03 TOP_LCD \ 4- send again DB5=DB4=1
45097 $5 20_US \ 5- wait 0,1 ms
45098 $03 TOP_LCD \ 6- send again again DB5=DB4=1
45099 $2 20_US \ wait 40 us = LCD cycle
45100 $02 TOP_LCD \ 7- send DB5=1 DB4=0
45101 $2 20_US \ wait 40 us = LCD cycle
45102 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45103 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
45104 LCD_Clear \ 10- "LCD_Clear"
45105 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
45106 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
45107 LCD_Clear \ 10- "LCD_Clear"
45108 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
45109 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
45111 ['] (CR) IS CR \ ' (CR) is CR
45112 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
45114 ." RC5toLCD is running. Type STOP to quit"
45115 \ NOECHO \ uncomment to run this app without terminal connexion
45116 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
45117 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
45121 : STOP \ stops multitasking, must to be used before downloading app
45122 ['] (WARM) IS WARM \ remove START app from FORTH init process
45123 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
45131 CODE MAX \ n1 n2 -- n3 signed maximum
45132 CMP @PSP,TOS \ n2-n1
45133 S< ?GOTO FW1 \ n2<n1
45139 CODE MIN \ n1 n2 -- n3 signed minimum
45140 CMP @PSP,TOS \ n2-n1
45141 S< ?GOTO BW1 \ n2<n1
45147 : U.R \ u n -- display u unsigned in n width (n >= 2)
45149 R> OVER - 0 MAX SPACES TYPE
45153 CODE 20_US \ n -- n * 20 us
45154 BEGIN \ 3 cycles loop + 6~
45155 \ MOV #5,W \ 3 MCLK = 1 MHz
45156 \ MOV #23,W \ 3 MCLK = 4 MHz
45157 MOV #51,W \ 3 MCLK = 8 MHz
45158 \ MOV #104,W \ 3 MCLK = 16 MHz
45159 \ MOV #158,W \ 3 MCLK = 24 MHz
45160 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
45170 CODE TOP_LCD \ LCD Sample
45171 \ \ if write : %xxxxWWWW --
45172 \ \ if read : -- %0000RRRR
45173 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
45174 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
45175 0= IF \ write LCD bits pattern
45176 AND.B #LCD_DB,TOS \
45177 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
45178 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45181 THEN \ read LCD bits pattern
45184 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45185 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
45186 AND.B #LCD_DB,TOS \
45191 CODE LCD_W \ byte -- write byte to LCD
45193 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
45194 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
45195 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
45196 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
45197 COLON \ high level word starts here
45198 TOP_LCD 2 20_US \ write high nibble first
45203 CODE LCD_WrC \ char -- Write Char
45204 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45209 CODE LCD_WrF \ func -- Write Fonction
45210 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45216 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
45221 $02 LCD_WrF 100 20_us
45225 \ : LCD_Entry_set $04 OR LCD_WrF ;
45227 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
45229 \ : LCD_Display_Shift $10 OR LCD_WrF ;
45231 \ : LCD_Fn_Set $20 OR LCD_WrF ;
45233 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
45235 \ : LCD_Goto $80 OR LCD_WrF ;
45237 \ CODE LCD_R \ -- byte read byte from LCD
45238 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
45239 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
45240 \ COLON \ starts a FORTH word
45241 \ TOP_LCD 2 20_us \ -- %0000HHHH
45242 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
45243 \ HI2LO \ switch from FORTH to assembler
45244 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
45245 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
45246 \ MOV @RSP+,IP \ restore IP saved by COLON
45251 \ CODE LCD_RdS \ -- status Read Status
45252 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45257 \ CODE LCD_RdC \ -- char Read Char
45258 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45263 \ -------------+------+------+------+------++---+---+---+---+---------+
45264 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
45265 \ -------------+------+------+------+------++---+---+---+---+---------+
45266 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
45267 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
45268 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
45269 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
45270 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
45271 \ -------------+------+------+------+------++---+---+---+---+---------+
45274 \ ******************************\
45275 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
45276 \ ******************************\
45277 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
45278 \ ------------------------------\
45279 \ define LPM mode for ACCEPT \
45280 \ ------------------------------\
45281 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45282 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45283 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45284 BIT.B #SW2,&SW2_IN \ test switch S2
45285 0= IF \ case of switch S2 pressed
45286 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
45288 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
45291 BIT.B #SW1,&SW1_IN \ test switch S1 input
45292 0= IF \ case of Switch S1 pressed
45293 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
45295 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
45299 RETI \ CPU is ON, GIE is OFF
45304 \ ------------------------------\
45305 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
45306 \ ******************************\
45307 ASM RC5_INT \ wake up on Px.RC5 change interrupt
45308 \ ******************************\
45309 \ \ in : SR(9)=old Toggle bit memory (ADD on)
45310 \ \ SMclock = 8|16|24 MHz
45311 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
45312 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
45313 \ \ SR(9)=new Toggle bit memory (ADD on)
45314 \ ------------------------------\
45315 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
45316 \ ------------------------------\
45317 \ define LPM mode for ACCEPT \
45318 \ ------------------------------\
45319 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45320 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45321 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45322 \ ------------------------------\
45323 \ RC5_FirstStartBitHalfCycle: \
45324 \ ------------------------------\
45325 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
45326 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
45327 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
45328 MOV #1778,X \ RC5_Period in us
45329 MOV #14,W \ count of loop
45331 \ ------------------------------\
45332 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
45333 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
45334 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
45335 \ RC5_Compute_3/4_Period: \ |
45336 RRUM #1,X \ X=1/2 cycle |
45340 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
45341 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
45343 \ ------------------------------\
45344 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
45345 \ ------------------------------\
45346 BIT.B #RC5,&IR_IN \ C_flag = IR bit
45347 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
45348 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
45349 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
45350 SUB #1,W \ decrement count loop
45351 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
45352 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
45353 0<> WHILE \ ----> out of loop ----+
45354 \ RC5_compute_7/4_Time_out: \ |
45355 ADD X,Y \ | out of bound = 7/4 period
45356 \ RC5_WaitHalfCycleP1.2_IFG: \ |
45358 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
45359 0>= IF \ | if cycle time out of bound
45360 BIC #$30,&TA0CTL \ | stop timer_A0
45361 RETI \ | then quit to do nothing
45363 \ ------------------------------\ |
45364 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
45366 MOV &TA0R,X \ | | get new RC5_period value
45367 REPEAT \ ----> loop back --+ |
45368 \ ------------------------------\ |
45369 \ RC5_SampleEndOf: \ <---------------------+
45370 \ ------------------------------\
45371 BIC #$30,&TA0CTL \ stop timer_A0
45372 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
45373 \ ******************************\
45374 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
45375 \ ******************************\
45376 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
45377 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
45378 XOR IP,X \ (new XOR old) Toggle bit (13)
45379 BIT #BIT13,X \ X(13) = New_RC5_command
45380 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
45382 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
45383 \ ******************************\
45384 \ RC5_ComputeNewRC5word \
45385 \ ******************************\
45387 MOV &BASE,2(PSP) \ save variable BASE before use
45388 MOV TOS,0(PSP) \ save TOS before use
45389 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
45390 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
45391 \ ******************************\
45392 \ RC5_ComputeC6bit \
45393 \ ******************************\
45394 BIT #$4000,IP \ test /C6 bit in IP
45395 0= IF BIS #$40,TOS \ set C6 bit in S
45396 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
45397 \ ******************************\
45398 \ RC5_CommandByteIsDone \ RC5_code --
45399 \ ******************************\
45401 \ ------------------------------\
45402 \ Display IR_RC5 code \
45403 \ ------------------------------\
45404 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
45405 \ ------------------------------\
45406 LO2HI \ switch from assembler to FORTH
45407 ['] LCD_CLEAR IS CR \ redirects CR
45408 ['] LCD_WrC IS EMIT \ redirects EMIT
45409 $10 BASE ! \ change BASE to hexadecimal
45410 CR ." $" 2 U.R \ print IR_RC5 code
45411 ['] (CR) IS CR \ restore CR
45412 ['] (EMIT) IS EMIT \ restore EMIT
45413 HI2LO \ switch from FORTH to assembler
45414 \ ------------------------------\
45415 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
45416 \ ------------------------------\
45417 MOV @PSP+,&BASE \ restore variable BASE
45418 RETI \ CPU is ON, GIE is OFF
45423 \ ------------------------------\
45424 \ TB0CTL = %0000 0010 1001 0100\$3C0
45425 \ - - \CNTL Counter lentgh \ 00 = 16 bits
45426 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
45427 \ -- \ID input divider \ 10 = /4
45428 \ -- \MC Mode Control \ 01 = up to TB0CCR0
45429 \ - \TBCLR TimerB Clear
45432 \ --------------------------------\\
45433 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
45434 \ -- \CM Capture Mode
45439 \ --- \OUTMOD \ 011 = set/reset
45445 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
45447 \ ------------------------------\
45448 \ set TimerB to make 50kHz PWM \
45449 \ ------------------------------\
45450 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45451 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
45452 \ ------------------------------\
45453 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45454 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
45455 \ ------------------------------\
45456 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45457 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
45458 \ ------------------------------\
45459 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45460 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
45461 \ ------------------------------\
45462 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45463 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
45464 \ ------------------------------\
45465 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
45466 \ ------------------------------\
45467 \ set TimerB to generate PWM for LCD_Vo
45468 \ ------------------------------\
45469 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
45470 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
45471 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45472 \ ------------------------------\
45473 BIS.B #LCDVo,&LCDVo_DIR \
45474 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
45475 \ ------------------------------\
45476 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45477 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45478 \ ------------------------------\
45479 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
45480 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
45481 \ ------------------------------\
45482 \ WDT interval init part \
45483 \ ------------------------------\
45484 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
45485 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
45486 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
45487 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
45488 \ ------------------------------\
45490 \ ------------------------------\
45491 BIS.B #RC5,&IR_IE \ enable RC5_Int
45492 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
45493 \ ------------------------------\
45494 \ init interrupt vectors
45495 \ ------------------------------\
45496 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
45497 MOV #RC5_INT,&IR_Vec \ init interrupt vector
45498 \ ------------------------------\
45499 \ define LPM mode for ACCEPT \
45500 \ ------------------------------\
45501 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45502 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45503 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45505 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
45507 \ ------------------------------\
45509 \ ------------------------------\
45510 $03E8 20_US \ 1- wait 20 ms
45511 $03 TOP_LCD \ 2- send DB5=DB4=1
45512 $CD 20_US \ 3- wait 4,1 ms
45513 $03 TOP_LCD \ 4- send again DB5=DB4=1
45514 $5 20_US \ 5- wait 0,1 ms
45515 $03 TOP_LCD \ 6- send again again DB5=DB4=1
45516 $2 20_US \ wait 40 us = LCD cycle
45517 $02 TOP_LCD \ 7- send DB5=1 DB4=0
45518 $2 20_US \ wait 40 us = LCD cycle
45519 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45520 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
45521 LCD_Clear \ 10- "LCD_Clear"
45522 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
45523 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
45524 LCD_Clear \ 10- "LCD_Clear"
45525 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
45526 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
45528 ['] (CR) IS CR \ ' (CR) is CR
45529 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
45531 ." RC5toLCD is running. Type STOP to quit"
45532 \ NOECHO \ uncomment to run this app without terminal connexion
45533 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
45534 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
45538 : STOP \ stops multitasking, must to be used before downloading app
45539 ['] (WARM) IS WARM \ remove START app from FORTH init process
45540 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
45548 CODE MAX \ n1 n2 -- n3 signed maximum
45549 CMP @PSP,TOS \ n2-n1
45550 S< ?GOTO FW1 \ n2<n1
45556 CODE MIN \ n1 n2 -- n3 signed minimum
45557 CMP @PSP,TOS \ n2-n1
45558 S< ?GOTO BW1 \ n2<n1
45564 : U.R \ u n -- display u unsigned in n width (n >= 2)
45566 R> OVER - 0 MAX SPACES TYPE
45570 CODE 20_US \ n -- n * 20 us
45571 BEGIN \ 3 cycles loop + 6~
45572 \ MOV #5,W \ 3 MCLK = 1 MHz
45573 \ MOV #23,W \ 3 MCLK = 4 MHz
45574 MOV #51,W \ 3 MCLK = 8 MHz
45575 \ MOV #104,W \ 3 MCLK = 16 MHz
45576 \ MOV #158,W \ 3 MCLK = 24 MHz
45577 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
45587 CODE TOP_LCD \ LCD Sample
45588 \ \ if write : %xxxxWWWW --
45589 \ \ if read : -- %0000RRRR
45590 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
45591 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
45592 0= IF \ write LCD bits pattern
45593 AND.B #LCD_DB,TOS \
45594 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
45595 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45598 THEN \ read LCD bits pattern
45601 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45602 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
45603 AND.B #LCD_DB,TOS \
45608 CODE LCD_W \ byte -- write byte to LCD
45610 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
45611 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
45612 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
45613 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
45614 COLON \ high level word starts here
45615 TOP_LCD 2 20_US \ write high nibble first
45620 CODE LCD_WrC \ char -- Write Char
45621 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45626 CODE LCD_WrF \ func -- Write Fonction
45627 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45633 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
45638 $02 LCD_WrF 100 20_us
45642 \ : LCD_Entry_set $04 OR LCD_WrF ;
45644 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
45646 \ : LCD_Display_Shift $10 OR LCD_WrF ;
45648 \ : LCD_Fn_Set $20 OR LCD_WrF ;
45650 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
45652 \ : LCD_Goto $80 OR LCD_WrF ;
45654 \ CODE LCD_R \ -- byte read byte from LCD
45655 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
45656 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
45657 \ COLON \ starts a FORTH word
45658 \ TOP_LCD 2 20_us \ -- %0000HHHH
45659 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
45660 \ HI2LO \ switch from FORTH to assembler
45661 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
45662 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
45663 \ MOV @RSP+,IP \ restore IP saved by COLON
45668 \ CODE LCD_RdS \ -- status Read Status
45669 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45674 \ CODE LCD_RdC \ -- char Read Char
45675 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45680 \ -------------+------+------+------+------++---+---+---+---+---------+
45681 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
45682 \ -------------+------+------+------+------++---+---+---+---+---------+
45683 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
45684 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
45685 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
45686 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
45687 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
45688 \ -------------+------+------+------+------++---+---+---+---+---------+
45691 \ ******************************\
45692 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
45693 \ ******************************\
45694 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
45695 \ ------------------------------\
45696 \ define LPM mode for ACCEPT \
45697 \ ------------------------------\
45698 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45699 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45700 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45701 BIT.B #SW2,&SW2_IN \ test switch S2
45702 0= IF \ case of switch S2 pressed
45703 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
45705 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
45708 BIT.B #SW1,&SW1_IN \ test switch S1 input
45709 0= IF \ case of Switch S1 pressed
45710 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
45712 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
45716 RETI \ CPU is ON, GIE is OFF
45721 \ ------------------------------\
45722 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
45723 \ ******************************\
45724 ASM RC5_INT \ wake up on Px.RC5 change interrupt
45725 \ ******************************\
45726 \ \ in : SR(9)=old Toggle bit memory (ADD on)
45727 \ \ SMclock = 8|16|24 MHz
45728 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
45729 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
45730 \ \ SR(9)=new Toggle bit memory (ADD on)
45731 \ ------------------------------\
45732 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
45733 \ ------------------------------\
45734 \ define LPM mode for ACCEPT \
45735 \ ------------------------------\
45736 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45737 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45738 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45739 \ ------------------------------\
45740 \ RC5_FirstStartBitHalfCycle: \
45741 \ ------------------------------\
45742 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
45743 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
45744 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
45745 MOV #1778,X \ RC5_Period in us
45746 MOV #14,W \ count of loop
45748 \ ------------------------------\
45749 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
45750 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
45751 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
45752 \ RC5_Compute_3/4_Period: \ |
45753 RRUM #1,X \ X=1/2 cycle |
45757 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
45758 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
45760 \ ------------------------------\
45761 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
45762 \ ------------------------------\
45763 BIT.B #RC5,&IR_IN \ C_flag = IR bit
45764 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
45765 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
45766 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
45767 SUB #1,W \ decrement count loop
45768 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
45769 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
45770 0<> WHILE \ ----> out of loop ----+
45771 \ RC5_compute_7/4_Time_out: \ |
45772 ADD X,Y \ | out of bound = 7/4 period
45773 \ RC5_WaitHalfCycleP1.2_IFG: \ |
45775 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
45776 0>= IF \ | if cycle time out of bound
45777 BIC #$30,&TA0CTL \ | stop timer_A0
45778 RETI \ | then quit to do nothing
45780 \ ------------------------------\ |
45781 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
45783 MOV &TA0R,X \ | | get new RC5_period value
45784 REPEAT \ ----> loop back --+ |
45785 \ ------------------------------\ |
45786 \ RC5_SampleEndOf: \ <---------------------+
45787 \ ------------------------------\
45788 BIC #$30,&TA0CTL \ stop timer_A0
45789 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
45790 \ ******************************\
45791 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
45792 \ ******************************\
45793 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
45794 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
45795 XOR IP,X \ (new XOR old) Toggle bit (13)
45796 BIT #BIT13,X \ X(13) = New_RC5_command
45797 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
45799 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
45800 \ ******************************\
45801 \ RC5_ComputeNewRC5word \
45802 \ ******************************\
45804 MOV &BASE,2(PSP) \ save variable BASE before use
45805 MOV TOS,0(PSP) \ save TOS before use
45806 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
45807 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
45808 \ ******************************\
45809 \ RC5_ComputeC6bit \
45810 \ ******************************\
45811 BIT #$4000,IP \ test /C6 bit in IP
45812 0= IF BIS #$40,TOS \ set C6 bit in S
45813 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
45814 \ ******************************\
45815 \ RC5_CommandByteIsDone \ RC5_code --
45816 \ ******************************\
45818 \ ------------------------------\
45819 \ Display IR_RC5 code \
45820 \ ------------------------------\
45821 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
45822 \ ------------------------------\
45823 LO2HI \ switch from assembler to FORTH
45824 ['] LCD_CLEAR IS CR \ redirects CR
45825 ['] LCD_WrC IS EMIT \ redirects EMIT
45826 $10 BASE ! \ change BASE to hexadecimal
45827 CR ." $" 2 U.R \ print IR_RC5 code
45828 ['] (CR) IS CR \ restore CR
45829 ['] (EMIT) IS EMIT \ restore EMIT
45830 HI2LO \ switch from FORTH to assembler
45831 \ ------------------------------\
45832 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
45833 \ ------------------------------\
45834 MOV @PSP+,&BASE \ restore variable BASE
45835 RETI \ CPU is ON, GIE is OFF
45840 \ ------------------------------\
45841 \ TB0CTL = %0000 0010 1001 0100\$3C0
45842 \ - - \CNTL Counter lentgh \ 00 = 16 bits
45843 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
45844 \ -- \ID input divider \ 10 = /4
45845 \ -- \MC Mode Control \ 01 = up to TB0CCR0
45846 \ - \TBCLR TimerB Clear
45849 \ --------------------------------\\
45850 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
45851 \ -- \CM Capture Mode
45856 \ --- \OUTMOD \ 011 = set/reset
45862 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
45864 \ ------------------------------\
45865 \ set TimerB to make 50kHz PWM \
45866 \ ------------------------------\
45867 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45868 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
45869 \ ------------------------------\
45870 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45871 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
45872 \ ------------------------------\
45873 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45874 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
45875 \ ------------------------------\
45876 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45877 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
45878 \ ------------------------------\
45879 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45880 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
45881 \ ------------------------------\
45882 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
45883 \ ------------------------------\
45884 \ set TimerB to generate PWM for LCD_Vo
45885 \ ------------------------------\
45886 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
45887 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
45888 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45889 \ ------------------------------\
45890 BIS.B #LCDVo,&LCDVo_DIR \
45891 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
45892 \ ------------------------------\
45893 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45894 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45895 \ ------------------------------\
45896 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
45897 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
45898 \ ------------------------------\
45899 \ WDT interval init part \
45900 \ ------------------------------\
45901 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
45902 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
45903 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
45904 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
45905 \ ------------------------------\
45907 \ ------------------------------\
45908 BIS.B #RC5,&IR_IE \ enable RC5_Int
45909 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
45910 \ ------------------------------\
45911 \ init interrupt vectors
45912 \ ------------------------------\
45913 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
45914 MOV #RC5_INT,&IR_Vec \ init interrupt vector
45915 \ ------------------------------\
45916 \ define LPM mode for ACCEPT \
45917 \ ------------------------------\
45918 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45919 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45920 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45922 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
45924 \ ------------------------------\
45926 \ ------------------------------\
45927 $03E8 20_US \ 1- wait 20 ms
45928 $03 TOP_LCD \ 2- send DB5=DB4=1
45929 $CD 20_US \ 3- wait 4,1 ms
45930 $03 TOP_LCD \ 4- send again DB5=DB4=1
45931 $5 20_US \ 5- wait 0,1 ms
45932 $03 TOP_LCD \ 6- send again again DB5=DB4=1
45933 $2 20_US \ wait 40 us = LCD cycle
45934 $02 TOP_LCD \ 7- send DB5=1 DB4=0
45935 $2 20_US \ wait 40 us = LCD cycle
45936 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45937 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
45938 LCD_Clear \ 10- "LCD_Clear"
45939 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
45940 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
45941 LCD_Clear \ 10- "LCD_Clear"
45942 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
45943 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
45945 ['] (CR) IS CR \ ' (CR) is CR
45946 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
45948 ." RC5toLCD is running. Type STOP to quit"
45949 \ NOECHO \ uncomment to run this app without terminal connexion
45950 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
45951 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
45955 : STOP \ stops multitasking, must to be used before downloading app
45956 ['] (WARM) IS WARM \ remove START app from FORTH init process
45957 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH