/*
 * TITLE		: 	SPI DRIVER FOR AT91SAM7S256
 * AUTHOR		:	BALAJI VENKATACHALAM
 * DATE			:	2ND OCTOBER 2008
 * FILENAME		:	spi.c
 * DESCRIPTION	:	COMPRISES 3 FUNCTIONS.
 * 					1. void spiInit(void) 		- Initializes SPI peripheral
 * 					2. u08 spiTransferByte(u08)	- Transfer a Character
 * 					3. u16 spiTransferWord(u16)	- Transfer a Word
 * */

#include "at91sam7s64.h"
#include "global.h"
#include "spi.h"

#ifndef SPI_SCKDIV
#define SPI_SCKDIV		2
#endif

AT91PS_SPI pSPI = AT91C_BASE_SPI;

void spiInit(void)
{
	AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_SPI);
	 //PIO PINS SETUP FOR SPI BUS
    *AT91C_PIOA_ASR   = AT91C_PA12_MISO|AT91C_PA13_MOSI|AT91C_PA14_SPCK;	// assign pins to SPI interface
    *AT91C_PIOA_PDR   = AT91C_PA12_MISO|AT91C_PA13_MOSI|AT91C_PA14_SPCK;
    *AT91C_PIOA_PPUER = AT91C_PA12_MISO|AT91C_PA13_MOSI|AT91C_PA14_SPCK;	// set pullups
    //CHIP SELECT SETTINGS
    AT91C_BASE_PIOA->PIO_ASR = AT91C_PA11_NPCS0;
	AT91C_BASE_PIOA->PIO_PDR = AT91C_PA11_NPCS0;
	AT91C_BASE_PIOA->PIO_OER = AT91C_PA11_NPCS0;
    
    //SPI CONTROL REGISTER
    //=========================================================================================
    //| -------- | -------- | -------- | -------- | -------- | -------- | -------- | LASTXFER |
    //=========================================================================================
    
    //=========================================================================================
    //| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
    //========================================================================================= 
    
    //=========================================================================================
    //| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
    //=========================================================================================
    
    //=========================================================================================
    //|  SWRST   | -------- | -------- | -------- | -------- | -------- |  SPIDIS  |   SPEN   |
    //=========================================================================================
    pSPI->SPI_CR = (AT91C_SPI_SPIEN | AT91C_SPI_SWRST);	
    pSPI->SPI_CR = AT91C_SPI_SPIEN;
    
    //SPI MODE REGISTER
    //=========================================================================================
    //|                                         DLYBCS                                        |
    //=========================================================================================
    
    //=========================================================================================
    //| -------- | -------- | -------- | -------- |                    PCS                    |
    //========================================================================================= 
    
    //=========================================================================================
    //| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
    //=========================================================================================
    
    //=========================================================================================
    //|   LLB    | -------- | -------- |  MODFDIS | -------- |  PCSDEC  |    PS    |   MSTR   |
    //=========================================================================================
    
    pSPI->SPI_MR = (AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PS_FIXED | ((0x0)<<16));
    //SPI CHIP SELECT REGISTER 0 
    //=========================================================================================
    //|                                         DLYBCT                                        |
    //=========================================================================================
    
    //=========================================================================================
    //|                                          DLYBS                                        |
    //========================================================================================= 
    
    //=========================================================================================
    //|                                          SCBR                                         |
    //=========================================================================================
    
    //=========================================================================================
    //|                 BITS                      |   CSAAT  | -------- |   NCPHA  |   CPOL   |
    //=========================================================================================
    pSPI->SPI_CSR[0] = (AT91C_SPI_CPOL | AT91C_SPI_NCPHA | AT91C_SPI_CSAAT | AT91C_SPI_BITS_8 | AT91C_SPI_SCBR | AT91C_SPI_SCBR | AT91C_SPI_DLYBCT);
    
    
}

u08 spiTransferByte(u08 TxData) 
{ 
	unsigned char RxData = 0;
	//ENABLE 8 BIT TRANSFER
	pSPI->SPI_CSR[0] |= AT91C_SPI_BITS_8;
	//MASK UNUSED BITS
	TxData &= 0x000000FF;
	//WAIT UNTIL TRANSMIT REGISTER IS EMPTY
	while (!(pSPI ->SPI_SR & AT91C_SPI_TXEMPTY));
	// TRANSMIT DATA	  
	pSPI ->SPI_TDR = TxData;
	//READ THE RECEIVED DATA
	//WAIT UNTIL RECEIVE REGISTER IS FULL
	while (!(pSPI -> SPI_SR & AT91C_SPI_RDRF));
	//READ RDR AND MASK UNUSED BITS	  
	RxData = (pSPI -> SPI_RDR & 0x000000FF); 
	return RxData; 
}
u16 spiTransferWord(u16 TxData) 
{ 
	unsigned int RxData = 0;
	//ENABLE 16 BIT TRANSFER
	pSPI->SPI_CSR[0] |= AT91C_SPI_BITS_16;
	//MASK UNUSED BITS
	TxData &= 0x0000FFFF;
	//WAIT UNTIL TRANSMIT REGISTER IS EMPTY
	while (!(pSPI ->SPI_SR & AT91C_SPI_TXEMPTY));
	// TRANSMIT DATA	  
	pSPI ->SPI_TDR = TxData;
	//READ THE RECEIVED DATA
	//WAIT UNTIL RECEIVE REGISTER IS FULL
	while (!(pSPI -> SPI_SR & AT91C_SPI_RDRF));
	//READ RDR AND MASK UNUSED BITS	  
	RxData = (pSPI -> SPI_RDR & 0x0000FFFF); 
	return RxData; 
}


