/**
  ******************************************************************************
 *
 * @file        Sample_SPI_Slave_StandardSPI_DMA_P2M.c
 *
 * @brief       Standard-SPI slave mode DMA SPI-to-SRAM sample code.
 *
 * @par         Project
 *              MG32
 * @version     V2.15
 * @date        2022/09/21
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2021 Megawin Technology Co., Ltd.
 *              All rights reserved.
 *
 ******************************************************************************
 * @par         Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 *******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "MG32_GPIO_DRV.h"
#include "MG32_SPI_DRV.h"
#include "MG32_DMA_DRV.h"


/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define MYBINARYIMAGE3_LENGTH   11
#define SPI_NSS                 PB0     // SPI_NSS

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
#if (defined(MG32F02A132) || defined(MG32_3RD))
static uint8_t SlvDest[MYBINARYIMAGE3_LENGTH] __attribute__((section(".ARM.__at_0x20003830")));
#else
static uint8_t SlvDest[MYBINARYIMAGE3_LENGTH];
#endif       

/* Private function prototypes -----------------------------------------------*/
void Sample_SPI_Slave_StandardSPI_DMA_P2M (SPI_Struct* SPIx);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/


/**
 *******************************************************************************
 * @brief  	    SPI Slave use DMA receive
 * @details  
 * @param[in]   SPIx
 * 	@arg\b			SPI0
 * @return      None
 * @note        
 * @par         Example
 * @code
    SPI_Slave_Use_DMA_Receive();
 * @endcode
 *******************************************************************************
 */
void Sample_SPI_Slave_StandardSPI_DMA_P2M (SPI_Struct* SPIx)
{
    uint32_t i;                             // Loop counter
    DMA_BaseInitTypeDef DMATestPattern;
    PIN_InitTypeDef     PINX_InitStruct;
    
    
    
    // SPI default initialization 
    SPI_DeInit(SPIx);
    // CLK configure
    SPI_PreDivider_Select(SPIx, SPI_PDIV_1);
    SPI_Prescaler_Select(SPIx, SPI_PSC_1);
    SPI_Divider_Select(SPIx, SPI_DIV_2);
    SPI_Clock_Select(SPIx, SPI_CK_SPIx_PR);
    
    // Standard SPI, slave with NSS, first bit LSB, CPHA =0, CPOL=0
    SPI_DataLine_Select(SPIx, SPI_Standard);
    SPI_ModeAndNss_Select(SPIx, SPI_SlaveWithNss);         
    SPI_FirstBit_Select(SPIx, SPI_LSB);
    
    // SPI transfer data size 8-bits
    SPI_DataSize_Select(SPIx, SPI_8bits);
    // Data bidirectional input
    SPI_BidirectionalOutput_Cmd(SPIx, DISABLE);
    // SPI receive threshold 1 byte
    SPI_SlaveModeReceivedThreshold_Select(SPIx, SPI_1Byte); 

    // IO initialPIN_InitTypeDef PINX_InitStruct;
    SPI_NSS = 1;
    PINX_InitStruct.PINX_Mode				= PINX_Mode_Digital_I;          // Pin select digital input mode
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Enable;      // Enable pull up resistor
    PINX_InitStruct.PINX_Speed              = PINX_Speed_High;              // Output high speed mode enable 
    PINX_InitStruct.PINX_OUTDrive           = PINX_OUTDrive_Level0;         // Pin output driver full strength.
    PINX_InitStruct.PINX_FilterDivider      = PINX_FilterDivider_Bypass;    // Pin input deglitch filter clock divider bypass
    PINX_InitStruct.PINX_Inverse            = PINX_Inverse_Disable;         // Pin input data not inverse
    PINX_InitStruct.PINX_Alternate_Function = 2;                            // Pin AFS = 2
    
    GPIO_PinMode_Config(PINB(0),&PINX_InitStruct);                          // NSS setup at PB0
    GPIO_PinMode_Config(PINB(2),&PINX_InitStruct);                          // CLK setup at PB2
    GPIO_PinMode_Config(PINB(3),&PINX_InitStruct);                          // MOSI setup at PB3

    PINX_InitStruct.PINX_Mode				= PINX_Mode_PushPull_O;         // Setting pusu pull mode
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Disable;     // Enable pull up resistor
    GPIO_PinMode_Config(PINB(1),&PINX_InitStruct);                          // MISO setup at PB1

    // Enable SPI function
    SPI_Cmd(SPIx, ENABLE);
    
    // prepare destination area
    for (i=0;i<MYBINARYIMAGE3_LENGTH;i++)
        SlvDest[i] = 0x00;
    
    // Enable DMA
    DMA_Cmd(ENABLE);
    // Enable Channel0
    DMA_Channel_Cmd(DMAChannel0, ENABLE);
    // Initial parameter
    DMA_BaseInitStructure_Init(&DMATestPattern);
    
    // Modify parameter
    {   
        // external trigger pin and mode config
        DMATestPattern.ExtTrgPin = DMA_ExtTRG0;
        DMATestPattern.ExtTrgMode = DMA_DisableExtTrg;
        // DMA channel select
        DMATestPattern.DMAChx = DMAChannel0;
        // channel x loop mode config
        DMATestPattern.DMALoopCmd = DISABLE;
        // channel x source/destination auto increase address
        DMATestPattern.SrcSINCSel = DISABLE;        
        DMATestPattern.DestDINCSel = ENABLE;
        // DMA Burst size config
        DMATestPattern.BurstDataSize = DMA_BurstSize_1Byte;
        // DMA transfer data count initial number (? Bytes ???)
        DMATestPattern.DMATransferNUM = MYBINARYIMAGE3_LENGTH;
        // DMA source peripheral config
        DMATestPattern.SrcSymSel = DMA_SPI0_RX;
        // DMA destination peripheral config
        DMATestPattern.DestSymSel = DMA_MEM_Write;
        // source config
        DMATestPattern.DMADestinationAddr = (uint8_t *)&SlvDest;
    }
    // M2P(CH0) simple parameter
    DMA_Base_Init(&DMATestPattern);
    
    // Start request
    SPI_RXDMA_Cmd(SPI0, ENABLE);
    DMA_StartRequest(DMAChannel0);
    
    // Waitting DMA trsnafer complete
    while(DMA_GetSingleFlagStatus(DMA, DMA_FLAG_CH0_TCF) == DRV_UnHappened);
    // Clear DMA event flag
    DMA_ClearFlag(DMA, (DMA_FLAG_CH0_TCF | DMA_FLAG_CH0_THF));
    
    // Clear SPI all flag
    SPI_ClearFlag(SPIx, SPI_ALLF);
    // Disable SPI function
    SPI_Cmd(SPIx, DISABLE);
}



