/*
 * TWI_slave.c
 *
 * Created: 21.3.2016 12:49:40
 *  Author: tomino
 */ 


#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include "TWI_slave.h"

static uint8_t adress;


void zapniTWI_slave(uint8_t adresa)
{
	//nastavi vlastni adresy na ktere zarizeni "slysi"
	adress=adresa;
	DDRE &= ~(1<<DDE4);		//SCL vstup
	DDRE &= ~(1<<DDE5);		//SDA vstup
	USICR=0b10101000;		//control register
	USISR=0b11110000;		//status register
}

uint8_t checkuj_adresu()
{
	uint8_t buff=0,vysledek;
	DDRE &= ~(1<<DDE5);		//nastavi SDA jako vstup
	USISR=0b00110000;		//nuluje flag pro preruseni a counter
	while ((USISR & 0b0001111)<=0b00001110) //ceka do naplneni counteru a flag
	{
	}
	vysledek=USIDR;
	/*overeni adresy a zaslani ACKnowledge */
	if ((vysledek & 0b11111110)==adress)
	{
		buff=vysledek;
		USIDR = 0;				//data buffer nula
		DDRE |= (1<<DDE5);		//SDA jako vystup
		_delay_us(1);
		while( !(PINE & (1<<PINE4)) );	//ceka na CLK 1
		while( (PINE & (1<<PINE4)) );	//ceka na CLK 0
		DDRE &= ~(1<<DDE5);		//nastavi SDA jako vstup
		if ((buff & 0b00000001)==0) return 1;			//je treba prijmout data
		else return 2;									//je treba odpovedet na dotaz
	}
	else if ((vysledek & 0b11111110)==0)					//univerzalni adresa pro vsechny
	{
		buff=vysledek;
		USIDR = 255;				//data buffer 255 neumozni ACK
		while( !(PINE & (1<<PINE4)) );	//ceka na CLK 1
		while( (PINE & (1<<PINE4)) );	//ceka na CLK 0
		DDRE &= ~(1<<DDE5);		//nastavi SDA jako vstup
		if ((buff & 0b00000001)==0) return 3;			//je treba prijmout data
		else return 4;									//je treba odpovedet na dotaz
		
		return 3;			//je treba odeslat data
	}
	return 25;
}

void precti_data (uint8_t *data)
{
	uint8_t instrukce=0, i=0, adresa=0;
	
	for (i=0;i<2;i++)
	{
		USIDR=0;
		DDRE &= ~(1<<DDE5);		//nastavi SDA jako vstup
		USISR=0b00110000;		//nuluje flag pro preruseni a counter
		while ((USISR & 0b0001111)<=0b00001110) //ceka do naplneni counteru
		{
			
		}
		instrukce=USIDR;
		USIDR = 0;				//data buffer nula
		DDRE |= (1<<DDE5);		//SDA jako vystup
		_delay_us(1);
		while( !(PINE & (1<<PINE4)) );	//ceka na CLK 1
		while( (PINE & (1<<PINE4)) );	//ceka na CLK 0
		DDRE &= ~(1<<DDE5);		//nastavi SDA jako vstup
		if (i==0) adresa=instrukce;
		else 
		{
			if (data[2*adresa-1]==0)
			{
				data[2*adresa-1]=instrukce;
			} 
			else
			{
				data[2*adresa]=instrukce;
			}
		}
		
	}
	
	
}	


uint8_t precti_instrukci (void)
{
	uint8_t instrukce=0;
	USIDR=0;
	DDRE &= ~(1<<DDE5);		//nastavi SDA jako vstup
	USISR=0b00110000;		//nuluje flag pro preruseni a counter
	while ((USISR & 0b0001111)<=0b00001110) //ceka do naplneni counteru
	{
		
	}
	instrukce=USIDR;
	USIDR = 0;	
	DDRE |= (1<<DDE5);		//SDA jako vystup
	while( !(PINE & (1<<PINE4)) );	//ceka na CLK 1
	while( (PINE & (1<<PINE4)) );	//ceka na CLK 0
	DDRE &= ~(1<<DDE5);		//nastavi SDA jako vstup
	USICR=0b10101000;
	USISR=0b11110000;
	return instrukce;
}

void odesli_odpoved (uint8_t odpoved)
{
	uint8_t i=0;
	USISR=0b01110000;
	USIDR=odpoved;
	DDRE |= (1<<DDE5);		//SDA jako vystup
	PORTE |= (1<<PE5);
	while (i<8)
	{
		while( !(PINE & (1<<PINE4)) );
		i++;
		while( (PINE & (1<<PINE4)) );
	}
	USISR=0b11110000;
	DDRE &= ~(1<<DDE5);		//nastavi SDA jako vstup	
}
