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