#include "spi.h"

#include <avr/io.h>
#include <avr/interrupt.h>

#define PORT_SPI    PORTA
#define DDR_SPI     DDRA
#define DD_SCK      DDA4
#define DD_MISO     DDA5
#define DD_MOSI     DDA6
#define DD_SS       DDA7



void spi_init()
// Initialize pins for spi communication
{
	DDR_SPI &= ~((1<<DD_MOSI)|(1<<DD_MISO)|(1<<DD_SS)|(1<<DD_SCK));
	// Define the following pins as output
	DDR_SPI |= ((1<<DD_MOSI)|(1<<DD_SS)|(1<<DD_SCK));
}

void spi_transfer_sync (uint8_t * dataout, uint8_t * datain, uint8_t len)
// Shift full array through target device
{
	uint8_t i;
	for (i = 0; i < len; i++) {
		USIDR = dataout[i];
		USISR = (1<<USIOIF);
		do
		{
			USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
		}
		while( !(USISR & (1<<USIOIF)) );
		datain[i] = USIDR;
	}
}

void spi_transmit_sync (uint8_t * dataout, uint8_t len)
// Shift full array to target device without receiving any byte
{
	uint8_t i;
	for (i = 0; i < len; i++) {
		USIDR = dataout[i];
		USISR = (1<<USIOIF);
		do
		{
			USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
		}
		while( !(USISR & (1<<USIOIF)) );
	}
}

uint8_t spi_fast_shift (uint8_t data)
// Clocks only one byte to target device and returns the received one
{
	USIDR = data;
	USISR = (1<<USIOIF);
	do
	{
		USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
	}
	while( !(USISR & (1<<USIOIF)) );
	return USIDR;
}