/*
 * kb.c
 *
 * Created: 01.06.2012 14:01:37
 *  Author: Technic
 */ 

#include <avr/pgmspace.h>
#include "kb.h"
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <stdio.h>


volatile unsigned char edge, bitcount,data,timer = 0,err=0;				// 0 = neg. 1 = pos.

void init_kb(void)
{
	MCUCR = 2;				// INT0 interrupt on falling edge
	edge = 0;				// 0 = falling edge 1 = rising edge
	bitcount = 11;
}

void decode (void)
{
	static uint8_t is_up=0;
	
		if (!is_up)												// Last data received was the up-key identifier
		{
			switch(data){
				case 0xF0 : is_up = 1; break;	//отпускание кнопки
				case 0x05 :								//Стоп 1
				case 0x16 :
				case 0x69 : PORTD |= 0b10000000; break;
				case 0x06 :								//Стоп 2
				case 0x1E :
				case 0x72 : PORTD |= 0b01000000; break;
				case 0x04 :								//Стоп 3
				case 0x26 :
				case 0x7A : PORTC |= 0b00000100; break;
				case 0x0C :								//Стоп 4
				case 0x25 :
				case 0x6B : PORTD |= 0b00100000; break;
				case 0x03 :								//Стоп 5
				case 0x2E :
				case 0x73 : PORTB |= 0b00000010; break;
				case 0x12 :								//Линии
				case 0x59 :
				case 0x7B : PORTC |= 0b00001000; break;
				case 0x14 :								//Уровень
				case 0x79 : PORTB |= 0b00000001; break;
				case 0x29 :								//Старт
				case 0x5A : PORTB |= 0b00000010; break;
				default:break;
				}
		}		
		else
		{
			is_up = 0;								// Two 0xF0 in a row not allowed
			switch(data){
				case 0x05 :								//Стоп 1
				case 0x16 :
				case 0x69 : PORTD &= ~0b10000000; break;
				case 0x06 :								//Стоп 2
				case 0x1E :
				case 0x72 : PORTD &= ~0b01000000; break;
				case 0x04 :								//Стоп 3
				case 0x26 :
				case 0x7A : PORTC &= ~0b00000100; break;
				case 0x0C :								//Стоп 4
				case 0x25 :
				case 0x6B : PORTD &= ~0b00100000; break;
				case 0x03 :								//Стоп 5
				case 0x2E :
				case 0x73 : PORTB &= ~0b00000010; break;
				case 0x12 :								//Линии
				case 0x59 :
				case 0x7B : PORTC &= ~0b00001000; break;
				case 0x14 :								//Уровень
				case 0x79 : PORTB &= ~0b00000001; break;
				case 0x29 :								//Старт
				case 0x5A : PORTB &= ~0b00000010; break;
				default:break;
				}
		}
}

ISR (INT0_vect)
{	
	cli();
		
		if(!timer){
			timer = 1;
			TCNT0 = 0x06;
			TIMSK = 1;
		}
		
	if (!edge)								// Routine entered at falling edge
	{
		if(bitcount < 11 && bitcount > 2)	// Bit 3 to 10 is data. Parity bit,
		{									// start and stop bits are ignored.
			data = (data >> 1);
				if(PIND & 8)
				data = data | 0x80;			// Store a '1'
		}
	MCUCR = 3;								// Set interrupt on rising edge
	edge = 1;
	}
	else
	{										// Routine entered at rising edge
		MCUCR = 2;							// Set interrupt on falling edge
		edge = 0;
		if(--bitcount == 0)					// All bits received
		{
			bitcount = 11;
			TIMSK = 0;
			TCNT0 = 0x06;
			timer = 0;
			decode();
			PORTC &= ~(1<<PC5);
		}
	}
	sei();
}

ISR (TIMER0_OVF_vect)
{
	cli();
		init_kb();
		data = 0;
		PORTC |= 1<<PC5;
		TIMSK = 0;
		timer = 1;
		TCNT0 = 0x00;
	sei();
}