version 4.1.0 from http://fpga4u.epfl.ch/wiki/FX2
[fx2fw-sdcc] / fx2 / i2c.c
1 /* -*- c++ -*- */\r
2 \r
3 /*-----------------------------------------------------------------------------\r
4 \r
5  * I2C read/write functions for FX2\r
6 \r
7  *-----------------------------------------------------------------------------\r
8 \r
9  * Code taken from USRP2 firmware (GNU Radio Project), version 3.0.2,\r
10 \r
11  * Copyright 2003 Free Software Foundation, Inc.\r
12 \r
13  *-----------------------------------------------------------------------------\r
14 \r
15  * This code is part of usbjtag. usbjtag is free software; you can redistribute\r
16 \r
17  * it and/or modify it under the terms of the GNU General Public License as\r
18 \r
19  * published by the Free Software Foundation; either version 2 of the License,\r
20 \r
21  * or (at your option) any later version. usbjtag is distributed in the hope\r
22 \r
23  * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied\r
24 \r
25  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
26 \r
27  * GNU General Public License for more details.  You should have received a\r
28 \r
29  * copy of the GNU General Public License along with this program in the file\r
30 \r
31  * COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin\r
32 \r
33  * St, Fifth Floor, Boston, MA  02110-1301  USA\r
34 \r
35  *-----------------------------------------------------------------------------\r
36 \r
37  */\r
38 \r
39 \r
40 \r
41 #include "i2c.h"\r
42 \r
43 #include "fx2regs.h"\r
44 \r
45 #include <string.h>\r
46 \r
47 \r
48 \r
49 \r
50 \r
51 // issue a stop bus cycle and wait for completion\r
52 \r
53 \r
54 \r
55 \r
56 \r
57 // returns non-zero if successful, else 0\r
58 \r
59 unsigned char\r
60 \r
61 i2c_read (unsigned char addr, xdata unsigned char *buf, unsigned char len)\r
62 \r
63 {\r
64 \r
65   volatile unsigned char        junk;\r
66 \r
67   \r
68 \r
69   if (len == 0)                 // reading zero bytes always works\r
70 \r
71     return 1;\r
72 \r
73   \r
74 \r
75   while (I2CS & bmSTOP)         // wait for stop to clear\r
76 \r
77     ;\r
78 \r
79 \r
80 \r
81   I2CS = bmSTART;\r
82 \r
83   I2DAT = (addr << 1) | 1;      // write address and direction (1's the read bit)\r
84 \r
85 \r
86 \r
87   while ((I2CS & bmDONE) == 0)\r
88 \r
89     ;\r
90 \r
91 \r
92 \r
93   if ((I2CS & bmBERR) || (I2CS & bmACK) == 0)   // no device answered...\r
94 \r
95     goto fail;\r
96 \r
97 \r
98 \r
99   if (len == 1)\r
100 \r
101     I2CS |= bmLASTRD;           \r
102 \r
103 \r
104 \r
105   junk = I2DAT;                 // trigger the first read cycle\r
106 \r
107 \r
108 \r
109   while (--len != 0){\r
110 \r
111     while ((I2CS & bmDONE) == 0)\r
112 \r
113       ;\r
114 \r
115 \r
116 \r
117     if (I2CS & bmBERR)\r
118 \r
119       goto fail;\r
120 \r
121 \r
122 \r
123     if (len == 1)\r
124 \r
125       I2CS |= bmLASTRD;\r
126 \r
127     \r
128 \r
129     *buf++ = I2DAT;             // get data, trigger another read\r
130 \r
131   }\r
132 \r
133 \r
134 \r
135   // wait for final byte\r
136 \r
137   \r
138 \r
139   while ((I2CS & bmDONE) == 0)\r
140 \r
141     ;\r
142 \r
143   \r
144 \r
145   if (I2CS & bmBERR)\r
146 \r
147     goto fail;\r
148 \r
149 \r
150 \r
151   I2CS |= bmSTOP;\r
152 \r
153   *buf = I2DAT;\r
154 \r
155 \r
156 \r
157   return 1;\r
158 \r
159 \r
160 \r
161  fail:\r
162 \r
163   I2CS |= bmSTOP;\r
164 \r
165   return 0;\r
166 \r
167 }\r
168 \r
169 \r
170 \r
171 \r
172 \r
173 \r
174 \r
175 // returns non-zero if successful, else 0\r
176 \r
177 unsigned char\r
178 \r
179 i2c_write (unsigned char addr, xdata const unsigned char *buf, unsigned char len)\r
180 \r
181 {\r
182 \r
183   while (I2CS & bmSTOP)         // wait for stop to clear\r
184 \r
185     ;\r
186 \r
187 \r
188 \r
189   I2CS = bmSTART;\r
190 \r
191   I2DAT = (addr << 1) | 0;      // write address and direction (0's the write bit)\r
192 \r
193 \r
194 \r
195   while ((I2CS & bmDONE) == 0)\r
196 \r
197     ;\r
198 \r
199 \r
200 \r
201   if ((I2CS & bmBERR) || (I2CS & bmACK) == 0)   // no device answered...\r
202 \r
203     goto fail;\r
204 \r
205 \r
206 \r
207   while (len > 0){\r
208 \r
209     I2DAT = *buf++;\r
210 \r
211     len--;\r
212 \r
213 \r
214 \r
215     while ((I2CS & bmDONE) == 0)\r
216 \r
217       ;\r
218 \r
219 \r
220 \r
221     if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered...\r
222 \r
223       goto fail;\r
224 \r
225   }\r
226 \r
227 \r
228 \r
229   I2CS |= bmSTOP;\r
230 \r
231   return 1;\r
232 \r
233 \r
234 \r
235  fail:\r
236 \r
237   I2CS |= bmSTOP;\r
238 \r
239   return 0;\r
240 \r
241 }\r
242 \r