OSDN Git Service

la der de der
[fast-forth/master.git] / forthMSP430FR_TERM_I2C.asm
1 ; -*- coding: utf-8 -*-
2 ;
3 ; ---------------------------------------------------              ---------------------------
4 ; TERMINAL driver for I2CFastForth target (I2C Slave)              see MSP430-FORTH/UARTI2CS.f
5 ; ---------------------------------------------------              ---------------------------
6 ;        |                                                                      |
7 ;        |                                                                      |
8 ;        |             GND------------------------------GND                     |
9 ;        |             3V3-------------o---o------------3V3                     |
10 ;        |                             |   |                                    | 
11 ;        |                             1   1                                    | 
12 ;        |                             k   k                Txy.z output        | 
13 ;        v                             0   0                     to             v                 GND-------------------------------------GND 
14 ;   I2C_FastForth                      |   |                  Px.y int       UARTI2CS              +-------------------------------------->+
15 ;     (hardware         +<-------------|---o------------>+     jumper       (Software              |    +<----------------------------+    |
16 ;     I2C Slave)        ^      +<------o----------+      ^     +--->+       I2C Master)            |    |    +------(option)---->+    |    |
17 ;                       v      v                  ^      v     ^    |                              ^    v    ^                   v    ^    v
18 ; I2C_FastForth(s)     SDA    SCL  connected to: SCL    SDA    |    v   I2C_to_UART_bridge        TXD  RXD  RTS  connected to : CTS  TXD  RXD  UARTtoUSB <--> COMx <--> TERMINAL
19 ; ------------------   ----   ----               ----   ----             ----------------         ---  ---  ---                 ---  ---  ---  ---------      ----      --------
20 ; MSP_EXP430FR2355     P1.2   P1.3               P3.3   P3.2  P1.7 P1.6  MSP_EXP430FR2355 (24MHz) P4.3 P4.2 P2.0                               PL2303GC                    |      
21 ; MSP_EXP430FR5739     P1.6   P1.7               P4.1   P4.0  P1.1 P1.0  MSP_EXP430FR5739 (24MHz) P2.0 P2.1 P2.2                               PL2303HXD                   v
22 ; MSP_EXP430FR5969     P1.6   P1.7               P1.3   P1.2  P2.2 P3.4  MSP_EXP430FR5969 (16MHz) P2.0 P2.1 P4.1                               PL2303TA               TERATERM.EXE     
23 ; MSP_EXP430FR5994     P7.0   P7.1               P8.1   P8.2  P1.5 P1.4  MSP_EXP430FR5994 (16MHz) P2.0 P2.1 P4.2                               CP2102                       
24 ; MSP_EXP430FR6989     P1.6   P1.7               P1.5   P1.3  P3.6 P3.7  MSP_EXP430FR6989 (16MHz) P3.4 P3.5 P3.0                                                                  
25 ; MSP_EXP430FR4133     P5.2   P5.3               P8.3   P8.2  P1.6 P1.7  MSP_EXP430FR4133 (16MHz) P1.0 P1.1 P2.3                                                                  
26 ; MSP_EXP430FR2433     P1.2   P1.3               P3.1   P3.2  P1.2 P1.3  MSP_EXP430FR2433 (16MHz) P1.4 P1.5 P1.0                                                                      
27 ; LP_MSP430FR2476      P4.4   P4.3               P3.3   P3.2  P1.2 P1.1  LP_MSP430FR2476  (16MHz) P1.4 P1.5 P6.1                                                                                                                                
28 ;
29 ; don't forget to link 3V3 and GND on each side and to add 3k3 pullup resistors on SDA and SCL.
30 ;
31 ;-----------------------------------------------------------------------------------------------------------
32 ; I2C TERMINAL: ?ABORT, INIT values of ABORT_APP, BACKGRND_APP, HARD_APP, COLD_APP and SOFT_APP
33 ;-----------------------------------------------------------------------------------------------------------
34
35 ; ==================================;
36 ABORT_TERM                          ; INIT value of ABORT_APP,  used by SD_CARD_ERROR
37 ; ==================================;
38             MOV.B #-1,Y             ; send $FF (QABORT_YES Ctrl_Char) to UARTtoI2C bridge (I2C Master), used by SD_CARD_ERROR
39             JMP I2C_CTRL_CH         ; then RET
40 ;-----------------------------------;
41
42 ; ?ABORT defines the run-time part of ABORT"
43 ;-----------------------------------;
44 QABORT      CMP #0,2(PSP)           ; -- f addr cnt     if f is true abort current process then display ABORT" msg.
45             JNZ QABORT_YES          ;
46             ADD #4,PSP              ; -- cnt
47             JMP DROP                ;
48 ; ----------------------------------;
49 QABORT_YES  CALL &ABORT_APP         ;                   QABORT_YES called by INTERPRET, QREVEAL, TYPE2DOES
50 ; ----------------------------------;
51             CALL #INIT_FORTH        ;                   common ?ABORT|PUC subroutine
52             .word   DUP             ; -- f addr cnt cnt
53             .word   QFBRAN,ABORT_END; -- f addr 0       if cnt = 0 display nothing
54             .word   ECHO            ; -- f addr cnt     force ECHO
55             .word   XSQUOTE         ;
56             .byte   5,27,"[7m",'@'  ;
57             .word   TYPE            ;                       cmd "reverse video" + displays "@"
58             .word   LIT,I2CSLAVEADR ;
59             .word   FETCH,DOT       ;                       displays I2C_Slave_Address<<1
60 ; ----------------------------------;
61 ; Display ABORT|WARM message        ; -- f addr cnt     <== WARM jumps here
62 ; ----------------------------------;
63 ABORT_TYPE  .word   TYPE            ; -- f              display QABORT|WARM message
64 SDABORT_END .word   XSQUOTE         ;                   set normal video Display then goto ABORT
65             .byte   4,27,"[0m"      ;
66             .word   TYPE            ;                   set normal video
67 ABORT_END   .word   ABORT           ; -- f|f addr 0     no return
68 ; ----------------------------------;
69
70 ; ==================================;
71 INIT_BACKGRND                       ; INIT value of BACKGRND_APP
72 ; ==================================;
73 I2C_ACCEPT  MOV.B #0,Y              ; ACCEPT request Ctrl_Char = $00
74             JMP I2C_CTRL_CH         ; then RET
75 ; ----------------------------------;
76
77 ;-------------------------------------------------------------------------------
78 ; INIT TERMinal then enable I/O
79 ;-------------------------------------------------------------------------------
80
81 ; ==================================;
82 INIT_TERM                           ; INIT value of HARD_APP called by WARM
83 ; ==================================;
84         BIS #07C0h,&TERM_CTLW0      ; set I2C_Slave in RX mode to receive I2C_address
85         MOV &I2CSLAVEADR,Y          ; I2C_Slave_address<<1 value found in FRAM INFO
86         RRA Y                       ; shift it right one 
87         BIS #400h,Y                 ; enable I2COA0 Slave address
88         MOV Y,&TERM_I2COA0          ;
89         BIS.B #BUS_TERM,&TERM_SEL   ; Configure pins TERM_I2C
90         BIC #1,&TERM_CTLW0          ; release UC_TERM from reset...
91         BIS #WAKE_UP,&TERM_IE       ; ...enable interrupt for wake up on START
92         BIC #LOCKLPM5,&PM5CTL0      ; then activate all previous I/O settings.
93 ; ==================================;
94 INIT_STOP                           ; INIT value of STOP_APP called by SYS, does nothing
95 ; ==================================;
96 INIT_SOFT                           ; INIT value of SOFT_APP
97 ; ==================================;
98    MOV @RSP+,PC                     ;
99 ; ----------------------------------;
100
101 ;-------------------------------------------------------------------------------
102 ; I2C TERMINAL : SYS COLD RESET WARM
103 ;-------------------------------------------------------------------------------
104
105 ;-----------------------------------;
106 WARM                                ; (n) --
107 ;-----------------------------------;
108         CALL &HARD_APP              ; init HARD_APP, i.e. I2C_TERMinal then unlock IO's
109         mASM2FORTH                  ;
110         .word   ECHO                ;
111         .word   XSQUOTE             ;
112         .byte   7,13,10,27,"[7m@"   ; CR+LF + cmd "reverse video" + @
113         .word   TYPE                ;
114         .word   LIT,I2CSLAVEADR     ;
115         .word   FETCH,DOT           ; display decimal I2C_address<<1
116         .word   LIT,'#',EMIT        ;
117         .word   DOT                 ; display signed USERSYS
118         .word   XSQUOTE             ;
119         .byte   25,"FastForth ",169 ;
120         .byte   "J.M.Thoorens, "    ;
121         .word   TYPE                ;
122         .word   LIT,FRAM_FULL       ;
123         .word   HERE,MINUS,UDOT     ;
124         .word   XSQUOTE             ;
125         .byte   10,"bytes free"     ; bytes free
126         .word   BRAN,ABORT_TYPE     ; no return
127 ;-----------------------------------;
128
129             FORTHWORD "SYS"         ; n --      select COLD, DEEP_COLD, WARM (as software RST,DEEP_RST,WARM)
130 ;-----------------------------------;
131 SYS         CALL &STOP_APP          ; default STOP_APP = INIT_STOP, set by DEEP_RESET.
132             CMP #0,TOS              ;
133             JL TOS2COLD             ; if -n SYS  --> COLD --> PUC --> INIT_FORTH --> DEEP_RESET --> WARM
134             JZ TOS2WARM             ; if [0] SYS --> INIT_FORTH --> WARM
135             BIT #1,TOS              ;
136             JZ TOS2COLD             ; if +n SYS (+n even)--> COLD --> PUC --> INIT_FORTH --> WARM
137 TOS2WARM    CALL #INIT_FORTH        ; if +n SYS (+n odd) --> INIT_FORTH --> WARM
138 FWARM       .word WARM              ; no return
139 TOS2COLD    MOV TOS,&USERSYS        ;
140 ;*******************************************************************************
141 COLD        ; <--- USER_NMI vector <--- <RESET> and <RESET> + <SW1> (DEEP_RESET)
142 ;*******************************************************************************
143 ; as pin RST is replaced by pin NMI, RESET by pin activation is redirected here via USER NMI vector
144 ; that allows actions to be performed before executing software BOR.
145             BIT.B #SW1,&SW1_IN      ; <SW1> pressed ?
146             JNZ DO_BOR              ; no
147             MOV #-1,&USERSYS        ; yes, set negative value to force DEEP_RESET
148 DO_BOR      MOV #0A504h,&PMMCTL0    ; ---------------------------> software_BOR --->+
149 ;*******************************************************************************    |
150 RESET                               ; <-- RST vect. <-- SYS_failures PUC POR BOR <--+
151 ;*******************************************************************************
152 ; PUC 1: replace pin RESET by pin NMI, stops WDT_RESET
153 ;-------------------------------------------------------------------------------
154             BIS #1,&SFRRPCR         ; pin RST becomes pin NMI with rising edge, so SYSRSTIV = 6
155             BIS #10h,&SFRIE1        ; enable NMI interrupt ==> hardware RESET is redirected to COLD.
156             MOV #5A80h,&WDTCTL      ; disable WDT RESET
157 ;-------------------------------------------------------------------------------
158 ; PUC 2: INIT STACK
159 ;-------------------------------------------------------------------------------
160             MOV #RSTACK,RSP         ; init return stack
161             MOV #PSTACK,PSP         ; init parameter stack
162 ;-------------------------------------------------------------------------------
163 ; PUC 3: I/O, RAM, RTC, CS, SYS initialisation limited to FastForth usage.
164 ;          All unused I/O are set as input with pullup resistor.
165 ;-------------------------------------------------------------------------------
166         .include "TargetInit.asm"   ; include target specific init code
167 ;-------------------------------------------------------------------------------
168 ; PUC 4: init RAM to 0
169 ;-------------------------------------------------------------------------------
170             MOV #RAM_LEN,X          ; 2 RAM_LEN must be even and > 1, obviously.
171 INITRAMLOOP SUB #2,X                ; 1
172             MOV #0,RAM_ORG(X)       ; 3
173             JNZ INITRAMLOOP         ; 2     6 cycles loop !
174 ; ;-------------------------------------------------------------------------------
175 ; ; PUC 5: GET SYSRSTIV and USERSYS
176 ; ;-------------------------------------------------------------------------------
177 ;             MOV &SYSRSTIV,X        ; X <-- SYSRSTIV <-- 0
178 ;-------------------------------------------------------------------------------
179 ; PUC 5: GET SYSUNIV_SYSSNIV_SYSRSTIV ( %0_UUU0_SSSS0_RRRRR0) and USERSYS
180 ;-------------------------------------------------------------------------------
181             MOV &SYSUNIV,X          ; 0 --> SYSUNIV --> X   (%0000_0000_0000_UUU0) (7 values)
182             RLAM #4,X               ; make room for SYSSNIV (%0000_0000_UUU0_0000)
183             ADD X,X                 ;                       (%0000_000U_UU00_0000)
184             BIS &SYSSNIV,X          ; 0 --> SYSSNIV --> X   (%0000_000U_UU0S_SSS0) (15 values)
185             RLAM #4,X               ; make room for SYSRSTIV(%000U_UU0S_SSS0_0000)
186             RLAM #2,X               ;                       (%0UUU_0SSS_S000_0000)
187             BIS.B &SYSRSTIV,X       ; 0 --> SYSRSTIV --> X  (%0UUU_0SSS_S0RR_RRR0) (31 values)
188 ;-------------------------------------------------------------------------------
189             MOV &USERSYS,TOS        ; TOS = USERSYS (FRAM)
190             MOV #0,&USERSYS         ; and clear USERSYS
191             BIT.B #-1,TOS           ; high byte reserved use
192             JNZ PUC6                ; if TOS <> 0, keep this USERSYS value
193             MOV X,TOS               ; else TOS = SYSRSTIV
194 ;-------------------------------------------------------------------------------
195 ; PUC 6: START FORTH engine: WARM (BOOT)
196 ;-------------------------------------------------------------------------------
197 PUC6        CALL #INIT_FORTH        ; common part of QABORT|PUC
198 PUCNEXT     .word WARM              ; no return. May be replaced by XBOOT by BOOT ;-)
199 ;-----------------------------------;
200
201 ;-------------------------------------------------------------------------------
202 ; INTERPRETER INPUT: ACCEPT KEY EMIT ECHO NOECHO
203 ;-------------------------------------------------------------------------------
204
205             FORTHWORD "ACCEPT"      ;
206 ; ----------------------------------;
207 ;https://forth-standard.org/standard/core/ACCEPT
208 ;C ACCEPT  addr addr len -- addr len'  get a line from TERMINAL
209 ACCEPT      MOV @PC+,PC             ;3 Code Field Address (CFA) of ACCEPT
210 PFAACCEPT   .word   BODYACCEPT      ;  Parameter Field Address (PFA) of ACCEPT
211 ; ----------------------------------;
212 ; ACCEPT part I prepare TERMINAL_INT;
213 ; ----------------------------------;
214 BODYACCEPT  MOV TOS,W               ;1 -- org len   W=len
215             MOV @PSP,TOS            ;2 -- org ptr                                               )
216             ADD TOS,W               ;1 -- org ptr   W=buf_end                                   )
217             MOV #0Ah,T              ;2              T = 'LF' to speed up char loop in part II   > prepare stack and registers for TERMINAL_INT use
218             MOV #20h,S              ;2              S = 'BL' to speed up char loop in part II   )
219             PUSHM #4,IP             ;6              PUSH IP,S,T,W  R-- IP, 'BL', 'LF', buf_end  )
220
221 ; here, FAST FORTH sleeps, waiting any interrupt. With LPM4, supply current is below 1uA.
222 ; IP,S,T,W,X,Y registers (R13 to R8) are free...
223 ; ...and also TOS, PSP and RSP stacks within their rules of use.
224 ;###################################################################################
225 BACKGRND    CALL &BACKGRND_APP  ;   default BACKGRND_APP = INIT_BACKGRND = I2C_ACCEPT, value set by DEEP_RESET.
226             BIS &LPM_MODE,SR    ;2  enter in LPM4 mode with GIE=1
227             JMP BACKGRND        ;2  return for all interrupts.
228 ;###################################################################################
229
230 ; As TI says nothing about the reset of the UCSTTIFG flag by the I2C_Slave,
231 ; it is assumed that it clears it as soon as the first byte has been exchanged.
232 ; **********************************;
233 TERMINAL_INT                        ; <--- 80us <--- START interrupt vector, bus is stalled, I2C_Master waits ACK on address
234 ; **********************************;
235 ; ACCEPT part II wake on TERM_INT   ; Org Ptr --
236 ; ----------------------------------;
237             ADD #4,RSP              ;1      remove SR and PC from stack, SR flags are lost (unused by FORTH interpreter)
238             BIC #WAKE_UP,&TERM_IFG  ;       clear UCSTTIFG before return to BACKGRND if any (here, UCSTTIFG is not yet cleared !)
239             BIT #10h,&TERM_CTLW0    ;4      test UCTR
240             JNZ BACKGRND            ;       if Master RX loop back to BACKGRND
241 ACCEPT_YES  POPM #4,IP              ;6      POPM  S=20h, T=0Ah, W=src_end, IP=ret_IP
242 QNEWCHAR    BIT #RX_TERM,&TERM_IFG  ;3      test RX BUF IFG
243             JZ QNEWCHAR             ;2      wait RX BUF full
244 ; ----------------------------------;
245 AKEYREAD    MOV.B &TERM_RXBUF,Y     ;3      read char into Y, RX_IFG is cleared, bus unstalled by I2C_Slave
246 ; ----------------------------------;
247             CMP.B S,Y               ;1      printable char ?
248             JC ASTORETEST           ;2      jump if char U>= BL
249             CMP.B T,Y               ;1      char = LF ?
250             JZ LF_NEXT              ;2      jump if char = LF
251 ; ----------------------------------;
252             CMP.B #8,Y              ;       char = BS ?
253             JNZ QNEWCHAR            ;       case of all other control chars: skip them
254 ; ----------------------------------;
255 ; case of backspace                 ;       made only by an human
256 ; ----------------------------------;
257             CMP @PSP,TOS            ;       Ptr = Org ?
258             JZ QNEWCHAR             ;       yes: does nothing
259             SUB #1,TOS              ;       no : dec Ptr
260             JMP QNEWCHAR            ;
261 ; ----------------------------------;
262 ASTORETEST  CMP W,TOS               ; 1     end of buffer is reached ?
263             JC QNEWCHAR             ; 2     yes: don't store char @ dst_Ptr, don't increment TOS
264             MOV.B Y,0(TOS)          ; 3     no: store char @ dst_Ptr
265             ADD #1,TOS              ; 1     increment dst_Ptr
266             JMP QNEWCHAR            ;
267 ; ----------------------------------;
268 LF_NEXT     BIT #10h,&TERM_CTLW0    ;4      test UCTR, instead of BUS idle because a ReSTART perhaps used by Master
269             JZ LF_NEXT              ;       wait until Master switched from TX to RX
270 ; ----------------------------------;
271             SUB @PSP+,TOS           ; -- len'
272             MOV S,Y                 ;       output a BL on TERMINAL (for the case of error occuring)
273             JMP QYEMIT              ;       before going to INTERPRET
274 ; **********************************;
275
276             FORTHWORD "KEY"         ;
277 ; ----------------------------------;
278 ; https://forth-standard.org/standard/core/KEY
279 ; KEY      -- c      wait character from input device ; primary DEFERred word
280 KEY         MOV @PC+,PC             ; Code Field Address (CFA) of KEY
281 PFAKEY      .word BODYKEY           ; Param Field Address (PFA) of KEY, with its default value
282 BODYKEY     PUSH #KEYNEXT           ;
283             MOV.B #1,Y              ; KEY request Ctrl_Char = $01
284 ; ----------------------------------;
285 I2C_CTRL_CH BIT #TX_TERM,&TERM_IFG  ; send it to I2C_Master_RX to restart it in TX mode
286             JZ I2C_CTRL_CH          ; wait TX buffer empty
287             MOV.B Y,&TERM_TXBUF     ; send Ctrl_Char
288             MOV @RSP+,PC            ;
289 ; ----------------------------------;
290 KEYNEXT     SUB #2,PSP              ;1          push old TOS..
291             MOV TOS,0(PSP)          ;           ..onto stack
292 BKEYLOOP    BIT #RX_TERM,&TERM_IFG  ;           received char ?
293             JZ BKEYLOOP             ;           wait char received
294             MOV &TERM_RXBUF,TOS     ; -- char
295             CALL #I2C_ACCEPT        ;           send Ctrl_Char $00 to I2C_Master to restart its UART in TX mode
296 BKEYEND     MOV @IP+,PC             ; -- char
297 ; ----------------------------------;
298
299             FORTHWORD "EMIT"        ;
300 ; ----------------------------------;
301 ; https://forth-standard.org/standard/core/EMIT
302 ; EMIT     c --    output character to an output device ; primary DEFERred word
303 EMIT        MOV @PC+,PC             ;3 Code Field Address (CFA) of EMIT
304 PFAEMIT     .word BODYEMIT          ;  Parameter Field Address (PFA) of EMIT, with its default value
305 BODYEMIT    MOV TOS,Y               ;1 sends character to the default output TERMINAL
306             MOV @PSP+,TOS           ;2
307 QYEMIT      BIT #TX_TERM,&TERM_IFG  ;3 NOECHO stores here : MOV @IP+,PC, ECHO store here the first word of: BIT #TX_TERM,&TERM_IFG
308             JZ QYEMIT               ;2 wait TX buffer empty
309             MOV.B Y,&TERM_TXBUF     ;3
310             MOV @IP+,PC             ;4 11 words
311 ; ----------------------------------;
312
313             FORTHWORD "ECHO"        ; --    connect EMIT to TERMINAL (default)
314 ;-----------------------------------;
315 ECHO        MOV #0B3A2h,&QYEMIT     ;       MOV #'BIT #TX_TERM,0(PC)',&QYEMIT
316             MOV.B #5,Y              ;       ECHO request Ctrl_Char = $05
317 ECHOEND     CALL #I2C_CTRL_CH       ;
318             MOV @IP+,PC             ;
319 ; ----------------------------------;
320
321             FORTHWORD "NOECHO"      ; --    disconnect TERMINAL from EMIT
322 ;-----------------------------------;
323 NOECHO      MOV #4D30h,&QYEMIT      ;       MOV #'MOV @IP+,PC',&QYEMIT
324             MOV.B #4,Y              ;       NOECHO request Ctrl_Char = $04
325             JMP ECHOEND             ;
326 ; ----------------------------------;