/*#######################################################################################
SPI Funktionen 

Copyright (C) 2005 Branko Golubovic
branko.golubovic@gmx.at
#######################################################################################*/

#include "main.h"
#include "spi.h"



//############################################################################
//Routine zur Initialisierung der SUNCRONOUS PHERIPHERAL INTERFACE (SPI)
void spi_init(void)
//############################################################################
{
	//Konfiguration des SPI Ports
	SPI_Direction &=~(1<<SPI_DI);			//Setzen von Pin SPI_DI auf Input
	SPI_Direction |= (1<<SPI_Clock);		//Setzen von Pin SPI_Clock auf Output
	SPI_Direction |= (1<<SPI_DO);			//Setzen von Pin SPI_DO auf Output
	SPI_Direction |= (1<<SPI_SS);			//Setzen von Pin SPI_SS auf Output
	#if CLOCKPOL	
		SPI_Write |=(1<<SPI_Clock); //erzeugt ein Clock Impuls (High)
	#else
			SPI_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)
	#endif	//CLOCKPOL
	
	#if HARDWARE_SPI
		//Aktiviren des SPI - Bus
		//SPI Clock teilen durch 128
		SPCR = (1<<MSTR)|(B_SPI_MODE)|(B_SPI_PRESCALER); // SPI in Master Mode	
		SPSR = (0<<SPI2X);
		spi_enable();
	#else
		spi_disable();
		
	#endif //HARDWARE_SPI
}

void spi_write(unsigned char Byte)
{
  
	#if	HARDWARE_SPI
	SPDR = Byte; 	//Sendet ein Byte
	while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
	{
	}
	#else			//Routine für Software SPI

	#if MSB_FIRST
		unsigned char Bit=128;	//das Byte wird Bitweise nacheinander Gesendet MSB First
 
	#else
		unsigned char Bit=1;		//das Byte wird Bitweise nacheinander Gesendet LSB First
 	
	#endif	// MSB_FIRST
	
	while(Bit)
	{ 
		#if (CLOCKPHA==0)
		if(Byte&Bit)	//Ist Bit in Byte gesetzt	
				{
				SPI_Write |= (1<<SPI_DO); //Set Output High
				}
			else
				{
				SPI_Write &= ~(1<<SPI_DO); //Set Output Low
				}
		nop();
		#endif // CLOCKPHA==0
		
		#if (CLOCKPOL==1)
			SPI_Write &= ~(1<<SPI_Clock);	//erzeugt ein Clock Impuls (LOW)
			nop();
			SPI_Write |= (1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)
			nop();
		#else
			SPI_Write |= (1<<SPI_Clock); //erzeugt ein Clock Impuls (High)
			nop();
			SPI_Write &= ~(1<<SPI_Clock);	//setzt Clock Impuls wieder auf (LOW)
			nop();
		#endif // CLOCKPOL
		
		#if (CLOCKPHA==1)
		if(Byte&Bit)	//Ist Bit a in Byte gesetzt 
				{
				SPI_Write |= (1<<SPI_DO); //Set Output High
				}
			else
				{
				SPI_Write &= ~(1<<SPI_DO); //Set Output Low
				}
		#endif // CLOCKPHA==1
	#if MSB_FIRST
		Bit/=2;
	#else
		Bit*=2;
	#endif	// MSB_FIRST
	}
#endif	// HARDWARE_SPI
}

unsigned char spi_read(void)
{
	unsigned char Byte = 0;
#if HARDWARE_SPI	//Routine für Hardware SPI
	SPDR = 0;
	while(!(SPSR & (1<<SPIF))){};
	Byte = SPDR;

#else			//Routine für Software SPI
	#if MSB_FIRST
		unsigned char Bit=128;
	#else
		unsigned char Bit=1;	
	#endif	// MSB_FIRST
	  while(Bit)
		{
		#if (CLOCKPHA==0) // Lesen mit erste Flanke
		if (bit_is_set(SPI_Read,SPI_DI) > 0) //Lesen des Pegels von MISO
				{
				Byte |=Bit;
				}
			else
				{
				Byte &=~Bit;
				}
		#endif // (CLOCKPHA==0)		
		
		#if (CLOCKPOL==0)	// Erste CLOCK Flanke
			SPI_Write |=(1<<SPI_Clock); //erzeugt ein Clock Impuls (High)
		#else
			SPI_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)	
		#endif	//CLOCKPOL
		nop();
		
				#if (CLOCKPHA==1) // Lesen mit Zweite Flanke
		if (bit_is_set(SPI_Read,SPI_DI) > 0) //Lesen des Pegels von MISO
				{
				Byte |= Bit;
				}
			else
				{
				Byte &=~Bit;
				}
		#endif // (CLOCKPHA==1)

		
		#if (CLOCKPOL==1) // Zweite CLOCK Flanke
			SPI_Write |=(1<<SPI_Clock); //erzeugt ein Clock Impuls (High)
		#else
			SPI_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)
		#endif	//CLOCKPOL
		nop();
		#if MSB_FIRST
			Bit/=2;
		#else
			Bit*=2;
		#endif	// MSB_FIRST
		}

#endif // HARDWARE_SPI
	return (Byte);
}

unsigned char spi_read_write(unsigned char Byte)
{
	unsigned char Data ;
#if HARDWARE_SPI	//Routine für Hardware SPI
	
	SPDR = Byte;
	while(!(SPSR & (1<<SPIF))){};
	Data = SPDR;
	
	#else			//Routine für Software SPI
	#if MSB_FIRST
		unsigned char Bit=128;//das Byte wird Bitweise nacheinander Gesendet MSB First
	#else
		unsigned char Bit=1;//das Byte wird Bitweise nacheinander Gesendet LSB First	 
	#endif	// MSB_FIRST
		while(Bit)
		{
		#if (CLOCKPHA==0) // Schreiben  mit Erste Flanke
			if (Byte&Bit)	//Ist Bit a in Byte gesetzt
				{
				SPI_Write |= (1<<SPI_DO); //Set Output High
				}
			else
				{
				SPI_Write &= ~(1<<SPI_DO); //Set Output Low
				}
				
			if (bit_is_set(SPI_Read,SPI_DI) > 0) // Lesen mit Erste Flanke
				{
				Data |= Bit;
				}
			else
				{
				Data &=~Bit;
				}
		#endif // (CLOCKPHA==0)
		
		#if (CLOCKPOL==0)	// Erste CLOCK Flanke
			SPI_Write |=(1<<SPI_Clock); //erzeugt ein Clock Impuls (High)
		#else
			SPI_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)
		#endif	//CLOCKPOL
		nop(); 

		#if (CLOCKPHA==1)
			if(Byte&Bit)	// Schreiben  mit Zweite Flanke
				{
				SPI_Write |= (1<<SPI_DO); //Set Output High
				}
			else
				{
				SPI_Write &= ~(1<<SPI_DO); //Set Output Low
				}
				
			if (bit_is_set(SPI_Read,SPI_DI) > 0) //  Lesen mit Zweite Flanke
				{
				Data |= Bit);
				}
			else
				{
				Data &=~Bit;
				}
		#endif // (CLOCKPHA==1)
		
		#if (CLOCKPOL==1) // Zweite CLOCK Flanke
			SPI_Write |=(1<<SPI_Clock); //erzeugt ein Clock Impuls (High)
		#else
			SPI_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)
		#endif	//CLOCKPOL
		nop();
		#if MSB_FIRST
			Bit/=2;
			#else
			Bit*=2;
			#endif	// MSB_FIRST	
		}

#endif // HARDWARE_SPI
	return (Data);
}


