OSDN Git Service

V205; added MSP-EXP430FR2355.
[fast-forth/master.git] / MSP430-FORTH / lib / I2C_Master.f
1 \ name : msp430FR5xxx_I2C_Master.asm
2 \
3 \ Copyright (C) <2016>  <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
20 \ Target: MSP-EXP430FR5969 @ 8,16MHz
21 \ version 1.1 2016-03-18
22 \
23 \ ---------------------------------------------------------------------------------------------------------------------;
24 \ SCL clock generation, timing, and test of data(s) number are made by I2C_Master.
25 \ slave can strech SCL low after Start Condition and after any bit.
26 \
27 \ address Ack/Nack is generated by the slave on SDA line (released by the master)
28 \ Two groups of eight addresses (000$xxy and 1111xxxy) are not allowed (reserved)
29 \ after address or data is sent, the transmitter (Master or Slave) must release SDA line to allow (N)Ack by the receiver
30 \ data Ack/Nack are generated by the receiver (master or slave) on SDA line
31 \ a master receiver must signal the end of data to the slave transmitter by sending a Nack bit
32 \ Stop or restart conditions must be generated by master after a Nack bit.
33 \ after Ack bit is sent, Slave must release SDA line to allow master to do stop or restart conditions
34 \
35 \     __      _____ _____ _..._ _____ _____ _NACK _____ _____ _..._ _____ _____ _NACK     _
36 \ SDA   \____/_MSB_X_____X_..._X_LSB_X_R/W_x_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X___/
37 \     _____     _     _           _     _     _     _     _           _     _     _     ___
38 \ SCL      \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/
39 \       ^   ^                             ^     ^                             ^     ^    ^
40 \       |   |Slave Stretch Low            |SSL  |SSL                          |SSL  |SSL |
41 \       |                                                                                |
42 \       |Start Condition                                                                 |stoP Condition
43 \
44 \     __      _____ _____ _..._ _____ _____ _NACK _____ _____ _..._ _____ _____ _NACK ___
45 \ SDA   \____/_MSB_X_____X_..._X_LSB_X_R/W_x_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X   \____...
46 \     _____     _     _           _     _     _     _     _           _     _     _     ____
47 \ SCL      \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/    \_...
48 \       ^   ^                             ^     ^                             ^     ^    ^
49 \       |   |Slave Stretch Low            |SSL  |SSL                          |SSL  |SSL |
50 \       |                                                                                |
51 \       |Start Condition                                                                 |reStart Condition
52 \
53 \ tHIGH : SCL high time
54 \ tLOW : SCL low time
55 \ tBUF : SDA high time between Stop and Start conditions
56 \ tHD:STA : Start_Condition SCL high time after SDA is low
57 \ tSU:STO : Stop_Condition SCL high time before SDA rise
58 \ tSU:STA : Start_Condition SCL high time before SDA fall
59 \ tHD:DAT : SDA data change time after SCL is low
60 \ the SDA line must be strobe just after SCL is high
61 \ the SDA data must be change just after SCL is low
62 \ standard mode (up to 100 kHz) :   tHIGH   =   tHD:STA =   tSU:STO =   4µs
63 \                                   tLOW    =   tSU:STA =   tBUF    =   4,7µs
64 \                                   tHD:DAT <=  3,45 µs
65 \
66 \ fast mode     (up to 400 kHz) :   tHIGH   =   tHD:STA =   tSU:STO =   0,6µs
67 \                                   tLOW    =   tSU:STA =   tBUF    =   1,3µs
68 \                                   tHD:DAT <=  0,9 µs
69 \ -------------------------------------------------------------------------------------------------------------------;
70
71 \ =================================================================
72 \ =================================================================
73                           
74 \ ###  #####   #####      #     #
75 \  #  #     # #     #     ##   ##   ##    ####  ##### ###### #####
76 \  #        # #           # # # #  #  #  #        #   #      #    #
77 \  #   #####  #           #  #  # #    #  ####    #   #####  #    #
78 \  #  #       #           #     # ######      #   #   #      #####
79 \  #  #       #     #     #     # #    # #    #   #   #      #   #
80 \ ### #######  #####      #     # #    #  ####    #   ###### #    #
81                           
82 \ =================================================================
83 \ =================================================================
84
85 \ tested with P1.6 SDA, P1.7 SCL :
86 \ Start + Adr + Write 3 bytes + Stop + Start + adr + read 2 bytes + stop = 204us ==> 308 kHz  (STOP=10us)
87 \ See MSP430FR5xxx_I2C_Master.png
88
89
90
91 VARIABLE I2CS_ADR   \ low(I2CS_ADR) = slave I2C address with RW flag, high(I2CS_ADR) = RX buffer,data0
92 2 ALLOT             \ data1,data2
93 VARIABLE I2CM_BUF   \ low(I2CM_BUF) = RX or TX lentgh, high(I2CM_BUF) = TX buffer,data0
94 2 ALLOT             \ data1,data2
95     \
96
97
98
99 \ ----------------------------------\
100 ASM I2C_M                           \
101 \ ----------------------------------\
102 \                                   \ in    I2CS_ADR/I2CM_BUF as RX/TX buffer requested by I2CS_ADR(0(0))
103 \                                   \       I2CS_ADR(0) = I2C_Slave_addr&R/w
104 \                                   \       I2CM_BUF(0) = TX/RX count of datas
105 \                                   \       I2CM_BUF(0) = 0 ==> send only I2C address
106 \                                   \ used  S = BUF ptr
107 \                                   \       T
108 \                                   \ out   I2CSLA_ADR & (R/W) unCHNGd
109 \                                   \       S = BUF PTR pointing on first data not exCHNGd
110 \                                   \       T = count of TX/RX datas exCHNGd
111 \                                   \       T = -1 ==> NACK on address
112 \                                   \       I2CS_ADR(0) = unCHNGd
113 \                                   \       I2CM_BUF(0) = unCHNGd
114 BIS #1,&UCB0CTLW0                   \ SWRST 
115 MOV #$0FD3,&UCB0CTLW0               \ master mode + UCTR + START + SWRST, IFG=IE=0 
116 MOV #$00C8,&UCB0CTLW1               \ set automatic stop (count byte reached)
117 MOV #$14,&UCB0BRW                   \ baudrate = SMCLK/20 = 400 kHz @8MHz ; 340 kHz measured
118 MOV #I2CM_BUF,S                     \ count & TX buf
119 MOV.B @S+,&UCB0TBCNT                \
120 CMP.B #0,&UCB0TBCNT                 \
121 0= IF                               \ count = 0
122     BIS #4,&UCB0CTLW0               \ add Stop cmd to Start cmd ==> Master send only I2C address
123 THEN    
124 MOV #I2CS_ADR,T                     \ I2Cadr & RX buf
125 MOV.B @T+,&UCB0I2CSA                \ UCB0I2CSA = slave_address & R/w bit
126 RRA &UCB0I2CSA                      \ UCB0I2CSA = slave_address, C flag = R/w flag
127 U>= IF                              \ C flag = 1
128     MOV T,S                         \ Master read  : S = RX buffer
129     BIC #$10,&UCB0CTLW0             \                UCB0CTLW0 <-- UCTR=0
130 THEN                                \
131 \ ------------------------------    \
132 \ Start                             \
133 \ ------------------------------    \
134 MOV.B #-1,T                         \ T=-1
135 BIC #1,&UCB0CTLW0                   \ UCB0CTLW0 : clear SWRST, start I2C MASTER
136 BIT.B #1,&I2CS_ADR                  \ R/W test
137 0= IF                               \
138 \   ----------------------------    \
139 \   MASTER TX                       \
140 \   ----------------------------    \
141     BEGIN                           \
142         MOV.B &UCBCNT0,T            \ store count of byte
143         BIT #8,&UCB0IFG             \ test UCSTPIFG
144         0<> IF                      \
145             MOV @RSP+,PC            \ end of I2C_M TX driver
146         THEN                        \
147         BIT #$20,&UCB0IFG           \ test UCNACKIFG
148         0<> IF                      \
149             BIS #4,&UCB0CTLW0       \ generate stop bit
150             MOV @RSP+,PC            \ end of I2C_M TX driver
151         THEN                        \
152         BIT #2,&UCB0IFG             \ test UCTXIFG0
153         0<> IF                      \
154             MOV.B @S+,&UCB0TXBUF    \ load data into UCB0TXBUF
155         THEN                        \
156     AGAIN                           \
157 THEN                                \
158 \ ------------------------------    \
159 \ MASTER RX                         \
160 \ ------------------------------    \
161 BEGIN                               \ of Master RX
162     MOV.B &UCBCNT0,T                \ store count of byte
163     BIT #8,&UCB0IFG                 \ test UCSTPIFG
164     0<> IF                          \
165         MOV @RSP+,PC                \ end of I2C_M RX driver
166     THEN                            \
167     BIT #1,&UCB0IFG                 \ test UCRXIFG0
168     0<> IF                          \
169         MOV.B &UCB0RXBUF,0(S)       \ load data from UCB0RXBUF
170         ADD   #1,S                  \
171     THEN                            \
172 AGAIN                               \
173 ENDASM                              \ 62 words + 9 init words
174     \
175
176 \ ------------------------------\
177 CODE START                      \ init
178 \ ------------------------------\
179 \ init I2C_Master               \
180 \ ------------------------------\
181 \       %0000 1111 1101 0011     $640 = $0FD3
182 \           -                     UCMM = 1  : multi master mode
183 \              -                  UCMST = 1 : I2C_Master
184 \               --                UCMODE = %11 = I2C
185 \                 _               USYNC=1 (always 1)
186 \                   --            UCSSEL=SMCLK=8MHz
187 \                     -           UCTXACK=0 not auto ACK slave address
188 \                      -          UCTR=1/0 : TX/RX modes
189 \                         -       UCTXSTP
190 \                          -      UCTXSTT send start
191 \                           -     UCSWRST=1
192 \ ------------------------------\
193 \       %0000 0000 1100 1000     $642 = $00C8
194 \                 -               UCETXINT=0 : UCTXIFG0 set address match UCxI2COAx and TX mode
195 \                   --            UCCLTO=%11 : SCL low time out = 34 ms
196 \                      -          UCSWACK=1 : UCTXACK must be written to continue
197 \                        --       UCASTP0=%10 : automatic Stop when UCBxTBCNT is reached
198 \ ------------------------------\
199 \ PORTX (PORTx:y) default values\ DIR0,REN1,OUT1 (input with pullup resistors)
200 \ ------------------------------\
201 \ notice : UCB0 I2C driver seems to control only DIR register !!!
202 BIC.B #M_BUS,&I2CM_REN          \ REN0 : no_resistor
203 BIC.B #M_BUS,&I2CM_OUT          \ OUT0 : preset output low
204 BIS.B #M_BUS,&I2CM_SEL1         \ SEL11 : enable I2C I/O
205 COLON
206 ." type stop to stop :-)"
207 LIT RECURSE IS WARM             \ insert this starting routine between COLD and WARM...
208 (WARM)                          \ ...and continue with (WARM)
209 ;
210
211 : STOP                  \ stops multitasking, must to be used before downloading app
212     ['] (WARM) IS WARM  \ remove START app from FORTH init process
213     ECHO COLD           \ reset CPU, interrupt vectors, and start FORTH
214 ;
215     \
216