5 #include <avr/interrupt.h>
6 #include <util/delay.h>
15 #define TWINT_BIT (1 << TWINT)
16 #define TWSTA_BIT (1 << TWSTA)
17 #define TWSTO_BIT (1 << TWSTO)
18 #define TWEN_BIT (1 << TWEN)
19 #define TWIE_BIT (1 << TWIE)
21 #define I2C_START() (TWCR = TWINT_BIT | TWSTA_BIT | TWEN_BIT | TWIE_BIT)
22 #define I2C_STOP() (TWCR = TWINT_BIT | TWSTO_BIT | TWEN_BIT | TWIE_BIT)
23 #define I2C_WRITE() (TWCR = TWINT_BIT | TWEN_BIT | TWIE_BIT)
25 unsigned char i2c_addr, i2c_subaddr, i2c_mode;
26 int i2c_seq, i2c_ndata;
27 unsigned char *i2c_data;
31 uint16_t evq[EVQ_SIZE];
32 volatile int evq_wr, evq_rd;
37 evq_wr = (evq_wr + 1) & (EVQ_SIZE - 1); \
38 if(evq_wr == evq_rd) { \
39 evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1); \
43 /* serial input buffer */
44 static char input[64];
45 static unsigned char inp_cidx;
47 static void proc_cmd(char *input);
48 void i2c_write(unsigned char addr, unsigned char subaddr, int ndata, unsigned char *data);
52 /* tri-state everything and disable pullups */
53 DDRB = 1; /* B0: activity LED */
60 TWBR = 10; /* 10 with 1x prescaler should make it about 100khz */
61 TWSR = 0; /* prescaler 1x */
63 TWCR = (1 << TWEN) | (1 << TWIE); /* enable i2c, don't ack, enable intr */
65 TWAMR = 0;//0xff; /* match all addresses to monitor the bus */
72 printf("Starting i2c hack\n");
75 uint16_t val = 0xffff;
81 if(c == '\r' || c == '\n') {
86 } else if(inp_cidx < sizeof input - 1) {
87 input[inp_cidx++] = c;
91 /* read from queue and send over the serial port */
93 if(evq_wr != evq_rd) {
95 evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1);
100 printf("s(%u): %x\n", (unsigned int)(val >> 8), (unsigned int)(val & 0xff));
106 static void proc_cmd(char *input)
108 unsigned char data[8];
110 if(strcmp(input, "rgb") == 0) {
111 printf("OK sending RGB switch command\n");
113 /* i2c addr 8b: jungle
114 * subaddr 2b: Control 1 reg
118 i2c_write(0x8a, 0x2b, 1, data);
120 } else if(memcmp(input, "vol ", 4) == 0) {
121 int vol = atoi(input + 4);
122 if(vol < 1 || vol > 63) {
123 printf("ERR invalid vol (%s)\n", input + 4);
126 i2c_write(0x8a, 0x1f, 1, data);
127 printf("OK volume: %d\n", vol);
130 } else if(strcmp(input, "zoom") == 0) {
132 i2c_write(0x8a, 0x10, 1, data);
133 printf("OK zoom in\n");
135 } else if(strcmp(input, "unzoom") == 0) {
137 i2c_write(0x8a, 0x10, 1, data);
138 printf("OK unzoom\n");
140 } else if(strcmp(input, "sat") == 0) {
142 i2c_write(0x8a, 0x1c, 1, data);
143 printf("OK saturate\n");
145 } else if(strcmp(input, "abort") == 0) {
146 if(i2c_mode != I2C_IDLE) {
149 printf("OK aborting i2c op\n");
151 printf("ERR i2c is idle\n");
155 printf("ERR invalid command (%s)\n", input);
159 void i2c_write(unsigned char addr, unsigned char subaddr, int ndata, unsigned char *data)
161 printf("i2c: write %x (sub: %x)\n", addr, subaddr);
162 i2c_addr = addr & 0xfe;
163 i2c_subaddr = subaddr;
164 i2c_mode = I2C_MASTER_SEND;
171 void i2c_handle_send(void)
173 unsigned char state = TWSR & 0xf8;
175 //printf("DBG i2c state (%x)\n", (unsigned int)state);
180 /* repeated start, same as start, but also increment i2c_seq */
183 /* start initiated, write the slave address */
184 //printf("DBG i2c SLA: %x\n", (unsigned int)i2c_addr);
190 /* slave addr sent and ACKed, send subaddr or data */
192 /* this is the first packet, send subaddr */
194 LOGNUM(0x100 | i2c_subaddr);
199 LOGNUM(0x200 | *i2c_data);
203 /* done sending, send stop */
211 /* slave addr sent but not ACKed, abort */
214 printf("i2c: NACK after SLA+W\n");
218 /* data (or subaddr) sent and ACKed, send more data (or restart) if available */
221 /* subaddr was sent, send repeated start */
225 /* data was sent, send more data or stop */
227 LOGNUM(0x200 | *i2c_data);
238 /* data (or subaddr) sent but not ACKed */
240 /* NACK after subaddr, abort */
241 printf("i2c: NACK after subaddr\n");
243 /* NACK after data */
245 printf("i2c: NACK with %d data packets pending\n", i2c_ndata);
253 /* arbitration lost */
254 printf("i2c: arbitration lost\n");
259 printf("i2c: invalid start/stop\n");
265 printf("i2c: unexpected state (W): 0x%x\n", state);
271 void i2c_handle_recv(void)
273 printf("i2c: recv unimplemented\n");
281 case I2C_MASTER_SEND:
285 case I2C_MASTER_RECV:
290 /* log traffic on the bus */
291 ev = (uint16_t)(TWSR & 0xf8) << 8;
292 switch(TWSR & 0xf8) {
293 case 0x80: /* own SLA+W received, ack */
294 case 0x88: /* own SLA+W recv, no-ack */
295 case 0x90: /* general recv, ack */
296 case 0x98: /* general recv, no-ack */
303 /* append data to input queue */
308 evq_wr = (evq_wr + 1) & (EVQ_SIZE - 1);
309 if(evq_wr == evq_rd) {
310 evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1);