OSDN Git Service

V309 Modified APPEND" in the long run, clusters can become non-contiguous
[fast-forth/master.git] / MSP430-FORTH / lib / I2C_Soft_MultiMaster.f
1 \ name : msp430FR5xxx_I2C_Soft_MultiMaster.f
2
3 \ I2C MASTER Standard Mode software driver without interrupt, with detection collision
4 \ Target: MSP430FR5xxx, tested @ 8,16,24 MHz and adjusted @ 16,24 MHz
5 \         SDA = P1.2, SCL = P1.3,  with 3k3 pullup resistors
6
7 \ version 1.0 2016-04-10
8
9 WIPE
10 \ ========================================================================================================
11 \ ========================================================================================================
12                                                         
13 \ ###  #####   #####       #####                         #     # #     #
14 \  #  #     # #     #     #     #  ####  ###### #####    ##   ## ##   ##   ##    ####  ##### ###### #####
15 \  #        # #           #       #    # #        #      # # # # # # # #  #  #  #        #   #      #    #
16 \  #   #####  #            #####  #    # #####    #      #  #  # #  #  # #    #  ####    #   #####  #    #
17 \  #  #       #                 # #    # #        #      #     # #     # ######      #   #   #      #####
18 \  #  #       #     #     #     # #    # #        #      #     # #     # #    # #    #   #   #      #   #
19 \ ### #######  #####       #####   ####  #        #      #     # #     # #    #  ####    #   ###### #    #
20                                                         
21 \ ========================================================================================================
22 \ ========================================================================================================
23
24 \ P1.2 = SDA, P1.3 = SCL
25 \ use Px.0 to Px.3 for good timing at 8 MHz (immediate addressing is less of one cycle) 
26
27 \ tested with P1.6 SDA, P1.7 SCL @ 8MHz :
28 \ Start + Adr + Write 3 bytes + Stop + Start + adr + read 2 bytes + stop = 628us ==> 100 kHz 
29 \ See MSP430FR5xxx_I2C_Soft_MultiMaster.png
30
31 VARIABLE I2CS_ADR   \ low(I2CS_ADR) = slave I2C address with RW flag, high(I2CS_ADR) = RX buffer,data0
32 2 ALLOT             \ data1,data2
33 VARIABLE I2CM_BUF   \ low(I2CM_BUF) = RX or TX lentgh, high(I2CM_BUF) = TX buffer,data0
34 2 ALLOT             \ data1,data2
35     \
36
37 \ ------------------------------\
38 ASM T_I2C                       \ 4 init first once !!!
39 \ ------------------------------\
40 BEGIN                           \ 3~ loop
41     SUB #1,Y                    \ 1
42 0= UNTIL                        \ 2
43     MOV #1,Y                    \ 2 set I2C tHIGH time @ 8MHz
44 \    MOV #9,Y                   \ 2 set I2C tHIGH time @ 16MHz
45 \    MOV #20,Y                  \ 2 set I2C tHIGH time @ 24MHz
46     MOV @RSP+,PC                \ 4 ret
47 ENDASM                          \
48     \
49
50
51 \ ------------------------------\
52 ASM I2C_PLS                     \ SCL Pulse
53 \ ------------------------------\
54     CALL #R11_I2C               \   _   wait tLOW
55     BIC.B #SMMSCL,&I2CSMM_DIR   \ _^    release SCL (high)
56     BEGIN
57        BIT.B #SMMSCL,&I2CSMM_IN \       test if SCL is released
58     0<> UNTIL
59     CALL #R11_I2C               \       wait tHIGH
60     BIT.B #SMMSDA,&I2CSMM_IN    \ _     get SDA
61     BIS.B #SMMSCL,&I2CSMM_DIR   \  v_   force SCL low
62     MOV @RSP+,PC                \       ret
63 ENDASM                          \
64     \
65
66 \ ------------------------------\
67 ASM I2C_BTX                     \ MASTER TX \ one bit shared code for address and TX data
68 \ ------------------------------\
69     ADD.B X,X                   \ 1 l   shift one left
70     U>= IF                      \ 2 l   carry set ?
71       BIC.B #SMMSDA,&I2CSMM_DIR \ 4 l   yes : SDA as input  ==> SDA high because pull up resistor
72     ELSE                        \ 2 l
73       BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l   no  : SDA as output ==> SDA low
74     THEN                        \   l   _
75     JMP I2C_PLS                 \ SCL _| |_ pulse
76 ENDASM                          \
77     \
78
79 \ ==================================\
80 ASM I2C_MM                          \ soft I2C_MultiMaster driver
81 \ ==================================\
82 \                                   \ in  : I2CS_ADR pointer
83 \                                   \     : I2CM_BUF pointer
84 \                                   \ used: S   datas pointer
85 \                                   \       T   count of I2C datas exchanged
86 \                                   \       W   count of bits
87 \                                   \       X   data
88 \                                   \       Y   I2C_time
89 \                                   \       SR(10) collision flag
90 \                                   \ out : I2CS_ADR(0) unchanged
91 \                                   \       I2CM_BUF(0) = count of data not exchanged (normally = 0)
92 \                                   \       I2CM_BUF(0) = -1 <==> Nack on address
93 \ ----------------------------------\
94 \ I2CMM_Stop_UCBxI2CSlave           \ if SDA SCL of I2C_MultiMaster are hard wired onto SDA SCL of I2C_Slave under interrupt...
95 \ ----------------------------------\
96 \ BIS #1,&UCB0CTLW0                  \ set eUSCI_B0 in reset state, reset StartCond int in UCB0IFG
97 \ BIC.B #I2CM_BUS,&I2CSMM_SEL1       \ disable I2C I/O
98 \ ----------------------------------\
99 \ I2C_MR_DC_ListenBeforeStart:      \ test if SCL & SDA lines are idle (high)
100 \ ----------------------------------\
101 BW1                                 \
102     BIC.B #SMM_BUS,&I2CSMM_DIR      \ SDA & SCL pins as input
103     BIC.B #SMM_BUS,&I2CSMM_OUT      \ preset output LOW for SDA & SCL pins
104 BW2
105 BW3                                 \ 14~ loop 
106     MOV #2,T                        \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 8 MHz
107 \    MOV #4,T                        \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 16 MHz
108 \    MOV #6,T                        \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 24 MHz
109     BEGIN
110         BIT.B #SMMSCL,&I2CSMM_IN    \ 3 P1DIR.3 SCL high ? 
111         0= ?GOTO BW2                \ 2
112         BIT.B #SMMSDA,&I2CSMM_IN    \ 3 P1IN.2 SDA high ?
113         0= ?GOTO BW3                \ 2
114         SUB #1,T                    \ 1
115     0= UNTIL                        \ 2 here the I2C bus is idle
116 \   --------------------------------\
117 \     I2CMR_DC_Shutdown_Slave_Int   \ if SDA SCL of I2C_MultiMaster are hard wired onto SDA SCL of I2C_Slave under interrupt...
118 \   --------------------------------\
119 \    BIS #1,&$640                   \ ...set eUSCI_B0 in reset state, that allows I/O use for SDA & SCL...
120 \    BIC.B #SMM_BUS,&PI2CSSEL1      \ disable I2C I/O
121 \   --------------------------------\
122 \     I2C_Master_Start_Cond:        \ here, SDA and SCL are in idle state
123 \   --------------------------------\
124     BIS.B #SMMSDA,&I2CSMM_DIR       \ 4- force SDA output (low)
125     MOV #I2CS_ADR,S                 \ 2 l
126     MOV.B @S+,X                     \ 3 l X = slave address, S = RX buffer
127     MOV #I2CM_BUF,W                 \ 2 l
128     MOV.B @W+,T                     \ 2 l T = count of datas, W = TX buffer
129     ADD.B #1,T                      \     to include address in count
130     BIT.B #1,X                      \ 1 l test I2C R/w flag
131     0= IF                           \ 2 l write flag
132         MOV W,S                     \ 3 l TX buffer
133     THEN                            \
134     MOV #5,Y                        \  2 tHD\STA time 8 MHz complement
135 \    MOV #14,Y                       \ 2 tHD\STA time 16MHz complement
136 \    MOV #25,Y                       \ 2 tHD\STA time 24MHz complement
137     CALL #R11_I2C                   \    wait 4 us
138     BIS.B #SMMSCL,&I2CSMM_DIR       \ 4- force SCL output (low)
139 \   --------------------------------\
140 \     I2C_Master_Start_EndOf:       \
141 \   --------------------------------\
142 \     I2C_Master_Send_address       \
143 \   --------------------------------\
144     MOV.B #8,W                      \ 1 l   prepare 8 bit Master writing
145     BEGIN                           \
146          MOV #1,Y                   \       2 tHD\STA time =8MHz  complement
147 \        MOV #2,Y                    \       2 tHD\STA time =16MHz complement
148 \        MOV #13,Y                   \       2 tHD\STA time =24MHz complement
149         CALL #I2C_BTX               \ l     send one bit
150 \       ----------------------------\
151 \       collision detection         \
152 \       ----------------------------\
153         0= IF                       \ 2     if SDA low
154             BIT.B #SMMSDA,&I2CSMM_DIR   \ 3
155             0= ?GOTO BW1            \ 2     collision : IN(MMSDA=0) XOR DIR(MMSDA=0) = 0
156         THEN                        \
157         SUB #1,W                    \ 3     dec count of bits
158     0= UNTIL                        \ 2  
159 BIC.B #SMMSDA,&I2CSMM_DIR           \ 5     release SDA high before 9th bit
160 \ ----------------------------------\
161 \   I2C_Master_Loop                 \
162 \ ----------------------------------\
163 BEGIN
164 \   --------------------------------\
165 \   Master TX/RX ACK/NACK           \
166 \   --------------------------------\
167     MOV #1,Y                        \ 2     tLOW time complement @ 8MHz
168 \    MOV #7,Y                       \ 2     tLOW time complement @ 16MHz
169 \    MOV #18,Y                      \ 2     tLOW time complement @ 24MHz
170     CALL #I2C_PLS                   \ _| |_ SCL pulse with SDA bit test
171     0<> IF  BIS #2,SR               \ l     if Nack, force Z=1 ==> StopCond
172     ELSE    SUB.B #1,T              \       else dec count
173     THEN                            \ l
174 \   --------------------------------\
175 \   I2C_Master_CheckCountDown       \       count=0 or Nack received
176 \   --------------------------------\
177     0= IF                           \       count reached or Nack
178 \   --------------------------------\
179 \   I2C_Master_StopCond             \
180 \   --------------------------------\       before releasing SCL
181         BIS.B #SMMSDA,&I2CSMM_DIR   \   l   force SDA low
182         MOV #1,Y                    \ 2 l   tLOW time complement @ 8MHz
183 \        MOV #7,Y                   \ 2     tLOW time complement @ 16MHz
184 \        MOV #18,Y                  \ 2     tLOW time complement @ 24MHz
185         CALL #R11_I2C               \   _       wait 4 us
186         BIC.B #SMMSCL,&I2CSMM_DIR   \ _|     release SCL (high with pull up resistor)
187         SUB.B T,&I2CM_BUF           \ 4      refresh buffer length
188         MOV #5,Y                    \ 2      tSU:STO time 8 MHz complement
189 \        MOV #15,Y                  \ 2     tSU:STO time 16MHz complement
190 \        MOV #25,Y                  \ 2     tSU:STO time 24MHz complement
191         CALL #R11_I2C               \     _  wait tSU:STO
192         BIC.B #SMMSDA,&I2CSMM_DIR   \   _|   release SDA (high with pull up resistor)
193 \       ----------------------------\
194 \       I2C_Master_Endof            \
195 \       ----------------------------\
196 \       Restart I2C_Slave_Int       \   if any
197 \       ----------------------------\
198 \        BIC #1,&UCB0CTLW0           \   restart eUSCI_B
199 \        BIS.B #SMM_BUS,&I2CSMM_SEL1 \   reenable I2C I/O
200 \       ----------------------------\
201         MOV @RSP+,PC                \ ====> 
202 \   --------------------------------\
203     THEN                            \
204 \   --------------------------------\
205     MOV.B #8,W                      \ 1 l     prepare 8 bits transaction
206     BIT.B #1,&I2CS_ADR              \ 3 l     I2C_Master Read/write bit test
207     0=  IF                          \ 2 l     write flag test
208 \       ============================\
209 \       I2C_Master_TX               \
210 \       ============================\
211         MOV.B @S+,X                 \ 2 l   next byte to TX
212         BEGIN                       \
213             MOV #1,Y                \ 2 tHD\STA time =8MHz  complement
214 \            MOV #2,Y                \ 2 tHD\STA time =16MHz complement
215 \            MOV #13,Y               \ 2 tHD\STA time =24MHz complement
216             CALL #I2C_BTX           \ l     send one bit
217             SUB.B #1,W              \ l     count of bits
218         0= UNTIL                    \ l
219         BIC.B #SMMSDA,&I2CSMM_DIR   \ 5 l   release SDA high before 9th bit
220     ELSE                            \ l
221 \       ============================\
222 \       I2C_Master_RX:              \       here, SDA is indetermined, SCL is strech low by master
223 \       ============================\
224         BIC.B #SMMSDA,&I2CSMM_DIR   \ 5 l _    After ACK we must release SDA
225         BEGIN                       \
226             MOV #3,Y                \ 2     tLOW time complement @ 8 MHz
227 \            MOV #15,Y               \ 2    tLOW time complement @ 16MHz
228 \            MOV #24,Y               \ 2    tLOW time complement @ 24MHz
229             CALL #I2C_PLS           \ _| |_ SCL pulse with SDA bit test
230             ADDC.B X,X              \ 1 l   C <-- X <--- C ; C flag = SDA
231             SUB #1,W                \ 1 l   count of bits
232         0= UNTIL                    \ 2 l
233         MOV.B X, 0(S)               \ 3 l     store RX byte in buffer
234         ADD #1,S                    \ 1 l
235 \       ----------------------------\
236 \       Compute RX Ack/Nack         \
237 \       ----------------------------\
238         CMP #1,T                    \ 1 l     here, SDA is released by slave = Nack
239         0<> IF                      \ 2
240             BIS.B #SMMSDA,&I2CSMM_DIR   \ 4 l     send Ack if byte count <> 1
241         THEN                        \ l
242     THEN                            \
243 AGAIN                               \ l
244 ENDASM                              \
245     \
246
247 \ ------------------------------\
248 CODE START                      \ 
249 \ ------------------------------\
250 \ init PORTA (P2:P1) (complement) when reset occurs all I/O are set in input with resistors pullup 
251 BIC.B #SMM_BUS,&I2CSMM_OUT      \ preset SDA + SCL output low
252 BIC.B #SMM_BUS,&I2CSMM_REN      \ SDA + SCL pullup/down disable
253 \ ------------------------------\
254     LO2HI
255     ." Type STOP to stop :-)"
256     LIT RECURSE IS WARM         \ insert this starting routine between COLD and WARM...
257     ['] WARM >BODY EXECUTE      \ ...and continue with WARM (very, very usefull after COLD or RESET !:-)
258  ;
259
260 : STOP                          \ stops multitasking, must to be used before downloading app
261     ['] WARM >BODY  IS WARM     \ remove START app from FORTH init process
262     ECHO COLD                   \ reset CPU, interrupt vectors, and start FORTH
263 ;
264
265 RST_HERE
266
267 \ ---------------------------------------------------------------------------------------------------------------------\
268 \ SCL clock generation, timing, and test of data(s) number are made by I2C_Master.
269 \ slave can strech SCL low after Start Condition and after any bit.
270
271 \ address Ack/Nack is generated by the slave on SDA line (released by the master)
272 \ Two groups of eight addresses (000xxxy and 1111xxxy) are not allowed (reserved)
273 \ after address or data is sent, the transmitter (Master or Slave) must release SDA line to allow (N)Ack by the receiver
274 \ data Ack/Nack are generated by the receiver (master or slave) on SDA line
275 \ a master receiver must signal the end of data to the slave transmitter by sending a Nack bit
276 \ Stop or restart conditions must be generated by master after a Nack bit.
277 \ after Ack bit is sent, Slave must release SDA line to allow master to do stop or restart conditions
278 \
279 \     __      _____ _____ _..._ _____ _____ _NACK _____ _____ _..._ _____ _____ _NACK     _
280 \ SDA   \____/_MSB_X_____X_..._X_LSB_X_R/Wx_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X___/
281 \     _____     _     _           _     _     _     _     _           _     _     _     ___
282 \ SCL      \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/
283 \       ^   ^                             ^     ^                             ^     ^    ^
284 \       |   |Slave Stretch Low            |SSL  |SSL                          |SSL  |SSL |
285 \       |                                                                                |
286 \       |Start Condition                                                                 |stoP Condition
287 \
288 \     __      _____ _____ _..._ _____ _____ _NACK _____ _____ _..._ _____ _____ _NACK ___
289 \ SDA   \____/_MSB_X_____X_..._X_LSB_X_R/W_x_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X   \____...
290 \     _____     _     _           _     _     _     _     _           _     _     _     ____
291 \ SCL      \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/    \_...
292 \       ^   ^                             ^     ^                             ^     ^    ^
293 \       |   |Slave Stretch Low            |SSL  |SSL                          |SSL  |SSL |
294 \       |                                                                                |
295 \       |Start Condition                                                                 |reStart Condition
296 \
297 \ tHIGH : SCL high time
298 \ tLOW : SCL low time
299 \ tBUF : SDA high time between Stop and Start conditions
300 \ tHD:STA : Start_Condition SCL high time after SDA is low
301 \ tSU:STO : Stop_Condition SCL high time before SDA rise
302 \ tSU:STA : Start_Condition SCL high time before SDA fall
303 \ tHD:DAT : SDA data change time after SCL is low
304 \ the SDA line must be strobe just after SCL is high
305 \ the SDA data must be change just after SCL is low
306 \ standard mode (up to 100 kHz) :   tHIGH   =   tHD:STA =   tSU:STO =   4µs
307 \                                   tLOW    =   tSU:STA =   tBUF    =   4,7µs
308 \                                   tHD:DAT <=  3,45 µs
309 \ -------------------------------------------------------------------------------------------------------------------\