version 4.2.0
[fx2fw-sdcc] / fx2 / i2c.c
1 /* -*- c++ -*- */\r
2 /*-----------------------------------------------------------------------------\r
3  * I2C read/write functions for FX2\r
4  *-----------------------------------------------------------------------------\r
5  * Code taken from USRP2 firmware (GNU Radio Project), version 3.0.2,\r
6  * Copyright 2003 Free Software Foundation, Inc.\r
7  *-----------------------------------------------------------------------------\r
8  * This code is part of usbjtag. usbjtag is free software; you can redistribute\r
9  * it and/or modify it under the terms of the GNU General Public License as\r
10  * published by the Free Software Foundation; either version 2 of the License,\r
11  * or (at your option) any later version. usbjtag is distributed in the hope\r
12  * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied\r
13  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.  You should have received a\r
15  * copy of the GNU General Public License along with this program in the file\r
16  * COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin\r
17  * St, Fifth Floor, Boston, MA  02110-1301  USA\r
18  *-----------------------------------------------------------------------------\r
19  */\r
20 \r
21 #include "i2c.h"\r
22 #include "fx2regs.h"\r
23 #include <string.h>\r
24 \r
25 \r
26 // issue a stop bus cycle and wait for completion\r
27 \r
28 \r
29 // returns non-zero if successful, else 0\r
30 unsigned char\r
31 i2c_read (unsigned char addr, xdata unsigned char *buf, unsigned char len)\r
32 {\r
33   volatile unsigned char        junk;\r
34   \r
35   if (len == 0)                 // reading zero bytes always works\r
36     return 1;\r
37   \r
38   while (I2CS & bmSTOP)         // wait for stop to clear\r
39     ;\r
40 \r
41   I2CS = bmSTART;\r
42   I2DAT = (addr << 1) | 1;      // write address and direction (1's the read bit)\r
43 \r
44   while ((I2CS & bmDONE) == 0)\r
45     ;\r
46 \r
47   if ((I2CS & bmBERR) || (I2CS & bmACK) == 0)   // no device answered...\r
48     goto fail;\r
49 \r
50   if (len == 1)\r
51     I2CS |= bmLASTRD;           \r
52 \r
53   junk = I2DAT;                 // trigger the first read cycle\r
54 \r
55   while (--len != 0){\r
56     while ((I2CS & bmDONE) == 0)\r
57       ;\r
58 \r
59     if (I2CS & bmBERR)\r
60       goto fail;\r
61 \r
62     if (len == 1)\r
63       I2CS |= bmLASTRD;\r
64     \r
65     *buf++ = I2DAT;             // get data, trigger another read\r
66   }\r
67 \r
68   // wait for final byte\r
69   \r
70   while ((I2CS & bmDONE) == 0)\r
71     ;\r
72   \r
73   if (I2CS & bmBERR)\r
74     goto fail;\r
75 \r
76   I2CS |= bmSTOP;\r
77   *buf = I2DAT;\r
78 \r
79   return 1;\r
80 \r
81  fail:\r
82   I2CS |= bmSTOP;\r
83   return 0;\r
84 }\r
85 \r
86 \r
87 \r
88 // returns non-zero if successful, else 0\r
89 unsigned char\r
90 i2c_write (unsigned char addr, xdata const unsigned char *buf, unsigned char len)\r
91 {\r
92   while (I2CS & bmSTOP)         // wait for stop to clear\r
93     ;\r
94 \r
95   I2CS = bmSTART;\r
96   I2DAT = (addr << 1) | 0;      // write address and direction (0's the write bit)\r
97 \r
98   while ((I2CS & bmDONE) == 0)\r
99     ;\r
100 \r
101   if ((I2CS & bmBERR) || (I2CS & bmACK) == 0)   // no device answered...\r
102     goto fail;\r
103 \r
104   while (len > 0){\r
105     I2DAT = *buf++;\r
106     len--;\r
107 \r
108     while ((I2CS & bmDONE) == 0)\r
109       ;\r
110 \r
111     if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered...\r
112       goto fail;\r
113   }\r
114 \r
115   I2CS |= bmSTOP;\r
116   return 1;\r
117 \r
118  fail:\r
119   I2CS |= bmSTOP;\r
120   return 0;\r
121 }\r