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