/**
  ******************************************************************************
 *
 * @file        Sample_SPI_Master_StandardSPI_IT_Receive.c
 *
 * @brief       SPI master standard SPI sample code
 *
 * @par         Project
 *              MG32
 * @version     V1.13
 * @date        2022/02/24
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2019 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_DRV.h"
#define Dummy_Data 0xFFFFFFFF

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static uint8_t ReceiveLangth;

/* Private function prototypes -----------------------------------------------*/
void Sample_SPI_MasterStandardSPI_IT_Receive (void);
void SPI0_IRQHandler (void);


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


/**
 *******************************************************************************
 * @brief       Sample SPI Master Standard SPI Interrupt recive code
 * @details     1. Enable CSC to SPI clock
 *      \n      2. Default Initial SPI
 *      \n      3. Configure clock divider
 *      \n      4. Configure SPI data line, mode and data size...
 *      \n      5. Config SPI0 IO
 *      \n      6. Config SPI & NVIC interrupt
 *      \n      7. Enable SPI
 *      \n      8. Read data trigger
 *      \n      9. Disable SPI
 * @return
 * @note        SCLK = PB2
 *      \n      NSS = PB0
 *      \n      MISO = PB1
 * @par         Example
 * @code
    Sample_SPI_MasterStandardSPI(8. Send data);
 * @endcode
 *******************************************************************************
 */
void Sample_SPI_MasterStandardSPI_IT_Receive (void)
{
    PIN_InitTypeDef PINX_InitStruct;

    
    
    //===Set CSC init====
    //MG32_CSC_Init.h(Configuration Wizard)
    //Select CK_HS source = CK_IHRCO
    //Select IHRCO = 12Mz
    //Select CK_MAIN Source = CK_PLLO
    //Configure PLL->Select APB Prescaler = CK_MAIN/1
    
    /*=== 1. Enable CSC to SPI clock ===*/
    //[A] When Use Wizard
    //Configure Peripheral On Mode Clock->SPI0 = Enable and Select SPI0_PR Source = CK_APB
    //Configure Peripheral On Mode Clock->Port B = Enable
    //[B] When Use Driver
//    UnProtectModuleReg(CSCprotect);                             // Unprotect CSC module
//    CSC_PeriphOnModeClock_Config(CSC_ON_SPI0, ENABLE);          // Enable SPI0 module clock
//    CSC_PeriphOnModeClock_Config(CSC_ON_PortB, ENABLE);		  // Enable PortB clock
//    CSC_PeriphProcessClockSource_Config(CSC_SPI0_CKS, CK_APB);  // CK_SPIx_PR = CK_APB = 12MHz
//    ProtectModuleReg(CSCprotect);                               // protect CSC module
       
    /*=== 2. Default Initial SPI ===*/
    SPI_DeInit(SPI0);
    
    /*=== 3. Configure clock divider ===*/                      // SPI clock = 1MHz
    SPI_Clock_Select(SPI0, SPI_CK_SPIx_PR);                     // CK_SPIx = CK_SPIx_PR
    SPI_PreDivider_Select(SPI0, SPI_PDIV_1);                    // PDIV outpu = CK_SPIx /2
    SPI_Prescaler_Select(SPI0, SPI_PSC_1);                      // Prescaler outpu = PDIV outpu /3
    SPI_Divider_Select(SPI0, SPI_DIV_4);                        // DIV outpu = PDIV outpu /2
    
    /*=== 4. Configure SPI data line, mode and data size... ===*/
    SPI_DataLine_Select(SPI0, SPI_Standard);                    // SPI data line standard SPI
    SPI_ModeAndNss_Select(SPI0, SPI_MasterWithNss);                    // Master
    SPI_ClockPhase_Select(SPI0, SPI_LeadingEdge);               // CPHA = 0
    SPI_ClockPolarity_Select(SPI0, SPI_Low);                    // CPOL = 0
    SPI_FirstBit_Select(SPI0, SPI_MSB);                         // MSB first
    SPI_DataSize_Select(SPI0, SPI_16bits);                       // Data size 8bits
    SPI_SingleMasterModeNssPulse_Cmd(SPI0, ENABLE);
    
    /*=== 5. Config SPI0 IO ===*/
    PINX_InitStruct.PINX_Mode			    = PINX_Mode_PushPull_O;     // Pin select pusu pull mode
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Enable;  // Enable pull up resistor
    PINX_InitStruct.PINX_Speed              = PINX_Speed_Low;           
    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(2),&PINX_InitStruct);                      // CLK setup at PB2
    
    PINX_InitStruct.PINX_OUTDrive           = PINX_OUTDrive_Level2;     // Pin output drive strength 1/4
    PINX_InitStruct.PINX_Alternate_Function = 2;                        // Pin AFS = 0
    GPIO_PinMode_Config(PINB(0),&PINX_InitStruct);                      // NSS setup at PB0
    
    PINX_InitStruct.PINX_Mode				= PINX_Mode_Digital_I;      // Setting digital  mode
    PINX_InitStruct.PINX_Alternate_Function = 2;                        // Pin AFS = 2
    GPIO_PinMode_Config(PINB(1),&PINX_InitStruct);                      // MISO setup at PB1

    /*=== 6. Config SPI & NVIC interrupt ===*/
    NVIC_EnableIRQ(SPI0_IRQn);                                          // Enable NVIC SPI0 IRQ
    SPI_ClearFlag(SPI0, SPI_ALLF);                                      // Clear SPI all flag
    SPI_IT_Config(SPI0, SPI_INT_RX, ENABLE);                            // Enable SPI TCF interupt
    SPI_ITEA_Cmd(SPI0, ENABLE);                                         // Enable SPI all interupt (IEA)
    
    /*=== 7. Enable SPI ===*/
    SPI_Cmd(SPI0, ENABLE);                                              // Enable SPI
    
    /*=== 8. Read data trigger ===*/
    SPI_SetTxData(SPI0, SPI_2Byte, Dummy_Data);                         // Received data
    ReceiveLangth = 100;                                                 // Read 100 times
    while(ReceiveLangth > 0);                                           // Waiting read 100 times

    /*=== 9. Disable SPI ===*/
    SPI_Cmd(SPI0, DISABLE);                                             // Disable SPI
}


/**
 *******************************************************************************
 * @brief       SPI0 IRQ Handler
 * @details  
 * @return
 * @note
 * @par         Example
 * @code
        
 * @endcode
 *******************************************************************************
 */
void SPI0_IRQHandler (void)
{
    uint32_t REG;
    
    REG = SPI_GetRxData(SPI0);                      // Get RX data
    SPI_ClearFlag (SPI0, SPI_RXF | SPI_ROVRF);      // Clear RXF and ROVRF
    REG++;
    ReceiveLangth --;                               // Data langth -1
    
    if(ReceiveLangth > 0)                           // When receive langth > 0
        SPI_SetTxData(SPI0, SPI_2Byte, Dummy_Data); // Read 16-bit
}

