/**
  ******************************************************************************
  * @file    SPI_MASTER_NonOptimized/main.c
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    19-August-2011
  * @brief   Main program body for SPI Master Non optimized project
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f2xx.h"

/** @addtogroup SPI_MASTER_NonOptimized
  * @{
  */

/** @addtogroup SPI_MASTER_NonOptimized_MAIN
  * @{
  */

/* External variables --------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#define BUFFER_SIZE       1022
#define USE_POLLING
//#define USE_DMA

/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
SPI_InitTypeDef    SPI_InitStructure;
DMA_InitTypeDef    DMA_InitStructure;
RCC_ClocksTypeDef  RCC_Clocks;

uint16_t SPI_MASTER_Buffer_Tx[BUFFER_SIZE] = {0x5555};
uint16_t SPI_SLAVE_Buffer_Rx[BUFFER_SIZE];
uint16_t length = 0x00;
__IO uint16_t index_recieve = 0x00;
__IO uint8_t  sys_flag = 0x00;
/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */

  /* System clocks configuration */
  RCC_Configuration();

  /* Get RCC clocks */
  RCC_GetClocksFreq(&RCC_Clocks);

  /* Program systick to generate interrupt each 20ms */
  SysTick_Config(RCC_Clocks.SYSCLK_Frequency / 50);

  /* Out put the system clock Div2 for debug purpose */
  RCC_MCO2Config(RCC_MCO2Source_SYSCLK, RCC_MCO2Div_2);

  /* GPIO configuration */
  GPIO_Configuration();

  /* SPI_MASTER configuration */
  SPI_I2S_DeInit (SPI1);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_Init(SPI1, &SPI_InitStructure);

#ifdef USE_DMA
  /* DMA clock */
  RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_DMA2, ENABLE);

  /* Configure DMA */
  DMA_InitStructure.DMA_Channel = DMA_Channel_3;
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001300C;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
#endif

  /* Enable SPI_MASTER */
  SPI_Cmd(SPI1, ENABLE);

  while (1)
  {
    /* Wait for sys_flag to be 1 */
    while (sys_flag == 0x00);

    /* Set sys_flag to 0 */
    sys_flag = 0x00;

    /* Send SPI1 dummy data */
    SPI_I2S_SendData(SPI1, 0x5555);

    /* Wait for SPI_MASTER Tx buffer empty */
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

    /* Wait for SPI1 data reception */
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

    /* Read SPI1 received length */
    length = SPI_I2S_ReceiveData(SPI1);

#ifdef USE_POLLING

    /* Recieve the length data useful from the slave */
    for (index_recieve = 0x00; index_recieve < length; index_recieve++)
    {
      /* Wait for SPI1 Tx buffer empty */
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

      /* Send SPI1 data */
      SPI_I2S_SendData(SPI1, 0x4444);

      /* Wait for SPI1 Tx buffer empty */
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

      /*Recieve the useful data*/
      SPI_SLAVE_Buffer_Rx[index_recieve] = SPI_I2S_ReceiveData(SPI1);
    }
  }
#endif //POLLING

#ifdef USE_DMA

  /* Init DMA2 stream 2, stream3 */
  DMA_DeInit(DMA2_Stream2);
  DMA_DeInit(DMA2_Stream3);

  /* Set the DMA NDTR counter to length value  */
  DMA_InitStructure.DMA_BufferSize = length;

  /* DMA2_Stream0 channel3 SPI1_RX */
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_SLAVE_Buffer_Rx;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_Init(DMA2_Stream2, &DMA_InitStructure);

  /* DMA2_Stream3 channel3 SPI1_TX */
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_MASTER_Buffer_Tx;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
  DMA_Init(DMA2_Stream3, &DMA_InitStructure);

  /* Enable SPI DMA request for TX and RX */
  SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
  SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);

  /* DMA2_Stream2 enable for SPI1_RX*/
  DMA_Cmd(DMA2_Stream2, ENABLE);

  /* DMA2_Stream3 enable for SPI1_TX*/
  DMA_Cmd(DMA2_Stream3, ENABLE);

  /* Enter CPU to sleep mode */
  __WFI();
}
#endif //DMA
}

/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval None
  */
void RCC_Configuration(void)
{
  /* Enable GPIOA and GPIOC clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);

  /* Enable SPI1 clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
}

/**
  * @brief  Configures SPI1 pins.
  * @param  None
  * @retval None
  */
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure SPI pin: SCK*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure SPI pin: MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure SPI pin: MISO */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Enable alternate function for SPI pins */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

  /* Configure PC9 as MCO pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* Enable PC9 alternate function */
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_MCO);
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {}
}
#endif

/**
  * @}
  */

/**
  * @}
  */

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
