code cleanup, dropped the sniffer
[tv_i2c_hack] / src / main.c
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..2584292
--- /dev/null
@@ -0,0 +1,215 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "serial.h"
+#include "i2c.h"
+
+/* TODO
+ * IR decoding, connected to PCINT0
+ * enable/disable with switch on PCINT1
+ * some of the buttons multiplexed on ADC0
+ */
+
+#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 uint16_t dump_addr;
+static int dump_count;
+static int dbgmode;
+
+static void proc_cmd(char *input);
+static void printstat(void);
+static void printdump(void);
+
+
+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;
+
+       i2c_init();
+
+       init_serial(38400);
+       sei();
+
+       printf("TV i2c hack\n");
+
+       for(;;) {
+               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;
+                       printf("%02x: %02x\n", 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, "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);
+               i2c_wait();
+               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) {
+               i2c_abort();
+               printf("OK\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');
+       }
+}