Contiki 2.6

i2c.c

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 
00030 /*
00031  * Small and portable implementation of a bit-banging I2C bus master.
00032  *
00033  * The code should port really easily to platforms other than the
00034  * msp430 but has some hardcoded constants in it.
00035  *
00036  * More info at:
00037  *   http://i2c-bus.org/
00038  *   http://www.esacademy.com/faq/i2c/
00039  */
00040 
00041 #include <contiki.h>
00042 #include <dev/spi.h>
00043 #include <dev/leds.h>
00044 
00045 #include "dev/i2c.h"
00046 
00047 /*
00048  * On the Tmote sky access to I2C/SPI/UART0 must always be exclusive.
00049  */
00050 
00051 void     i2c_enable(void);
00052 void     i2c_disable(void);
00053 int      i2c_start(void);
00054 unsigned i2c_read(int send_ack);
00055 int      i2c_write(unsigned);
00056 void     i2c_stop(void);
00057 
00058 #define I2C_PxDIR   P3DIR
00059 #define I2C_PxIN    P3IN
00060 #define I2C_PxOUT   P3OUT
00061 #define I2C_PxSEL   P3SEL
00062 /*
00063  * SDA == P3.1
00064  * SCL == P3.3
00065  */
00066 #define SDA       1
00067 #define SCL       3
00068 
00069 #define SDA_0()   (I2C_PxDIR |=  BV(SDA))               /* SDA Output */
00070 #define SDA_1()   (I2C_PxDIR &= ~BV(SDA))               /* SDA Input */
00071 #define SDA_IS_1  (I2C_PxIN & BV(SDA))
00072 
00073 #define SCL_0()   (I2C_PxDIR |=  BV(SCL))               /* SCL Output */
00074 #define SCL_1()   (I2C_PxDIR &= ~BV(SCL))               /* SCL Input */
00075 #define SCL_IS_1  (I2C_PxIN & BV(SCL))
00076 
00077 /*
00078  * Should avoid infinite looping while waiting for SCL_IS_1. xxx/bg
00079  */
00080 #define SCL_WAIT_FOR_1() do{}while (!SCL_IS_1)
00081 
00082 #define delay_4_7us() do{ _NOP(); _NOP(); _NOP(); _NOP(); \
00083                           _NOP(); _NOP(); _NOP(); _NOP(); \
00084                           _NOP(); _NOP(); _NOP(); _NOP(); }while(0)
00085 
00086 #define delay_4us()   do{ _NOP(); _NOP(); _NOP(); _NOP(); \
00087                           _NOP(); _NOP(); _NOP(); _NOP(); \
00088                           _NOP(); _NOP(); }while(0)
00089 
00090 static unsigned char old_pxsel, old_pxout, old_pxdir;
00091 
00092 /*
00093  * Grab SDA and SCL pins for exclusive use but remember old
00094  * configuration so that it may be restored when we are done.
00095  */
00096 void
00097 i2c_enable(void)
00098 {
00099   unsigned char sda_scl = BV(SDA)|BV(SCL);
00100 
00101   old_pxsel = I2C_PxSEL & sda_scl;
00102   old_pxout = I2C_PxOUT & sda_scl;
00103   old_pxdir = I2C_PxDIR & sda_scl;
00104 
00105   spi_busy = 1;
00106 
00107   I2C_PxSEL &= ~sda_scl;
00108 
00109   I2C_PxOUT &= ~sda_scl;
00110 
00111   I2C_PxDIR |=  BV(SCL);                /* SCL Output */
00112   I2C_PxDIR &= ~BV(SDA);                /* SDA Input */
00113 }
00114 
00115 /*
00116  * Restore bus to what it was before i2c_enable.
00117  *
00118  */
00119 void
00120 i2c_disable(void)
00121 {
00122   unsigned char not_sda_scl = ~(BV(SDA)|BV(SCL));
00123 
00124   I2C_PxDIR = (I2C_PxDIR & not_sda_scl) | old_pxdir;
00125   I2C_PxOUT = (I2C_PxOUT & not_sda_scl) | old_pxout;
00126   I2C_PxSEL = (I2C_PxSEL & not_sda_scl) | old_pxsel;
00127 
00128   spi_busy = 0;
00129 }
00130 
00131 int
00132 i2c_start(void)
00133 {
00134   SDA_1();
00135   SCL_1();
00136 #if 1
00137   SCL_WAIT_FOR_1();
00138 #else
00139   {
00140     unsigned long n;
00141     for (n = 0; n < 100000 && !SCL_IS_1; n++)
00142       ;
00143     if (!SCL_IS_1)
00144       return -1;
00145   }
00146 #endif
00147   delay_4_7us();
00148   SDA_0();
00149   delay_4us();
00150   SCL_0();
00151   return 0;
00152 }
00153 
00154 void
00155 i2c_stop(void)
00156 {
00157   SDA_0();
00158   delay_4us();
00159   SCL_1();
00160   SCL_WAIT_FOR_1();
00161   SDA_1();
00162 }
00163 
00164 /*
00165  * Return true if we received an ACK.
00166  */
00167 int
00168 i2c_write(unsigned _c)
00169 {
00170   unsigned char c = _c;
00171   unsigned long n;
00172   int i;
00173   int ret;
00174 
00175   for (i = 0; i < 8; i++, c <<= 1) {
00176     if (c & 0x80)
00177       SDA_1();
00178     else
00179       SDA_0();
00180     SCL_1();
00181     SCL_WAIT_FOR_1();
00182     SCL_0();
00183   }
00184 
00185   SDA_1();
00186   SCL_1();
00187   ret = 0;                 /* Loop waiting for an ACK to arrive. */
00188   for (n = 0; n < 250000; n++) {
00189     if (!SDA_IS_1) {
00190       ret = 1;
00191       break;
00192     }
00193   }
00194   SCL_WAIT_FOR_1();             /* clock stretching? */
00195   SCL_0();
00196 
00197   return ret;
00198 }
00199 
00200 unsigned
00201 i2c_read(int send_ack)
00202 {
00203   int i;
00204   unsigned char c = 0x00;
00205 
00206   SDA_1();
00207   for (i = 0; i < 8; i++) {
00208     c <<= 1;
00209     SCL_1();
00210     SCL_WAIT_FOR_1();
00211     if (SDA_IS_1)
00212       c |= 0x1;
00213     SCL_0();
00214   }
00215 
00216   if (send_ack)
00217     SDA_0();
00218   SCL_1();
00219   SCL_WAIT_FOR_1();
00220   SCL_0();
00221 
00222   return c;
00223 }