/*
 * SPI_master.c
 *
 * Created: 23.3.2016 11:59:47
 *  Author: tomino
 */
#include <avr/io.h>
#include <util/delay.h>


uint32_t adresa (uint16_t soubor)
{
	uint32_t adr=0;
	while (soubor !=0)
	{
		adr= adr+4096;
		soubor--;
	}
	return adr;
}


uint8_t SPI_nahrej(uint8_t co)
{
	uint8_t vysledek=0;
	
	SPDR = co;						//data register vezme promennou k odeslani
	while(!(SPSR & (1<<SPIF)))		//ceka na flag po dokonceni prenosu bytu
	{
		
	}
	vysledek=SPDR;					//prijaty byte nahraje do pameti jako vysledek
	
	return vysledek;				//vrati hodnotu obdrzenou zpet
}


void zapni_SPI_master(void)
{
	/* Set MOSI, SCK and CS output, all others input */
	DDRB = (1<<DDB2)|(1<<DDB1)|(1<<DDB0);
	/* Enable SPI, Master, set clock rate fck/16 */
	SPCR=0b01010011;
	PORTB |= (1<<PB0);
	
}


void SPI_zapis(const uint8_t *data, uint16_t soubor)
{
	//ziskani adresy
	uint32_t adr=0, i=0;
	uint8_t adr_1=0, adr_2=0, adr_3=0, pocitadlo=0;
	adr=adresa(soubor);				//4bajty, tri z nich obsahuji adresu
	//deleni adresy do jednotlivych bajtu
	adr_3=adr;
	adr_2=adr>>8;
	adr_1=adr>>16;
	
	//umozneni prenosu
	PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
	SPI_nahrej(6);					//write enable
	PORTB |= (1<<PB0);				//uzavre kanal k pameti
	PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
	SPI_nahrej(2);					//write instruction	
		
	//adresa (3byty)
	SPI_nahrej(adr_1);
	SPI_nahrej(adr_2);
	SPI_nahrej(adr_3);
	i=0;
	while (data[i]!=0)		//prohledava zdrojova data a dokud nejsou nula tak zapisuje
	{
		SPI_nahrej(data[i]);
		i++;
		pocitadlo++;
		if (i == 255)
		{
			SPI_nahrej(data[i]);
			i++;
			//ukonceni prenosu a zacatek ukladani na dalsi strance
			PORTB |= (1<<PB0);				//uzavre kanal k pameti
			PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
			SPI_nahrej(4);					//write disable
			PORTB |= (1<<PB0);				//uzavre kanal k pameti
			_delay_us(750);					//zpozdeni aby se stihly vykonat predchozi prikazy
			PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
			SPI_nahrej(6);					//write enable
			PORTB |= (1<<PB0);				//uzavre kanal k pameti
			PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
			SPI_nahrej(2);					//write instruction
			
			//adresa (3byty)
			SPI_nahrej(0);
			SPI_nahrej(1);
			SPI_nahrej(0);
			pocitadlo=0;
		}
	}
	
	SPI_nahrej(0);
	//ukonceni prenosu
	PORTB |= (1<<PB0);				//uzavre kanal k pameti
	PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
	SPI_nahrej(4);					//write disable
	PORTB |= (1<<PB0);				//uzavre kanal k pameti
}


void SPI_precti(uint16_t soubor)
{	
	//ziskani adresy
	uint32_t adr=0;					
	uint8_t adr_1=0, adr_2=0, adr_3=0;
	adr=adresa(soubor);				//4bajty, tri z nich obsahuji adresu
	//deleni adresy do jednotlivych bajtu
	adr_3=adr;
	adr_2=adr>>8;
	adr_1=adr>>16;
	
	PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
	SPI_nahrej(3);					//prikaz pro cteni
	
	//adresa (3byty)
	SPI_nahrej(adr_1);
	SPI_nahrej(adr_2);
	SPI_nahrej(adr_3);
	
	//cteni	
	adr=0;
	SPI_nahrej(15);
	while (SPDR!=0)
	{	
		adr++;
		SPI_nahrej(15);
		_delay_ms(1000);
	}
	_delay_ms(400);
	PORTB |= (1<<PB0);				//uzavre kanal k pameti
}


void SPI_vymaz(uint16_t soubor)
{
	//ziskani adresy
	uint32_t adr=0;
	uint8_t adr_1=0, adr_2=0, adr_3=0;
	adr=adresa(soubor);				//4bajty, tri z nich obsahuji adresu
	//deleni adresy do jednotlivych bajtu
	adr_3=adr;
	adr_2=adr>>8;
	adr_1=adr>>16;
	//pro umozneni vymazani je nutne umoznit zapisovani
	PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
	SPI_nahrej(6);					//write enable
	PORTB |= (1<<PB0);				//uzavre kanal k pameti
	
	PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
	SPI_nahrej(0b00100000);			//subsector erase
	//adresa
	SPI_nahrej(adr_1);
	SPI_nahrej(adr_2);
	SPI_nahrej(adr_3);
	PORTB |= (1<<PB0);				//uzavre kanal k pameti
	_delay_ms(150);					//zpozdeni pro nejdelsi cas pro vymazani subsektoru
	//po dokonceni mazani se zakaze zapis
	PORTB &= ~(1<<PB0);				//CS je nula pro otevreni kanalu
	SPI_nahrej(4);					//write disable
	PORTB |= (1<<PB0);				//uzavre kanal k pameti
}