GoodFET firmware on the Telos B reveals the Flash chip.
[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 #include <signal.h>
17 #include <io.h>
18 #include <iomacros.h>
19
20
21 //Pins and I/O
22 #include <jtag.h>
23
24 //! Handles an i2c command.
25 void i2c_handle_fn( uint8_t const app,
26                                         uint8_t const verb,
27                                         uint32_t const len);
28
29 // define the i2c app's app_t
30 app_t const i2c_app = {
31
32         /* app number */
33         I2C,
34
35         /* handle fn */
36         i2c_handle_fn,
37
38         /* name */
39         "I2C",
40
41         /* desc */
42         "\tThe I2C app implements the i2c bus protocol thus\n"
43         "\tturning your GoodFET into a USB-to-i2c adapter.\n"
44 };
45
46 #define SDA TDI
47 #define SCL TDO
48
49 #define I2CDELAY(x) delay(x<<4)
50
51
52 //2xx only, need 1xx compat code
53 #define CLRSDA P5OUT&=~SDA
54 #define SETSDA P5OUT|=SDA
55 #define CLRSCL P5OUT&=~SCL
56 #define SETSCL P5OUT|=SCL
57
58 #define READSDA (P5IN&SDA?1:0)
59 #define SETBOTH P5OUT|=(SDA|SCL)
60
61 #define I2C_DATA_HI() SETSDA
62 #define I2C_DATA_LO() CLRSDA
63
64 #define I2C_CLOCK_HI() SETSCL
65 #define I2C_CLOCK_LO() CLRSCL
66
67 //#warning "Using internal resistors.  Won't work on 161x devices."
68
69 //! Inits bitbanging port, must be called before using the functions below
70 void I2C_Init()
71 {
72   
73   //Clear SDA and SCL.
74   //Direction, not value, is used to set the value.
75   //(Pull-up or 0.)
76   
77   P5DIR|=(SDA|SCL);
78   //P5REN|=SDA|SCL;
79   
80   
81   I2C_CLOCK_HI();
82   I2C_DATA_HI();
83
84   I2CDELAY(1);
85 }
86
87 //! Write an I2C bit.
88 void I2C_WriteBit( unsigned char c )
89 {
90   if(c>0)
91     I2C_DATA_HI();
92   else
93     I2C_DATA_LO();
94
95   I2C_CLOCK_HI();
96   I2CDELAY(1);
97
98   I2C_CLOCK_LO();
99   I2CDELAY(1);
100
101   if(c>0)
102     I2C_DATA_LO();
103
104   I2CDELAY(1);
105 }
106
107 //! Read an I2C bit.
108 unsigned char I2C_ReadBit()
109 {
110   I2C_DATA_HI();
111
112   I2C_CLOCK_HI();
113   I2CDELAY(1);
114   
115   unsigned char c = READSDA;
116
117   I2C_CLOCK_LO();
118   I2CDELAY(1);
119
120   return c;
121 }
122
123
124 //! Send a START Condition
125 void I2C_Start()
126 {
127   // set both to high at the same time
128   SETBOTH;
129   I2CDELAY(1);
130   
131   I2C_DATA_LO();
132   I2CDELAY(1);
133   
134   I2C_CLOCK_LO();
135   I2CDELAY(1);
136 }
137
138 //! Send a STOP Condition
139 void I2C_Stop()
140 {
141   I2C_CLOCK_HI();
142   I2CDELAY(1);
143
144   I2C_DATA_HI();
145   I2CDELAY(1);
146 }
147
148 //! write a byte to the I2C slave device
149 unsigned char I2C_Write( unsigned char c )
150 {
151   char i;
152   for (i=0;i<8;i++){
153     I2C_WriteBit( c & 0x80 );
154     c<<=1;
155   }
156   
157   return I2C_ReadBit();
158 }
159
160
161 //! read a byte from the I2C slave device
162 unsigned char I2C_Read( unsigned char ack )
163 {
164   unsigned char res = 0;
165   char i;
166   
167   for (i=0;i<8;i++){
168     res <<= 1;
169     res |= I2C_ReadBit();  
170   }
171   
172   if( ack > 0)
173     I2C_WriteBit(0);
174   else
175     I2C_WriteBit(1);
176   
177   I2CDELAY(1);
178   
179   return res;
180 }
181
182
183 //! Handles an i2c command.
184 void i2c_handle_fn( uint8_t const app,
185                                         uint8_t const verb,
186                                         uint32_t const len)
187 {
188         unsigned char i;
189         unsigned long l;
190         switch(verb)
191         {
192
193         case PEEK:
194                 break;
195         case POKE:
196                 break;
197
198         case READ:
199                 l = len;
200                 if(l > 0)                                       //optional parameter of length
201                         l=cmddata[0];
202                 if(!l)                                          //default value of 1
203                         l=1;
204                 for(i = 0; i < l; i++)
205                         cmddata[i]=I2C_Read(1); //Always acknowledge
206                 txdata(app,verb,l);
207                 break;
208         case WRITE:
209                 cmddata[0]=0;
210                 for(i=0;i<len;i++)
211                         cmddata[0]+=I2C_Write(cmddata[i]);
212                 txdata(app,verb,1);
213                 break;
214         case START:
215                 I2C_Start();
216                 txdata(app,verb,0);
217                 break;
218         case STOP:
219                 I2C_Stop();
220                 txdata(app,verb,0);
221                 break;
222         case SETUP:
223                 I2C_Init();
224                 txdata(app,verb,0);
225                 break;
226         }
227 }