OSDN Git Service

bug bug bug...
[fast-forth/master.git] / MSP430-FORTH / lib / I2CF_Soft_MultiMaster.f
1 \ name : msp430FR5xxx_I2CF_Soft_MultiMaster.asm
2
3 \ Copyright (C) <2015>  <J.M. THOORENS>
4 \
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.
9 \
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.
14 \
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/>.
17
18
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
22
23 \ version 1.0 2015-03-24
24
25 WIPE
26 \ ==============================================================================================================
27 \ ==============================================================================================================
28                      
29 \ ###  #####   #####  ######     #####                         #     # #     #
30 \  #  #     # #     # #         #     #  ####  ###### #####    ##   ## ##   ##   ##    ####  ##### ###### #####
31 \  #        # #       #         #       #    # #        #      # # # # # # # #  #  #  #        #   #      #    #
32 \  #   #####  #       #####      #####  #    # #####    #      #  #  # #  #  # #    #  ####    #   #####  #    #
33 \  #  #       #       #               # #    # #        #      #     # #     # ######      #   #   #      #####
34 \  #  #       #     # #         #     # #    # #        #      #     # #     # #    # #    #   #   #      #   #
35 \ ### #######  #####  #          #####   ####  #        #      #     # #     # #    #  ####    #   ###### #    #
36                      
37 \ ==============================================================================================================
38 \ ==============================================================================================================
39
40 \ use Px.0 to Px.3 for good timing at 8 MHz
41
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
45
46 VARIABLE I2CS_ADR   \ low(I2CS_ADR) = slave I2C address with RW flag, high(I2CS_ADR) = RX buffer,data0
47 2 ALLOT             \ data1,data2
48 VARIABLE I2CM_BUF   \ low(I2CM_BUF) = RX or TX lentgh, high(I2CM_BUF) = TX buffer,data0
49 2 ALLOT             \ data1,data2
50     \
51
52 \ ==================================\
53 ASM I2C_MM                          \ soft I2C_MultiMaster driver
54 \ ==================================\
55 \                                   \ in  : I2CS_ADR pointer
56 \                                   \     : I2CM_BUF pointer
57 \                                   \ used: S   BUF_PTR
58 \                                   \       T   count of I2C datas exchanged
59 \                                   \       W   count of bits
60 \                                   \       X   data
61 \                                   \       Y   BUF_ORG
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 \ ----------------------------------\
74 BEGIN                               \
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
78     BEGIN                           \ 15~loop
79       BEGIN                         \
80         BEGIN                       \
81           BIT.B #SMMSCL,&I2CSMM_IN  \ 4 SCL high ? 
82         0<> UNTIL                   \ 2
83         BIT.B #SMMSDA,&I2CSMM_IN    \ 4 SDA high ?
84       0<> UNTIL                     \ 2
85       SUB #1,T                      \ 1
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)
91     MOV #I2CS_ADR,S                 \ 2 l
92     MOV.B @S+,X                     \ 3 l   X = slave address, S = RX buffer
93     MOV #I2CM_BUF,W                 \ 2 l
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
99     THEN                            \
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
108     BEGIN                           \
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
112         ELSE                        \ 2 l
113           BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l no  : set as output ==> SDA low
114         THEN                        \   l   _
115         BIC.B #SMMSCL,&I2CSMM_DIR   \ 4 l _^    release SCL (high)
116         BEGIN                       \
117           BIT.B #SMMSCL,&I2CSMM_IN  \ 4 h       test if SCL is released
118         0<> UNTIL                   \ 2 h
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
128         THEN                        \
129     0= UNTIL                        \ 2  
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 \ ----------------------------------\
134 \   I2C_Master_Loop                 \
135 \ ----------------------------------\
136 BEGIN                               \ 4 l
137 \   --------------------------------\   l
138 \   Master TX/RX ACK/NACK           \
139 \   --------------------------------\   l   _
140     BIC.B #SMMSCL,&I2CSMM_DIR       \ 3 l _^    release SCL (high)
141     BEGIN                           \
142         BIT.B #SMMSCL,&I2CSMM_IN    \ 3 h       test if SCL is released
143     0<> UNTIL                       \ 2 h
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
151     THEN                            \
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)
162         BEGIN                       \
163           BIT.B #SMMSCL,&I2CSMM_IN  \ 3 h   SCL released ?
164         0<> UNTIL                   \ 2 h _
165         BIC.B #SMMSDA,&I2CSMM_DIR   \   _|      as input  ==> SDA high with the hard wired pull up resistor
166 \       ----------------------------\
167 \       I2C_Master_Endof            \
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 \       ----------------------------\
177     THEN                            \
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 \       ----------------------------\
182 \       I2C Master write            \
183 \       ----------------------------\
184         MOV.B @S+,X                     \ 2 l   X = TX data
185         BEGIN                           \
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)
189             ELSE                        \ 2 l
190               BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l no  : force SDA low
191             THEN                        \   l   _
192             BIC.B #SMMSCL,&I2CSMM_DIR   \ 4 l _^    release SCL (high)
193             BEGIN                       \
194                BIT.B #SMMSCL,&I2CSMM_IN \ 4 h       test if SCL is released
195             0<> UNTIL                   \ 2 h _
196             BIS.B #SMMSCL,&I2CSMM_DIR   \ 4 h  v_   force SCL low
197             SUB #1,W                    \ 1 l       count of bits
198         0= UNTIL                        \ 2 l
199         BIC.B #SMMSDA,&I2CSMM_DIR       \ 4 l       release SDA high
200     ELSE                                \ 2 l
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
205         BEGIN                       \
206 \           ------------------------\       _
207 \           send bit                \ SCL _| |_
208 \           ------------------------\       _
209             BIC.B #SMMSCL,&I2CSMM_DIR   \ 3 l _^    release SCL (high)
210             BEGIN                       \
211                BIT.B #SMMSCL,&I2CSMM_IN \ 3 h       test if SCL is released
212             0<> UNTIL                   \ 2 h
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
217         0= UNTIL                        \ 2 l
218         MOV.B X,0(S)                    \ 3 l       store byte @ BUF_PTR
219         ADD #1,S                        \ 1 l
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 ?
224         0<> IF                      \ 2
225           BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l     prepare send Ack if byte count <> 1
226         THEN                        \   
227     THEN                            \
228 AGAIN                               \ 2 l
229 ENDASM                              \
230     \
231
232 \ ------------------------------\
233 CODE START                      \ 
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 \ ------------------------------\
239 LO2HI
240 ." Type STOP to stop :-)"
241 LIT RECURSE IS WARM         \ insert this routine between COLD and WARM...
242 (WARM) ;                    \ ...and continue with WARM
243     \
244
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
248 ;
249     \
250
251 RST_HERE
252
253
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.
257
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
265 \
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\___/
270 \       ^   ^                             ^     ^                             ^     ^    ^
271 \       |   |Slave Stretch Low            |SSL  |SSL                          |SSL  |SSL |
272 \       |                                                                                |
273 \       |Start Condition                                                                 |stoP Condition
274 \
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\___/    \_...
279 \       ^   ^                             ^     ^                             ^     ^    ^
280 \       |   |Slave Stretch Low            |SSL  |SSL                          |SSL  |SSL |
281 \       |                                                                                |
282 \       |Start Condition                                                                 |reStart Condition
283 \
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
295 \                                   tHD:DAT <=  3,45 µs
296 \ -------------------------------------------------------------------------------------------------------------------\