\ -*- coding: utf-8 -*-
\
-\ TARGET SELECTION ( = the name of \INC\target.pat file without the extension)
+\ TARGET SELECTION ( = the name of \INC\target.pat file without extension)
\ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
\ MSP_EXP430FR4133 (can't use LED1 because wired on UART TX)
\ MSP_EXP430FR2433 CHIPSTICK_FR2433 MSP_EXP430FR2355
\ ASSEMBLER conditionnal usage before ?GOTO : S< S>= U< U>= 0= 0<> 0<
\
\ ================================================================================
-\ coupled to a PL2303HXD cable, this driver enables a FastForth target to do an USB to I2C_Slave bridge,
+\ coupled to a PL2303HXD/TA cable, this driver enables a FastForth target to act as USB to I2C_Slave bridge,
\ thus, from TERATERM.exe you can take the entire control of up to 112 I2C_FastForth targets.
-\ In addition, it simulates a full duplex communication while the I2C bus is half duplex.
+\ In addition, it simulates a full duplex communication while the I2C bus is only half duplex.
\ Don't forget to wire 3k3 pull up resistors on wires SDA SCL!
\ ================================================================================
\
\ test results :
\ ------------
\
-\ downloading (+ interpret + compile + execute) CORETEST.4TH to I2C Master target, best time = 531ms.
-\ downloading (+ interpret + compile + execute) CORETEST.4TH to I2C Slave target, best time = 844ms.
-\ the difference (313 ms) is the time of the I2C Half duplex exchange (we reach the speed of the I2C Fast-mode Plus (Fm+)).
+\ downloading (+ interpret + compile + execute) CORETEST.4TH to I2C Master target = 1016ms.
+\ downloading (+ interpret + compile + execute) CORETEST.4TH to I2C Slave target = 1422ms.
+\ the difference (406 ms) is the time of the I2C Half duplex exchange.
+\ [(45906 chars * 9 bits) + (1533 * 31)] / 0,406 = 1,135 MHz (9 bits / char + (2*START + 2*STOP + 2*addr + CTRL_Char) / line)
+\ ==> 113 % of I2C Fast-mode Plus (Fm+)!
\
\ also connected to and tested with another I2C_FastForth target with MCLK = 1MHz (I2C CLK = MCLK ! ).
\
\
\ the other interruption U2I_TERM_INT is used to communicate with TERMINAL, by replacing of the TERM_INT one.
\
+\ Software +----------------------------------+ Hardware
+\ I2C Master | +-------------------+ | I2C Slave
+\ | | | |
+\ UART to I2C bridge SCL SDA connected to: SDA SCL I2CFastForth target
+\ ------------------- ---- ---- ---- ---- ------------------
+\ MSP_EXP430FR5739 P4.1 P4.0 P1.6 P1.7 MSP_EXP430FR5739
+\ MSP_EXP430FR5969 P1.3 P1.2 P1.6 P1.7 MSP_EXP430FR5969
+\ MSP_EXP430FR5994 P8.1 P8.2 P7.0 P7.1 MSP_EXP430FR5994
+\ MSP_EXP430FR6989 P1.5 P1.3 P1.6 P1.7 MSP_EXP430FR6989
+\ MSP_EXP430FR4133 P8.3 P8.2 P5.2 P5.3 MSP_EXP430FR4133
+\ CHIPSTICK_FR2433 P2.2 P2.0 P1.2 P1.3 CHIPSTICK_FR2433
+\ MSP_EXP430FR2433 P3.1 P3.2 P1.2 P1.3 MSP_EXP430FR2433
+\ MSP_EXP430FR2355 P3.3 P3.2 P1.2 P1.3 MSP_EXP430FR2355
+\ LP_MSP430FR2476 P3.3 P3.2 P4.4 P4.3 LP_MSP430FR2476
+\
+\ don't forget to link 3V3 and GND on each side and to add 3k3 pullup resistors on SDA and SCL.
+
; ----------------------------------------------------------------------
-; UARTI2CS.f
+; UARTI2CS.f (Software I2C Master)
; ----------------------------------------------------------------------
\ first, we do some tests before downloading application
0<> IF MOV #0,TOS THEN \ if TOS <> 0 (UART TERMINAL), set TOS = 0
MOV TOS,0(PSP)
MOV &VERSION,TOS
-SUB #307,TOS \ FastForth V3.7
+SUB #308,TOS \ FastForth V3.8
COLON
$0D EMIT \ return to column 1 without CR
-ABORT" FastForth version = 3.7 please!"
+ABORT" FastForth V3.8 please!"
ABORT" <-- Ouch! unexpected I2C_FastForth target!"
PWR_STATE \ remove the ABORT_UARTI2CS definition before continuing the download.
;
ABORT_UARTI2CS \ abort test
-[DEFINED] {UARTI2CS}
-[IF] {UARTI2CS} \ remove {UARTI2CS} if already defined
-[THEN]
+[DEFINED] {UARTI2CS} [IF] {UARTI2CS} [THEN] \ remove {UARTI2CS} if already defined
-MARKER {UARTI2CS} \ {UARTI2CS}+8 = RET_ADR to do nothing by default
-6 ALLOT \ {UARTI2CS}+10 <-- previous INI_APP
+MARKER {UARTI2CS} \ {UARTI2CS}+8 = RET_ADR by default
+8 ALLOT \ {UARTI2CS}+10 <-- previous INI_APP
\ {UARTI2CS}+12 <-- previous TERM_VEC
\ {UARTI2CS}+14 <-- previous Tx0_x_VEC
+\ {UARTI2CS}+16 <-- Half_Duplex flag : 0=ECHO, <>0=NOECHO
[UNDEFINED] CONSTANT [IF]
\ https://forth-standard.org/standard/core/CONSTANT
[THEN]
I2CSLA0 CONSTANT I2CS_ADR \ I2CSLA0=$FFA2
-I2CSLA1 CONSTANT HALF_DUPLEX \ I2CSLA1=$FFA4
-0 HALF_DUPLEX ! \ =0 --> ECHO, <>0 --> NOECHO
-\ note: ASM definitions are hidden and cannot be executed from TERMINAL
+\ note: HDNCODE definitions are HiDdeN and cannot be executed from TERMINAL
\---------------------------\
-ASM I2CSTOP \ sends a STOP on I2C_BUS
+HDNCODE I2CSTOP \ sends a STOP on I2C_BUS
\---------------------------\ _
BIS.B #SM_SCL,&I2CSM_DIR \ 3 h v_ force SCL as output (low)
NOP3 \ 3 l _
NOP3 \ 3 h _
BIC.B #SM_SDA,&I2CSM_DIR \ 3 h _^ relase SDA (high) when SCL is high = STOP
MOV @RSP+,PC \
-ENDASM \
+ENDCODE \
\---------------------------\
-\ note: ASM definitions are hidden and cannot be executed from TERMINAL
\---------------------------\
-ASM STOP_U2I \ STOP_APP subroutine, the next of TERATERM(ALT+B)|SW2+RST|SYS_failures
+HDNCODE STOP_U2I \ STOP_APP subroutine, the next of TERATERM(ALT+B)|SW2+RST|SYS_failures
\ --------------------------\ UARTI2CS can't be stopped by any other means.
BW1 \ <-- I2C_MASTER_RX <-- TERATERM break (Alt+B)
CMP #RET_ADR,&{UARTI2CS}+8 \
THEN \
\ --------------------------\ when STOP_U2I is the next of: TERATERM(ALT+B)|SW2+RESET|SYS_failures
MOV @RSP+,PC \ RET to: WARM_BODY|WARM_BODY|WARM_BODY
-ENDASM \
+ENDCODE \
\ --------------------------\
\ \ vvvvvvvMulti-Master-Modevvvvvv\
-\ ASM DO_IDLE \
+\ HDNCODE DO_IDLE \
\ MOV #4,W \ 1 wait bus idle time = 5 µs @ 16 MHz
\ BEGIN
\ BIT.B #SM_SCL,&I2CSM_IN \ 3
\ SUB #1,W \ 1
\ 0= UNTIL \ 2
\ MOV @RSP+,PC
-\ ENDASM
+\ ENDCODE
\ \ ^^^^^^^Multi-Master-Mode^^^^^^\
-\ note: ASM definitions are hidden and cannot be executed from TERMINAL
\ **************************************\
-ASM U2I_TERM_INT \ UART RX interrupt starts on first char of each line sent by TERMINAL
+HDNCODE U2I_TERM_INT \ UART RX interrupt starts on first char of each line sent by TERMINAL
\ **************************************\
ADD #4,RSP \ 1 remove unused PC_RET and SR_RET
\ --------------------------------------\
-MOV &HALF_DUPLEX,W \ 3 W = HALF_DUPLEX = 0 if ECHO, -1 if NOECHO
+MOV &{UARTI2CS}+16,W \ 3 W = HALF_DUPLEX = 0 if ECHO, -1 if NOECHO
MOV #PAD_ORG,T \ 2 T = buffer pointer for UART_TERMINAL input
MOV #$0D,S \ 2 S = 'CR' = penultimate char of line to be RXed by UART
BEGIN \
\ ======================================\
\ END OF I2C MASTER TX \ SCL is kept low until START RX --┐
\ ======================================\ |
-ENDASM \ |
+ENDCODE \ |
\ **************************************\ v
-\ note: ASM definitions are hidden and cannot be executed from TERMINAL
\ **************************************\
-ASM HALF_S_INT \ wakes up every 1/2s to listen I2C Slave or break from TERMINAL.
+HDNCODE HALF_S_INT \ wakes up every 1/2s to listen I2C Slave or break from TERMINAL.
\ **************************************\
ADD #4,RSP \ 1 remove PC_RET and SR_RET |
\ --------------------------------------\ |
\ --------------------------------\ see forthMSP430FR_TERM_I2C.asm
CMP.B #4,X \ 1
U>= IF \ 2
- MOV #0,&HALF_DUPLEX \ preset ECHO
+ MOV #0,&{UARTI2CS}+16 \ preset ECHO
0= IF \ 2
- MOV #-1,&HALF_DUPLEX \ 3 set NOECHO if char $04
+ MOV #-1,&{UARTI2CS}+16 \ 3 set NOECHO if char $04
THEN
BIS.B #SM_SDA,&I2CSM_DIR \ 3 l prepare Ack for Ctrl_Chars $04 $05
THEN
\ CTRL_Char $02|$03 \ l if ABORT|WARM requests, SDA is high, SCL is low
\ ------------------------------------\
0= IF \ if ABORT request:
- MOV #0,&HALF_DUPLEX \ set echo ON I2C_Master side
+ MOV #0,&{UARTI2CS}+16 \ set echo ON I2C_Master side
CALL #UART_RXON \ resume UART downloading source file
BEGIN \
BIC #UCRXIFG,&TERM_IFG \ clear UCRXIFG
\ --------------------------------------\
\ I2C_Master se réveillera au premier caractère saisi sur le TERMINAL ==> TERM_INT,
\ ou en fin du temps TxIFG ==> HALF_S_INT\
-ENDASM \
+ENDCODE \
\ **************************************\
-\ note: ASM definitions are hidden and cannot be executed from TERMINAL
\---------------------------\
-ASM INI_U2I \ define INI_HARD_APP subroutine called by WARM
+HDNCODE INI_U2I \ define INI_HARD_APP subroutine called by WARM
\ --------------------------\
CALL &{UARTI2CS}+10 \ previous INI_APP executing init TERM_UC, activates I/O and sets TOS = RSTIV_MEM.
\ --------------------------\ TOS = SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
\ --------------------------\
GOTO BW3 \ goto I2C_Master START RX loop, with no other return than ALT+B|SW2+RST
\ --------------------------\
-ENDASM \
+ENDCODE \
\ --------------------------\
\
-\
-\ ========================================================
-\ Driver UART to I2CM to do an USB to I2C_FastForth bridge
-\ ========================================================
+\ ==============================================================
+\ Driver UART to I2CM which does the bridge USB to I2C_FastForth
+\ ==============================================================
\ I2C address mini = 10h, maxi = 0EEh (I2C-bus specification and user manual V6)
\ type on TERMINAL "16 UARTI2CS" to link teraterm TERMINAL with FastForth I2C_Slave at address $10
\ you can also link with last known I2C_Slave address : "I2CS_ADR @ UARTI2CS"
\
-CODE UARTI2CS \ I2C_Slave_Address_%0 --
+: UARTI2CS \ I2C_Slave_Address_%0 --
+CR I2CS_ADR ! \ -- save I2C_Slave_Address_%0
+HI2LO
CMP #RET_ADR,&{UARTI2CS}+8 \
0= IF \ save parameters only if MARKER_DOES is not initialized
MOV #STOP_U2I,&{UARTI2CS}+8 \ MARKER_DOES of {UARTI2CS} will do CALL &{UARTI2CS}+8 = CALL #STOP_U2I
MOV &WARM+2,&{UARTI2CS}+10 \ save previous INI_APP from WARM PFA to {UARTI2CS}+10
- MOV #INI_U2I,&WARM+2 \ and replace it by new INI_APP
MOV &TERM_VEC,&{UARTI2CS}+12 \ save previous TERM_VEC value to {UARTI2CS}+12, see target.pat
- MOV #U2I_TERM_INT,&TERM_VEC \ and replace it by U2I_TERM_INT
- \ MOV &TA0_X_VEC,&{UARTI2CS}+14 \ save previous TA0_x_VEC value to {UARTI2CS}+14
- \ MOV #HALF_S_INT,&TA0_X_VEC \ and replace it by HALF_S_INT
- MOV &TB0_X_VEC,&{UARTI2CS}+14 \ save previous TB0_x_VEC value to {UARTI2CS}+14
- MOV #HALF_S_INT,&TB0_X_VEC \ and replace it by HALF_S_INT
+ MOV &TB0_X_VEC,&{UARTI2CS}+14 \ save previous TB0_X_VEC value to {UARTI2CS}+14
+ \ MOV &TA0_X_VEC,&{UARTI2CS}+14 \ save previous TA0_X_VEC value to {UARTI2CS}+14
+ MOV #0,&{UARTI2CS}+16 \ reset Half_Duplex variable (set ECHO ON)
+ MOV #INI_U2I,&WARM+2 \ replace INI_APP by new INI_U2I
+ MOV #U2I_TERM_INT,&TERM_VEC \ set TERM_VEC with U2I_TERM_INT
+ MOV #HALF_S_INT,&TB0_X_VEC \ set TB0_X_VEC with HALF_S_INT
+ \ MOV #HALF_S_INT,&TA0_X_VEC \ set TA0_X_VEC with HALF_S_INT
THEN
-COLON
-CR I2CS_ADR ! \ -- save I2C_Slave_Address_%0
-WARM \ execute INI_U2I then goto BW3; abort with Alt-B or SW2+RST.
-;
+MOV #WARM,PC \ execute INI_U2I then goto BW3; abort with Alt-B or SW2+RST.
+ENDCODE
RST_HERE ECHO
18 UARTI2CS ; TERATERM(Alt-B) or I2C_Master(SW2+RST) to quit