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;
26 volatile unsigned char i2c_mode;
27 int i2c_seq, i2c_ndata;
28 unsigned char *i2c_data;
32 uint16_t evq[EVQ_SIZE];
33 volatile int evq_wr, evq_rd;
38 evq_wr = (evq_wr + 1) & (EVQ_SIZE - 1); \
39 if(evq_wr == evq_rd) { \
40 evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1); \
44 /* serial input buffer */
45 static char input[64];
46 static unsigned char inp_cidx;
48 static unsigned char data[8];
50 static void proc_cmd(char *input);
51 void i2c_write(unsigned char addr, unsigned char subaddr, int ndata, unsigned char *data);
55 /* tri-state everything and disable pullups */
56 DDRB = 1; /* B0: activity LED */
57 DDRC = 0x20; /* SCL output so we can hold the clock low when disabling i2c */
63 TWBR = 10; /* 10 with 1x prescaler should make it about 100khz */
64 TWSR = 0; /* prescaler 1x */
65 TWAR = 0x8a; /* let's monitor for commands going to the jungle */
67 TWCR = (1 << TWEN) | (1 << TWIE); /* enable i2c, don't ack, enable intr */
74 printf("Starting i2c hack\n");
77 //uint16_t val = 0xffff;
83 if(c == '\r' || c == '\n') {
88 } else if(inp_cidx < sizeof input - 1) {
89 input[inp_cidx++] = c;
93 /* read from queue and send over the serial port */
96 if(evq_wr != evq_rd) {
98 evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1);
103 printf("s(%u): %x\n", (unsigned int)(val >> 8), (unsigned int)(val & 0xff));
109 i2c_write(0x8a, 0x1c, 1, data);
115 static void proc_cmd(char *input)
117 if(strcmp(input, "rgb") == 0) {
118 printf("OK sending RGB switch command\n");
120 /* i2c addr 8b: jungle
121 * subaddr 2b: Control 1 reg
125 i2c_write(0x8a, 0x2b, 1, data);
127 } else if(memcmp(input, "vol ", 4) == 0) {
128 int vol = atoi(input + 4);
129 if(vol < 1 || vol > 63) {
130 printf("ERR invalid vol (%s)\n", input + 4);
133 i2c_write(0x8a, 0x1f, 1, data);
134 printf("OK volume: %d\n", vol);
137 } else if(strcmp(input, "zoom") == 0) {
139 i2c_write(0x8a, 0x10, 1, data);
140 printf("OK zoom in\n");
142 } else if(strcmp(input, "unzoom") == 0) {
144 i2c_write(0x8a, 0x10, 1, data);
145 printf("OK unzoom\n");
147 } else if(memcmp(input, "sat", 3) == 0) {
148 printf("OK saturate\n");
149 data[0] = atoi(input + 3);
150 if(data[0] <= 0 || data[0] > 0x3f) {
153 i2c_write(0x8a, 0x1c, 1, data);
157 } else if(strcmp(input, "abort") == 0) {
158 if(i2c_mode != I2C_IDLE) {
161 printf("OK aborting i2c op\n");
163 printf("ERR i2c is idle\n");
167 printf("ERR invalid command (%s)\n", input);
171 void i2c_write(unsigned char addr, unsigned char subaddr, int ndata, unsigned char *data)
173 i2c_addr = addr & 0xfe;
174 i2c_subaddr = subaddr;
175 i2c_mode = I2C_MASTER_SEND;
182 void i2c_handle_send(void)
184 unsigned char state = TWSR & 0xf8;
186 //printf("DBG i2c state (%x)\n", (unsigned int)state);
191 /* repeated start, same as start, but also increment i2c_seq */
194 /* start initiated, write the slave address */
195 //printf("DBG i2c SLA: %x\n", (unsigned int)i2c_addr);
201 /* slave addr sent and ACKed, send subaddr or data */
203 /* this is the first packet, send subaddr */
205 LOGNUM(0x100 | i2c_subaddr);
210 LOGNUM(0x200 | *i2c_data);
214 /* done sending, send stop */
222 /* slave addr sent but not ACKed, abort */
225 printf("i2c: NACK after SLA+W\n");
229 /* data (or subaddr) sent and ACKed, send more data (or restart) if available */
232 /* subaddr was sent, send repeated start */
236 /* data was sent, send more data or stop */
238 LOGNUM(0x200 | *i2c_data);
249 /* data (or subaddr) sent but not ACKed */
251 /* NACK after subaddr, abort */
252 printf("i2c: NACK after subaddr\n");
254 /* NACK after data */
256 printf("i2c: NACK with %d data packets pending\n", i2c_ndata);
264 /* arbitration lost */
265 printf("i2c: arbitration lost\n");
270 printf("i2c: invalid start/stop\n");
276 printf("i2c: unexpected state (W): 0x%x\n", state);
282 void i2c_handle_recv(void)
284 printf("i2c: recv unimplemented\n");
292 case I2C_MASTER_SEND:
296 case I2C_MASTER_RECV:
301 /* log traffic on the bus */
302 ev = (uint16_t)(TWSR & 0xf8) << 8;
303 switch(TWSR & 0xf8) {
304 case 0x80: /* own SLA+W received, ack */
305 case 0x88: /* own SLA+W recv, no-ack */
306 case 0x90: /* general recv, ack */
307 case 0x98: /* general recv, no-ack */
315 /* append data to the event queue */
316 TWCR = TWINT_BIT | TWEN_BIT | TWIE_BIT;
319 evq_wr = (evq_wr + 1) & (EVQ_SIZE - 1);
320 if(evq_wr == evq_rd) {
321 evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1);