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