Poking works in MSP430X2.
[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   
50   P5DIR|=(SDA|SCL);
51   P5REN|=SDA|SCL;
52   
53   
54   I2C_CLOCK_HI();
55   I2C_DATA_HI();
56
57   I2CDELAY(1);
58 }
59
60 //! Write an I2C bit.
61 void I2C_WriteBit( unsigned char c )
62 {
63   if(c>0)
64     I2C_DATA_HI();
65   else
66     I2C_DATA_LO();
67
68   I2C_CLOCK_HI();
69   I2CDELAY(1);
70
71   I2C_CLOCK_LO();
72   I2CDELAY(1);
73
74   if(c>0)
75     I2C_DATA_LO();
76
77   I2CDELAY(1);
78 }
79
80 //! Read an I2C bit.
81 unsigned char I2C_ReadBit()
82 {
83   I2C_DATA_HI();
84
85   I2C_CLOCK_HI();
86   I2CDELAY(1);
87   
88   unsigned char c = READSDA;
89
90   I2C_CLOCK_LO();
91   I2CDELAY(1);
92
93   return c;
94 }
95
96
97 //! Send a START Condition
98 void I2C_Start()
99 {
100   // set both to high at the same time
101   SETBOTH;
102   I2CDELAY(1);
103   
104   I2C_DATA_LO();
105   I2CDELAY(1);
106   
107   I2C_CLOCK_LO();
108   I2CDELAY(1);
109 }
110
111 //! Send a STOP Condition
112 void I2C_Stop()
113 {
114   I2C_CLOCK_HI();
115   I2CDELAY(1);
116
117   I2C_DATA_HI();
118   I2CDELAY(1);
119 }
120
121 //! write a byte to the I2C slave device
122 unsigned char I2C_Write( unsigned char c )
123 {
124   char i;
125   for (i=0;i<8;i++){
126     I2C_WriteBit( c & 0x80 );
127     c<<=1;
128   }
129   
130   return I2C_ReadBit();
131 }
132
133
134 //! read a byte from the I2C slave device
135 unsigned char I2C_Read( unsigned char ack )
136 {
137   unsigned char res = 0;
138   char i;
139   
140   for (i=0;i<8;i++){
141     res <<= 1;
142     res |= I2C_ReadBit();  
143   }
144   
145   if( ack > 0)
146     I2C_WriteBit(0);
147   else
148     I2C_WriteBit(1);
149   
150   I2CDELAY(1);
151   
152   return res;
153 }
154
155
156 //! Handles a monitor command.
157 void i2chandle(unsigned char app,
158                unsigned char verb,
159                unsigned char len){
160   unsigned char i;
161   switch(verb){
162     
163   case PEEK:
164     break;
165   case POKE:
166     break;
167     
168   case READ:
169     if(len>0)          //optional parameter of length
170       len=cmddata[0];
171     if(!len)           //default value of 1
172       len=1;
173     for(i=0;i<len;i++)
174       cmddata[i]=I2C_Read(1);  //Always acknowledge
175     txdata(app,verb,len);
176     break;
177   case WRITE:
178     cmddata[0]=0;
179     for(i=0;i<len;i++)
180       cmddata[0]+=I2C_Write(cmddata[i]);
181     txdata(app,verb,1);
182     break;
183   case START:
184     I2C_Start();
185     txdata(app,verb,0);
186     break;
187   case STOP:
188     I2C_Stop();
189     txdata(app,verb,0);
190     break;
191   case SETUP:
192     I2C_Init();
193     txdata(app,verb,0);
194     break;
195   }
196 }