OSDN Git Service

V303, newcomer: FastForth I2C TERMINAL
[fast-forth/master.git] / MSP430-FORTH / UART2I2CS.f
diff --git a/MSP430-FORTH/UART2I2CS.f b/MSP430-FORTH/UART2I2CS.f
new file mode 100644 (file)
index 0000000..1c266b8
--- /dev/null
@@ -0,0 +1,589 @@
+\ -*- coding: utf-8 -*-
+
+\ Fast Forth For Texas Instrument MSP430FRxxxx FRAM devices
+\ Copyright (C) <2019>  <J.M. THOORENS>
+\
+\ This program is free software: you can redistribute it and/or modify
+\ it under the terms of the GNU General Public License as published by
+\ the Free Software Foundation, either version 3 of the License, or
+\ (at your option) any later version.
+\
+\ This program is distributed in the hope that it will be useful,
+\ but WITHOUT ANY WARRANTY\ without even the implied warranty of
+\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+\ GNU General Public License for more details.
+\
+\ You should have received a copy of the GNU General Public License
+\ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+\
+; ----------------------------------------------------------------------
+; UART2I2CS.f
+; ----------------------------------------------------------------------
+\
+\ TARGET SELECTION
+\ MSP_EXP430FR5739  MSP_EXP430FR5969    MSP_EXP430FR5994    MSP_EXP430FR6989
+\ MSP_EXP430FR4133  MSP_EXP430FR2433    MSP_EXP430FR2355    CHIPSTICK_FR2433
+\
+\ FastForth kernel compilation minimal options:
+\ DTC = 2, THREADS = 16, FREQUENCY = 16
+\ TERMINALBAUDRATE = 921600, TERMINAL3WIRES, TERMINAL4WIRES
+\ MSP430ASSEMBLER, CONDCOMP
+\
+\
+\     notebook                                 USB to I2C_Slave bridge                                     any I2C_slave
+\ +---------------+         +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - --+
+\ |               |         |   PL2303HXD               master running UART2I2CS @ 16MHz |
+\ |               |         +---------------+           +--------------------------------+         +-------------------------------+
+\ |               |         |               |           |                                |         |                               |
+\ |   TERATERM   -o--> USB -o--> USB2UART --o--> UART --o--> FAST FORTH ---> UART2I2CS --o--> I2C -o--> FAST FORTH with kernel     |
+\ |   terminal    |         |               | 921600Bds |                                |  450kHz |     option TERMINAL_I2C       |
+\ |               |         +---------------+           +--------------------------------+         +-------------------------------+
+\ |               |         |                                                            | 
+\ +---------------+         +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - --+
+\
+\
+\ software I2C MASTER, you can use any I/O for SDA and SCL,
+\ Preferably use a couple of I/O in the interval Px0...Px3.
+\ don't forget to wire 3.3k pullup resitors on SDA and SCL.
+
+
+\ the LEDs TX and RX work fine, uncomment if you want.
+
+\ Multi Master Mode work but is not tested in real word.
+
+
+PWR_STATE
+
+[DEFINED] {FF_I2C} [IF]  {FF_I2C} [THEN]
+
+MARKER {FF_I2C}
+
+[UNDEFINED] @ [IF]
+\ https://forth-standard.org/standard/core/Fetch
+\ @     c-addr -- char   fetch char from memory
+CODE @
+MOV @TOS,TOS
+MOV @IP+,PC
+ENDCODE
+[THEN]
+
+[UNDEFINED] CONSTANT [IF]
+\ https://forth-standard.org/standard/core/CONSTANT
+\ CONSTANT <name>     n --                      define a Forth CONSTANT 
+: CONSTANT 
+CREATE
+HI2LO
+MOV TOS,-2(W)           \   PFA = n
+MOV @PSP+,TOS
+MOV @RSP+,IP
+MOV @IP+,PC
+ENDCODE
+[THEN]
+
+$1820 CONSTANT SLAVE_ADR    \ to save I2C_Slave address in FRAM
+
+
+ASM QUIT_I2C                    \ as ASM word, QUIT_I2C is hidden.
+\ ------------------------------\
+BW1 \   STOP I2C                \
+\ \ ------------------------------\
+\     BIC.B #LED2,&LED2_DIR       \ RX green led OFF
+\     BIC.B #LED2,&LED2_OUT       \ RX green led OFF
+\     BIC.B #LED1,&LED1_DIR       \ TX red led OFF
+\     BIC.B #LED1,&LED1_OUT       \ TX red led OFF
+\ \ ------------------------------\
+    BIS #M_BUS,&I2CM_REN        \ reset I/O as reset state
+    BIC #M_BUS,&I2CM_DIR        \
+    BIS #M_BUS,&I2CM_OUT        \
+    MOV #$5A88,&WDTCTL          \ stop WDT
+    BIC #1,&SFRIE1              \ disable WDT int
+    MOV &$FFFA,&WDT_VEC         \ [USER_NMI_vector] = COLD, restore default WDT_VEC value
+    MOV &TERMINAL_INT,&TERM_VEC \ restore default TERM_VEC value (in FRAM INFO)
+    MOV #WARM,X                 \
+    ADD #4,X
+    MOV X,-2(X)                 \ restore default WARM
+\    MOV @IP+,PC                 \ quiet return without COLD
+    MOV X,PC                    \ explicit return with COLD
+ENDASM
+
+ASM WDT_INT                     \ enable Alt+B when I2C_Master is sleeping
+BIT #8,&TERM_STATW              \ UART break sent by TERATERM ?
+0<> IF
+    ADD #4,RSP                  \ remove RETI
+    POPM #6,IP                  \ remove Y,X,W,T,S,IP from return stack, restore IP
+    GOTO BW1                    \
+THEN
+RETI
+ENDASM
+
+\ \ vvvvvvvMulti-Master-Modevvvvvv\
+\ ASM DO_IDLE                     \ 
+\ MOV #4,W                        \ 1   wait bus idle time = 5 µs @ 16 MHz
+\ BEGIN
+\     BIT #8,&TERM_STATW          \ 3         break sent by TERATERM ?
+\     0<> IF                      \ 2
+\         ADD #2,RSP              \           remove RET
+\         MOV #QUIT_I2C,PC        \           STOP I2C
+\     THEN  
+\     BIT.B #MSCL,&I2CM_IN        \ 3 
+\     0= IF                       \ 2
+\         MOV #4,W                \ 1 if SCL is LOW
+\     THEN
+\         BIT.B #MSDA,&I2CM_IN    \ 3
+\     0= IF                       \ 2
+\         MOV #4,W                \ 1 if SDA is LOW
+\     THEN
+\     SUB #1,W                    \ 1
+\ 0= UNTIL                        \ 2
+\ MOV @RSP+,PC
+\ ENDASM
+\ \ ^^^^^^^Multi-Master-Mode^^^^^^\
+
+
+\ **************************************\
+ASM TERM_INT                            \  starts with first char of line input from TERMINAL
+\ **************************************\
+ADD #4,RSP                              \ 1   remove RET and SR
+POPM #6,IP                              \ 8   pop Y,X,W,T,S,IP
+\                                       \ S = last char to RX from UART
+\                                       \ T = UART RX buffer
+\                                       \ W = flag NOECHO/ECHO to TERMINAL
+\                                       \ X = UART RX char
+\                                       \ Y = I2C TX buffer
+\ --------------------------------------\
+BEGIN                                   \
+    BEGIN                               \
+        BEGIN                           \   wait for a char or for a break
+            BIT #1,&TERM_IFG            \ 3 received char ?
+        0<> UNTIL                       \ 2 
+BW1     MOV.B &TERM_RXBUF,X             \ 3 received char in TERMRXBUF
+        MOV.B X,0(T)                    \ 3 fill I2C_input... ...buffer
+        CMP.B S,X                       \ 1 char = char end = $0A ?
+        0= ?GOTO FW1                    \ 2 goto out of UART RX loop
+        ADD #1,T                        \ 1
+        CMP.B #$0D,X                    \ 2 CR ?
+    0<> WHILE                           \ 2  32 cycles loop ==> up to 2.5Mbds @ 8MHz
+        CMP #0,W                        \ 1
+        0= IF                           \ 2  if echo ON requested by I2C_Slave
+            MOV.B X,&TERM_TXBUF         \ 3
+        THEN
+    REPEAT                              \ 2
+    CALL &RXOFF                         \ stops UART RX after received char CR and before receive char LF
+AGAIN                                   \ then take again one loop back to get LF
+\ --------------------------------------\
+FW1 \ END OF UART RX                    \  CR+LF ends the line input from TERMIANL
+\ ======================================\ S = last char to transmit
+\ ======================================\ T = last char transmitted
+BW2 \ I2C MASTER TX                     \ W = bits count / delay count down
+\ ======================================\ X = I2C_Address / I2C_Data
+\ ======================================\ Y = buffer TX address            
+\ \ --------------------------------------\
+\ BIS.B #LED1,&LED1_DIR                   \ red led ON = I2C TX 
+\ BIS.B #LED1,&LED1_OUT                   \ red led ON = I2C TX
+\ \ --------------------------------------\
+\ BW3 \ I2C_Master TX Start               \ here, SDA and SCL must be in idle state
+\ --------------------------------------\
+BIS.B   #MSDA,&I2CM_DIR                 \ 4 l   force SDA as output (low)
+MOV.B   &SLAVE_ADR,X                    \ 1 h   X = Slave_Address
+BIC.B   #1,X                            \ 1 h   Master TX
+NOP3                                    \ 3 h
+NOP3                                    \ 3 h
+BIS.B   #MSCL,&I2CM_DIR                 \ 4 h   force SCL as output (low)
+MOV S,T                                 \       
+XOR #-1,T                               \ 1     set T <> S before sending I2C address 
+\ --------------------------------------\
+BEGIN
+\   ------------------------------------\
+\   I2C Master TX address/Data          \
+\   ------------------------------------\
+    MOV.B #8,W                          \ 1 l       prepare 8 bits address
+    BEGIN                               \
+        ADD.B X,X                       \ 1 l       shift one left
+        U>= IF                          \ 2 l       carry set ?
+            BIC.B #MSDA,&I2CM_DIR       \ 4 l       yes : SDA as input  ==> SDA high because pull up resistor
+        ELSE                            \ 2 l
+            BIS.B #MSDA,&I2CM_DIR       \ 4 l       no  : SDA as output ==> SDA low
+            NOP2                        \ 2
+        THEN                            \   l   _
+        BIC.B #MSCL,&I2CM_DIR           \ 4 l _^    release SCL (high)
+        BEGIN                           \           9~h/16~l
+            BIT.B #MSCL,&I2CM_IN        \ 3 h       test if SCL is released
+        0<> UNTIL                       \ 2 h 
+\ \       vvvvvvvvMulti-Master-Modevvvvvvv\
+\         BIT.B #MSDA,&I2CM_IN            \ 3 h _     test SDA
+\ \       ^^^^^^^^Multi-Master-Mode^^^^^^^\
+        BIS.B #MSCL,&I2CM_DIR           \ 4 h  v_   SCL as output : force SCL low
+\ \       vvvvvvvvvvvvMulti-Master-Modevvvvvvvvvvv\
+\         0= IF                                   \ 2 l
+\             BIT.B #MSDA,&I2CM_DIR               \ 3 l
+\             0= IF                               \ 2 l
+\ \               --------------------------------\
+\ \               collision detected              \   l collision if SDA(IN)=0 AND SDA(DIR)=0
+\ \               --------------------------------\
+\                 BIS.B #MSCL,&I2CM_DIR           \ 4 l release SCL first
+\                 CALL #DO_IDLE                   \     wait stable idle state 
+\                 GOTO BW3                        \ 2 l goto START TX
+\             THEN
+\         THEN
+\ \       ^^^^^^^^^^^^Multi-Master-Mode^^^^^^^^^^^\
+        SUB #1,W                        \ 1 l       bits count-1
+    0= UNTIL                            \ 2 l
+\   ------------------------------------\
+    BIC.B   #MSDA,&I2CM_DIR             \ 4 l       after TX byte we must release SDA to read Ack/Nack from Slave
+\   ------------------------------------\
+\   I2C Master get Slave Ack/Nack       \
+\   ------------------------------------\       _
+    BIC.B   #MSCL,&I2CM_DIR             \ 3 l _^    release SCL (high)
+    BEGIN                               \
+        BIT.B #MSCL,&I2CM_IN            \ 3 h       test if SCL is released
+    0<> UNTIL                           \ 2 h
+    BIT.B   #MSDA,&I2CM_IN              \ 3 h _     get SDA state
+    BIS.B   #MSCL,&I2CM_DIR             \ 3 h  v_   SCL as output : force SCL low
+\   ------------------------------------\
+0= WHILE \ 1 Slave Ack received         \ 2 l       goto THEN; out of loop if Nack
+\   ------------------------------------\           
+\   I2C_Master_TX_data_loop             \
+\   ------------------------------------\
+    CMP.B S,T                           \ 1         T = S = last char to transmit ?
+0<> WHILE \ 2                           \ 2         goto beyond REPEAT; out of loop if =
+    MOV.B @Y+,X                         \ 2 l       get next byte to TX
+    MOV X,T                             \ 1         T = last char TX for comparaison above
+REPEAT                                  \           <-- WHILE2  search "Extended control-flow patterns"... 
+THEN                                    \           <-- WHILE1  ...in https://forth-standard.org/standard/rationale
+\   ------------------------------------\
+\ Nack or Ack on last char              \           Nack = I2C_Slave request or I2C_Slave RESET, Ack = last char has been TX
+\   ------------------------------------\
+    NOP3                                \ 3 l   _   delay to reach I2C tLO
+    BIC.B #MSCL,&I2CM_DIR               \ 4 l _^    release SCL to enable reSTART
+\ \ --------------------------------------\
+\     BIC.B #LED1,&LED1_DIR               \ red led OFF = endof I2C TX 
+\     BIC.B #LED1,&LED1_OUT               \ red led OFF = endof I2C TX
+\ \ --------------------------------------\
+\ ======================================\
+\ END OF I2C MASTER TX                  \
+\ ======================================\
+\ ======================================\
+\ I2C MASTER RX                         \
+\ ======================================\
+BW3 \ I2C_Master START RX               \
+\ --------------------------------------\
+\ le driver I2C_Master envoie START RX en boucle.
+\ le test d'un break en provenance de l'UART est intégré dans cette boucle.
+\ --------------------------------------\
+BEGIN                                   \           I2C MASTER RX
+\ --------------------------------------\
+    BEGIN                               \           I2C MASTER START RX
+\   ------------------------------------\
+\       I2C_Master_Start_Cond           \           here, SDA and SCL must be in idle state
+\       --------------------------------\
+        BIS.B   #MSDA,&I2CM_DIR         \ 4 l       force SDA as output (low)
+        MOV.B   &SLAVE_ADR,X            \ 1 h       X = Slave_Address
+        BIS.B   #1,X                    \ 1 h       Master RX
+        NOP3                            \ 3
+        NOP3                            \ 3
+        BIS.B   #MSCL,&I2CM_DIR         \ 4 h       force SCL as output (low)
+\       --------------------------------\
+\       I2C_Master_Send_address         \           may be SCL is held low by slave
+\       --------------------------------\
+        MOV.B   #8,W                    \ 1 l       prepare 8 bits address
+        BEGIN                           \
+            ADD.B X,X                   \ 1 l       shift one left
+            U>= IF                      \ 2 l       carry set ?
+                BIC.B #MSDA,&I2CM_DIR   \ 4 l yes : SDA as input  ==> SDA high because pull up resistor
+            ELSE                        \ 2 l
+                BIS.B #MSDA,&I2CM_DIR   \ 4 l no  : SDA as output ==> SDA low
+                NOP2                    \ 2 l
+            THEN                        \       _
+            BIC.B #MSCL,&I2CM_DIR       \ 4 l _^    release SCL (high)
+            BEGIN                       \
+                BIT.B #MSCL,&I2CM_IN    \ 3 h       test if SCL is released
+            0<> UNTIL                   \ 2 h
+\ \           vvvvvvMulti-Master-Modevvvvv\
+\             BIT.B #MSDA,&I2CM_IN                    \ 3 h _     test SDA
+\ \           ^^^^^^Multi-Master-Mode^^^^^\
+            BIS.B #MSCL,&I2CM_DIR       \ 4 h  v_   SCL as output : force SCL low
+\ \           vvvvvvvvvvvvMulti-Master-Modevvvvvvvvvvv\
+\             0= IF                                   \ 2 l
+\                 BIT.B #MSDA,&I2CM_DIR               \ 3 l
+\                 0= IF                               \ 2 l
+\ \               ------------------------------------\
+\ \               collision detection                 \   l collision if SDA(IN)=0 AND SDA(DIR)=0
+\ \               ------------------------------------\
+\                     BIS.B #MSCL,&I2CM_DIR           \ 4 l release SCL first
+\                     CALL #DO_IDLE                   \     wait stable idle state 
+\                     GOTO BW3                        \ 2 l goto START RX
+\                 THEN
+\             THEN
+\ \           ^^^^^^^^^^^^Multi-Master-Mode^^^^^^^^^^^\
+            SUB #1,W                    \ 1 l       bits count - 1
+        0= UNTIL                        \ 2 l
+\       --------------------------------\
+        BIC.B   #MSDA,&I2CM_DIR         \ 4 l   _   after TX address we must release SDA to read Ack/Nack from Slave
+        BIC.B   #MSCL,&I2CM_DIR         \ 3 l _^    release SCL (high)
+        BEGIN                           \
+            BIT.B #MSCL,&I2CM_IN        \ 3 h       test if SCL is released
+        0<> UNTIL                       \ 2 h
+        BIT.B   #MSDA,&I2CM_IN          \ 3 h _     get SDA
+        BIS.B   #MSCL,&I2CM_DIR         \ 3 h  v_   SCL as output : force SCL low
+\       --------------------------------\  
+    0<> WHILE   \ Nack_On_Address       \ 2 l
+\       --------------------------------\  
+        NOP3                            \ 3 l       delay to reach tLO
+\       --------------------------------\
+\       I2C_Master Send STOP            \           after Nack_On_Address
+\       --------------------------------\     _
+        BIS.B #MSDA,&I2CM_DIR           \ 4 l  v_   SDA as output ==> SDA low
+        NOP3                            \ 3 l   _
+        BIC.B #MSCL,&I2CM_DIR           \ 4 l _^    release SCL (high)
+        NOP3                            \ 3 h
+        NOP3                            \ 3 h   _
+        BIC.B #MSDA,&I2CM_DIR           \ 4 h _^    SDA as input  ==> SDA high with pull up resistor
+\       --------------------------------\
+        BIT #8,&TERM_STATW              \ 3         break sent by TERATERM ?
+        0<> IF
+            MOV #QUIT_I2C,PC            \ 2         STOP I2C
+        THEN
+\       --------------------------------\
+    REPEAT                              \ 2         loop back to MASTER START RX
+\ \   ------------------------------------\
+\     BIS.B #LED2,&LED2_DIR               \           green led ON = I2C RX
+\     BIS.B #LED2,&LED2_OUT               \           green led ON = I2C RX
+\ \   ------------------------------------\
+\   I2C_Master_RX_data                  \
+\   ------------------------------------\
+    BEGIN
+        BEGIN
+            MOV.B #8,W                  \ 1 l       prepare 8 bits transaction
+\           ----------------------------\
+            BEGIN                       \
+\               ------------------------\       _
+\               do SCL pulse            \ SCL _| |_
+\               ------------------------\       _
+                BIC.B #MSCL,&I2CM_DIR   \ 4 l _^    release SCL (high)
+                BEGIN                   \           9/16~l
+                BIT.B #MSCL,&I2CM_IN    \ 3 h       test if SCL is released
+                0<> UNTIL               \ 2 h
+                BIT.B #MSDA,&I2CM_IN    \ 3 h _     get SDA
+                BIS.B #MSCL,&I2CM_DIR   \ 4 h  v_   SCL as output : force SCL low   13~
+                ADDC.B X,X              \ 1 l       C <--- X(7) ... X(0) <--- SDA
+                SUB #1,W                \ 1 l       count down of bits
+            0= UNTIL                    \ 2 l
+\           ----------------------------\
+            CMP.B #8,X                  \ 1 l       $08 = char BS
+\           ----------------------------\
+        U>= WHILE                       \ 2 l       normal char received, comprizing BS
+\           ----------------------------\
+            BEGIN                       \
+                BIT #2,&TERM_IFG        \ 3 l       TX buffer empty ?
+            0<> UNTIL                   \ 2 l       loop if no
+\           ----------------------------\   
+            BIS.B #MSDA,&I2CM_DIR       \ 4 l       prepare Ack
+\           ----------------------------\       _   
+            BIC.B   #MSCL,&I2CM_DIR     \ 3 l _^    release SCL (high)
+            BEGIN                       \
+                BIT.B #MSCL,&I2CM_IN    \ 3 h       test if SCL is released
+            0<> UNTIL                   \ 2 h
+            MOV.B X,&TERM_TXBUF         \ 3 h _     send RX char to UART TERMINAL
+            BIS.B #MSCL,&I2CM_DIR       \ 3 h  v_   SCL as output : force SCL low
+\           ----------------------------\  
+            BIC.B #MSDA,&I2CM_DIR       \ 4 l       before RX next byte, we must release SDA
+\           ----------------------------\  
+        REPEAT                          \ 2 l       loop back to I2C_Master_RX_data
+\       --------------------------------\
+\       Ctrl_char received              \
+\       --------------------------------\ 
+        CMP.B #4,X                      \ 1         
+        U>= IF                          \ 2
+\           ----------------------------\
+            BIS.B #MSDA,&I2CM_DIR       \ 4 l       prepare Ack for $04=NOECHO,$05=ECHO
+\           ----------------------------\
+        THEN
+\       --------------------------------\       _   
+        BIC.B   #MSCL,&I2CM_DIR         \ 3 l _^    release SCL (high)
+        BEGIN                           \
+            BIT.B #MSCL,&I2CM_IN        \ 3 h       test if SCL is released
+        0<> UNTIL                       \ 2 h
+        BIT.B   #MSDA,&I2CM_IN          \ 3 h _     get SDA
+        BIS.B   #MSCL,&I2CM_DIR         \ 3 h  v_   SCL as output : force SCL low
+\       --------------------------------\       
+    0= WHILE                            \ 2 l       if Ack sent by Master (4 >= char < 8) 
+\       --------------------------------\       
+        BIC.B #MSDA,&I2CM_DIR           \           before RX next byte, we must release SDA
+\       --------------------------------\       
+        CMP.B #4,X                      \
+\       --------------------------------\       
+        0= IF                           \           $04 = ctrl_char for NOECHO request
+            MOV #1,&TIB_I2CADR          \           set NOECHO
+        ELSE                            \           $05 = ctrl_char for ECHO request
+            MOV #0,&TIB_I2CADR          \           set ECHO
+        THEN
+    REPEAT                              \           loop back to I2C_Master_RX_data
+\   ------------------------------------\   
+\   if Nack sent by Master              \           SDA is released HIGH
+\   ------------------------------------\   
+    CMP.B #2,X                          \ 1 l       $02 = ctrl_char for ABORT request
+0= WHILE                                \ 2 l       if Ctrl_char = $02
+    MOV #0,&TIB_I2CADR                  \           set echo on I2C_Master side
+\   ------------------------------------\   
+\   UART_ABORT                          \
+\   ------------------------------------\
+    CALL &RXON                          \           resume UART downloading source file
+    BEGIN                               \
+        BIC #UCRXIFG,&TERM_IFG          \           clear UCRXIFG ('ESC' char is lost)
+        MOV &FREQ_KHZ,Y                 \           1000, 2000, 4000, 8000, 16000, 240000
+        BEGIN MOV #32,X                 \           2~        <-------+ windows 10 seems very slow... ==> ((32*3)+5) = 101ms delay
+            BEGIN SUB #1,X              \           1~        <---+   |
+            0= UNTIL                    \           2~ 3~ loop ---+   | to refill its USB buffer
+            SUB #1,Y                    \           1~                |
+        0= UNTIL                        \           2~ 101~ loop -----+
+        BIT #UCRXIFG,&TERM_IFG          \           4 new char in TERMRXBUF during this delay ?
+    0= UNTIL                            \           2 yes, the input stream may be still active: loop back
+REPEAT                                  \           loop back to I2C MASTER reSTART RX
+\ --------------------------------------\
+\ I2C_Master Send STOP                  \           after RX Data(s) 
+\ --------------------------------------\       _
+BIC.B #MSCL,&I2CM_DIR                   \ 4 l _^    release SCL (high)
+NOP3                                    \ 3 h
+NOP3                                    \ 3 h   _
+BIC.B #MSDA,&I2CM_DIR                   \ 4 h _^    SDA as input  ==> SDA high with pull up resistor
+\ \ --------------------------------------\
+\ BIC.B #LED2,&LED2_DIR                   \ 4 l green led OFF = endof I2C RX
+\ BIC.B #LED2,&LED2_OUT                   \ 4 l green led OFF = endof I2C RX
+\ \ --------------------------------------\
+\ ======================================\
+\ ======================================\
+\ END OF I2C MASTER RX                  \   here I2C_bus is free and Nack on Ctrl_char $00|$01 remains to be processed.
+\ ======================================\
+\ ======================================\
+\ TERMINAL TX --> UART RX               \
+\ --------------------------------------\
+\ I2C_Slave KEY ctl_char $01            \ I2C_Slave request for KEY input
+\ --------------------------------------\
+CMP.B #1,X                              \ 1 l
+\ Quand I2C_Master reçoit ce caractère de contrôle,
+\ il attend un caractère en provenance de TERMINAL UART
+\ et une fois ce caractère reçu reSTART TX pour l'envoyer à I2C_Slave
+0= IF                                   \ 2 l
+    CALL &RXON                          \ 4 l  to enable UART RX; use no registers
+    MOV #TIB_I2CCNT,Y                   \ Y = input buffer for I2C_Master TX
+    MOV Y,T                             \ T = input buffer for UART RX
+    BEGIN                               \   wait for a char or for a break
+        BIT #UCRXIFG,&TERM_IFG          \ 3 received char ?
+    0<> UNTIL                           \ 2 
+    MOV.B &TERM_RXBUF,X                 \ 3 X = UART RX char
+    MOV.B X,0(T)                        \ 3 fill I2C_input... ...buffer
+    MOV.B X,S                           \ 2 S = KEY char = last char to send with I2C_MASTER TX !
+    CALL &RXOFF                         \ stops UART RX
+    GOTO BW2                            \ goto I2C MASTER TX
+THEN                                    \                             
+\ --------------------------------------\
+\ I2C_Slave ACCEPT ctrl_char $00        \ I2C_Slave requests I2C_Master to stop RX and start TX
+\ --------------------------------------\
+\ en début de sa routine ACCEPT, I2C_Slave envoie sur le bus I2C le caractère de contrôle $00
+\ avant de s'endormir avec SLEEP
+\ I2C_Master envoie NACK + STOP pour signifier la fin de la transaction.
+\ --------------------------------------\
+\ I2C_Slave SLEEP ctrl_char $00         \ as request to stop I2C_Master RX     
+\ --------------------------------------\
+\ si I2C_Slave est sorti de son sommeil par un START RX, idem.
+\ --------------------------------------\
+\ I2C_Master envoie un XON sur l'UART, à destination de TERMINAL
+\ I2C_Master attend un flux de caractères en provenance du TERMINAL 
+\     ou l'occurence d'un break qui génère la sortie du programme. 
+\ les caractères reçus de TERMINAL sont stockés dans un buffer.
+\ A la réception du caractère CR, I2C_Master envoie XOFF à TERMINAL
+\ et refait encore un tour pour capter LF.
+\ pendant ce temps, I2C_Slave est dans l'état SLEEP, le bus I2C est libre
+\ --------------------------------------\
+MOV #TIB_ORG,Y                          \ Y = input buffer for I2C_Master TX
+MOV &TIB_I2CADR,W                       \ W = 0 if ECHO, 1 if NOECHO
+MOV Y,T                                 \ T = input buffer for UART RX
+MOV #$0A,S                              \ S = last char to send with I2C_MASTER TX
+PUSHM #6,IP                             \ push IP,S,T,W,X,Y, as ACCEPT
+MOV #SLEEP,PC                           \ execute RXON then goto dodo
+ENDASM                                  \ 
+\ --------------------------------------\
+
+
+
+
+
+\ --------------------------------------\
+ASM WARM_I2C                            \           replace default WARM
+\ --------------------------------------\
+CMP #4,&SAVE_SYSRSTIV                   \
+0= IF
+    MOV #QUIT_I2C,PC                    \           if <reset> STOP I2C
+THEN                
+    CMP #$10,&SAVE_SYSRSTIV             \
+    U>= IF
+        MOV #QUIT_I2C,PC                \           if other SYS failure >= $10 STOP I2C
+    THEN                                \
+MOV #0,&SAVE_SYSRSTIV                   \           
+\ --------------------------------------\
+\ init WDT timer                        \
+\ --------------------------------------\
+MOV #%0101_1010_0101_1111,&WDTCTL       \           start Watchdog Timer : XDTPW, WDTSSEL=VLOCLK, WDTCNTCL=1, WDTIS=2^6 (8ms)
+BIS #1,&SFRIE1                          \           enable WDT
+MOV #WDT_INT,&WDT_VEC                   \           replace WDT_VEC default value (COLD) by WDT_INT
+\ --------------------------------------\
+\ init TERMINAL UART                    \
+\ --------------------------------------\
+BIS #IE_TERM,&TERM_IE                   \           then enable RX interrupt for wake up on terminal input
+BIS.B #TERM_BUS,&TERM_SEL               \           Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
+MOV #TERM_INT,&TERM_VEC                 \           replace TERM_VEC default value (TERMINAL_INT) by TERM_INT
+\ --------------------------------------\
+\ initialisation I2C_MASTER             \           I2CM_DIR(M_BUS) = 0,  M_BUS as input
+\ --------------------------------------\
+BIC #M_BUS,&I2CM_REN                    \           remove internal pullup resistors (presence of external pullup resistor 3.3k)
+BIC #M_BUS,&I2CM_OUT                    \           preset SDA + SCL LOW
+\ --------------------------------------\
+\ activate I/O                          \           SYSRSTIV = $02 | $0E = POWER ON | SVSH threshold
+\ --------------------------------------\
+BIC #1,&PM5CTL0                         \           activate all previous I/O settings; if not activated, nothing works after reset !
+\ ======================================\
+\ ENDOF WARM part                       \
+\ ======================================\
+GOTO BW3                                \           goto I2C_Master START RX
+ENDASM
+
+\ ================================================================================
+\ Driver UART to I2CM : this FastForth launchpad becomes an USB to I2C_Slave bridge
+\ ================================================================================
+\
+\ I2C = 450 kHz @ MCLK = 16 MHz, better than an hardware UCB0 I2C Master !
+\ I2C bus resistors pullup = 3.3k
+\ type on TERMINAL "$10 UART2I2CS" to link TERMINAL with FastForth I2C_Slave at address hex $10
+\
+\ type Alt+B on TERATERM TERMINAL to send a break to quit, or <reset> on I2C_Master.
+
+\ UART to I2C_Master 
+CODE UART2I2CS                         \ SlaveAddress --
+MOV @RSP+,IP
+MOV TOS,&SLAVE_ADR                  \ save in FRAM
+MOV @PSP+,TOS
+MOV #WARM,X
+MOV #WARM_I2C,2(X)                  \ replace WARM by WARM_I2C, so POR execute WARM_I2C
+MOV X,PC                            \ execute WARM_I2C
+ENDCODE
+
+RST_HERE
+
+; Since there is no difference in behavior whether the TERMINAL is connected to the Master
+; or to a Slave, the convenient way to check which target is connected to is to execute WARM,
+; because WARM displays first the decimal I2C address when TERMINAL is connected to I2C FastForth.
+
+WARM    \ to show the target linked to TERMINAL before: no I2C Slave address 
+
+; v---- in forthMSP430FR.asm file search "I2CSLAVEADR" value used when compiling FastForth for TERMINAL_I2C
+ $10 UART2I2CS
+
+WARM    \ to show the target linked to TERMINAL after: see the decimal I2C Slave address first.
+
+; remember: from scite menu or in the SendSourceFileToTarget.bat file, select the good target to download UART2I2CS
+;           then select the good target to download sources file to the target running FastForth I2C
+;           at the specified I2C address !
+
+;           Alt-B to quit UART2I2CS
+
+; ready for a cluster of FastForth(s) ?