#include "spi.h"

#include <avr/io.h>
#include <avr/interrupt.h>

#define PORT_SPI    PORTB
#define DDR_SPI     DDRB
#define DD_MISO     DDB4
#define DD_MOSI     DDB3
#define DD_SS       DDB2
#define DD_SCK      DDB5


void spi_init()
// Initialize pins for spi communication
{
		//Intialise the SPI-USI Communication
		DDRB |= (1<<DD_SS) | (1<<DD_SCK) | (1<<DD_MISO);
		DDRB &= ~(1<<DD_MOSI);
		PORTB |= (1<<DD_MOSI);
		
		USICR |= (1<<USIWM0) | (1<<USICS1) | (1<<USICLK); // Three-Wire Mode - Uses DO, DI, and USCK pins; 
		PORTB|= (1 << DD_SS);
}

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];
		while(!(USISR & (1<<USIOIF))){
			USICR |= (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
		}
		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];
		while(!(USISR & (1<<USIOIF))){
			USICR |= (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
		}
	}
}

uint8_t spi_fast_shift (uint8_t data)
{
	// load USI Data Register with data to transmit
	USIDR = data;
	while(!(USISR & (1<<USIOIF))){
		USICR |= (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
	}
	return USIDR;
}
