/* * foxtel.c: A foxtel (Aussie cable TV) IR control client routines * * By: Alan Yates */ #include #include #include #include #include #include #include #include "irctrl-cl.h" struct code_t foxtel_codes[] = { {"pwr", "x100010000"}, {"0", "x100000000"}, {"1", "x100000001"}, {"2", "x100000010"}, {"3", "x100000011"}, {"4", "x100000100"}, {"5", "x100000101"}, {"6", "x100000110"}, {"7", "x100000111"}, {"8", "x100001000"}, {"9", "x100001001"}, {"up", "x100011010"}, {"rcl", "x100011010"}, {"f", "x100011001"}, {"-", "x100010110"}, {"left", "x100010110"}, {"menu", "x100010111"}, {"+", "x100010001"}, {"right", "x100010001"}, {"i", "x100011111"}, {"down", "x100001011"}, {"fav", "x100001011"}, {"store", "x100010011"}, {"norm", "x100010101"}, {"mute", "x100011110"}, {0, 0} }; char foxtel_press = 0; /* toggle key-press state */ /* foxtel protocol definitions */ #define foxtel_ir_t 21 /* IR carrier period */ #define foxtel_bit_t 600 /* IR TX time */ #define foxtel_one_t 7000 /* delay that codes '1' */ #define foxtel_zero_t 4400 /* delay that codes '0' */ #define foxtel_sync_t 3200 /* sync pulse spacing */ #define foxtel_tailspace 1 /* last 'space' time given to kernel */ /* transmit code */ int foxtel_tx(char *cmd) { int i = 0, p = 0; char bit = 0, buf[BUFSIZE], *data; struct stat sb; while(strcmp(foxtel_codes[i++].name, cmd)) { if(foxtel_codes[i].name == 0) { fprintf(stderr, "%s: foxtel packet '%s' unknown\n", PROG, cmd); return -1; } } data = foxtel_codes[--i].code; /* x bit toggle per press */ (foxtel_press == '0') ? (foxtel_press = '1') : (foxtel_press = '0'); /* irctrl carrier period and compensate values */ p += sprintf(&buf[p], "%d\n", foxtel_ir_t); /* IR data sync header */ p += sprintf(&buf[p], "%d %d\n", foxtel_bit_t, foxtel_sync_t); p += sprintf(&buf[p], "%d %d\n", foxtel_bit_t, foxtel_sync_t); /* IR data packet */ for(i = 0; i < strlen(data); i++) { bit = data[i]; if(bit == 'x') bit = foxtel_press; if(bit == '1') p += sprintf(&buf[p], "%d %d\n", foxtel_bit_t, foxtel_one_t); else p += sprintf(&buf[p], "%d %d\n", foxtel_bit_t, foxtel_zero_t); } /* Stop bit */ p += sprintf(&buf[p], "%d %d\n", foxtel_bit_t, foxtel_tailspace); buf[p] = 0; /* write */ if(write(DEV, buf, p) == p) return 0; return -1; } int new = 0; unsigned long startsec; unsigned long startusec; char frame_buffer[32]; int frame_cursor = 0; /* bit string comparison with 'dont cares' */ int dcbitcmp(char *p1, char *p2) { int i; if(strlen(p1) != strlen(p2)) return -1; for(i = 0; i < strlen(p1); i++) { if((p1[i] != p2[i]) & (p1[i] != 'x') & (p2[i] != 'x')) return -1; } return 0; } /* truely ugly code begins here - its horrible and I _will_ clean it up shortly */ int decode_frame() { int i = 0; if(frame_cursor != 10) return 0; frame_buffer[frame_cursor] = 0; while(foxtel_codes[i].name) { if(!dcbitcmp(foxtel_codes[i].code, frame_buffer)) { printf("\n%s: received frame '%s' => %s\n", PROG, foxtel_codes[i].code, foxtel_codes[i].name); frame_cursor = 0; return -1; } i++; } printf("\n%s: received unknown frame '%s'\n", PROG, frame_buffer); return -1; } int foxtel_rx(int *dc) { char buf[BUFSIZE]; unsigned int i = 0, j = 0, sec_time, usec_time, ret; unsigned long long t, last_t, delay; struct timeval tv[1024]; while((i + *dc)%BUFSIZE != recv_cursor) buf[i] = rxbuffer[(*dc + i++)%BUFSIZE]; *dc = recv_cursor; while(sscanf(&buf[j++*17], "%lu%lu", &sec_time, &usec_time) > 0) { if(new == 0) { new = 1; startsec = sec_time; startusec = usec_time; } t = sec_time*1000000 + usec_time; delay = t - last_t; last_t = t; if(delay > 10000) { ret = decode_frame(); frame_cursor = 0; } else if(delay > 3*2500) frame_buffer[frame_cursor++] = '1'; else if(delay > 2*2500) frame_buffer[frame_cursor++] = '0'; ret = decode_frame(); } if(ret) return -1; return 0; }