#include "AT91SAM7X512.h"



int at45db_init(void)
{

	AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SPI0;

	// Configure PIO controllers to periph mode
	AT91C_BASE_PIOA->PIO_ASR = ((unsigned int) AT91C_PA16_SPI0_MISO   ) |
	((unsigned int) AT91C_PA17_SPI0_MOSI   ) |
	((unsigned int) AT91C_PA18_SPI0_SPCK   ) |
	((unsigned int) AT91C_PA12_SPI0_NPCS0  );
	AT91C_BASE_PIOA->PIO_PDR = (((unsigned int) AT91C_PA16_SPI0_MISO   ) |
	((unsigned int) AT91C_PA17_SPI0_MOSI   ) |
	((unsigned int) AT91C_PA18_SPI0_SPCK   ) |
	((unsigned int) AT91C_PA12_SPI0_NPCS0  ));// | ((unsigned int) AT91C_PA7_SPI0_NPCS1  ) |



// Control register
	AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SWRST;         	// SPI SW reset
	AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SWRST;         	// SPI SW reset
// Mode register
	AT91C_BASE_SPI0->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED | AT91C_SPI_MODFDIS;  //
// Control register
	AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SPIEN;         	// SPI Enable

	return 0;
}
int at45db_cs_down(void)
{
// Chip select register

	AT91C_BASE_SPI0->SPI_CSR[0] = AT91C_SPI_CPOL | AT91C_SPI_NCPHA | AT91C_SPI_CSAAT | AT91C_SPI_BITS_8 | (4 << 8);

	return 0;
}

int at45db_cs_up(void)
{
// Control register
	AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_LASTXFER;         	// Last Tx transfer

	return 0;
}

unsigned char at45db_write_byte(unsigned char data)
{
//send data
    AT91C_BASE_SPI0->SPI_TDR = data;

//wait for sending
  while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);

//check if data received
  while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_RDRF) == 0);

  return AT91C_BASE_SPI0->SPI_RDR & 0xFF;
}
int at45db_write(unsigned int addr1, unsigned int addr2, unsigned int addr3, unsigned char *data, unsigned int length)
{
  unsigned int i;

  at45db_init();
  at45db_cs_down();
//OP code
  at45db_write_byte(0x82);

//address
  at45db_write_byte(addr1);
  at45db_write_byte(addr2);
  at45db_write_byte(addr3);

//data
  for (i = 0; i < length; i++)
  {
	at45db_write_byte(data[i]);
  }
  at45db_write_byte(0x00);
  at45db_cs_up();

  return i;
}

int at45db_read(unsigned int addr1, unsigned int addr2, unsigned int addr3, unsigned char *data, unsigned int length)
{
  unsigned int i;

  at45db_init();
  at45db_cs_down();
//OP code
  at45db_write_byte(0xD2);


//address
  at45db_write_byte(addr1);
  at45db_write_byte(addr2);
  at45db_write_byte(addr3);

//Dont care
  at45db_write_byte(0);
  at45db_write_byte(0);
  at45db_write_byte(0);
  at45db_write_byte(0);

//data
  for (i = 0; i < length; i++)
  {
	  data[i] = at45db_write_byte(i);
  }

  at45db_cs_up();


  return i;

}
