/****************************************************************************
 *
 * Projekt			:	Magnetfeldmessgerät
 * Dateiname		:	SPI.h
 * Autor			:	Eros Schatzmayer
 * Erstellungsdatum	:	18.06.2020
 * Beschreibung		:	"SPI Treiber"
 *
 *
 * Versionsgeschichte
 * 	Revision 1.0	18.06.2020
 *
 ****************************************************************************/

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

uint8_t SPITransmitting;
uint8_t gudt_ReceivedData;

void SPIInit(uint8_t u8_SPE)
{
	// MOSI, SCK, und SS pins als Ausgänge definieren
	DDRB |= (1 << PB5) | (1 << PB7) | (1 << PB4); 
	
	// MISO als Eingang definieren
	DDRB &= ~(1 << PB6);
	
	// SPI Register initialisieren
	SPCR =	(0 << SPIE)		|	// SPI Interrupt enable
			(u8_SPE << SPE)	|	// SPIE Enable
			(0 << DORD)		|	// Data order			--> 1 = LSB first, 0 = MSB first
			(1 << MSTR)		|	// Master/Slave select	--> 1 = Master Mode, 0 = Slave
			(0 << CPOL)		|	// Clock Polarity		--> 1 = SCK high when idle, 0 = SCK low when idle
			(0 << CPHA)		|	// Clock Phase			--> 1 = Sample on Trailing Edge, 0 = Sample on Leading Edge
			(0 << SPR1)		|	// SPI Clock Rate Select
			(1 << SPR0);		// f_osc/8
	SPSR = 1;					// Sets SPI2X Double Speed bit. SCK Frequency will be doubled when the SPI is in Master mode
	
	// Die aktuellen Einstellungen löschen das SPI Interrupt Flag im Register SPSR,
	// also wird das globale Flag genutzt um zu signalisieren, dass noch keine Übertragung stattfindet
	SPITransmitting = 0;
}

void SPITransmit(uint8_t data)
{
	// Globales Flag abfragen, ob gerade eine Übertragung stattfindet
	if (SPITransmitting)
	{
		while ( ! (SPSR & (1 << SPIF)));  // Warten bis aktuelle Übertragung abgeschlossen
	}
	SPDR = data;				// Übertragung starten
	SPITransmitting = 1;	// Mit dem Flag kennzeichnen, dass eine Übertragung in Arbeit ist
}

uint8_t SPIReceive(uint8_t data)	// data ist in der Regel ein dummy byte --> 0
{
	if (SPITransmitting)
	{
		while ( ! (SPSR & (1 << SPIF)));  // Warten bis aktuelle Übertragung abgeschlossen
	}
	_delay_us(3);

	
	SPDR = data;							// Bidirektionalen Transfer starten
	while ( ! (SPSR & (1 << SPIF)));		// Warten bis Übertragung abgeschlossen
	
	// Die aktuellen Einstellungen löschen das SPI Interrupt Flag im Register SPSR,
	// also wird das globale Flag genutzt um zu signalisieren, dass noch keine Übertragung stattfindet
	SPITransmitting = 0;
	return SPDR;
}

uint16_t SPIReceive16Bit(uint8_t dataMSB, uint8_t dataLSB)
{
	uint8_t u8_adcRegMSB, u8_adcRegLSB, u8_configRegMSB, u8_configRegLSB;
	uint16_t u16_result;
	
	if (SPITransmitting)
	{
		while ( ! (SPSR & (1 << SPIF)));  // Warten bis aktuelle Übertragung abgeschlossen
	}
	_delay_us(3);
	
	// 1. Byte
	SPDR = dataMSB;							// Sende Konfigurationsregister MSB
	while ( ! (SPSR & (1 << SPIF)));		// Warten bis Übertragung abgeschlossen
	u8_adcRegMSB = SPDR;
	
	// 2. Byte
	SPDR = dataLSB;
	while ( ! (SPSR & (1 << SPIF)));		// Warten bis Übertragung abgeschlossen
	u8_adcRegLSB = SPDR;
	
	
	// Die aktuellen Einstellungen löschen das SPI Interrupt Flag im Register SPSR,
	// also wird das globale Flag genutzt um zu signalisieren, dass noch keine Übertragung stattfindet
	SPITransmitting = 0;
	
	// Aus 2 8-Bit-Zahlen eine 16-Bit-Zahl machen
	u16_result = ((uint16_t)u8_adcRegMSB << 8) | u8_adcRegLSB;
	
	return u16_result;
}
