#include <stdio.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#include "usart.h"

void ledOn(void)
{
	PORTB |= 128;
}

void ledOff(void)
{
	PORTB &= ~128;
}

void ledToggle(void)
{
	if (PORTB & 128) {
		ledOff();
	} else {
		ledOn();
	}
}

static volatile unsigned int counter_ms=0;
static volatile unsigned int counter_sec=0;

SIGNAL(SIG_OUTPUT_COMPARE0)
{
	counter_ms++;
	if (counter_ms>1000) { 
		counter_ms = 0; 
		counter_sec++;
	}
}

static unsigned char output_buffer[25];

#define STATE_STOPPED	0
#define STATE_NORMAL	1

int main(void)
{
	int a, b, c;
	unsigned int elaps_ms;
	int state = STATE_STOPPED;
	
	usart_init(25);
	cli();
	
	DDRB |= 128;
	ledOff();

	// input
	DDRE &= ~(1<<4); // PE4 input
	
	// timer
	TCCR0 = 0;

	TCNT0 = 0;
	OCR0 = 125; // divide by 125, output_compare0 occurs at 1 khz

	TIMSK |= (1<<OCIE0);
	
	TCCR0 |= 8; // CTC mode
	TCCR0 |= 3; // /32 prescaler ( 125khz)

	
	for (c=0; c<4; c++) {
		for (a=0; a<500; a++) {
			for (b=0; b<500; b++) {
				asm volatile("nop");
			}
		}
		ledToggle();
	}

	counter_ms = counter_sec = 0;
	sei();
	
	sprintf(output_buffer, "status: ready\n");
	usart_write(output_buffer, strlen(output_buffer));
	
	while(1) {

		ledOff();
		
		// wait for a rising edge
		while (!(PINE & (1<<4))) {
			if (state!=STATE_STOPPED) {
				// after 10 seconds I guess it is stopped for good.
				if (counter_sec > 10) {
					state = STATE_STOPPED;
					sprintf(output_buffer, "status: stopped\n");
					usart_write(output_buffer, strlen(output_buffer));
				}
			}
		}

		// save elapsed time, reset timer and wait 16 ms for debounce
		cli();
		elaps_ms = counter_ms + (counter_sec * 1000);
		counter_ms = counter_sec = 0;
		sei();

		// this commented area purpose was to debounce the signal. It worked
		// up to 30hz when testing, but testing was done with a symetric
		// square wave. The signal received from the tower has very short pulses
		// due to the fact that a slotted ir sensor is used. 
		//
		// Because of this code, the pulse was ignored at high speed (cause it is
		// shorter)
		//
		// So let's remove the debounce code and 'hope for the best(tm)'
		/*
		while(1) {
			cli();
			if (counter_ms >= 16) { sei(); break; }
			sei();
			asm volatile("nop\nnop\nnop\nnop\nnop\n");
		}
		
		if (PINE & (1<<4)) {
			ledOn();
			if (state == STATE_STOPPED) {
				state = STATE_NORMAL;
			} else {
				sprintf(output_buffer, "delta: %d\n", elaps_ms);
				usart_write(output_buffer, strlen(output_buffer));
			}
		}
		else {
			continue;
		}
		*/
		
		ledOn();

		if (state == STATE_STOPPED) {
			state = STATE_NORMAL;
		} else {
			sprintf(output_buffer, "delta: %d\n", elaps_ms);
			usart_write(output_buffer, strlen(output_buffer));
		}

		// wait for a falling edge
		while (PINE & (1<<4))
		{
			if (state!=STATE_STOPPED) {
				// after 10 seconds I guess it is stopped for good.
				if (counter_sec > 10) {
					state = STATE_STOPPED;
					sprintf(output_buffer, "status: stopped\n");
					usart_write(output_buffer, strlen(output_buffer));
				}
			}
		}
		


	}
}


