Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2006, Swedish Institute of Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * @(#)$Id: i2c.c,v 1.2 2007/01/12 13:41:57 bg- Exp $ 00030 */ 00031 00032 /* 00033 * Small and portable implementation of a bit-banging I2C bus master. 00034 * 00035 * The code should port really easily to platforms other than the 00036 * msp430 but has some hardcoded constants in it. 00037 * 00038 * More info at: 00039 * http://i2c-bus.org/ 00040 * http://www.esacademy.com/faq/i2c/ 00041 */ 00042 00043 #include <stdio.h> 00044 #include <contiki.h> 00045 #include <dev/spi.h> 00046 #include <dev/leds.h> 00047 00048 #include "dev/i2c.h" 00049 00050 /* 00051 * On the Tmote sky access to I2C/SPI/UART0 must always be exclusive. 00052 */ 00053 00054 void i2c_enable(void); 00055 void i2c_disable(void); 00056 int i2c_start(void); 00057 unsigned i2c_read(int send_ack); 00058 int i2c_write(unsigned); 00059 void i2c_stop(void); 00060 00061 #define I2C_PxDIR P3DIR 00062 #define I2C_PxIN P3IN 00063 #define I2C_PxOUT P3OUT 00064 #define I2C_PxSEL P3SEL 00065 /* 00066 * SDA == P3.1 00067 * SCL == P3.3 00068 */ 00069 #define SDA 1 00070 #define SCL 3 00071 00072 #define SDA_0() (I2C_PxDIR |= BV(SDA)) /* SDA Output */ 00073 #define SDA_1() (I2C_PxDIR &= ~BV(SDA)) /* SDA Input */ 00074 #define SDA_IS_1 (I2C_PxIN & BV(SDA)) 00075 00076 #define SCL_0() (I2C_PxDIR |= BV(SCL)) /* SCL Output */ 00077 #define SCL_1() (I2C_PxDIR &= ~BV(SCL)) /* SCL Input */ 00078 #define SCL_IS_1 (I2C_PxIN & BV(SCL)) 00079 00080 /* 00081 * Should avoid infinite looping while waiting for SCL_IS_1. xxx/bg 00082 */ 00083 #define SCL_WAIT_FOR_1() do{}while (!SCL_IS_1) 00084 00085 #define delay_4_7us() do{ _NOP(); _NOP(); _NOP(); _NOP(); \ 00086 _NOP(); _NOP(); _NOP(); _NOP(); \ 00087 _NOP(); _NOP(); _NOP(); _NOP(); }while(0) 00088 00089 #define delay_4us() do{ _NOP(); _NOP(); _NOP(); _NOP(); \ 00090 _NOP(); _NOP(); _NOP(); _NOP(); \ 00091 _NOP(); _NOP(); }while(0) 00092 00093 static unsigned char old_pxsel, old_pxout, old_pxdir; 00094 00095 /* 00096 * Grab SDA and SCL pins for exclusive use but remember old 00097 * configuration so that it may be restored when we are done. 00098 */ 00099 void 00100 i2c_enable(void) 00101 { 00102 unsigned char sda_scl = BV(SDA)|BV(SCL); 00103 00104 old_pxsel = I2C_PxSEL & sda_scl; 00105 old_pxout = I2C_PxOUT & sda_scl; 00106 old_pxdir = I2C_PxDIR & sda_scl; 00107 00108 spi_busy = 1; 00109 00110 I2C_PxSEL &= ~sda_scl; 00111 00112 I2C_PxOUT &= ~sda_scl; 00113 00114 I2C_PxDIR |= BV(SCL); /* SCL Output */ 00115 I2C_PxDIR &= ~BV(SDA); /* SDA Input */ 00116 } 00117 00118 /* 00119 * Restore bus to what it was before i2c_enable. 00120 * 00121 */ 00122 void 00123 i2c_disable(void) 00124 { 00125 unsigned char not_sda_scl = ~(BV(SDA)|BV(SCL)); 00126 00127 I2C_PxDIR = (I2C_PxDIR & not_sda_scl) | old_pxdir; 00128 I2C_PxOUT = (I2C_PxOUT & not_sda_scl) | old_pxout; 00129 I2C_PxSEL = (I2C_PxSEL & not_sda_scl) | old_pxsel; 00130 00131 spi_busy = 0; 00132 } 00133 00134 int 00135 i2c_start(void) 00136 { 00137 SDA_1(); 00138 SCL_1(); 00139 #if 1 00140 SCL_WAIT_FOR_1(); 00141 #else 00142 { 00143 unsigned long n; 00144 for (n = 0; n < 100000 && !SCL_IS_1; n++) 00145 ; 00146 if (!SCL_IS_1) 00147 return -1; 00148 } 00149 #endif 00150 delay_4_7us(); 00151 SDA_0(); 00152 delay_4us(); 00153 SCL_0(); 00154 return 0; 00155 } 00156 00157 void 00158 i2c_stop(void) 00159 { 00160 SDA_0(); 00161 delay_4us(); 00162 SCL_1(); 00163 SCL_WAIT_FOR_1(); 00164 SDA_1(); 00165 } 00166 00167 /* 00168 * Return true if we received an ACK. 00169 */ 00170 int 00171 i2c_write(unsigned _c) 00172 { 00173 unsigned char c = _c; 00174 unsigned long n; 00175 int i; 00176 int ret; 00177 00178 for (i = 0; i < 8; i++, c <<= 1) { 00179 if (c & 0x80) 00180 SDA_1(); 00181 else 00182 SDA_0(); 00183 SCL_1(); 00184 SCL_WAIT_FOR_1(); 00185 SCL_0(); 00186 } 00187 00188 SDA_1(); 00189 SCL_1(); 00190 ret = 0; /* Loop waiting for an ACK to arrive. */ 00191 for (n = 0; n < 250000; n++) { 00192 if (!SDA_IS_1) { 00193 ret = 1; 00194 break; 00195 } 00196 } 00197 SCL_WAIT_FOR_1(); /* clock stretching? */ 00198 SCL_0(); 00199 00200 return ret; 00201 } 00202 00203 unsigned 00204 i2c_read(int send_ack) 00205 { 00206 int i; 00207 unsigned char c = 0x00; 00208 00209 SDA_1(); 00210 for (i = 0; i < 8; i++) { 00211 c <<= 1; 00212 SCL_1(); 00213 SCL_WAIT_FOR_1(); 00214 if (SDA_IS_1) 00215 c |= 0x1; 00216 SCL_0(); 00217 } 00218 00219 if (send_ack) 00220 SDA_0(); 00221 SCL_1(); 00222 SCL_WAIT_FOR_1(); 00223 SCL_0(); 00224 00225 return c; 00226 }