/*
 * frx.c:	RX code for foxtel box protocol
 *
 *	By:	Alan Yates <alany@ay.com.au>
 *
 */

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include "codes.h"

#define FRX_BUFSIZE 500
#define FRX_STKSIZE 100
#define FRX_DEVFILE "../irctrl"

/* globals */

int	frx_fd = 0;		/* device file descriptor */
char	frx_buf[FRX_BUFSIZE];	/* rx code bits buffer */
int	frx_buf_rcursor = 0;	/* rx buffer read cursor */
int	frx_buf_wcursor = 0;	/* rx buffer write cursor */
char	frx_stk[FRX_STKSIZE];	/* rx stack */
int	frx_stk_cursor = 0;	/* rx stack cursor */

int	frx_isnew = 1;		/* flag for first read */
unsigned long frx_sec = 0;	/* first read timing - sec */
unsigned long frx_usec = 0;	/* first read timing - usec */
unsigned long frx_last = 0;	/* time of last 'edge' */

/* init function - call with */
int
frx_init(char *path) {
	frx_fd = open(path, O_RDONLY | O_NONBLOCK);

	if(frx_fd < 0) {
		perror("open()");
		return -1;
	}

	frx_stk_cursor = 0;
	frx_buf_rcursor = 0;
	frx_buf_wcursor = 0;

	return 0;
}


/* exit function - cleans up */
int
frx_close() {
	close(frx_fd);
	return 0;
}

/* buffer dump - debug */
void
frx_buffer_dump() {
	int i;
	printf("buffer dump: (r=%d, w=%d)\n", frx_buf_rcursor, frx_buf_wcursor);
	for(i = 0; i < FRX_BUFSIZE; i++) {
		printf("%.2x", frx_buf[i]);
		if(i%38 == 37) printf("\n");
	}
	printf("\n");
}

/* buffer update function - loads data from kernel into local buffer */
int
frx_buffer() {
	char buf[FRX_BUFSIZE];
	int bytes, i;

	bytes = read(frx_fd, buf, FRX_BUFSIZE);
	if(bytes < 0) return;
	for(i = 0; i < bytes; i++)
		frx_buf[(frx_buf_wcursor+i)%FRX_BUFSIZE] = buf[i];
	frx_buf_wcursor += bytes;
	frx_buf_wcursor %= FRX_BUFSIZE;

	frx_buffer_dump();
	return bytes;
}


/* stack dump - debug */
void
frx_dump_stack() {
	int i;
	printf("frx_stack: (%d) [", frx_stk_cursor);
	for(i = 0; i < frx_stk_cursor; i++) printf("%s%c", (i==0) ? "":",", frx_stk[i]);
	printf("]\n");
}


/* stack update function - reads fd and fills stack with decoded bits */
int
frx_stack() {
	unsigned long sec, usec, t, d;
	int bytes, i;

	while(frx_buf_rcursor != frx_buf_wcursor) {
		sscanf(&frx_buf[frx_buf_rcursor], "%lu%lu", &sec, &usec);
		/* store first timing for offset */
		if(frx_isnew) {
			frx_isnew = 0;
			frx_sec = sec;
			frx_usec = usec;
		}
		frx_buf_rcursor += 17;
		t = frx_sec*1000000 + frx_usec;
		d = t - frx_last;

		if(d > 10000) {
			frx_stk_cursor = 0;
		} else if(d > 3*2500) {
			frx_stk[frx_stk_cursor++] = '1';
		} else if(d > 2*2500) {
			frx_stk[frx_stk_cursor++] = '0';
		}
	}
	frx_dump_stack();
	return 0;
}


/* poll function - updates stack and returns !0 if packet is available */
int
frx_poll() {
	/* frame _may_ be available */
	if(frx_stk_cursor >= 10) return -1;

	/* scan stack for good packets */

	/* nothing yet */
	return 0;
}



char
*frx_decode() {
	return 0;
}

int
main() {
	struct timeval tv;
	
	if(frx_init(FRX_DEVFILE)) return 1;
	while(-1) {
		frx_buffer();
		frx_stack();
		//if(frx_poll())
		//	printf("%s\n", frx_decode());
		tv.tv_sec = 0;
		tv.tv_usec = 500;
		select(0, 0, 0, 0, &tv);
	}

	frx_close();
}
