/****************************************************************************//**
  \file spiMemInterface.c

  \brief Implementation of external spi memory interface.

  \author
    Atmel Corporation: http://www.atmel.com \n
    Support email: avr@atmel.com

  Copyright (c) 2008-2015, Atmel Corporation. All rights reserved.
  Licensed under Atmel's Limited License Agreement (BitCloudTM).

  \internal
  History:
    02/01/13 Agasthian - Created
*******************************************************************************/
/******************************************************************************
                   Includes section
******************************************************************************/
#ifdef EXT_MEMORY
#include <atomic.h>
#include <spiMemInterface.h>
#include <wdt.h>

/******************************************************************************
                   global variables section
******************************************************************************/
SpiChannel_t spiTty;

/******************************************************************************
                   Implementations section
******************************************************************************/
static inline bool hwSpiCtrlBSyncing(SpiChannel_t tty)
{
  return (tty->SYNCBUSY.reg & SC4_SPI_SYNCBUSY_CTRLB);
}
/*****************************************************************************
Inline function to check the SPI ENABLE BUSY status
*****************************************************************************/
static inline bool hwSpiEnableSyncing(SpiChannel_t tty)
{
  return (tty->SYNCBUSY.reg & SC4_SPI_SYNCBUSY_ENABLE);
}
/*****************************************************************************
Inline function to check the SPI ENABLE BUSY status
*****************************************************************************/
static inline bool hwSpiSwrstSyncing(SpiChannel_t tty)
{
  return (tty->SYNCBUSY.reg & SC4_SPI_SYNCBUSY_SWRST);
}
/**************************************************************************//**
\brief Initializes spi.
******************************************************************************/
void spiMemInit(void)
{
  spiTty = SPI_CHANNEL;

  /* Configure PIOs for SPI */
  GPIO_EXT_MEM_CS_make_out();
  GPIO_SPI_MISO_make_in();
  GPIO_SPI_MOSI_make_out();
  GPIO_SPI_SCK_make_out();

  GPIO_SPI_MISO_pmuxen();
  GPIO_SPI_MOSI_pmuxen();
  GPIO_SPI_SCK_pmuxen();

  GPIO_SPI_SCK_config_pin();
  GPIO_SPI_MISO_config_pin();
  GPIO_SPI_MOSI_config_pin();

  PM_APBCMASK |= (1 << (2 + SPI_SERCOM));

  /* clk settings */
  GCLK_CLKCTRL_s.id = SPI_SERCOM_CLOCK(SPI_SERCOM);
  GCLK_CLKCTRL_s.gen = 0;
  GCLK_CLKCTRL_s.clken = 1;

  /* Reset */
  spiTty->CTRLA.bit.SWRST = 1;
  while(hwSpiSwrstSyncing(spiTty));

  spiTty->CTRLB.reg  = SC4_SPI_CTRLB_RXEN;
  while(hwSpiCtrlBSyncing(spiTty));

  spiTty->BAUD.reg = SPI_CLOCK_RATE_2000;

  /* setup spi mode master, pad & enable it */
  spiTty->CTRLA.reg |=  SC3_SPI_CTRLA_MODE(3) | SC3_SPI_CTRLA_DOPO(SPI_CTRLA_DOPO) | SC3_SPI_CTRLA_DIPO(SPI_CTRLA_DIPO) | SC3_SPI_CTRLA_ENABLE;
  while(hwSpiEnableSyncing(spiTty));

}

/**************************************************************************//**
\brief Writes or reads a length bytes from the external spi memory.

\param[in]
  type   -  transaction type;
\param[in]
  buffer -  pointer to the data buffer;
\param[in]
  length -  number bytes for transfer;
******************************************************************************/
void spiMemTransac(TransactionType_t type, uint8_t *buffer, uint16_t length)
{
  uint16_t i;
  uint8_t temp;

  hwRestartWdt();

  for (i = 0; i < length; i++)
  {
    ATOMIC_SECTION_ENTER
    spiTty->DATA.reg = buffer[i];
    while (!(spiTty->INTFLAG.reg & SC4_SPI_INTFLAG_RXC));
    ATOMIC_SECTION_LEAVE

    if (SPI_TRANSACTION_TYPE_WRITE  == type)
      temp = spiTty->DATA.reg;   
    else
      buffer[i] = spiTty->DATA.reg;

  }
  (void)temp;
}

/**************************************************************************//**
\brief Unintializies usart.
******************************************************************************/
void spiMemUnInit(void)
{
#if (USE_SPI == 1)
  GPIO_EXT_MEM_CS_set();
  // disable spi
  spiTty->CTRLA.bit.ENABLE = 0x00; // disable
  
  GPIO_EXT_MEM_CS_make_in();
  GPIO_SPI_MOSI_make_in();
  GPIO_SPI_SCK_make_in();
#endif //(USE_SPI != 1)  
}
#endif //EXT_MEMORY

// eof spiMemInterface.c

