7cc74c2f5be801782331a5692e5a8c0abcd231b9
[goodfet] / firmware / apps / i2c / i2c.c
1 /*! \file i2c.c
2   \author Travis Goodspeed
3   \brief I2C Master  
4 */
5
6
7 //Higher level left to client application.
8
9 //Based upon a neighborly example at
10 //http://codinglab.blogspot.com/2008/10/i2c-on-avr-using-bit-banging.html
11
12 #include "platform.h"
13 #include "command.h"
14 #include "i2c.h"
15
16 #ifndef _GNU_ASSEMBLER_
17 #include <msp430.h>
18 #endif
19
20 //Pins and I/O
21 #include <jtag.h>
22
23 //! Handles an i2c command.
24 void i2c_handle_fn( uint8_t const app,
25                                         uint8_t const verb,
26                                         uint32_t const len);
27
28 // define the i2c app's app_t
29 app_t const i2c_app = {
30
31         /* app number */
32         I2C_APP,
33
34         /* handle fn */
35         i2c_handle_fn,
36
37         /* name */
38         "I2C",
39
40         /* desc */
41         "\tThe I2C app implements the i2c bus protocol thus\n"
42         "\tturning your GoodFET into a USB-to-i2c adapter.\n"
43 };
44
45 #define I2CDELAY(x) delay(x<<4)
46
47
48 //2xx only, need 1xx compat code
49 #define SDA TDI
50 #define SCL TDO
51
52 #define SDAINPUT SPIDIR&=~SDA
53 #define SDAOUTPUT SPIDIR|=SDA
54 #define SCLINPUT SPIDIR&=~SCL
55 #define SCLOUTPUT SPIDIR|=SCL
56
57 #define PULLON SPIREN|=(SDA|SCL)
58 #define PULLOFF SPIREN&=~(SDA|SCL)
59
60 #define CLRSDA SPIOUT&=~SDA
61 #define SETSDA SPIOUT|=SDA
62 #define CLRSCL SPIOUT&=~SCL
63 #define SETSCL SPIOUT|=SCL
64
65 #define READSDA (SPIIN&SDA?1:0)
66 #define SETBOTH SPIOUT|=(SDA|SCL)
67
68 #define I2C_DATA_HI() SETSDA
69 #define I2C_DATA_LO() CLRSDA
70
71 #define I2C_CLOCK_HI() SETSCL
72 #define I2C_CLOCK_LO() CLRSCL
73
74 //#warning "Using internal resistors.  Won't work on 161x devices."
75
76 //! Inits bitbanging port, must be called before using the functions below
77 void I2C_Init()
78 {
79   
80   //Clear SDA and SCL.
81   //Direction, not value, is used to set the value.
82   
83   SCLOUTPUT;
84   SDAOUTPUT;
85   
86   I2C_CLOCK_HI();
87   I2C_DATA_HI();
88   //PULLON;
89
90   I2CDELAY(1);
91 }
92
93 // This is never called...
94 void I2C_Exit()
95 {
96   SDAINPUT;
97   SCLINPUT;
98   PULLOFF;
99 }
100
101 //! Write an I2C bit.
102 void I2C_WriteBit( unsigned char c )
103 {
104   if(c>0)
105     I2C_DATA_HI();
106   else
107     I2C_DATA_LO();
108
109   I2C_CLOCK_HI();
110   I2CDELAY(1);
111
112   I2C_CLOCK_LO();
113   I2CDELAY(1);
114
115   /*if(c>0)
116    *I2C_DATA_LO();
117    *
118    *I2CDELAY(1);
119    */
120 }
121
122 //! Read an I2C bit.
123 unsigned char I2C_ReadBit()
124 {
125   SDAINPUT;
126   I2C_CLOCK_HI();
127   
128   unsigned char c = READSDA;
129   if(c)
130     I2C_DATA_HI();
131   else
132     I2C_DATA_LO();
133
134   SDAOUTPUT;
135   I2CDELAY(1);
136   I2C_CLOCK_LO();
137   I2CDELAY(1);
138
139   return c;
140 }
141
142 unsigned char I2C_ReadBit_Wait()
143 {
144   SDAINPUT;
145   I2C_CLOCK_HI();
146   
147   unsigned int i = 0;
148   unsigned char c = READSDA;
149
150   while(c>0 && i<=35)
151   {
152     I2CDELAY(1);
153     c = READSDA;
154     i++;
155   }
156
157   if(c)
158     I2C_DATA_HI();
159   else
160     I2C_DATA_LO();
161
162   SDAOUTPUT;
163   I2CDELAY(1);
164   I2C_CLOCK_LO();
165   I2CDELAY(1);
166
167   return c?0:1; // return true on ACK (0)
168 }
169
170 //! Send a START Condition
171 void I2C_Start()
172 {
173   // set both to high at the same time
174   SETBOTH;
175   I2CDELAY(3);
176   
177   I2C_DATA_LO();
178   I2CDELAY(3);
179   
180   I2C_CLOCK_LO();
181   I2CDELAY(1);
182 }
183
184 //! Send a STOP Condition
185 void I2C_Stop()
186 {
187   I2C_DATA_LO();
188   I2CDELAY(3);
189
190   I2C_CLOCK_HI();
191   I2CDELAY(3);
192
193   I2C_DATA_HI();
194   I2CDELAY(1);
195 }
196
197 //! write a byte to the I2C slave device
198 unsigned char I2C_Write( unsigned char c )
199 {
200   char i;
201   for (i=0;i<8;i++){
202     I2C_WriteBit( c & 0x80 );
203     c<<=1;
204   }
205   
206   return I2C_ReadBit_Wait();
207 }
208
209
210 //! read a byte from the I2C slave device
211 unsigned char I2C_Read( unsigned char ack )
212 {
213   unsigned char res = 0;
214   char i;
215   
216   for (i=0;i<8;i++){
217     res <<= 1;
218     res |= I2C_ReadBit();  
219   }
220   
221   if( ack > 0)
222     I2C_WriteBit(0);
223   else
224     I2C_WriteBit(1);
225   
226   I2CDELAY(1);
227   
228   return res;
229 }
230
231 //! Handles an i2c command.
232 void i2c_handle_fn( uint8_t const app,
233                                         uint8_t const verb,
234                                         uint32_t const len)
235 {
236         unsigned char i;
237         unsigned long l;
238         switch(verb)
239         {
240         case READ:
241                 l = len;
242                 if(l > 0)                                       //optional parameter of length
243                         l=cmddata[0];
244                 if(!l)                                          //default value of 1
245                         l=1;
246                 I2C_Start();
247                 for(i=0; i < l; i++)
248                         cmddata[i]=I2C_Read(i<l?1:0);
249                 I2C_Stop();
250                 txdata(app,verb,l);
251                 break;
252         case WRITE:
253                 I2C_Start();
254                 cmddata[0] = cmddata[0] << 1;
255                 for(i=0; i<len; i++) {
256                         if (!I2C_Write(cmddata[i]))             //if NACK
257                                 break;
258                 }
259                 I2C_Stop();
260                 cmddata[0] = i;
261                 txdata(app,verb,1);
262                 break;
263         case PEEK:
264                 l = cmddata[0];
265                 I2C_Start();
266                 unsigned char address = cmddata[1] << 1;
267                 I2C_Write(address);
268                 for(i=2; i < len; i++){
269                         I2C_Write(cmddata[i]);
270                 }
271                 I2C_Start();
272                 I2C_Write(address|1);                           // spit out the target address again and flip the read bit
273                 I2CDELAY(1);    // XXX We should wait for clock to go high here XXX
274                 for(i=0; i < l; i++)
275                         cmddata[i]=I2C_Read(i+1<l?1:0);         // If the next i is still less than l, then ACK
276                 I2C_Stop();
277                 txdata(app,verb,l);
278                 break;
279         case POKE:
280                 break;
281
282         case START:
283                 I2C_Start();
284                 txdata(app,verb,0);
285                 break;
286         case STOP:
287                 I2C_Stop();
288                 txdata(app,verb,0);
289                 break;
290         case SETUP:
291                 I2C_Init();
292                 txdata(app,verb,0);
293                 break;
294         }
295 }