Contiki 3.x
i2c.c
1 /*
2  * Copyright (c) 2006, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /*
31  * Small and portable implementation of a bit-banging I2C bus master.
32  *
33  * The code should port really easily to platforms other than the
34  * msp430 but has some hardcoded constants in it.
35  *
36  * More info at:
37  * http://i2c-bus.org/
38  * http://www.esacademy.com/faq/i2c/
39  */
40 
41 #include <contiki.h>
42 #include <dev/spi.h>
43 #include <dev/leds.h>
44 
45 #include "dev/i2c.h"
46 
47 /*
48  * On the Tmote sky access to I2C/SPI/UART0 must always be exclusive.
49  */
50 
51 void i2c_enable(void);
52 void i2c_disable(void);
53 int i2c_start(void);
54 unsigned i2c_read(int send_ack);
55 int i2c_write(unsigned);
56 void i2c_stop(void);
57 
58 #define I2C_PxDIR P3DIR
59 #define I2C_PxIN P3IN
60 #define I2C_PxOUT P3OUT
61 #define I2C_PxSEL P3SEL
62 /*
63  * SDA == P3.1
64  * SCL == P3.3
65  */
66 #define SDA 1
67 #define SCL 3
68 
69 #define SDA_0() (I2C_PxDIR |= BV(SDA)) /* SDA Output */
70 #define SDA_1() (I2C_PxDIR &= ~BV(SDA)) /* SDA Input */
71 #define SDA_IS_1 (I2C_PxIN & BV(SDA))
72 
73 #define SCL_0() (I2C_PxDIR |= BV(SCL)) /* SCL Output */
74 #define SCL_1() (I2C_PxDIR &= ~BV(SCL)) /* SCL Input */
75 #define SCL_IS_1 (I2C_PxIN & BV(SCL))
76 
77 /*
78  * Should avoid infinite looping while waiting for SCL_IS_1. xxx/bg
79  */
80 #define SCL_WAIT_FOR_1() do{}while (!SCL_IS_1)
81 
82 #define delay_4_7us() do{ _NOP(); _NOP(); _NOP(); _NOP(); \
83  _NOP(); _NOP(); _NOP(); _NOP(); \
84  _NOP(); _NOP(); _NOP(); _NOP(); }while(0)
85 
86 #define delay_4us() do{ _NOP(); _NOP(); _NOP(); _NOP(); \
87  _NOP(); _NOP(); _NOP(); _NOP(); \
88  _NOP(); _NOP(); }while(0)
89 
90 static unsigned char old_pxsel, old_pxout, old_pxdir;
91 
92 /*
93  * Grab SDA and SCL pins for exclusive use but remember old
94  * configuration so that it may be restored when we are done.
95  */
96 void
97 i2c_enable(void)
98 {
99  unsigned char sda_scl = BV(SDA)|BV(SCL);
100 
101  old_pxsel = I2C_PxSEL & sda_scl;
102  old_pxout = I2C_PxOUT & sda_scl;
103  old_pxdir = I2C_PxDIR & sda_scl;
104 
105  spi_busy = 1;
106 
107  I2C_PxSEL &= ~sda_scl;
108 
109  I2C_PxOUT &= ~sda_scl;
110 
111  I2C_PxDIR |= BV(SCL); /* SCL Output */
112  I2C_PxDIR &= ~BV(SDA); /* SDA Input */
113 }
114 
115 /*
116  * Restore bus to what it was before i2c_enable.
117  *
118  */
119 void
120 i2c_disable(void)
121 {
122  unsigned char not_sda_scl = ~(BV(SDA)|BV(SCL));
123 
124  I2C_PxDIR = (I2C_PxDIR & not_sda_scl) | old_pxdir;
125  I2C_PxOUT = (I2C_PxOUT & not_sda_scl) | old_pxout;
126  I2C_PxSEL = (I2C_PxSEL & not_sda_scl) | old_pxsel;
127 
128  spi_busy = 0;
129 }
130 
131 int
132 i2c_start(void)
133 {
134  SDA_1();
135  SCL_1();
136 #if 1
137  SCL_WAIT_FOR_1();
138 #else
139  {
140  unsigned long n;
141  for (n = 0; n < 100000 && !SCL_IS_1; n++)
142  ;
143  if (!SCL_IS_1)
144  return -1;
145  }
146 #endif
147  delay_4_7us();
148  SDA_0();
149  delay_4us();
150  SCL_0();
151  return 0;
152 }
153 
154 void
155 i2c_stop(void)
156 {
157  SDA_0();
158  delay_4us();
159  SCL_1();
160  SCL_WAIT_FOR_1();
161  SDA_1();
162 }
163 
164 /*
165  * Return true if we received an ACK.
166  */
167 int
168 i2c_write(unsigned _c)
169 {
170  unsigned char c = _c;
171  unsigned long n;
172  int i;
173  int ret;
174 
175  for (i = 0; i < 8; i++, c <<= 1) {
176  if (c & 0x80)
177  SDA_1();
178  else
179  SDA_0();
180  SCL_1();
181  SCL_WAIT_FOR_1();
182  SCL_0();
183  }
184 
185  SDA_1();
186  SCL_1();
187  ret = 0; /* Loop waiting for an ACK to arrive. */
188  for (n = 0; n < 250000; n++) {
189  if (!SDA_IS_1) {
190  ret = 1;
191  break;
192  }
193  }
194  SCL_WAIT_FOR_1(); /* clock stretching? */
195  SCL_0();
196 
197  return ret;
198 }
199 
200 unsigned
201 i2c_read(int send_ack)
202 {
203  int i;
204  unsigned char c = 0x00;
205 
206  SDA_1();
207  for (i = 0; i < 8; i++) {
208  c <<= 1;
209  SCL_1();
210  SCL_WAIT_FOR_1();
211  if (SDA_IS_1)
212  c |= 0x1;
213  SCL_0();
214  }
215 
216  if (send_ack)
217  SDA_0();
218  SCL_1();
219  SCL_WAIT_FOR_1();
220  SCL_0();
221 
222  return c;
223 }
void i2c_write(uint8_t data)
Send a byte to I2C bus.
Definition: i2c.c:106
void i2c_stop(void)
Generate I2C STOP condition.
Definition: i2c.c:95
uint8_t i2c_read(int ack)
Read a byte from I2C bus.
Definition: i2c.c:121
void i2c_start(void)
Generate I2C START condition.
Definition: i2c.c:85
void i2c_enable(void)
Configure serial controller in I2C mode and set I2C speed.
Definition: i2c.c:52
Basic SPI macros
void i2c_disable(void)
Configure serial controller in disabled mode.
Definition: i2c.c:76