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