/*
 * main.c
 *
 * Created: 2.12.2013 14:08:38
 *  Author: Pavel Marek
 */ 

//# define F_CPU 2000000

#include <avr/io.h>
#include <avr/interrupt.h>
#include "aes.h"
//#include <util/delay.h>

/* Counter of received bytes. */
uint8_t ctr = 0;

/* Buffer for received data and key. */
uint8_t buffer[35];

/* Key, key must be located in RAM. */
uint8_t key[32];

/* Data, you can encrypt what you want but keep in mind that only 128 bits (not less not more) get encrypted. */
uint8_t data[16];

/* The context where the round keys are stored. */
aes256_ctx_t ctx;	

/* Method to initialize serial port */
void serial_init()
{
	/* Set baud rate 9600 bps with 2 MHz. */
	UBRR0H = 0;
	UBRR0L = 12;
	
	/* Enable serial transmission and receive and RX interrupt. */
	UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
	
	/* Set stop bit value as 1 and data frame size as 8 bit (parity is disabled). */
	UCSR0C |= (1 << URSEL0) | (1 << UCSZ00) | (1 << UCSZ01);
}

void switch_init()
{
	/* Set PD as input (Using for interrupt INT0). */
	DDRD =	0x00;
	
	/* Enable PD2 and PD3 pull-up resistor. */											
	PORTD = 1<<PD2 | 1<<PD3;
	
	/* Enable INT0 and INT1. */							
	GICR =	1<<INT0| 1<<INT1;
	
	/* Trigger INT0 and INT1 on rising edge. */								
	MCUCR =	 1<<ISC01 | 1<<ISC00 | 1<<ISC10 | 1<<ISC10;
}

/* Method to initialize key for encryption. */
void key_init()
{	
	for (uint8_t i = 0; i < buffer[1]; i++)
	{
		key[i] = buffer[i+2];	
	}	

	/* Generating the round keys from the 256 bit key. */
	aes256_init(key, &ctx);									
}

/* Method to initialize data for encryption. */
void data_init()
{
	for (uint8_t i = 0; i < buffer[1]; i++)
	{
		data[i] = buffer[i+2];
	}
}

/* Method main. */
int main(void)
{
	/* Set PB and PC as output. */
	DDRB  = 0xFF;
	PORTB = 0xFF;
	DDRC  = 0xFF;
	PORTC = 0xFF;
	
	CLKPR = 0B10000000;					// enable CLKPR change
	CLKPR = 0B00000010;					// set scale factor to 4
	
	serial_init();
	switch_init();
	
	/* Enable global interrupt. */
	sei();

	while(1)
    {
		PORTC = ~0b00000011;
		
		if (buffer[0] == 1)
		{
			PORTC = ~0b00000000;
			
			for (;;)
			{
				data_init();

				/* Encrypting the data block. */
				aes256_enc(data, &ctx);

				if (buffer[0] == 0xFF)
				{
					break;	
				}
			}
		}	
    }
}

/* USART RX interrupt. */
ISR(USART0_RXC_vect	)
{
	/* Received key or data to aux. buffer. */
	while((UCSR0A&0x80)==0x00);
	buffer[ctr] = UDR0;
	ctr += 1;
	
	/* Prijem klice. */
	if (ctr == 35 && buffer[0] == 0x00 && buffer[34] == 0xFF)
	{
		ctr = 0;
		key_init();
	}
	/* Prijem dat. */
	else if (ctr == 19 && buffer[0] == 0x01 && buffer[18] == 0xFF)
	{
		ctr = 0;
		data_init();
	}
	
	/* Prijem ACK. */
	else if (ctr == 4 && buffer[0] == 0x02 && buffer[3 == 0xFF])
	{
		ctr = 0;
		buffer[0] = 0xFF;
	}	
}

/* INT0 interrupt. */
ISR(INT0_vect)
{							
	/* Send data to Matlab. */
	for (uint8_t i = 0; i < 16; i++)
	{
		while((UCSR0A&0x20)==0x00);
		UDR0 = data[i];
		while((UCSR0A&0x40)==0x00);
	}
}

/* INT1 interrupt. */
ISR(INT1_vect)
{
	buffer[0] = 0xFF;
}

/* Poznamka: Preruseni INT0_vect a INT1_vect je vyuzito pouze pro overeni funkci. */