--- /dev/null
+#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');
+ }
+}