/*
 * TWI_MASTER.c
 *
 * Created: 18.3.2016 1:26:47
 *  Author: tomino
 */ 

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

/********************************************************************************************
									vnitøní funkce
********************************************************************************************/
void nastav_SCL (void)
{
	PORTE |= (1<<PE4);
}

void nuluj_SCL (void)
{
	PORTE &= ~(1<<PE4);
}

void nastav_SDA (void)
{
	PORTE |= (1<<PE5);
}

void nuluj_SDA (void)
{
	PORTE &= ~(1<<PE5);
}

void start_TWI (void)
{
	nastav_SCL();								//SCL jedna
	while( !(PINE & (1<<PINE4)) );				//prazdna smycka ceka na to, dokud SCL nebude nastaveno
	nuluj_SDA();
	_delay_us(1);					            //SDA dolu
	USICR = 0b00101011;							//clock dolu
	nastav_SDA();
		
}

void stop_TWI (void)
{
	USIDR=0b10000000;
	nuluj_SDA();
	PORTE |= (1<<PE4);            // Release SCL.
	while( !(PINE & (1<<PINE4)) );  // Wait for SCL to go high.
	nastav_SDA();            // Release SDA.
}

uint8_t ack(void)
{
	USIDR=0;
	_delay_us(1);
	DDRE &= ~(1<<DDE5);		//SDA vstup
	_delay_us(1);
	nastav_SCL();				// nabezna hrana clocku
	while( !(PINE & (1<<PINE4)) );	// kontrola zapnuti clocku
	nuluj_SCL();
	DDRE |= (1<<DDE5);				//SDA vystup
	//return (USIDR & 1);
	return 0;
}


/***************************************************************************************************************
											VOLATELNE FUNKCE
***************************************************************************************************************/

void zapniTWI_master(void)
{
	nastav_SCL();
	nastav_SDA();
	PORTE |= (1<<PE4);
	PORTE |= (1<<PE5);
	DDRE  |= (1<<DDE5);		//vystup SDA
	DDRE  |= (1<<DDE4);		//vystup SCL
	USIDR=255;
	USISR=0b11110000;
	USICR=0b00101010;
}


uint8_t TWI_data(uint8_t cislo ,uint8_t data, uint8_t adresa)
{
	uint8_t pocitadlo=0, vysledek=0, potvrzeni=0;
	start_TWI();
	USIDR=adresa;
	USISR=0b11110000;
	for (vysledek=0;vysledek<3;vysledek++)
	{
		for(pocitadlo=0;pocitadlo<8;pocitadlo++)		//cyklus zapise 8bitu do sbernice
		{
			_delay_us(1);
			USICR = 0b00101011;				// nabezna hrana clocku
			while( !(PINE & (1<<PINE4)) );	// kontrola zapnuti clocku
			_delay_us(1);
			USICR = 0b00101011;				//sestupna hrana clocku
		}
		USISR=0b11110000;
		potvrzeni = ack();
		if (potvrzeni == 0)					//ack prisel
		{
			if (vysledek==0)
			{
				USIDR=cislo;
			}
			else USIDR=data;
		}
		else
		{
			stop_TWI();
			return 15;			
		}
	}
	stop_TWI();
	return 1;						//pouze pri uspesnem prenosu dat
}


void TWI_instrukce(uint8_t prikaz)
{
	uint8_t pocitadlo=0, vysledek=0;
	USIDR=0;
	start_TWI();
	USISR=0b11110000;
	for (vysledek=0;vysledek<2;vysledek++)
	{
		for(pocitadlo=0;pocitadlo<8;pocitadlo++)		//cyklus zapise 8bitu do sbernice
		{
			_delay_us(1);
			USICR = 0b00101011;				// nabezna hrana clocku
			while( !(PINE & (1<<PINE4)) );	// kontrola zapnuti clocku
			_delay_us(1);
			USICR = 0b00101011;				//sestupna hrana clocku
		}
		USISR=0b11110000;
		ack();
		USIDR=prikaz;
	}
	_delay_ms(1);
	USISR=0b11110000;
	stop_TWI();
}


uint8_t TWI_zeptej_se(uint8_t koho,uint8_t na_co)
{
	koho++;				//tazaci adresa je stejna ale posledni bit se nastavi do jednicky pro cteni
	uint8_t pocitadlo=0, vysledek=0, pocet_bytu=0;
	start_TWI();
	USIDR=koho;
	USISR=0b11110000;
	while (pocet_bytu < 2)
	{
		for(pocitadlo=0;pocitadlo<8;pocitadlo++)		//cyklus zapise 8bitu do sbernice
		{
			_delay_us(1);
			USICR = 0b00101011;				// nabezna hrana clocku
			while( !(PINE & (1<<PINE4)) );	// kontrola zapnuti clocku
			_delay_us(1);
			USICR = 0b00101011;				//sestupna hrana clocku
		}
		USIDR=0;
		vysledek=ack();
		if (vysledek ==0) 
		{
			USIDR=na_co;
			pocet_bytu++;	
		}
		else
		{
			start_TWI();
			pocet_bytu=0;
			USIDR=koho;
		}
		
	}
	//cast pro prijem odpovedi
	_delay_ms(15);						//cas pro protistranu na pripravu/test
	{
		DDRE &= ~(1<<DDE5);				//SDA vstup
		for (vysledek=0;vysledek<8;vysledek++)
		{
			_delay_us(1);
			nastav_SCL();				// nabezna hrana clocku
			while( !(PINE & (1<<PINE4)) );	// kontrola zapnuti clocku
			_delay_us(1);
			nuluj_SCL();
		}
		vysledek=USIDR;
		DDRE |= (1<<DDE5);				//SDA vystup
		_delay_us(1);
		nastav_SCL();				// nabezna hrana clocku
		while( !(PINE & (1<<PINE4)) );	// kontrola zapnuti clocku
		_delay_us(1);
		nuluj_SCL();
		
	}
	stop_TWI();
	return vysledek;

}