/**
 ******************************************************************************
 *
 * @file        Sample_SPI_Slave_StandardSPI.c
 *
 * @brief       Standard-SPI slave mode sample code.
 *
 * @par         Project
 *              MG32
 * @version     V1.15
 * @date        2026/06/30
 * @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"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define Dummy_Data  0xFFFFFFFF
#if !defined(MG32_6TH)
#define SPI_NSS    	PB0     // SPI_NSS
#endif
#if defined(MG32_6TH)
#define SPI_NSS    	PC2     // SPI_NSS
#endif

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void Sample_SPI_SlaveStandardSPI (void);

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



/**
 *******************************************************************************
 * @brief  	    Sample SPI Slave Standard SPI
 * @details     1. Enable CSC to SPI clock
 *      \n      2. DeInitial SPI
 *      \n      3. Configure clock divider
 *      \n      4. Configure SPI data line, mode and data size...
 *      \n      5. Config SPI0 IO
 *      \n      6. Enable SPI 
 *      \n      7. Read data
 *      \n      8. Send data
 *      \n      9. Disable SPI
 *      \n      
 * @return	    	
 * @note        
 * @par         Example
 * @code
    Sample_SPI_SlaveStandardSPI();
 * @endcode
 *******************************************************************************
 */
void Sample_SPI_SlaveStandardSPI (void)
{
    PIN_InitTypeDef PINX_InitStruct;
    uint32_t RDAT0, RDAT1;
    uint8_t  LOOP;

    
    
    /*=== 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. Config SPI0 IO ===*/
#if defined(MG32_6TH)
    // For MG32F02D032 IO setting
    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_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 = 8;                            // Pin AFS = 2
    
    GPIO_PinMode_Config(PINC(2),&PINX_InitStruct);                          // NSS setup at PC2
    GPIO_PinMode_Config(PINC(6),&PINX_InitStruct);                          // CLK setup at PC6
    GPIO_PinMode_Config(PINC(7),&PINX_InitStruct);                          // MOSI setup at PC7
    
    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(PINC(3),&PINX_InitStruct);                          // MISO setup at PC3
#endif
    
#if !defined(MG32_6TH)
    // For others IO setting
    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);     
#endif
    
    /*=== 2. DeInitial 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 /1
    SPI_Prescaler_Select(SPI0, SPI_PSC_1);                      // Prescaler outpu = PDIV outpu /1
    SPI_Divider_Select(SPI0, SPI_DIV_2);                        // 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
#if (defined(MG32F02A132) || defined(MG32F02A072))
    SPI_ModeAndNss_Select(SPI0, SPI_Slave);                     // Slave
#endif

#if (!(defined(MG32F02A132) || defined(MG32F02A072)))
    SPI_ModeAndNss_Select(SPI0, SPI_SlaveWithNss);              // SPI Slave With Nss
#endif
    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_8bits);                       // Data size 8bits
    SPI_SlaveModeReceivedThreshold_Select(SPI0, SPI_1Byte);     // Set SPI0 received data buffer high threshold



    /*=== 6. Enable SPI ===*/
    SPI_Cmd(SPI0, ENABLE);     
    // Enable SPI 
#if (defined(MG32_1ST))
    /*=== 7. Read data ===*/
    // If you want get 1 byte, please send 1 byte 0x00.
    SPI_SetTxData(SPI0, SPI_1Byte, Dummy_Data);                         // Received 1 byte and send 1 byte the same time
    while(SPI_GetSingleFlagStatus(SPI0, SPI_RXF) == DRV_UnHappened);    // Wait RXF flag
    SPI_ClearFlag(SPI0, (SPI_TXF | SPI_RXF));                           // Clear TXF and RXF
    RDAT = SPI_GetRxData(SPI0);                                         // Get received data
    
    while(SPI_GetSingleFlagStatus(SPI0, SPI_TCF) == DRV_UnHappened);    // Wait TCF flag
    SPI_ClearFlag(SPI0, SPI_TCF);                                       // Clear TCF
     
    /*=== 8. Send data ===*/
    TDAT = RDAT;
    SPI_SetTxData(SPI0, SPI_1Byte, TDAT);                               // Send 1 byte and received 1 byte the same time
    while(SPI_GetSingleFlagStatus(SPI0, SPI_TXF) == DRV_UnHappened);    // Wait TXF flag
    SPI_ClearFlag(SPI0, (SPI_TXF | SPI_RXF));                           // Clear TXF and RXF
    
    while(SPI_GetSingleFlagStatus(SPI0, SPI_TCF) == DRV_UnHappened);    // Wait TCF flag
    SPI_ClearFlag(SPI0, SPI_TCF | SPI_RXF);      
#endif

#if (defined(MG32_2ND) || defined(MG32_3RD) || defined(MG32_4TH)) || defined(MG32_5TH) || defined(MG32_6TH)
    for(LOOP=3; LOOP>0; LOOP--)                                             // 
    {
        /*=== 7. Read data ===*/
        SPI_SlaveModeReceivedThreshold_Select(SPI0, SPI_4Byte);
        while(SPI_GetSingleFlagStatus(SPI0, SPI_RXF) == DRV_UnHappened);    // Wait RXF flag
        RDAT0 = SPI_GetRxData(SPI0);                                        // Get received data
        while(SPI_GetSingleFlagStatus(SPI0, SPI_RXF) == DRV_UnHappened);    // Wait RXF flag
        RDAT1 = SPI_GetRxData(SPI0);    

        /*=== 8. Send data ===*/
        SPI_SetTxData(SPI0, SPI_3Byte, RDAT0);                               // Send 1 byte and received 1 byte the same time
        while(SPI_GetSingleFlagStatus(SPI0, SPI_TCF) == DRV_UnHappened);    // Wait TCF flag
        SPI_ClearRxData(SPI0);                                              // Clear RX buffer
        SPI_ClearFlag(SPI0, SPI_TCF | SPI_RXF);                             // Clear TCF and RXF
    }
    ((void)RDAT1);
#endif

    /*=== 9. Disable SPI ===*/
    while(SPI_GetSingleFlagStatus(SPI0, SPI_IDLF) == DRV_UnHappened);   // Wait SPI idle
    SPI_Cmd(SPI0, DISABLE);                                             // Disable SPI
}


