1 ; -*- coding: utf-8 -*-
3 ; Fast Forth For Texas Instrument MSP430FRxxxx FRAM devices with I2C TERMINAL
4 ; Copyright (C) <2019> <J.M. THOORENS>
6 ; This program is free software: you can redistribute it and/or modify
7 ; it under the terms of the GNU General Public License as published by
8 ; the Free Software Foundation, either version 3 of the License, or
9 ; (at your option) any later version.
11 ; This program is distributed in the hope that it will be useful,
12 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ; GNU General Public License for more details.
16 ; You should have received a copy of the GNU General Public License
17 ; along with this program. If not, see <http://www.gnu.org/licenses/>.
19 ; for I2C_Slave init, see in /inc/TARGET.asm file
21 ; ----------------------------------;
22 ; ACCEPT part I prepare TERMINAL_INT; a START can be match here, with START ifg flag
23 ; ----------------------------------;
24 MOV TOS,W ;1 -- addr len W=len
25 MOV @PSP,TOS ;2 -- org ptr )
26 ADD TOS,W ;1 -- org ptr W=buf_end )
27 MOV #0Ah,T ;2 T = 'LF' to speed up char loop in part II > prepare stack and registers for TERMINAL_INT use
28 MOV #20h,S ;2 S = 'BL' to speed up char loop in part II )
29 PUSHM #4,IP ;6 PUSH IP,S,T,W r-- IP, 'BL', 'LF', buf_end )
30 ACCEPT1 BIC #IE_TERM,&TERM_IFG ; clear UCSTTIFG before use during SLEEP
31 ; ----------------------------------;
32 ;; -test-v-test-v-test-v-test-v-test-;
33 ; BIC.B #LED1,&LED1_DIR ; Red led OFF, end of Slave TX
34 ; BIC.B #LED1,&LED1_OUT ; Red led OFF, end of Slave TX
35 ;; -test-^-test-^-test-^-test-^-test-;
36 ; ----------------------------------;
37 BIT #10h,&TERM_CTLW0 ;4 test UCTR
38 JZ SLEEP ;2 UCTR=0, IC2_Slave RX mode or I2C_Slave unplugged, 16~
39 ACCEPT2 BIT #TX_TERM,&TERM_IFG ;3 UCTR=1, IC2_Slave TX mode
40 JZ ACCEPT2 ;2 wait complete send of char
41 MOV.B #0,&TERM_TXBUF ; send ctrl_char $00
42 ; ----------------------------------;
43 JMP SLEEP ;2 which calls RXON before shut down to LPMx mode
44 ; ----------------------------------;
46 ; **********************************;
47 TERMINAL_INT ; <--- START interrupt vector, bus stalled, waiting ACK first char by I2C_Slave RX
48 ; **********************************;
49 ; (ACCEPT) part II under interrupt ; Org Ptr --
50 ; ----------------------------------;
51 ADD #4,RSP ;1 remove SR and PC from stack, SR flags are lost (unused by FORTH interpreter)
52 BIT #10h,&TERM_CTLW0 ;4 test UCTR
53 JNZ ACCEPT1 ; if I2C_Master RX, send $00 then return to SLEEP
54 POPM #4,IP ;6 POPM IP=ret_IP,W=src_end,T=0Ah,S=20h
55 ;; -test-v-test-v-test-v-test-v-test-;
56 ; BIS.B #LED2,&LED2_OUT ; green led ON, start of Slave RX
57 ; BIS.B #LED2,&LED2_DIR ; green led ON, start of Slave RX
58 ;; -test-^-test-^-test-^-test-^-test-;
59 QNEWCHAR BIT #RX_TERM,&TERM_IFG ;3 test RX BUF IFG
60 JZ QNEWCHAR ;2 wait RX BUF full
61 AREADCHAR MOV.B &TERM_RXBUF,Y ;3 read char into Y, RX_IFG is cleared, bus unstalled by I2C_Slave
62 CMP.B S,Y ;1 printable char ?
63 JC ASTORETEST ;2 char U>= BL --> yes
64 CMP.B T,Y ;1 char = LF ?
66 ; ----------------------------------;
67 CMP.B #8,Y ; char = BS ?
68 JNZ QNEWCHAR ; case of other control chars
69 ; ----------------------------------;
70 ; start of backspace ; made only by an human
71 ; ----------------------------------;
72 CMP @PSP,TOS ; Ptr = Org ?
73 JZ QNEWCHAR ; yes: do nothing else
74 SUB #1,TOS ; no : dec Ptr
76 ; ----------------------------------;
77 ASTORETEST CMP W,TOS ; 1 end of buffer is reached ?
78 JZ QNEWCHAR ; 2 yes: loopback
79 MOV.B Y,0(TOS) ; 3 no: store char @ dst_Ptr
80 ADD #1,TOS ; 1 increment dst_Ptr
82 ; ----------------------------------;
83 ENDACCEPT ; here, after char 'LF' TXed, I2C_Master reSTARTs in RX mode
84 ;; -test-v-test-v-test-v-test-v-test-;
85 ; BIC.B #LED2,&LED2_DIR ; green led OFF, end of Slave RX
86 ; BIC.B #LED2,&LED2_OUT ; green led OFF, end of Slave RX
87 ; BIS.B #LED1,&LED1_DIR ; Red led ON, start of Slave TX
88 ; BIS.B #LED1,&LED1_OUT ; Red led ON, start of Slave TX
89 ;; -test-^-test-^-test-^-test-^-test-;
90 ; ----------------------------------; -- Org Ptr
92 JZ ACCEPTEND ; if LINE <> 0 increment LINE
94 ACCEPTEND SUB @PSP+,TOS ; -- len'
95 AWAITTX BIT #40h,&TERM_STATW ; wait SCL held low, i.e. I2C_Master RX waits a char from I2C_Slave
97 ; ----------------------------------;
98 ; MOV #CPUOFF+GIE,&LPM_MODE ; reset LPM_MODE to default mode LPM0 for next line of input stream
99 MOV #LPM4+GIE,&LPM_MODE ; reset LPM_MODE to default mode LPM4 for next line of input stream
100 ; ----------------------------------;
101 MOV @IP+,PC ; ...until next falling down to LPMx mode of (ACCEPT) part1,
102 ; **********************************; i.e. when the FORTH interpreter has no more to do.
104 ; ----------------------------------;
106 ; ----------------------------------;
107 RXON MOV @RSP+,PC ; <======= SLEEP
108 ; ----------------------------------;
110 ; ----------------------------------;
112 ; ----------------------------------;
113 MOV #5A4Dh,&WDTCTL ; start Watchdog Reset : XDTPW, WDTSSEL=VLOCLK, WDTCNTCL=1, WDTIS=2^13 (1s)
114 ; ----------------------------------; WDT_RST time = 1s because the ABORT loop time on I2C_Master side.
115 ; send $02 (ABORT request) ;
116 ; ----------------------------------;
117 BIT #10h,&TERM_CTLW0 ;4 test UCTR
118 JZ COLDI2CEND2 ;2 UCTR=0, IC2_Slave RX mode or I2C_Slave unplugged, 16~
119 COLDI2C BIT #TX_TERM,&TERM_IFG ;3 UCTR=1, IC2_Slave TX mode
120 JZ COLDI2C ;2 wait complete send of previous char
121 MOV.B #2,&TERM_TXBUF ; send ctrl_char $02 to I2C_Master which will execute QABORT_TERM
122 ; ----------------------------------;
123 ; wait STOP from Master ;
124 ; ----------------------------------;
125 COLDI2CEND BIC #8,&TERM_IFG ; clear STOP ifg before test
126 COLDI2CEND1 BIT #8,&TERM_IFG ; test STOP occurring
128 ; ----------------------------------;
129 COLDI2CEND2 MOV #0A504h,&PMMCTL0 ; performs BOR
130 ; ----------------------------------;
132 ; ------------------------------------------------------------------------------
133 ; TERMINAL I/O, input part
134 ; ------------------------------------------------------------------------------
137 ; https://forth-standard.org/standard/core/KEY
138 ; KEY -- c wait character from input device ; primary DEFERred word
139 KEY MOV @PC+,PC ; Code Field Address (CFA) of KEY
140 PFAKEY .word BODYKEY ; Param Field Address (PFA) of KEY, with its default value
141 BODYKEY SUB #2,PSP ; push old TOS..
142 MOV TOS,0(PSP) ; ..onto stack
143 MOV #0,TOS ; -- 0 aborted KEY value
144 ; ----------------------------------;
145 BIT #10h,&TERM_CTLW0 ; test UCTR
146 JZ BKEYEND ; when UCTR=0, IC2_Slave is in (RX|SWRST) mode, KEY can't work.
147 ; ----------------------------------;
148 KEYQEMIT BIT #TX_TERM,&TERM_IFG ; TX buffer empty ?
149 JZ KEYQEMIT ; wait TX buffer empty
150 MOV.B #1,&TERM_TXBUF ; send $01 to I2C_Master RX as KEY request
151 BKEYLOOP BIT #RX_TERM,&TERM_IFG ; received char ?
152 JZ BKEYLOOP ; wait char received
153 MOV &TERM_RXBUF,TOS ; -- char
154 ; ----------------------------------;
155 BKEYEND MOV @IP+,PC ; -- char|0 Z=aborted KEY
157 ; ------------------------------------------------------------------------------
158 ; TERMINAL I/O, output part
159 ; ------------------------------------------------------------------------------
162 ; https://forth-standard.org/standard/core/EMIT
163 ; EMIT c -- output character to an output device ; primary DEFERred word
164 EMIT MOV @PC+,PC ;3 Code Field Address (CFA) of EMIT
165 PFAEMIT .word BODYEMIT ; Parameter Field Address (PFA) of EMIT, with its default value
166 BODYEMIT MOV TOS,Y ;1 sends character to the default output TERMINAL
168 ; ----------------------------------;
169 YEMIT2 BIT #10h,&TERM_CTLW0 ;4 test UCTR
170 JZ YEMITEND ;2 UCTR=0, IC2_Slave RX mode or I2C_Slave unplugged, 16~
171 ; ----------------------------------;
172 YEMIT1 BIT #TX_TERM,&TERM_IFG ;3 UCTR=1, IC2_Slave TX mode
173 JZ YEMIT1 ;2 wait complete send of previous char
174 YEMIT .word 4882h ; 4882h = MOV Y,&<next_adr>
176 ; ----------------------------------;
177 YEMITEND MOV @IP+,PC ;4 14 words
180 ;Z ECHO -- connect EMIT to TERMINAL (default)
181 ECHO MOV #4882h,&YEMIT ; 4882h = MOV Y,&<next_adr>
184 JMP YEMIT2 ; send ctrl_char $05 to I2C_Master
187 ;Z NOECHO -- disconnect EMIT to TERMINAL
188 NOECHO MOV #1,&LINE ;
191 .word YEMIT2 ; send ctrl_char $04 to I2C_Master
193 MOV #NEXT,&YEMIT ; NEXT = 4030h = MOV @IP+,PC