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