3514 |
miho |
1 |
/* Name: main.c |
|
|
2 |
* Project: i2c-tiny-usb |
|
|
3 |
* Author: Till Harbaum |
|
|
4 |
* Tabsize: 4 |
|
|
5 |
* Copyright: (c) 2005 by Till Harbaum <till@harbaum.org> |
|
|
6 |
* License: GPL |
|
|
7 |
* This Revision: $Id: main.c,v 1.9 2007/06/07 13:53:47 harbaum Exp $ |
|
|
8 |
* |
|
|
9 |
* $Log: main.c,v $ |
|
|
10 |
* Revision 1.9 2007/06/07 13:53:47 harbaum |
|
|
11 |
* Version number fixes |
|
|
12 |
* |
|
|
13 |
* Revision 1.8 2007/05/19 12:30:11 harbaum |
|
|
14 |
* Updated USB stacks |
|
|
15 |
* |
|
|
16 |
* Revision 1.7 2007/04/22 10:34:05 harbaum |
|
|
17 |
* *** empty log message *** |
|
|
18 |
* |
|
|
19 |
* Revision 1.6 2007/01/05 19:30:58 harbaum |
|
|
20 |
* i2c clock bug fix |
|
|
21 |
* |
|
|
22 |
* Revision 1.5 2007/01/03 18:35:07 harbaum |
|
|
23 |
* usbtiny fixes and pcb layouts |
|
|
24 |
* |
|
|
25 |
* Revision 1.4 2006/12/03 21:28:59 harbaum |
|
|
26 |
* *** empty log message *** |
|
|
27 |
* |
|
|
28 |
* Revision 1.3 2006/11/22 19:12:45 harbaum |
|
|
29 |
* Added usbtiny support |
|
|
30 |
* |
|
|
31 |
* Revision 1.2 2006/11/14 19:15:13 harbaum |
|
|
32 |
* *** empty log message *** |
|
|
33 |
* |
|
|
34 |
*/ |
|
|
35 |
|
|
|
36 |
#include <stdio.h> |
|
|
37 |
#include <ctype.h> |
|
|
38 |
#include <string.h> |
|
|
39 |
|
|
|
40 |
#include <avr/io.h> |
|
|
41 |
#include <avr/interrupt.h> |
|
|
42 |
#include <avr/pgmspace.h> |
|
|
43 |
#include <avr/wdt.h> |
|
|
44 |
|
|
|
45 |
#include <util/delay.h> |
|
|
46 |
|
3516 |
miho |
47 |
#include "config.h" |
|
|
48 |
|
|
|
49 |
// Include USB library (AVRUSB or USBTINY) |
|
|
50 |
// ------------------- |
|
|
51 |
|
3514 |
miho |
52 |
#ifndef USBTINY |
3516 |
miho |
53 |
// use avrusb library |
|
|
54 |
#include "usbdrv.h" |
|
|
55 |
#include "oddebug.h" |
3514 |
miho |
56 |
#else |
3516 |
miho |
57 |
// use usbtiny library |
|
|
58 |
#include "usb.h" |
|
|
59 |
#include "usbtiny.h" |
|
|
60 |
typedef byte_t uchar; |
|
|
61 |
#define usbInit() usb_init() |
|
|
62 |
#define usbPoll() usb_poll() |
3514 |
miho |
63 |
#endif |
|
|
64 |
|
|
|
65 |
/* commands from USB, must e.g. match command ids in kernel driver */ |
|
|
66 |
#define CMD_ECHO 0 |
|
|
67 |
#define CMD_GET_FUNC 1 |
|
|
68 |
#define CMD_SET_DELAY 2 |
|
|
69 |
#define CMD_GET_STATUS 3 |
|
|
70 |
|
|
|
71 |
#define CMD_I2C_IO 4 |
|
|
72 |
#define CMD_I2C_BEGIN 1 // flag fo I2C_IO |
|
|
73 |
#define CMD_I2C_END 2 // flag fo I2C_IO |
|
|
74 |
|
|
|
75 |
/* linux kernel flags */ |
|
|
76 |
#define I2C_M_TEN 0x10 /* we have a ten bit chip address */ |
|
|
77 |
#define I2C_M_RD 0x01 |
|
|
78 |
#define I2C_M_NOSTART 0x4000 |
|
|
79 |
#define I2C_M_REV_DIR_ADDR 0x2000 |
|
|
80 |
#define I2C_M_IGNORE_NAK 0x1000 |
|
|
81 |
#define I2C_M_NO_RD_ACK 0x0800 |
|
|
82 |
|
|
|
83 |
/* To determine what functionality is present */ |
|
|
84 |
#define I2C_FUNC_I2C 0x00000001 |
|
|
85 |
#define I2C_FUNC_10BIT_ADDR 0x00000002 |
|
|
86 |
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */ |
|
|
87 |
#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */ |
|
|
88 |
#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */ |
|
|
89 |
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */ |
|
|
90 |
#define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */ |
|
|
91 |
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */ |
|
|
92 |
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ |
|
|
93 |
#define I2C_FUNC_SMBUS_QUICK 0x00010000 |
|
|
94 |
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 |
|
|
95 |
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 |
|
|
96 |
#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 |
|
|
97 |
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 |
|
|
98 |
#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 |
|
|
99 |
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 |
|
|
100 |
#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 |
|
|
101 |
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 |
|
|
102 |
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 |
|
|
103 |
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ |
|
|
104 |
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ |
|
|
105 |
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */ |
|
|
106 |
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */ |
|
|
107 |
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */ |
|
|
108 |
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */ |
|
|
109 |
|
|
|
110 |
#define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \ |
|
|
111 |
I2C_FUNC_SMBUS_WRITE_BYTE |
|
|
112 |
#define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \ |
|
|
113 |
I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
|
|
114 |
#define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \ |
|
|
115 |
I2C_FUNC_SMBUS_WRITE_WORD_DATA |
|
|
116 |
#define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ |
|
|
117 |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA |
|
|
118 |
#define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ |
|
|
119 |
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
|
|
120 |
|
|
|
121 |
#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \ |
|
|
122 |
I2C_FUNC_SMBUS_BYTE | \ |
|
|
123 |
I2C_FUNC_SMBUS_BYTE_DATA | \ |
|
|
124 |
I2C_FUNC_SMBUS_WORD_DATA | \ |
|
|
125 |
I2C_FUNC_SMBUS_PROC_CALL | \ |
|
|
126 |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ |
|
|
127 |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \ |
|
|
128 |
I2C_FUNC_SMBUS_I2C_BLOCK |
|
|
129 |
|
|
|
130 |
/* the currently support capability is quite limited */ |
|
|
131 |
const unsigned long func PROGMEM = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
|
|
132 |
|
|
|
133 |
#ifdef DEBUG |
|
|
134 |
#define DEBUGF(format, args...) printf_P(PSTR(format), ##args) |
|
|
135 |
|
|
|
136 |
/* ------------------------------------------------------------------------- */ |
|
|
137 |
static int uart_putchar(char c, FILE *stream) { |
|
|
138 |
if (c == '\n') |
|
|
139 |
uart_putchar('\r', stream); |
|
|
140 |
loop_until_bit_is_set(UCSRA, UDRE); |
|
|
141 |
UDR = c; |
|
|
142 |
return 0; |
|
|
143 |
} |
|
|
144 |
|
|
|
145 |
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, |
|
|
146 |
_FDEV_SETUP_WRITE); |
|
|
147 |
#else |
|
|
148 |
#define DEBUGF(format, args...) |
|
|
149 |
#endif |
|
|
150 |
|
|
|
151 |
/* ------------------------------------------------------------------------- */ |
|
|
152 |
#define DEFAULT_DELAY 10 // default 10us (100khz) |
|
|
153 |
static unsigned short clock_delay = DEFAULT_DELAY; |
|
|
154 |
static unsigned short clock_delay2 = DEFAULT_DELAY/2; |
|
|
155 |
|
|
|
156 |
static unsigned short expected; |
|
|
157 |
static unsigned char saved_cmd; |
|
|
158 |
|
|
|
159 |
#if! defined (__AVR_ATtiny45__) |
|
|
160 |
#define I2C_PORT PORTC |
|
|
161 |
#define I2C_PIN PINC |
|
|
162 |
#define I2C_DDR DDRC |
|
|
163 |
#define I2C_SDA _BV(4) |
|
|
164 |
#define I2C_SCL _BV(5) |
|
|
165 |
#else |
|
|
166 |
#define I2C_PORT PORTB |
|
|
167 |
#define I2C_PIN PINB |
|
|
168 |
#define I2C_DDR DDRB |
|
|
169 |
#define I2C_SDA _BV(1) |
|
|
170 |
#define I2C_SCL _BV(5) |
|
|
171 |
#endif |
|
|
172 |
|
|
|
173 |
static void i2c_io_set_sda(uchar hi) { |
|
|
174 |
if(hi) { |
|
|
175 |
I2C_DDR &= ~I2C_SDA; // high -> input |
|
|
176 |
I2C_PORT |= I2C_SDA; // with pullup |
|
|
177 |
} else { |
|
|
178 |
I2C_DDR |= I2C_SDA; // low -> output |
|
|
179 |
I2C_PORT &= ~I2C_SDA; // drive low |
|
|
180 |
} |
|
|
181 |
} |
|
|
182 |
|
|
|
183 |
static uchar i2c_io_get_sda(void) { |
|
|
184 |
return(I2C_PIN & I2C_SDA); |
|
|
185 |
} |
|
|
186 |
|
|
|
187 |
static void i2c_io_set_scl(uchar hi) { |
|
|
188 |
#ifdef ENABLE_SCL_EXPAND |
|
|
189 |
_delay_loop_2(clock_delay2); |
|
|
190 |
if(hi) { |
|
|
191 |
I2C_DDR &= ~I2C_SCL; // port is input |
|
|
192 |
I2C_PORT |= I2C_SCL; // enable pullup |
|
|
193 |
|
|
|
194 |
// wait while pin is pulled low by client |
|
|
195 |
while(!(I2C_PIN & I2C_SCL)); |
|
|
196 |
} else { |
|
|
197 |
I2C_DDR |= I2C_SCL; // port is output |
|
|
198 |
I2C_PORT &= ~I2C_SCL; // drive it low |
|
|
199 |
} |
|
|
200 |
_delay_loop_2(clock_delay); |
|
|
201 |
#else |
|
|
202 |
_delay_loop_2(clock_delay2); |
|
|
203 |
if(hi) I2C_PORT |= I2C_SCL; // port is high |
|
|
204 |
else I2C_PORT &= ~I2C_SCL; // port is low |
|
|
205 |
_delay_loop_2(clock_delay); |
|
|
206 |
#endif |
|
|
207 |
} |
|
|
208 |
|
|
|
209 |
static void i2c_init(void) { |
|
|
210 |
/* init the sda/scl pins */ |
|
|
211 |
I2C_DDR &= ~I2C_SDA; // port is input |
|
|
212 |
I2C_PORT |= I2C_SDA; // enable pullup |
|
|
213 |
#ifdef ENABLE_SCL_EXPAND |
|
|
214 |
I2C_DDR &= ~I2C_SCL; // port is input |
|
|
215 |
I2C_PORT |= I2C_SCL; // enable pullup |
|
|
216 |
#else |
|
|
217 |
I2C_DDR |= I2C_SCL; // port is output |
|
|
218 |
#endif |
|
|
219 |
|
|
|
220 |
/* no bytes to be expected */ |
|
|
221 |
expected = 0; |
|
|
222 |
} |
|
|
223 |
|
|
|
224 |
/* clock HI, delay, then LO */ |
|
|
225 |
static void i2c_scl_toggle(void) { |
|
|
226 |
i2c_io_set_scl(1); |
|
|
227 |
i2c_io_set_scl(0); |
|
|
228 |
} |
|
|
229 |
|
|
|
230 |
/* i2c start condition */ |
|
|
231 |
static void i2c_start(void) { |
|
|
232 |
i2c_io_set_sda(0); |
|
|
233 |
i2c_io_set_scl(0); |
|
|
234 |
} |
|
|
235 |
|
|
|
236 |
/* i2c repeated start condition */ |
|
|
237 |
static void i2c_repstart(void) |
|
|
238 |
{ |
|
|
239 |
/* scl, sda may not be high */ |
|
|
240 |
i2c_io_set_sda(1); |
|
|
241 |
i2c_io_set_scl(1); |
|
|
242 |
|
|
|
243 |
i2c_io_set_sda(0); |
|
|
244 |
i2c_io_set_scl(0); |
|
|
245 |
} |
|
|
246 |
|
|
|
247 |
/* i2c stop condition */ |
|
|
248 |
void i2c_stop(void) { |
|
|
249 |
i2c_io_set_sda(0); |
|
|
250 |
i2c_io_set_scl(1); |
|
|
251 |
i2c_io_set_sda(1); |
|
|
252 |
} |
|
|
253 |
|
|
|
254 |
uchar i2c_put_u08(uchar b) { |
|
|
255 |
char i; |
|
|
256 |
|
|
|
257 |
for (i=7;i>=0;i--) { |
|
|
258 |
if ( b & (1<<i) ) i2c_io_set_sda(1); |
|
|
259 |
else i2c_io_set_sda(0); |
|
|
260 |
|
|
|
261 |
i2c_scl_toggle(); // clock HI, delay, then LO |
|
|
262 |
} |
|
|
263 |
|
|
|
264 |
i2c_io_set_sda(1); // leave SDL HI |
|
|
265 |
i2c_io_set_scl(1); // clock back up |
|
|
266 |
|
|
|
267 |
b = i2c_io_get_sda(); // get the ACK bit |
|
|
268 |
i2c_io_set_scl(0); // not really ?? |
|
|
269 |
|
|
|
270 |
return(b == 0); // return ACK value |
|
|
271 |
} |
|
|
272 |
|
|
|
273 |
uchar i2c_get_u08(uchar last) { |
|
|
274 |
char i; |
|
|
275 |
uchar c,b = 0; |
|
|
276 |
|
|
|
277 |
i2c_io_set_sda(1); // make sure pullups are activated |
|
|
278 |
i2c_io_set_scl(0); // clock LOW |
|
|
279 |
|
|
|
280 |
for(i=7;i>=0;i--) { |
|
|
281 |
i2c_io_set_scl(1); // clock HI |
|
|
282 |
c = i2c_io_get_sda(); |
|
|
283 |
b <<= 1; |
|
|
284 |
if(c) b |= 1; |
|
|
285 |
i2c_io_set_scl(0); // clock LO |
|
|
286 |
} |
|
|
287 |
|
|
|
288 |
if(last) i2c_io_set_sda(1); // set NAK |
|
|
289 |
else i2c_io_set_sda(0); // set ACK |
|
|
290 |
|
|
|
291 |
i2c_scl_toggle(); // clock pulse |
|
|
292 |
i2c_io_set_sda(1); // leave with SDL HI |
|
|
293 |
|
|
|
294 |
return b; // return received byte |
|
|
295 |
} |
|
|
296 |
|
|
|
297 |
#ifdef DEBUG |
|
|
298 |
void i2c_scan(void) { |
|
|
299 |
uchar i = 0; |
|
|
300 |
|
|
|
301 |
for(i=0;i<127;i++) { |
|
|
302 |
i2c_start(); // do start transition |
|
|
303 |
if(i2c_put_u08(i << 1)) // send DEVICE address |
|
|
304 |
DEBUGF("I2C device at address 0x%x\n", i); |
|
|
305 |
|
|
|
306 |
i2c_stop(); |
|
|
307 |
} |
|
|
308 |
} |
|
|
309 |
#endif |
|
|
310 |
|
|
|
311 |
/* ------------------------------------------------------------------------- */ |
|
|
312 |
|
|
|
313 |
struct i2c_cmd { |
|
|
314 |
unsigned char type; |
|
|
315 |
unsigned char cmd; |
|
|
316 |
unsigned short flags; |
|
|
317 |
unsigned short addr; |
|
|
318 |
unsigned short len; |
|
|
319 |
}; |
|
|
320 |
|
|
|
321 |
#define STATUS_IDLE 0 |
|
|
322 |
#define STATUS_ADDRESS_ACK 1 |
|
|
323 |
#define STATUS_ADDRESS_NAK 2 |
|
|
324 |
|
|
|
325 |
static uchar status = STATUS_IDLE; |
|
|
326 |
|
|
|
327 |
static uchar i2c_do(struct i2c_cmd *cmd) { |
|
|
328 |
uchar addr; |
|
|
329 |
|
|
|
330 |
DEBUGF("i2c %s at 0x%02x, len = %d\n", |
|
|
331 |
(cmd->flags&I2C_M_RD)?"rd":"wr", cmd->addr, cmd->len); |
|
|
332 |
|
|
|
333 |
/* normal 7bit address */ |
|
|
334 |
addr = ( cmd->addr << 1 ); |
|
|
335 |
if (cmd->flags & I2C_M_RD ) |
|
|
336 |
addr |= 1; |
|
|
337 |
|
|
|
338 |
if(cmd->cmd & CMD_I2C_BEGIN) |
|
|
339 |
i2c_start(); |
|
|
340 |
else |
|
|
341 |
i2c_repstart(); |
|
|
342 |
|
|
|
343 |
// send DEVICE address |
|
|
344 |
if(!i2c_put_u08(addr)) { |
|
|
345 |
DEBUGF("I2C read: address error @ %x\n", addr); |
|
|
346 |
|
|
|
347 |
status = STATUS_ADDRESS_NAK; |
|
|
348 |
expected = 0; |
|
|
349 |
i2c_stop(); |
|
|
350 |
} else { |
|
|
351 |
status = STATUS_ADDRESS_ACK; |
|
|
352 |
expected = cmd->len; |
|
|
353 |
saved_cmd = cmd->cmd; |
|
|
354 |
|
|
|
355 |
/* check if transfer is already done (or failed) */ |
|
|
356 |
if((cmd->cmd & CMD_I2C_END) && !expected) |
|
|
357 |
i2c_stop(); |
|
|
358 |
} |
|
|
359 |
|
|
|
360 |
/* more data to be expected? */ |
|
|
361 |
#ifndef USBTINY |
|
|
362 |
return(cmd->len?0xff:0x00); |
|
|
363 |
#else |
|
|
364 |
return(((cmd->flags & I2C_M_RD) && cmd->len)?0xff:0x00); |
|
|
365 |
#endif |
|
|
366 |
} |
|
|
367 |
|
|
|
368 |
#ifndef USBTINY |
|
|
369 |
uchar usbFunctionSetup(uchar data[8]) { |
|
|
370 |
static uchar replyBuf[4]; |
|
|
371 |
usbMsgPtr = replyBuf; |
|
|
372 |
#else |
|
|
373 |
extern byte_t usb_setup ( byte_t data[8] ) |
|
|
374 |
{ |
|
|
375 |
byte_t *replyBuf = data; |
|
|
376 |
#endif |
|
|
377 |
|
|
|
378 |
DEBUGF("Setup %x %x %x %x\n", data[0], data[1], data[2], data[3]); |
|
|
379 |
|
|
|
380 |
switch(data[1]) { |
|
|
381 |
|
|
|
382 |
case CMD_ECHO: // echo (for transfer reliability testing) |
|
|
383 |
replyBuf[0] = data[2]; |
|
|
384 |
replyBuf[1] = data[3]; |
|
|
385 |
return 2; |
|
|
386 |
break; |
|
|
387 |
|
|
|
388 |
case CMD_GET_FUNC: |
|
|
389 |
memcpy_P(replyBuf, &func, sizeof(func)); |
|
|
390 |
return sizeof(func); |
|
|
391 |
break; |
|
|
392 |
|
|
|
393 |
case CMD_SET_DELAY: |
|
|
394 |
/* The delay function used delays 4 system ticks per cycle. */ |
|
|
395 |
/* This gives 1/3us at 12Mhz per cycle. The delay function is */ |
|
|
396 |
/* called twice per clock edge and thus four times per full cycle. */ |
|
|
397 |
/* Thus it is called one time per edge with the full delay */ |
|
|
398 |
/* value and one time with the half one. Resulting in */ |
|
|
399 |
/* 2 * n * 1/3 + 2 * 1/2 n * 1/3 = n us. */ |
|
|
400 |
clock_delay = *(unsigned short*)(data+2); |
|
|
401 |
if(!clock_delay) clock_delay = 1; |
|
|
402 |
clock_delay2 = clock_delay/2; |
|
|
403 |
if(!clock_delay2) clock_delay2 = 1; |
|
|
404 |
|
|
|
405 |
DEBUGF("request for delay %dus\n", clock_delay); |
|
|
406 |
break; |
|
|
407 |
|
|
|
408 |
case CMD_I2C_IO: |
|
|
409 |
case CMD_I2C_IO + CMD_I2C_BEGIN: |
|
|
410 |
case CMD_I2C_IO + CMD_I2C_END: |
|
|
411 |
case CMD_I2C_IO + CMD_I2C_BEGIN + CMD_I2C_END: |
|
|
412 |
// these are only allowed as class transfers |
|
|
413 |
|
|
|
414 |
return i2c_do((struct i2c_cmd*)data); |
|
|
415 |
break; |
|
|
416 |
|
|
|
417 |
case CMD_GET_STATUS: |
|
|
418 |
replyBuf[0] = status; |
|
|
419 |
return 1; |
|
|
420 |
break; |
|
|
421 |
|
|
|
422 |
default: |
|
|
423 |
// must not happen ... |
|
|
424 |
break; |
|
|
425 |
} |
|
|
426 |
|
|
|
427 |
return 0; // reply len |
|
|
428 |
} |
|
|
429 |
|
|
|
430 |
|
|
|
431 |
/*---------------------------------------------------------------------------*/ |
|
|
432 |
/* usbFunctionRead */ |
|
|
433 |
/*---------------------------------------------------------------------------*/ |
|
|
434 |
|
|
|
435 |
#ifndef USBTINY |
|
|
436 |
uchar usbFunctionRead( uchar *data, uchar len ) |
|
|
437 |
#else |
|
|
438 |
extern byte_t usb_in ( byte_t* data, byte_t len ) |
|
|
439 |
#endif |
|
|
440 |
{ |
|
|
441 |
uchar i; |
|
|
442 |
|
|
|
443 |
DEBUGF("read %d bytes, %d exp\n", len, expected); |
|
|
444 |
|
|
|
445 |
if(status == STATUS_ADDRESS_ACK) { |
|
|
446 |
if(len > expected) { |
|
|
447 |
DEBUGF("exceeds!\n"); |
|
|
448 |
len = expected; |
|
|
449 |
} |
|
|
450 |
|
|
|
451 |
// consume bytes |
|
|
452 |
for(i=0;i<len;i++) { |
|
|
453 |
expected--; |
|
|
454 |
*data = i2c_get_u08(expected == 0); |
|
|
455 |
DEBUGF("data = %x\n", *data); |
|
|
456 |
data++; |
|
|
457 |
} |
|
|
458 |
|
|
|
459 |
// end transfer on last byte |
|
|
460 |
if((saved_cmd & CMD_I2C_END) && !expected) |
|
|
461 |
i2c_stop(); |
|
|
462 |
|
|
|
463 |
} else { |
|
|
464 |
DEBUGF("not in ack state\n"); |
|
|
465 |
memset(data, 0, len); |
|
|
466 |
} |
|
|
467 |
return len; |
|
|
468 |
} |
|
|
469 |
|
|
|
470 |
/*---------------------------------------------------------------------------*/ |
|
|
471 |
/* usbFunctionWrite */ |
|
|
472 |
/*---------------------------------------------------------------------------*/ |
|
|
473 |
|
|
|
474 |
#ifndef USBTINY |
|
|
475 |
uchar usbFunctionWrite( uchar *data, uchar len ) |
|
|
476 |
#else |
|
|
477 |
extern void usb_out ( byte_t* data, byte_t len ) |
|
|
478 |
#endif |
|
|
479 |
{ |
|
|
480 |
uchar i, err=0; |
|
|
481 |
|
|
|
482 |
DEBUGF("write %d bytes, %d exp\n", len, expected); |
|
|
483 |
|
|
|
484 |
if(status == STATUS_ADDRESS_ACK) { |
|
|
485 |
if(len > expected) { |
|
|
486 |
DEBUGF("exceeds!\n"); |
|
|
487 |
len = expected; |
|
|
488 |
} |
|
|
489 |
|
|
|
490 |
// consume bytes |
|
|
491 |
for(i=0;i<len;i++) { |
|
|
492 |
expected--; |
|
|
493 |
DEBUGF("data = %x\n", *data); |
|
|
494 |
if(!i2c_put_u08(*data++)) |
|
|
495 |
err = 1; |
|
|
496 |
} |
|
|
497 |
|
|
|
498 |
// end transfer on last byte |
|
|
499 |
if((saved_cmd & CMD_I2C_END) && !expected) |
|
|
500 |
i2c_stop(); |
|
|
501 |
|
|
|
502 |
if(err) { |
|
|
503 |
DEBUGF("write failed\n"); |
|
|
504 |
//TODO: set status |
|
|
505 |
} |
|
|
506 |
|
|
|
507 |
} else { |
|
|
508 |
DEBUGF("not in ack state\n"); |
|
|
509 |
memset(data, 0, len); |
|
|
510 |
} |
|
|
511 |
|
|
|
512 |
#ifndef USBTINY |
|
|
513 |
return len; |
|
|
514 |
#endif |
|
|
515 |
} |
|
|
516 |
|
|
|
517 |
|
|
|
518 |
/* ------------------------------------------------------------------------- */ |
|
|
519 |
|
|
|
520 |
int main(void) { |
|
|
521 |
wdt_enable(WDTO_1S); |
|
|
522 |
|
|
|
523 |
#if DEBUG_LEVEL > 0 |
|
|
524 |
/* let debug routines init the uart if they want to */ |
|
|
525 |
odDebugInit(); |
|
|
526 |
#else |
|
|
527 |
#ifdef DEBUG |
|
|
528 |
/* quick'n dirty uart init */ |
|
|
529 |
UCSRB |= _BV(TXEN); |
|
|
530 |
UBRRL = F_CPU / (19200 * 16L) - 1; |
|
|
531 |
#endif |
|
|
532 |
#endif |
|
|
533 |
|
|
|
534 |
#ifdef DEBUG |
|
|
535 |
stdout = &mystdout; |
|
|
536 |
#endif |
|
|
537 |
|
|
|
538 |
DEBUGF("i2c-tiny-usb - (c) 2006 by Till Harbaum\n"); |
|
|
539 |
|
|
|
540 |
i2c_init(); |
|
|
541 |
|
|
|
542 |
#ifdef DEBUG |
|
|
543 |
i2c_scan(); |
|
|
544 |
#endif |
|
|
545 |
|
|
|
546 |
/* clear usb ports */ |
3516 |
miho |
547 |
PORT(CONFIG_USB_PORT) &= (uchar)~((1<<CONFIG_USB_DMINUS)|(1<<CONFIG_USB_DPLUS)); |
3514 |
miho |
548 |
|
|
|
549 |
/* make usb data lines outputs */ |
3516 |
miho |
550 |
DDR(CONFIG_USB_PORT) |= ((1<<CONFIG_USB_DMINUS)|(1<<CONFIG_USB_DPLUS)); |
3514 |
miho |
551 |
|
|
|
552 |
/* USB Reset by device only required on Watchdog Reset */ |
|
|
553 |
_delay_loop_2(40000); // 10ms |
|
|
554 |
|
|
|
555 |
/* make usb data lines inputs */ |
3516 |
miho |
556 |
DDR(CONFIG_USB_PORT) &= ~((1<<CONFIG_USB_DMINUS)|(1<<CONFIG_USB_DPLUS)); |
3514 |
miho |
557 |
|
|
|
558 |
usbInit(); |
|
|
559 |
|
|
|
560 |
sei(); |
|
|
561 |
for(;;) { /* main event loop */ |
|
|
562 |
wdt_reset(); |
|
|
563 |
usbPoll(); |
|
|
564 |
} |
|
|
565 |
|
|
|
566 |
return 0; |
|
|
567 |
} |
|
|
568 |
|
|
|
569 |
/* ------------------------------------------------------------------------- */ |