2584292e49d52d5998f3e5aff06d5897c42c2882
[tv_i2c_hack] / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <avr/io.h>
5 #include <avr/interrupt.h>
6 #include <util/delay.h>
7 #include "serial.h"
8 #include "i2c.h"
9
10 /* TODO
11  * IR decoding, connected to PCINT0
12  * enable/disable with switch on PCINT1
13  * some of the buttons multiplexed on ADC0
14  */
15
16 #define EVQ_SIZE        64
17 uint16_t evq[EVQ_SIZE];
18 volatile int evq_wr, evq_rd;
19
20 #define LOGNUM(x)       EVLOG(EV_DEBUG, (x))
21
22 #define EVLOG(ev, data) \
23         do { \
24                 if(ev != EV_DEBUG || dbgmode) { \
25                         evq[evq_wr] = ((uint16_t)(ev) << 8) | (data); \
26                         evq_wr = (evq_wr + 1) & (EVQ_SIZE - 1); \
27                         if(evq_wr == evq_rd) { \
28                                 evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1); \
29                         } \
30                 } \
31         } while(0)
32
33 /* serial input buffer */
34 static char input[64];
35 static unsigned char inp_cidx;
36
37 static unsigned char data[16];
38
39 static uint16_t dump_addr;
40 static int dump_count;
41 static int dbgmode;
42
43 static void proc_cmd(char *input);
44 static void printstat(void);
45 static void printdump(void);
46
47
48 int main(void)
49 {
50         uint16_t val;
51
52         /* tri-state everything and disable pullups */
53         DDRB = 1;       /* B0: activity LED */
54         DDRC = 0;       /* I2C pins as inputs */
55         DDRD = 0;
56         PORTB = 0;
57         PORTC = 0;
58         PORTD = 0;
59
60         i2c_init();
61
62         init_serial(38400);
63         sei();
64
65         printf("TV i2c hack\n");
66
67         for(;;) {
68                 i2c_check_async();
69
70                 if(have_input()) {
71                         int c = getchar();
72                         putchar(c);
73
74                         if(c == '\r' || c == '\n') {
75                                 putchar('\n');
76                                 input[inp_cidx] = 0;
77                                 proc_cmd(input);
78                                 inp_cidx = 0;
79                         } else if(inp_cidx < sizeof input - 1) {
80                                 input[inp_cidx++] = c;
81                         }
82                 }
83
84                 /* read from queue and send over the serial port */
85                 val = 0xffff;
86                 cli();
87                 if(evq_wr != evq_rd) {
88                         val = evq[evq_rd];
89                         evq_rd = (evq_rd + 1) & (EVQ_SIZE - 1);
90                 }
91                 sei();
92
93                 if(val != 0xffff) {
94                         unsigned char ev = val >> 8;
95                         printf("%02x: %02x\n", ev, val & 0xff);
96                 }
97         }
98         return 0;
99 }
100
101 static void proc_cmd(char *input)
102 {
103         char *endp;
104
105         if(strcmp(input, "dbg") == 0) {
106                 printf("OK dbg\n");
107                 dbgmode = 1;
108
109         } else if(strcmp(input, "nodbg") == 0) {
110                 printf("OK nodbg\n");
111                 dbgmode = 0;
112
113         } else if(strcmp(input, "av") == 0) {
114                 printf("OK AV\n");
115
116                 /* AV switch (22): 0 0 SVO CMB1 CMB0 INA INB 0 */
117                 data[0] = 0x22;
118                 i2c_write(0x8a, 0x22, data, 1);
119                 i2c_async(i2c_hold);
120
121         } else if(strcmp(input, "rgb") == 0) {
122                 printf("OK RGB\n");
123
124                 /* Control 0 (2a): 0 IE2 RBL AKB  CL3 CL2 CL1 CL0
125                  * Control 1 (2b): 0  0   0   0    0   0  YUV HBL
126                  */
127                 data[0] = 0x70;
128                 data[1] = 0;
129                 i2c_write(0x8a, 0x2a, data, 1);
130                 i2c_wait();
131                 i2c_write(0x8a, 0x2b, data + 1, 1);
132
133         } else if(memcmp(input, "vol ", 4) == 0) {
134                 int vol = atoi(input + 4);
135                 if(vol < 1 || vol > 63) {
136                         printf("ERR vol (%s)\n", input + 4);
137                 } else {
138                         data[0] = vol;
139                         i2c_write(0x8a, 0x1f, data, 1);
140                         printf("OK volume: %d\n", vol);
141                 }
142
143         } else if(memcmp(input, "sat", 3) == 0) {
144                 printf("OK sat\n");
145                 data[0] = atoi(input + 3);
146                 if(data[0] <= 0 || data[0] > 0x3f) {
147                         data[0] = 0x1f;
148                 }
149                 i2c_write(0x8a, 0x1c, data, 1);
150                 i2c_async(i2c_hold);    /* hold I2C when done */
151
152         } else if(strcmp(input, "rel") == 0) {
153                 printf("OK release\n");
154                 i2c_release();
155
156         } else if(strcmp(input, "status") == 0) {
157                 i2c_read(0x8a, 0, data, 3);
158                 i2c_async(printstat);
159
160         } else if(memcmp(input, "rd ", 3) == 0) {
161                 dump_addr = strtol(input + 3, &endp, 16);
162
163                 if(endp > input + 3 && dump_addr >= 0 && dump_addr < 2048) {
164                         dump_count = 1;
165                         i2c_read(0xa0 | ((dump_addr >> 7) & 0xe), dump_addr & 0xff, data, 1);
166                         i2c_async(printdump);
167                 } else {
168                         printf("ERR address: %s\n", input + 3);
169                 }
170
171         } else if(memcmp(input, "dump ", 5) == 0) {
172                 dump_addr = strtol(input + 5, &endp, 16);
173
174                 if(endp > input + 5 && dump_addr >= 0 && dump_addr < 2048) {
175                         dump_count = 1;
176                         dump_addr &= 0xff0;
177                         i2c_read(0xa0 | ((dump_addr >> 7) & 0xe), dump_addr & 0xff, data, 16);
178                         i2c_async(printdump);
179                 } else {
180                         printf("ERR address: %s\n", input + 5);
181                 }
182
183         } else if(strcmp(input, "abort") == 0) {
184                 i2c_abort();
185                 printf("OK\n");
186
187         } else {
188                 printf("ERR command (%s)\n", input);
189         }
190 }
191
192 static void printstat(void)
193 {
194         printf("OK status: %02x %02x %02x\n", (unsigned int)data[0],
195                         (unsigned int)data[1], (unsigned int)data[2]);
196 }
197
198 static void printdump(void)
199 {
200         int i;
201         while(dump_count > 0) {
202                 printf("OK %03x:", dump_addr);
203                 for(i=0; i<16; i++) {
204                         if(i == 8) putchar(' ');
205
206                         if(--dump_count >= 0) {
207                                 printf(" %02x", data[i]);
208                         } else {
209                                 printf("   ");
210                         }
211                         dump_addr += 16;
212                 }
213                 putchar('\n');
214         }
215 }