1 \ name : msp430FR5xxx_I2CF_Soft_MultiMaster.asm
3 \ Copyright (C) <2015> <J.M. THOORENS>
5 \ This program is free software: you can redistribute it and/or modify
6 \ it under the terms of the GNU General Public License as published by
7 \ the Free Software Foundation, either version 3 of the License, or
8 \ (at your option) any later version.
10 \ This program is distributed in the hope that it will be useful,
11 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
12 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 \ GNU General Public License for more details.
15 \ You should have received a copy of the GNU General Public License
16 \ along with this program. If not, see <http://www.gnu.org/licenses/>.
19 \ I2C MASTER Standard Mode software driver without interrupt, with detection collision
20 \ Target: MSP430FR5xxx, tested @ 8,16,24 MHz and adjusted @ 16,24 MHz
21 \ SDA = P1.2, SCL = P1.3, with 3k3 pullup resistors
23 \ version 1.0 2015-03-24
26 \ ==============================================================================================================
27 \ ==============================================================================================================
29 \ ### ##### ##### ###### ##### # # # #
30 \ # # # # # # # # #### ###### ##### ## ## ## ## ## #### ##### ###### #####
31 \ # # # # # # # # # # # # # # # # # # # # # # # #
32 \ # ##### # ##### ##### # # ##### # # # # # # # # # #### # ##### # #
33 \ # # # # # # # # # # # # # ###### # # # #####
34 \ # # # # # # # # # # # # # # # # # # # # # # #
35 \ ### ####### ##### # ##### #### # # # # # # # # #### # ###### # #
37 \ ==============================================================================================================
38 \ ==============================================================================================================
40 \ use Px.0 to Px.3 for good timing at 8 MHz
42 \ tested with P1.6 SDA, P1.7 SCL :
43 \ Start + Adr + Write 3 bytes + Stop + Start + adr + read 2 bytes + stop = 310us ==> 200 kHz
44 \ See MSP430FR5xxx_I2CF_Soft_MultiMaster.png
46 VARIABLE I2CS_ADR \ low(I2CS_ADR) = slave I2C address with RW flag, high(I2CS_ADR) = RX buffer,data0
48 VARIABLE I2CM_BUF \ low(I2CM_BUF) = RX or TX lentgh, high(I2CM_BUF) = TX buffer,data0
52 \ ==================================\
53 ASM I2C_MM \ soft I2C_MultiMaster driver
54 \ ==================================\
55 \ \ in : I2CS_ADR pointer
56 \ \ : I2CM_BUF pointer
58 \ \ T count of I2C datas exchanged
62 \ \ SR(10) collision flag
63 \ \ out : I2CS_ADR(0) unchanged
64 \ \ I2CM_BUF(0) = count of data not exchanged (normally = 0)
65 \ \ I2CM_BUF(0) = -1 <==> Nack on address
66 \ ----------------------------------\
67 \ I2CMM_Stop_UCBxI2CSlave \ if SDA SCL of I2C_MultiMaster are hard wired onto SDA SCL of I2C_Slave under interrupt...
68 \ ----------------------------------\
69 \ BIS #1,&UCB0CTLW0 \ set eUSCI_B0 in reset state, reset StartCond int in UCB0IFG
70 \ BIC.B #SMM_BUS,&PI2CMSEL1 \ disable I2C I/O
71 \ ----------------------------------\
72 \ I2C_MR_DC_listenBeforeStart: \ test if SCL & SDA lines are idle (high)
73 \ ----------------------------------\
75 BIC.B #SMM_BUS,&I2CSMM_DIR \ SDA & SCL pins as input
76 BIC.B #SMM_BUS,&I2CSMM_OUT \ preset output LOW for SDA & SCL pins
77 MOV #2,T \ I2C_MR_DC_Wait_Start_Loop = 3 µs @ 8 MHz
81 BIT.B #SMMSCL,&I2CSMM_IN \ 4 SCL high ?
83 BIT.B #SMMSDA,&I2CSMM_IN \ 4 SDA high ?
86 0= UNTIL \ 2 here the I2C bus is idle
87 \ --------------------------------\
88 \ I2C_Master_Start_Cond: \ here, SDA and SCL are in idle state
89 \ --------------------------------\
90 BIS.B #SMMSDA,&I2CSMM_DIR \ 4 h force SDA output (low)
92 MOV.B @S+,X \ 3 l X = slave address, S = RX buffer
94 MOV.B @W+,T \ 2 l T = count of datas, W = TX buffer
95 ADD.B #1,T \ 1 l to add address in count
96 BIT.B #1,X \ 1 l test I2C R/w flag
97 0= IF \ 2 l write flag ?
98 MOV W,S \ 3 l TX buffer
100 BIS.B #SMMSCL,&I2CSMM_DIR \ 4 h force SCL output (low)
101 \ --------------------------------\ l
102 \ I2C_Master_Start_EndOf: \ l
103 \ --------------------------------\
104 \ I2C_Master_Send_address \ l SCL
105 \ --------------------------------\
106 BIC #UF2,SR \ 2 reset detection collision SR(10) flag
107 MOV #8,W \ 1 l 8 bits TX
109 ADD.B X,X \ 1 l shift one left
110 U>= IF \ 2 l carry set ?
111 BIC.B #SMMSDA,&I2CSMM_DIR \ 4 l yes : releas SDA high because pull up resistor
113 BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l no : set as output ==> SDA low
115 BIC.B #SMMSCL,&I2CSMM_DIR \ 4 l _^ release SCL (high)
117 BIT.B #SMMSCL,&I2CSMM_IN \ 4 h test if SCL is released
119 MOV.B &I2CSMM_IN,Y \ 3 h _ get SDA in Y
120 BIS.B #SMMSCL,&I2CSMM_DIR \ 4 h v_ force SCL low
121 \ ----------------------------\
122 \ collision detection \ l
123 \ ----------------------------\
124 XOR.B &I2CSMM_DIR,Y \ 3 normal : IN(SMMSDA) XOR DIR(SMMSDA) = 1
125 BIT.B #SMMSDA,Y \ 2 collision : IN(SMMSDA=0) XOR DIR(SMMSDA=0) = 0
126 0= IF BIS #$0402,SR \ 6 set collision detection flag SR(10) and set Z=1 to force end of loop
127 ELSE SUB #1,W \ 3 dec count of bits
130 BIT #UF2,SR \ 2 collision ?
131 0= UNTIL \ 2 loop back if collision during send address
132 BIC.B #SMMSDA,&I2CSMM_DIR \ 5 release SDA high before 9th bit
133 \ ----------------------------------\
135 \ ----------------------------------\
137 \ --------------------------------\ l
138 \ Master TX/RX ACK/NACK \
139 \ --------------------------------\ l _
140 BIC.B #SMMSCL,&I2CSMM_DIR \ 3 l _^ release SCL (high)
142 BIT.B #SMMSCL,&I2CSMM_IN \ 3 h test if SCL is released
144 BIT.B #SMMSDA,&I2CSMM_IN \ 3 h _ get SDA
145 BIS.B #SMMSCL,&I2CSMM_DIR \ 3 h v_ force SCL low
146 \ --------------------------------\ 4 l here ack/nack is received/transmitted
147 \ I2C_Master_Loop_Data \
148 \ --------------------------------\
149 0<> IF BIS #Z,SR \ 5 if Nack (TX), force Z+1 ==> StopCond
150 ELSE SUB.B #1,T \ 3 else dec count
152 \ --------------------------------\
153 \ I2C_Master_CheckCountDown \ count=0 or Nack received
154 \ --------------------------------\
155 0= IF \ count reached or Nack
156 \ ----------------------------\
157 \ I2C_Master_StopCond \
158 \ ----------------------------\ _
159 BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l v_ force SDA low
160 SUB.B T,&I2CM_BUF \ 4 l refresh buffer length and reach tSU:STO
161 BIC.B #SMMSCL,&I2CSMM_DIR \ 4 l _^ release SCL (high)
163 BIT.B #SMMSCL,&I2CSMM_IN \ 3 h SCL released ?
165 BIC.B #SMMSDA,&I2CSMM_DIR \ _| as input ==> SDA high with the hard wired pull up resistor
166 \ ----------------------------\
168 \ ----------------------------\
169 \ Restart I2C_Slave_Int \ if any
170 \ ----------------------------\
171 \ MOV #4,&UCB0IE \ enable StartCond interrupt in UCB0IE register
172 \ BIC #1,&UCB0CTLW0 \ restart eUSCI_B
173 \ BIS.B #SMM_BUS,&I2CSMM_SEL1 \ reenable I2C I/O
174 \ ----------------------------\
175 MOV @RSP+,PC \ ====> out
176 \ ----------------------------\
178 MOV.B #8,W \ 1 l prepare 8 bits transaction
179 BIT #1,&I2CS_ADR \ 3 l I2C_Master Read/write bit test
180 0= IF \ 2 l write flag test
181 \ ----------------------------\
183 \ ----------------------------\
184 MOV.B @S+,X \ 2 l X = TX data
186 ADD.B X,X \ 1 l shift one left
187 U>= IF \ 2 l carry set ?
188 BIC.B #SMMSDA,&I2CSMM_DIR \ 4 l yes : release SDA (high because pull up resistor)
190 BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l no : force SDA low
192 BIC.B #SMMSCL,&I2CSMM_DIR \ 4 l _^ release SCL (high)
194 BIT.B #SMMSCL,&I2CSMM_IN \ 4 h test if SCL is released
196 BIS.B #SMMSCL,&I2CSMM_DIR \ 4 h v_ force SCL low
197 SUB #1,W \ 1 l count of bits
199 BIC.B #SMMSDA,&I2CSMM_DIR \ 4 l release SDA high
201 \ ============================\
202 \ I2C_Master_RX: \ here, SDA is indetermined, SCL is strech low by master
203 \ ============================\
204 BIC.B #SMMSDA,&I2CSMM_DIR \ 5 l _ After ACK we must release SDA
206 \ ------------------------\ _
207 \ send bit \ SCL _| |_
208 \ ------------------------\ _
209 BIC.B #SMMSCL,&I2CSMM_DIR \ 3 l _^ release SCL (high)
211 BIT.B #SMMSCL,&I2CSMM_IN \ 3 h test if SCL is released
213 BIT.B #SMMSDA,&I2CSMM_IN \ 3 h _ get SDA
214 BIS.B #SMMSCL,&I2CSMM_DIR \ 3 h v_ force SCL low
215 ADDC.B X,X \ 1 l C <-- X <--- C
216 SUB #1,W \ 1 l count of bits
218 MOV.B X,0(S) \ 3 l store byte @ BUF_PTR
220 \ ----------------------------\
221 \ I2C_MSendAckOrNack \ here, SDA is released by slave, SCL is strech low by master
222 \ ----------------------------\
223 CMP.B #1,T \ bytes count = 1 ?
225 BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l prepare send Ack if byte count <> 1
232 \ ------------------------------\
234 \ ------------------------------\
235 \ init PORTA (P2:P1) (complement) when reset occurs all I/O are set in input with resistors pullup
236 BIC.B #SMM_BUS,&I2CSMM_OUT \ preset SDA + SCL output low
237 BIC.B #SMM_BUS,&I2CSMM_REN \ SDA + SCL pullup/down disable
238 \ ------------------------------\
240 ." Type STOP to stop :-)"
241 LIT RECURSE IS WARM \ insert this routine between COLD and WARM...
242 (WARM) ; \ ...and continue with WARM
245 : STOP \ stops multitasking, must to be used before downloading app
246 ['] (WARM) IS WARM \ remove START app from FORTH init process
247 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
254 \ ---------------------------------------------------------------------------------------------------------------------\
255 \ SCL clock generation, timing, and test of data(s) number are made by I2C_Master.
256 \ slave can strech SCL low after Start Condition and after any bit.
258 \ address Ack/Nack is generated by the slave on SDA line (released by the master)
259 \ Two groups of eight addresses (000xxxy and 1111xxxy) are not allowed (reserved)
260 \ after address or data is sent, the transmitter (Master or Slave) must release SDA line to allow (N)Ack by the receiver
261 \ data Ack/Nack are generated by the receiver (master or slave) on SDA line
262 \ a master receiver must signal the end of data to the slave transmitter by sending a Nack bit
263 \ Stop or restart conditions must be generated by master after a Nack bit.
264 \ after Ack bit is sent, Slave must release SDA line to allow master to do stop or restart conditions
266 \ __ _____ _____ _..._ _____ _____ _NACK _____ _____ _..._ _____ _____ _NACK _
267 \ SDA \____/_MSB_X_____X_..._X_LSB_X_R/W_x_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X___/
268 \ _____ _ _ _ _ _ _ _ _ _ _ ___
269 \ SCL \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/
271 \ | |Slave Stretch Low |SSL |SSL |SSL |SSL |
273 \ |Start Condition |stoP Condition
275 \ __ _____ _____ _..._ _____ _____ _NACK _____ _____ _..._ _____ _____ _NACK ___
276 \ SDA \____/_MSB_X_____X_..._X_LSB_X_R/W_x_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X \____...
277 \ _____ _ _ _ _ _ _ _ _ _ _ ____
278 \ SCL \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/ \_...
280 \ | |Slave Stretch Low |SSL |SSL |SSL |SSL |
282 \ |Start Condition |reStart Condition
284 \ tHIGH : SCL high time
285 \ tLOW : SCL low time
286 \ tBUF : SDA high time between Stop and Start conditions
287 \ tHD:STA : Start_Condition SCL high time after SDA is low
288 \ tSU:STO : Stop_Condition SCL high time before SDA rise
289 \ tSU:STA : Start_Condition SCL high time before SDA fall
290 \ tHD:DAT : SDA data change time after SCL is low
291 \ the SDA line must be strobe just after SCL is high
292 \ the SDA data must be change just after SCL is low
293 \ standard mode (up to 100 kHz) : tHIGH = tHD:STA = tSU:STO = 4µs
294 \ tLOW = tSU:STA = tBUF = 4,7µs
296 \ -------------------------------------------------------------------------------------------------------------------\