summaryrefslogtreecommitdiff
path: root/firmware/drivers/i2c.c
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-04-23 09:13:23 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-04-23 09:13:23 +0000
commitc6773e1436ba3adda0a6456dbe54ba1320a095be (patch)
tree172c21804499aa84fcab2f755596a3272cfbd59a /firmware/drivers/i2c.c
parent34f948291202bdb42391bbc1200326e1aca00e5c (diff)
downloadrockbox-c6773e1436ba3adda0a6456dbe54ba1320a095be.tar.gz
rockbox-c6773e1436ba3adda0a6456dbe54ba1320a095be.zip
Moved driver to 'drivers' subdir
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@189 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/i2c.c')
-rw-r--r--firmware/drivers/i2c.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/firmware/drivers/i2c.c b/firmware/drivers/i2c.c
new file mode 100644
index 0000000000..3a5603ddd4
--- /dev/null
+++ b/firmware/drivers/i2c.c
@@ -0,0 +1,212 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "lcd.h"
20#include "sh7034.h"
21#include "debug.h"
22
23#define PB13 0x2000
24#define PB7 0x0080
25#define PB5 0x0020
26
27/* cute little functions */
28#define SDA_LO (PBDR &= ~PB7)
29#define SDA_HI (PBDR |= PB7)
30#define SDA_INPUT (PBIOR &= ~PB7)
31#define SDA_OUTPUT (PBIOR |= PB7)
32#define SDA (PBDR & PB7)
33
34#define SCL_INPUT (PBIOR &= ~PB13)
35#define SCL_OUTPUT (PBIOR |= PB13)
36#define SCL_LO (PBDR &= ~PB13)
37#define SCL_HI (PBDR |= PB13)
38#define SCL (PBDR & PB13)
39
40/* arbitrary delay loop */
41#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0)
42
43void i2c_start(void)
44{
45 SDA_OUTPUT;
46 SDA_HI;
47 SCL_HI;
48 SDA_LO;
49 DELAY;
50 SCL_LO;
51}
52
53void i2c_stop(void)
54{
55 SDA_LO;
56 SCL_HI;
57 DELAY;
58 SDA_HI;
59}
60
61void i2c_init(void)
62{
63 int i;
64
65 /* make PB5, PB7 & PB13 general I/O */
66 PBCR1 &= ~0x0c00; /* PB13 */
67 PBCR2 &= ~0xcc00; /* PB5 abd PB7 */
68
69 /* PB5 is "MAS enable". make it output and high */
70 PBIOR |= PB5;
71 PBDR |= PB5;
72
73 /* Set the clock line to an output */
74 PBIOR |= PB13;
75
76 SDA_OUTPUT;
77 SDA_HI;
78 SCL_LO;
79 for (i=0;i<3;i++)
80 i2c_stop();
81}
82
83void i2c_ack(int bit)
84{
85 /* Here's the deal. The MAS is slow, and sometimes needs to wait
86 before it can receive the acknowledge. Therefore it forces the clock
87 low until it is ready. We need to poll the clock line until it goes
88 high before we release the ack. */
89
90 SCL_LO; /* Set the clock low */
91 if ( bit )
92 SDA_HI;
93 else
94 SDA_LO;
95
96 SCL_INPUT; /* Set the clock to input */
97 while(!SCL); /* and wait for the MAS to release it */
98
99 DELAY;
100 SCL_OUTPUT;
101 SCL_LO;
102}
103
104int i2c_getack(void)
105{
106 unsigned short x;
107
108 /* Here's the deal. The MAS is slow, and sometimes needs to wait
109 before it can send the acknowledge. Therefore it forces the clock
110 low until it is ready. We need to poll the clock line until it goes
111 high before we read the ack. */
112
113 SDA_LO; /* First, discharge the data line */
114 SDA_INPUT; /* And set to input */
115 SCL_LO; /* Set the clock low */
116 SCL_INPUT; /* Set the clock to input */
117 while(!SCL); /* and wait for the MAS to release it */
118
119 x = SDA;
120 if (x)
121 /* ack failed */
122 return 0;
123 SCL_OUTPUT;
124 SCL_LO;
125 SDA_HI;
126 SDA_OUTPUT;
127 return 1;
128}
129
130void i2c_outb(unsigned char byte)
131{
132 int i;
133
134 /* clock out each bit, MSB first */
135 for ( i=0x80; i; i>>=1 ) {
136 if ( i & byte )
137 SDA_HI;
138 else
139 SDA_LO;
140 SCL_HI;
141 SCL_LO;
142 }
143
144 SDA_HI;
145}
146
147unsigned char i2c_inb(int ack)
148{
149 int i;
150 unsigned char byte = 0;
151
152 /* clock in each bit, MSB first */
153 for ( i=0x80; i; i>>=1 ) {
154 /* Tricky business. Here we discharge the data line by driving it low
155 and then set it to input to see if it stays low or goes high */
156 SDA_LO; /* First, discharge the data line */
157 SDA_INPUT; /* And set to input */
158 SCL_HI;
159 if ( SDA )
160 byte |= i;
161 SCL_LO;
162 SDA_OUTPUT;
163 }
164
165 i2c_ack(ack);
166
167 return byte;
168}
169
170int i2c_write(int address, unsigned char* buf, int count )
171{
172 int i,x=0;
173
174 i2c_start();
175 i2c_outb(address & 0xfe);
176 if (i2c_getack())
177 {
178 for (i=0; i<count; i++)
179 {
180 i2c_outb(buf[i]);
181 if (!i2c_getack())
182 {
183 x=-2;
184 break;
185 }
186 }
187 }
188 else
189 {
190 debugf("i2c_write() - no ack\n");
191 x=-1;
192 }
193 i2c_stop();
194 return x;
195}
196
197int i2c_read(int address, unsigned char* buf, int count )
198{
199 int i,x=0;
200
201 i2c_start();
202 i2c_outb(address | 1);
203 if (i2c_getack()) {
204 for (i=0; i<count; i++) {
205 buf[i] = i2c_inb(0);
206 }
207 }
208 else
209 x=-1;
210 i2c_stop();
211 return x;
212}