/*----------------------------------------------------------------------------
 *      RL-ARM - FlashFS
 *----------------------------------------------------------------------------
 *      Name:    SPI_STM32F107.c
 *      Purpose: Serial Peripheral Interface Driver for ST STM32F105/7
 *      Rev.:    V4.20
 *----------------------------------------------------------------------------
 *      This code is part of the RealView Run-Time Library.
 *      Copyright (c) 2004-2011 KEIL - An ARM Company. All rights reserved.
 *---------------------------------------------------------------------------*/

#include <File_Config.h>
#include <stdio.h> 

#include "stm32f10x.h"



/*##################### SPI1 ###################################*/
#define EVAL_SPIx                               SPI1
#define EVAL_SPIx_CLK	                          RCC_APB2Periph_SPI1
	 
	 
#define EVAL_SPIx_GPIO_CLK                      RCC_APB2Periph_GPIOA

#define EVAL_SPIx_MISO_MOSI_SCK_GPIO_PORT       GPIOA
#define EVAL_SPIx_MISO_PIN                      GPIO_Pin_6       
#define EVAL_SPIx_MOSI_PIN                      GPIO_Pin_7       
#define EVAL_SPIx_SCK_PIN                       GPIO_Pin_5
/**
  * @brief  SD Control Interface pins
  */
#define SD_CS_PIN                               GPIO_Pin_4        /* PA.04*/
#define SD_CS_GPIO_PORT                         GPIOA
#define SD_CS_GPIO_CLK                          RCC_APB2Periph_GPIOA

/**
  * @brief  SD Detect Interface pins
  */
#define SD_DETECT_PIN                           GPIO_Pin_10
#define SD_DETECT_GPIO_PORT                     GPIOA
#define SD_DETECT_EXTI_IRQn                     EXTI0_IRQn


/*##################### SD ###################################*/
/* Chip Select macro definition */
#define SD_CS_LOW()       GPIO_ResetBits(SD_CS_GPIO_PORT, SD_CS_PIN)
#define SD_CS_HIGH()      GPIO_SetBits(SD_CS_GPIO_PORT, SD_CS_PIN)



/*----------------------------------------------------------------------------
  SPI Driver instance definition
   spi0_drv: First SPI driver
   spi1_drv: Second SPI driver
 *---------------------------------------------------------------------------*/

#define __DRV_ID  spi0_drv
#define __FPCLK    72000000	

/* SPI Driver Interface functions */
static BOOL Init (void);


static BOOL UnInit (void);
static U8   Send (U8 outb);
static BOOL SendBuf (U8 *buf, U32 sz);
static BOOL RecBuf (U8 *buf, U32 sz);
static BOOL BusSpeed (U32 kbaud);
static BOOL SetSS (U32 ss);
static U32  CheckMedia (void);        /* Optional function for SD card check */

/* SPI Device Driver Control Block */
SPI_DRV __DRV_ID = {
  Init,
  UnInit,
  Send,
  SendBuf,
  RecBuf,
  BusSpeed,
  SetSS,
  CheckMedia                          /* Can be NULL if not existing         */
};





#define SPIx   SPI1


/* SPI_SR - bit definitions. */
#define RXNE    0x01
#define TXE     0x02
#define BSY     0x80
#define FPCLK   __FPCLK/1000


/*--------------------------- spi_init --------------------------------------*/

static BOOL Init (void) {
   /* Initialize and enable the SSP Interface module. */

  //SD_IO_Init();
	GPIO_InitTypeDef GPIO_InitStructure;
	  SPI_InitTypeDef  SPI_InitStructure;

  /* Enable SPI and GPIO clocks */
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | SD_CS_GPIO_CLK, ENABLE);
  RCC_APB2PeriphClockCmd(EVAL_SPIx_CLK,ENABLE);
  
	
// 	GPIO_PinRemapConfig(GPIO_Remap_SPI3, ENABLE);

  /* Configure SPI pins: SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = EVAL_SPIx_MISO_PIN | EVAL_SPIx_MOSI_PIN | EVAL_SPIx_SCK_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(EVAL_SPIx_MISO_MOSI_SCK_GPIO_PORT, &GPIO_InitStructure);

  /* Configure I/O for Flash Chip select */
  GPIO_InitStructure.GPIO_Pin = SD_CS_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(SD_CS_GPIO_PORT, &GPIO_InitStructure);
	
	 /* Configure SS Detect MMC */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure);

  /*------------Put SD in SPI mode--------------*/
  /* SD SPI Config */
    /* DeInitializes the SPI peripheral */


  /* SPI configuration */
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(EVAL_SPIx, &SPI_InitStructure);

  /* Enable the SPI  */
  SPI_Cmd(EVAL_SPIx, ENABLE);
		 
	
  return (__TRUE);
}


/*--------------------------- UnInit ----------------------------------------*/

static BOOL UnInit (void) {
  /* Return SSP interface to default state. */
  
  SPIx->CR1  = 0x0000;
  SPIx->CR2  = 0x0000;   

  return (__TRUE);
}



/*--------------------------- Send ------------------------------------------*/

static U8 Send (U8 outb) {
  /* Write and Read a byte on SPI interface. */

   SPIx->DR = outb;	 
	
  /* Wait if RNE cleared, Rx FIFO is empty. */
   while (!(SPIx->SR & RXNE));
   return (SPIx->DR);
	
}


/*--------------------------- SendBuf ---------------------------------------*/

static BOOL SendBuf (U8 *buf, U32 sz) {
  /* Send buffer to SPI interface. */
  U32 i;										   

   for (i = 0; i < sz; i++) {   
     SPIx->DR = buf[i];
 		
 	/* Wait if TXE cleared, Tx FIFO is full. */
     while (!(SPIx->SR & TXE));
     
     SPIx->DR;
   }
   /* Wait until Tx finished, drain Rx FIFO. */
   while (SPIx->SR & (BSY | RXNE)) {
     SPIx->DR;
   }
  return (__TRUE);							 
}


/*--------------------------- RecBuf ----------------------------------------*/

static BOOL RecBuf (U8 *buf, U32 sz) {
  /* Receive SPI data to buffer. */
  U32 i;

  for (i = 0; i < sz; i++) {
     SPIx->DR = 0xFF;
    /* Wait if RNE cleared, Rx FIFO is empty. */
    while (!(SPIx->SR & RXNE));
		buf[i] = SPIx->DR;
  }
  return (__TRUE);
}


/*--------------------------- BusSpeed --------------------------------------*/

static BOOL BusSpeed (U32 kbaud) {
  /* Set an SPI clock to required baud rate. */
  U8  br;

  if      (kbaud >= FPCLK / 2)   br = 0;                       /* FPCLK/2    */
  else if (kbaud >= FPCLK / 4)   br = 1;                       /* FPCLK/4    */
  else if (kbaud >= FPCLK / 8)   br = 2;                       /* FPCLK/8    */
  else if (kbaud >= FPCLK / 16)  br = 3;                       /* FPCLK/16   */
  else if (kbaud >= FPCLK / 32)  br = 4;                       /* FPCLK/32   */
  else if (kbaud >= FPCLK / 64)  br = 5;                       /* FPCLK/64   */
  else if (kbaud >= FPCLK / 128) br = 6;                       /* FPCLK/128  */
  else                           br = 7;                       /* FPCLK/256  */
	


  SPIx->CR1 = (SPIx->CR1 & ~(7 << 3)) | (br << 3); 
	
  
  return (__TRUE);
}


/*--------------------------- SetSS -----------------------------------------*/

static BOOL SetSS (U32 ss) {
  /* Enable/Disable SPI Chip Select (drive it high or low). */
	if (ss)
		GPIOC->BSRR = 0x2000;
	else
		GPIOC->BRR = 0x2000; 
		
	
	
	
  return (__TRUE);
}


/*--------------------------- CheckMedia ------------------------------------*/

static U32 CheckMedia (void) {
  /* Read CardDetect and WriteProtect SD card socket pins. */
  U32 stat = 0;
 
  //if (!(GPIOE->IDR & 1)) 
	//if( GPIO_ReadInputDataBit(SD_DETECT_GPIO_PORT, SD_DETECT_PIN )==0)
	//{
    /* Card is inserted (CD=0). */
    stat |= M_NOCHKMEDIA;
  //}

  return (stat);
}

/*----------------------------------------------------------------------------
 * end of file
 *---------------------------------------------------------------------------*/
