code cleanup, dropped the sniffer
[tv_i2c_hack] / main.c
diff --git a/main.c b/main.c
deleted file mode 100644 (file)
index fa0be2f..0000000
--- a/main.c
+++ /dev/null
@@ -1,702 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include "serial.h"
-
-#undef USE_PCINT
-
-enum {
-       I2C_IDLE,
-       I2C_MASTER_WRITE,
-       I2C_MASTER_READ
-};
-
-enum {
-       ST_INVALID                      = 0,
-       ST_UNKNOWN                      = 0xf8,
-       ST_START                        = 0x08,
-       ST_REP_START            = 0x10,
-       ST_SLA_W_ACK            = 0x18,
-       ST_SLA_W_NACK           = 0x20,
-       ST_WR_ACK                       = 0x28,
-       ST_WR_NACK                      = 0x30,
-       ST_ARBLOST                      = 0x38,
-       ST_SLA_R_ACK            = 0x40,
-       ST_SLA_R_NACK           = 0x48,
-       ST_RD_ACK                       = 0x50,
-       ST_RD_NACK                      = 0x58,
-       ST_MATCH_W                      = 0x60,
-       ST_ARBLOST_MATCH        = 0x68,
-       ST_GENMATCH                     = 0x70,
-       ST_ARBLOST_GENMATCH = 0x78,
-       ST_SLAVE_RD_ACK         = 0x80,
-       ST_SLAVE_RD_NACK        = 0x88,
-       ST_SLAVE_GENRD_ACK      = 0x90,
-       ST_SLAVE_GENRD_NACK     = 0x98,
-       ST_SLAVE_STARTSTOP      = 0xa0,
-       ST_SLAVE_SLA_WR_ACK     = 0xa8,
-       ST_SLAVE_ARBLOST_WR_ACK = 0xb0,
-       ST_SLAVE_WR_ACK         = 0xb8,
-       ST_SLAVE_WR_NACK        = 0xc0,
-       ST_SLAVE_LAST_WR_ACK = 0xc8
-};
-
-enum {
-       EV_DEBUG,
-       EV_START,
-       EV_STOP,
-       EV_SLA_W,
-       EV_SLA_R,
-       EV_DATA
-};
-
-static const char *evname[] = {
-       "DBG",
-       "STA",
-       "STO",
-       "A+W",
-       "A+R",
-       "DAT"
-};
-
-#define TWINT_BIT      (1 << TWINT)
-#define TWEA_BIT       (1 << TWEA)
-#define TWSTA_BIT      (1 << TWSTA)
-#define TWSTO_BIT      (1 << TWSTO)
-#define TWEN_BIT       (1 << TWEN)
-#define TWIE_BIT       (1 << TWIE)
-
-#define I2C_START()    (TWCR = TWINT_BIT | TWSTA_BIT | TWEN_BIT | TWIE_BIT)
-#define I2C_STOP()     (TWCR = TWINT_BIT | TWSTO_BIT | TWEN_BIT | TWIE_BIT)
-#define I2C_WRITE()    (TWCR = TWINT_BIT | TWEN_BIT | TWIE_BIT)
-#define I2C_READ_ACK() (TWCR = TWINT_BIT | TWEA_BIT | TWEN_BIT | TWIE_BIT)
-#define I2C_READ_NACK()        (TWCR = TWINT_BIT | TWEN_BIT | TWIE_BIT)
-
-unsigned char i2c_addr, i2c_subaddr;
-volatile unsigned char i2c_mode;
-int i2c_seq, i2c_ndata;
-unsigned char *i2c_data;
-int i2c_retry_delay;
-
-#define EVQ_SIZE       64
-uint16_t evq[EVQ_SIZE];
-volatile int evq_wr, evq_rd;
-
-#define LOGNUM(x)      EVLOG(EV_DEBUG, (x))
-
-#define EVLOG(ev, data)        \
-       do { \
-               if(ev != EV_DEBUG || dbgmode) { \
-                       evq[evq_wr] = ((uint16_t)(ev) << 8) | (data); \
-                       evq_wr = (evq_wr + 1) & (EVQ_SIZE - 1); \
-                       if(evq_wr == evq_rd) { \
-                               evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1); \
-                       } \
-               } \
-       } while(0)
-
-/* serial input buffer */
-static char input[64];
-static unsigned char inp_cidx;
-
-static unsigned char data[16];
-
-static void (*async_func)(void);
-
-static uint16_t dump_addr;
-static int dump_count;
-static int dbgmode;
-static int snooping;
-
-static void proc_cmd(char *input);
-static void printstat(void);
-static void printdump(void);
-
-void i2c_write(unsigned char addr, unsigned char subaddr, unsigned char *data, int ndata);
-void i2c_read(unsigned char addr, unsigned char subaddr, unsigned char *buf, int size);
-void i2c_wait(void);
-void i2c_async(void (*donecb)(void));
-void i2c_check_async(void);
-void i2c_hold(void);
-void i2c_release(void);
-void i2c_snoop(int onoff);
-#ifndef USE_PCINT
-void snoop(void);
-#endif
-
-int main(void)
-{
-       uint16_t val;
-
-       /* tri-state everything and disable pullups */
-       DDRB = 1;       /* B0: activity LED */
-       DDRC = 0;       /* I2C pins as inputs */
-       DDRD = 0;
-       PORTB = 0;
-       PORTC = 0;
-       PORTD = 0;
-
-       TWBR = 10;              /* 10 with 1x prescaler should make it about 100khz */
-       TWSR = 0;               /* prescaler 1x */
-       TWAR = 0;
-       TWAMR = 0;
-       TWCR = 0;               /* I2C disabled by default */
-
-       i2c_mode = I2C_IDLE;
-       i2c_snoop(0);   /* disable snooping by default */
-
-       init_serial(38400);
-       sei();
-
-       printf("Starting i2c hack\n");
-
-       for(;;) {
-#ifndef USE_PCINT
-               if(snooping) {
-                       snoop();
-                       if(have_input()) {
-                               i2c_snoop(0);
-                       }
-                       continue;
-               }
-#endif
-
-               i2c_check_async();
-
-               if(have_input()) {
-                       int c = getchar();
-                       putchar(c);
-
-                       if(c == '\r' || c == '\n') {
-                               putchar('\n');
-                               input[inp_cidx] = 0;
-                               proc_cmd(input);
-                               inp_cidx = 0;
-                       } else if(inp_cidx < sizeof input - 1) {
-                               input[inp_cidx++] = c;
-                       }
-               }
-
-               /* read from queue and send over the serial port */
-               val = 0xffff;
-               cli();
-               if(evq_wr != evq_rd) {
-                       val = evq[evq_rd];
-                       evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1);
-               }
-               sei();
-
-               if(val != 0xffff) {
-                       unsigned char ev = val >> 8;
-                       if(ev > EV_DATA) {
-                               printf("%02x: %02x\n", ev, val & 0xff);
-                       } else {
-                               printf("%s: %02x\n", evname[ev], val & 0xff);
-                       }
-               }
-       }
-       return 0;
-}
-
-static void proc_cmd(char *input)
-{
-       char *endp;
-
-       if(strcmp(input, "dbg") == 0) {
-               printf("OK dbg\n");
-               dbgmode = 1;
-
-       } else if(strcmp(input, "nodbg") == 0) {
-               printf("OK nodbg\n");
-               dbgmode = 0;
-
-       } else if(strcmp(input, "start") == 0) {
-               printf("OK snooping\n");
-               i2c_snoop(1);
-
-       } else if(strcmp(input, "stop") == 0) {
-               i2c_snoop(0);
-               printf("OK stopped snooping\n");
-
-       } else if(strcmp(input, "av") == 0) {
-               printf("OK AV\n");
-
-               /* AV switch (22): 0 0 SVO CMB1 CMB0 INA INB 0 */
-               data[0] = 0x22;
-               i2c_write(0x8a, 0x22, data, 1);
-               i2c_async(i2c_hold);
-
-       } else if(strcmp(input, "rgb") == 0) {
-               printf("OK RGB\n");
-
-               /* Control 0 (2a): 0 IE2 RBL AKB  CL3 CL2 CL1 CL0
-                * Control 1 (2b): 0  0   0   0    0   0  YUV HBL
-                */
-               data[0] = 0x70;
-               data[1] = 0;
-               i2c_write(0x8a, 0x2a, data, 1);
-               while(i2c_mode);
-               i2c_write(0x8a, 0x2b, data + 1, 1);
-
-       } else if(memcmp(input, "vol ", 4) == 0) {
-               int vol = atoi(input + 4);
-               if(vol < 1 || vol > 63) {
-                       printf("ERR vol (%s)\n", input + 4);
-               } else {
-                       data[0] = vol;
-                       i2c_write(0x8a, 0x1f, data, 1);
-                       printf("OK volume: %d\n", vol);
-               }
-
-       } else if(memcmp(input, "sat", 3) == 0) {
-               printf("OK sat\n");
-               data[0] = atoi(input + 3);
-               if(data[0] <= 0 || data[0] > 0x3f) {
-                       data[0] = 0x1f;
-               }
-               i2c_write(0x8a, 0x1c, data, 1);
-               i2c_async(i2c_hold);    /* hold I2C when done */
-
-       } else if(strcmp(input, "rel") == 0) {
-               printf("OK release\n");
-               i2c_release();
-
-       } else if(strcmp(input, "status") == 0) {
-               i2c_read(0x8a, 0, data, 3);
-               i2c_async(printstat);
-
-       } else if(memcmp(input, "rd ", 3) == 0) {
-               dump_addr = strtol(input + 3, &endp, 16);
-
-               if(endp > input + 3 && dump_addr >= 0 && dump_addr < 2048) {
-                       dump_count = 1;
-                       i2c_read(0xa0 | ((dump_addr >> 7) & 0xe), dump_addr & 0xff, data, 1);
-                       i2c_async(printdump);
-               } else {
-                       printf("ERR address: %s\n", input + 3);
-               }
-
-       } else if(memcmp(input, "dump ", 5) == 0) {
-               dump_addr = strtol(input + 5, &endp, 16);
-
-               if(endp > input + 5 && dump_addr >= 0 && dump_addr < 2048) {
-                       dump_count = 1;
-                       dump_addr &= 0xff0;
-                       i2c_read(0xa0 | ((dump_addr >> 7) & 0xe), dump_addr & 0xff, data, 16);
-                       i2c_async(printdump);
-               } else {
-                       printf("ERR address: %s\n", input + 5);
-               }
-
-       } else if(strcmp(input, "abort") == 0) {
-               if(i2c_mode != I2C_IDLE) {
-                       i2c_mode = I2C_IDLE;
-                       I2C_STOP();
-                       printf("OK\n");
-               } else {
-                       printf("ERR i2c is idle\n");
-               }
-
-       } else {
-               printf("ERR command (%s)\n", input);
-       }
-}
-
-static void printstat(void)
-{
-       printf("OK status: %02x %02x %02x\n", (unsigned int)data[0],
-                       (unsigned int)data[1], (unsigned int)data[2]);
-}
-
-static void printdump(void)
-{
-       int i;
-       while(dump_count > 0) {
-               printf("OK %03x:", dump_addr);
-               for(i=0; i<16; i++) {
-                       if(i == 8) putchar(' ');
-
-                       if(--dump_count >= 0) {
-                               printf(" %02x", data[i]);
-                       } else {
-                               printf("   ");
-                       }
-                       dump_addr += 16;
-               }
-               putchar('\n');
-       }
-}
-
-void i2c_write(unsigned char addr, unsigned char subaddr, unsigned char *data, int ndata)
-{
-       i2c_addr = addr & 0xfe;
-       i2c_subaddr = subaddr;
-       i2c_mode = I2C_MASTER_WRITE;
-       i2c_ndata = ndata;
-       i2c_data = data;
-       i2c_seq = 0;
-       I2C_START();
-}
-
-void i2c_read(unsigned char addr, unsigned char subaddr, unsigned char *buf, int size)
-{
-       i2c_addr = addr & 0xfe;
-       i2c_subaddr = subaddr;
-       i2c_mode = I2C_MASTER_READ;
-       i2c_ndata = size;
-       i2c_data = buf;
-       i2c_seq = 0;
-       I2C_START();
-}
-
-void i2c_handle_send(void)
-{
-       unsigned char state = TWSR & 0xf8;
-
-       //printf("DBG i2c state (%x)\n", (unsigned int)state);
-       LOGNUM(state);
-
-       switch(state) {
-       case ST_REP_START:      /* 0x10 */
-               /* repeated start, same as start, but also increment i2c_seq */
-               i2c_seq++;
-       case ST_START:  /* 0x8 */
-               /* start initiated, write the slave address */
-               //printf("DBG i2c SLA: %x\n", (unsigned int)i2c_addr);
-               TWDR = i2c_addr;
-               I2C_WRITE();
-               break;
-
-       case ST_SLA_W_ACK:      /* 0x18 */
-               /* slave addr sent and ACKed, send subaddr or data */
-               if(i2c_seq == 0) {
-                       /* this is the first packet, send subaddr */
-                       i2c_seq++;
-                       TWDR = i2c_subaddr;
-                       I2C_WRITE();
-               } else {
-                       if(i2c_ndata--) {
-                               TWDR = *i2c_data++;
-                               I2C_WRITE();
-                       } else {
-                               /* done sending, send stop */
-                               i2c_mode = I2C_IDLE;
-                               I2C_STOP();
-                       }
-               }
-               break;
-
-       case ST_SLA_W_NACK:     /* 0x20 */
-               /* slave addr sent but not ACKed, abort */
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-               printf("i2c: NACK after SLA+W\n");
-               break;
-
-       case ST_WR_ACK: /* 0x28 */
-               /* data (or subaddr) sent and ACKed, send more data (or restart) if available */
-#if 0
-               if(i2c_seq == 0) {
-                       /* subaddr was sent, send repeated start */
-                       I2C_START();
-               } else {
-#endif
-                       /* data was sent, send more data or stop */
-                       if(i2c_ndata--) {
-                               TWDR = *i2c_data++;
-                               I2C_WRITE();
-                       } else {
-                               i2c_mode = I2C_IDLE;
-                               I2C_STOP();
-                       }
-//             }
-               break;
-
-       case ST_WR_NACK:        /* 0x30 */
-               /* data (or subaddr) sent but not ACKed */
-               if(i2c_seq == 0) {
-                       /* NACK after subaddr, abort */
-                       printf("i2c: NACK after subaddr\n");
-               } else {
-                       /* NACK after data */
-                       if(i2c_ndata) {
-                               printf("i2c: NACK with %d pending\n", i2c_ndata);
-                       }
-               }
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-               break;
-
-       case ST_ARBLOST:        /* 0x38 */
-               /* arbitration lost */
-               printf("i2c: arb lost\n");
-               I2C_START();
-               break;
-
-       case ST_INVALID:        /* 0 */
-               printf("i2c: invalid start/stop\n");
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-               break;
-
-       default:
-               printf("i2c: unexpected state (W): 0x%x\n", state);
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-       }
-}
-
-void i2c_handle_recv(void)
-{
-       unsigned char state = TWSR & 0xf8;
-
-       LOGNUM(state);
-
-       switch(state) {
-       case ST_START:          /* 0x8 */
-               TWDR = i2c_addr;        /* start a *write* (we need to send the subaddress before reading) */
-               I2C_WRITE();
-               break;
-
-       case ST_REP_START:      /* 0x10 */
-               /* repeated start, now we can issue the actual read */
-               TWDR = i2c_addr | 1;
-               I2C_WRITE();
-               break;
-
-       case ST_SLA_W_ACK:      /* 0x18 */
-               /* SLA+W means we just started the write part, need to send the subaddress */
-               TWDR = i2c_subaddr;
-               I2C_WRITE();
-               break;
-
-       case ST_SLA_W_NACK:
-               /* slave addr sent but not ACKed, abort */
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-               printf("i2c: NACK after SLA+W (R)\n");
-               break;
-
-       case ST_WR_ACK:         /* 0x28 */
-               /* the subaddress write was ACKed, rep-start to issue the read */
-               I2C_START();
-               break;
-
-       case ST_WR_NACK:
-               /* the subaddress write was not ACKed, abort */
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-               printf("i2c: NACK after subaddr (R)\n");
-               break;
-
-       case ST_SLA_R_ACK:      /* 0x40 */
-               /* SLA+R was ACKed send ACK to start receiving */
-               I2C_READ_ACK();
-               break;
-
-       case ST_RD_ACK:         /* 0x50 */
-               /* ... or last read was ACKed, again read next and ACK for more */
-               *i2c_data++ = TWDR;
-               if(--i2c_ndata > 0) {
-                       I2C_READ_ACK();
-               } else {
-                       I2C_READ_NACK();
-               }
-               break;
-
-       case ST_SLA_R_NACK:     /* 0x48 */
-               /* SLA+R was sent but ACK was not received, abort */
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-               printf("i2c: NACK after SLA+R\n");
-               break;
-
-       case ST_RD_NACK:        /* 0x58 */
-               /* read without ACK, we get this after we send a NACK, or this is the last byte (?) */
-               if(i2c_ndata > 0) {
-                       *i2c_data++ = TWDR;
-                       i2c_ndata--;
-               }
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-               break;
-
-       case ST_ARBLOST:        /* 0x38 */
-               /* arbitration lost */
-               printf("i2c: arb lost\n");
-               I2C_START();
-               break;
-
-       case ST_INVALID:        /* 0 */
-               printf("i2c: invalid start/stop\n");
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-               break;
-
-       default:
-               printf("i2c: unexpected state (R): 0x%x\n", state);
-               i2c_mode = I2C_IDLE;
-               I2C_STOP();
-       }
-}
-
-ISR(TWI_vect)
-{
-       switch(i2c_mode) {
-       case I2C_MASTER_WRITE:
-               i2c_handle_send();
-               break;
-
-       case I2C_MASTER_READ:
-               i2c_handle_recv();
-               break;
-       }
-}
-
-void i2c_wait(void)
-{
-       while(i2c_mode);
-}
-
-void i2c_async(void (*donecb)(void))
-{
-       async_func = donecb;
-}
-
-void i2c_check_async(void)
-{
-       if(async_func && i2c_mode == I2C_IDLE) {
-               async_func();
-               async_func = 0;
-       }
-}
-
-void i2c_hold(void)
-{
-       TWCR = 0;               /* make sure the AVR i2c hardware is disabled */
-       DDRC = 0x20;    /* ... and drive SCL pin low */
-       PORTC = 0;
-}
-
-void i2c_release(void)
-{
-       DDRC = 0;
-}
-
-#define PC_SCL 5
-#define PC_SDA 4
-#define PC_SCL_BIT     (1 << PC_SCL)
-#define PC_SDA_BIT     (1 << PC_SDA)
-
-static unsigned char pcprev, state;
-static unsigned char value;
-static int nbits;
-
-/* use PCINT12,13 to snoop i2c traffic */
-void i2c_snoop(int onoff)
-{
-       snooping = onoff;
-
-       if(!onoff) {
-#ifdef USE_PCINT
-               /* to stop snooping just disable the interrupt */
-               cli();
-               PCMSK1 = 0;
-               PCICR &= ~(1 << PCIE1);
-               sei();
-#endif
-               return;
-       }
-
-       TWCR = 0;               /* make sure the i2c hw is disabled */
-       DDRC = 0;
-       PORTC = 0;
-
-#ifdef USE_PCINT
-       cli();
-       PCICR |= 1 << PCIE1;    /* enable the pin-change interrupt */
-       PCMSK1 = (1 << PCINT12) | (1 << PCINT13);
-#endif
-
-       pcprev = PINC;
-       state = 0;
-       value = 0;
-       nbits = 0;
-#ifdef USE_PCINT
-       sei();
-#endif
-}
-
-#ifdef USE_PCINT
-ISR(PCINT1_vect)
-#else
-void snoop(void)
-#endif
-{
-       unsigned char pinc, delta;
-
-       pinc = PINC;
-       delta = pinc ^ pcprev;
-       pcprev = pinc;
-
-       if(delta & PC_SDA_BIT) {
-               if(pinc & PC_SCL_BIT) {
-                       /* clock is high, so this is either a start or a stop */
-                       if(pinc & PC_SDA_BIT) {
-                               EVLOG(EV_STOP, 0);
-                               state = 0;
-                       } else {
-                               EVLOG(EV_START, 0);
-                               state = EV_START;
-                               value = 0;
-                               nbits = 0;
-                       }
-                       return;
-               }
-       }
-
-       if(!state) {
-               uint16_t val, ev;
-               if(evq_wr != evq_rd) {
-                       val = evq[evq_rd];
-                       evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1);
-                       ev = val >> 8;
-                       if(ev <= EV_STOP) {
-                               printf("%s\n", evname[ev]);
-                       } else {
-                               printf("%s: %02x\n", evname[ev], val & 0xff);
-                       }
-               }
-               return;
-       }
-
-       if(delta & PC_SCL_BIT) {
-               if(pinc & PC_SCL_BIT) {
-                       /* clock is going high, shift SDA */
-                       value = (value << 1) | ((pinc >> PC_SDA) & 1);
-                       if(++nbits >= 8) {
-                               switch(state) {
-                               case EV_START:
-                                       state = (value & 1) ? EV_SLA_R : EV_SLA_W;
-                                       EVLOG(state, value & 0xfe);
-                                       break;
-                               case EV_SLA_W:
-                               case EV_SLA_R:
-                                       state = EV_DATA;
-                                       EVLOG(state, value);
-                               case EV_DATA:
-                                       //EVLOG(state, value);
-                               default:
-                                       break;
-                               }
-                               nbits = 0;
-                               value = 0;
-                       }
-               }
-       }
-
-       PORTB ^= 1;
-}