1 \ name : msp430FR5xxx_I2C_Soft_Master.asm
5 \ Copyright (C) <2015> <J.M. THOORENS>
7 \ This program is free software: you can redistribute it and/or modify
8 \ it under the terms of the GNU General Public License as published by
9 \ the Free Software Foundation, either version 3 of the License, or
10 \ (at your option) any later version.
12 \ This program is distributed in the hope that it will be useful,
13 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
14 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 \ GNU General Public License for more details.
17 \ You should have received a copy of the GNU General Public License
18 \ along with this program. If not, see <http://www.gnu.org/licenses/>.
21 \ version 2.0 2015-07-30
22 \ ---------------------------------------------------------------------------------------------------------------------\
23 \ SCL clock generation, timing, and test of data(s) number are made by I2C_Master.
24 \ slave can strech SCL low after Start Condition and after any bit.
26 \ address Ack/Nack is generated by the slave on SDA line (released by the master)
27 \ Two groups of eight addresses (000xxxy and 1111xxxy) are not allowed (reserved)
28 \ after address or data is sent, the transmitter (Master or Slave) must release SDA line to allow (N)Ack by the receiver
29 \ data Ack/Nack are generated by the receiver (master or slave) on SDA line
30 \ a master receiver must signal the end of data to the slave transmitter by sending a Nack bit
31 \ Stop or restart conditions must be generated by master after a Nack bit.
32 \ after Ack bit is sent, Slave must release SDA line to allow master to do stop or restart conditions.
35 \ first byte = address + R/W flag | byte data (one, for example)
36 \ __ _____ _____ _..._ _____ __R__ _NAK_ _____ _____ _..._ _____ _____ _NAK_ _
37 \ SDA \____/_MSB_X_____X_..._X_LSB_X__W__x_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X___/
38 \ _____ _ _ _ _ _ _ _ _ _ _ ___
39 \ SCL \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/
41 \ | |SSL |SSL |SSL |SSL |SSL |
43 \ |Start Condition |stoP Condition
45 \ first byte = address + R/W flag | byte data (one, for example)
46 \ __ _____ _____ _..._ _____ __R__ _NAK_ _____ _____ _..._ _____ _____ _NAK_ ___
47 \ SDA \____/_MSB_X_____X_..._X_LSB_X__W__x_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X \____...
48 \ _____ _ _ _ _ _ _ _ _ _ _ ____
49 \ SCL \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/ \_...
51 \ | |SSL |SSL |SSL |SSL |SSL |
53 \ |Start Condition |reStart Condition
55 \ SSL : Slave can strech SCL low
56 \ tHIGH : SCL high time
58 \ tBUF : SDA high time between Stop and Start conditions
59 \ tHD:STA : Start_Condition SCL high time after SDA is low
60 \ tSU:STO : Stop_Condition SCL high time before SDA rise
61 \ tSU:STA : Start_Condition SCL high time before SDA fall
62 \ tHD:DAT : SDA data change time after SCL is low
63 \ the SDA line must be strobe just after SCL is high
64 \ the SDA data must be change just after SCL is low
65 \ standard mode (up to 100 kHz) : tHIGH = tHD:STA = tSU:STO = 4µs
66 \ tLOW = tSU:STA = tBUF = 4,7µs
68 \ -------------------------------------------------------------------------------------------------------------------\
71 \ -------------------------------------------------------------------------------------------------------------------\
72 \ I2C Soft MASTER, Standard MODE, 8,16,24MHz
73 \ -------------------------------------------------------------------------------------------------------------------\
75 \ ===============================================================================================
76 \ ===============================================================================================
78 \ ### ##### ##### ##### # #
79 \ # # # # # # # #### ###### ##### ## ## ## #### ##### ###### #####
80 \ # # # # # # # # # # # # # # # # # # #
81 \ # ##### # ##### # # ##### # # # # # # #### # ##### # #
82 \ # # # # # # # # # # ###### # # # #####
83 \ # # # # # # # # # # # # # # # # # # # #
84 \ ### ####### ##### ##### #### # # # # # # #### # ###### # #
86 \ ===============================================================================================
87 \ ===============================================================================================
89 \ use Px.0 to Px.3 pins as SCL and SDA pins to use immediate instruction in one byte (#1,#2,#4,#8)
91 \ tested with P1.6 SDA, P1.7 SCL @8 MHZ :
92 \ Start + Adr + Write 3 bytes + Stop + Start + adr + read 2 bytes + stop = 600us ==> 105 kHz
93 \ See MSP430FR5xxx_I2C_Soft_Master.png
95 VARIABLE I2CS_ADR \ low(I2CS_ADR) = slave I2C address with RW flag, high(I2CS_ADR) = RX buffer,data0
97 VARIABLE I2CM_BUF \ low(I2CM_BUF) = RX or TX lentgh, high(I2CM_BUF) = TX buffer,data0
101 \ ------------------------------\
102 ASM T_I2C \ 4 init first once !!!
103 \ ------------------------------\
107 MOV #1,Y \ 2 set I2C tHIGH time @ 8MHz
108 \ MOV #9,Y \ 2 set I2C tHIGH time @ 16MHz
109 \ MOV #20,Y \ 2 set I2C tHIGH time @ 24MHz
114 \ ------------------------------\ _
115 ASM I2C_PLS \ SCL _| |_ pulse
116 \ ------------------------------\
117 CALL #T_I2C \ _ wait tLOW
118 BIC.B #SMSCL,&I2CSM_DIR \ _^ release SCL (high)
120 BIT.B #SMSCL,&I2CSM_IN \ test if SCL is released
122 CALL #T_I2C \ wait tHIGH
123 BIT.B #SMSDA,&I2CSM_IN \ _ get SDA
124 BIS.B #SMSCL,&I2CSM_DIR \ v_ force SCL low
129 \ ------------------------------\
130 ASM I2C_MTX \ MASTER TX \ shared code for address and TX data
131 \ ------------------------------\
133 ADD.B X,X \ 1 l shift one left
134 U>= IF \ 2 l carry set ?
135 BIC.B #SMSDA,&I2CSM_DIR \ 4 l yes : SDA as input ==> SDA high because pull up resistor
137 BIS.B #SMSDA,&I2CSM_DIR \ 4 l no : SDA as output ==> SDA low
139 CALL I2C_PLS \ _| |_ SCL
140 SUB.B #1,W \ l count of bits
142 BIC.B #SMSDA,&I2CSM_DIR \ 5 l _ SDA as input : release SDA high to prepare read Ack/Nack
147 \ ==================================\
149 \ ==================================\
150 \ \ in I2CS_ADR/I2CM_BUF as RX/TX buffer requested by I2CS_ADR(0(0))
151 \ \ I2CS_ADR(0) = I2C_Slave_addr&R/w
152 \ \ I2CM_BUF(0) = TX/RX count of datas
153 \ \ I2CM_BUF(0) = 0 ==> send only I2C address
155 \ \ T datas countdown
158 \ \ out I2CSLA_ADR & (R/W) unCHNGd
159 \ \ S = BUF PTR pointing on first data not exCHNGd
160 \ \ T = count+1 of TX/RX datas exCHNGd
161 \ \ I2CS_ADR(0) = unCHNGd
162 \ \ I2CM_BUF(0) = count of data not exCHNGd (normally = 0)
163 \ \ I2CM_BUF(0) = -1 <==> Nack on address
164 \ ----------------------------------\
165 \ I2C_MR_DC_ListenBeforeStart: \ test if SCL & SDA lines are idle (high)
166 \ ----------------------------------\
167 BIC.B #SM_BUS,&I2CSM_DIR \ SDA & SCL pins as input
168 BIC.B #SM_BUS,&I2CSM_OUT \ preset output LOW for SDA & SCL pins
169 MOV #2,T \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 8 MHz
170 \ MOV #4,T \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 16 MHz
171 \ MOV #6,T \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 24 MHz
175 BIT.B #SMSCL,&I2CSM_IN \ 4 P1DIR.3 SCL high ?
177 BIT.B #SMSDA,&I2CSM_IN \ 4 P1IN.2 SDA high ?
180 0= UNTIL \ 2 here the I2C bus is idle
181 \ ------------------------------\
182 \ I2C_Master_Start_Cond: \ here, SDA and SCL are in idle state
183 \ ------------------------------\
184 BIS.B #SMSDA,&I2CSM_DIR \ 4- P1DIR.2 force SDA output (low)
185 MOV #5,Y \ 2 tHD\STA time 8 MHz
186 \ MOV #15,Y \ 2 tHD\STA time 16MHz
187 \ MOV #25,Y \ 2 tHD\STA time 24MHz
188 CALL #T_I2C \ wait tHD\STA
189 BIS.B #SMSCL,&I2CSM_DIR \ 4- P1DIR.3 force SCL output (low)
190 \ ------------------------------\
191 \ I2C_Master_Start_EndOf: \
192 \ ------------------------------\
193 MOV #I2CS_ADR,S \ 2 l
194 MOV.B @S+,X \ 3 l X = slave address, S = RX buffer
195 MOV #I2CM_BUF,W \ 2 l
196 MOV.B @W+,T \ 2 l T = count of datas, W = TX buffer
197 BIT.B #1,X \ 1 l test I2C R/w flag
198 0= IF \ 2 l write flag
199 MOV W,S \ 3 l TX buffer
201 \ ------------------------------\
202 \ I2C_Master_Send_address \ SCL is held low by slave
203 \ ------------------------------\
204 ADD #1,T \ to add address in count
205 MOV #8,W \ 1 l prepare 8 bit Master writing
206 MOV #1,Y \ 2 tHD\STA time 8 MHz value
207 \ MOV #5,Y \ 2 tHD\STA time 16MHz value
208 \ MOV #15,Y \ 2 tHD\STA time 24MHz value
209 CALL #I2C_MTX \ 4 to send address
210 \ ------------------------------\
211 \ I2C_Master_Loop_Data \
212 \ ------------------------------\
214 \ ----------------------------\
215 \ Master TX/RX ACK/NACK \
216 \ ----------------------------\
217 MOV #2,Y \ 2 tLOW time complement @ 8MHz
218 \ MOV #15,Y \ 2 tLOW time complement @ 16MHz
219 \ MOV #20,Y \ 2 tLOW time complement @ 24MHz
220 CALL #I2C_PLS \ _| |_ SCL with BIT SDA, then ret
221 0<> IF BIS #2,SR \ l if Nack (TX), force Z=1 ==> StopCond
222 ELSE SUB.B #1,T \ else dec count
224 \ ----------------------------\
225 \ I2C_Master_CheckCountDown \ count=0 or Nack received
226 \ ----------------------------\
227 0= IF \ count reached or Nack
228 \ ----------------------------\
229 \ I2C_Master_StopCond \
230 \ ----------------------------\ before releasing SCL
231 BIS.B #SMSDA,&I2CSM_DIR \ l P1DIR.2 as output ==> SDA low
232 CALL #T_I2C \ l _ wait 4 us
233 BIC.B #SMSCL,&I2CSM_DIR \ _| P1DIR.2 release SCL (high)
234 MOV #5,Y \ 2 tSU:STO time 8 MHz value
235 \ MOV #15,Y \ 2 tSU:STO time 16MHz value
236 \ MOV #25,Y \ 2 tSU:STO time 24MHz value
237 CALL #T_I2C \ _ wait tSU:STO
238 BIC.B #SMSDA,&I2CSM_DIR \ _| P1DIR.2 as input ==> SDA high with pull up resistor
239 SUB.B T,&I2CM_BUF \ 4 l refresh buffer length and reach tSU:STO
241 \ ----------------------------\
243 \ ----------------------------\
244 MOV.B #8,W \ 1 l prepare 8 bits transaction
245 BIT.B #1,&I2CS_ADR \ 3 l I2C_Master Read/write bit test
246 0= IF \ 2 l write flag test
247 \ ------------------------\
249 \ ------------------------\
250 MOV.B @S+,X \ 2 l next byte to transmit
251 CALL #I2C_MTX \ 4 to send data + test ack
253 \ ------------------------\
255 \ ========================\
256 \ I2C_Master_RX: \ here, SDA is indetermined, SCL is strech low by master
257 \ ========================\
259 BIC.B #SMSDA,&I2CSM_DIR \ 4 l _ P1DIR.2 as input ==> release SDA high because pull up resistor
260 MOV #3,Y \ 2 tLOW time complement @ 8 MHz
261 \ MOV #15,Y \ 2 tLOW time complement @ 16MHz
262 \ MOV #24,Y \ 2 tLOW time complement @ 24MHz
263 CALL #I2C_PLS \ _| |_ SCL + BIT SDA input (SDA-->carry)
264 ADDC.B X,X \ 1 l C <-- X <--- C
265 SUB #1,W \ 1 l count of bits
267 MOV.B X, 0(S) \ 3 l store byte in buffer
269 \ ------------------------\
270 \ Compute Ack Or Nack \ here, SDA is released by slave, SCL is strech low by master
271 \ ------------------------\
272 CMP #1,T \ 1 l here, SDA is released by slave = Nack
274 BIS.B #SMSDA,&I2CSM_DIR \ 4 l send Ack if byte count <> 1
281 \ ------------------------------\
283 \ ------------------------------\
284 \ init PORTA (P2:P1) (complement) when reset occurs all I/O are set in input with resistors pullup
285 BIC.B #SM_BUS,&I2CSM_OUT \ P1OUT.32 preset SDA + SCL output low
286 BIC.B #SM_BUS,&I2CSM_REN \ P1REN.32 SDA + SCL pullup/down disable
287 \ ------------------------------\
289 ." \ type stop to stop :-)"
290 LIT recurse is WARM \ insert this starting routine between COLD and WARM...
291 (WARM) \ ...and continue with (WARM)
295 : STOP \ stops multitasking, must to be used before downloading app
296 ['] (WARM) IS WARM \ remove START app from FORTH init process
297 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH