/*
  ******************************************************************************
  * @file    APP.c
  * @author  PJ
  * @version V1.0.0
  * @date    2021
  * @brief   I2C Slave demo source code.
  ******************************************************************************
*/
#include "app.h"



uint8_t gu8_TxBuffer[BUFFER_LENGTH];
uint8_t gu8_RxBuffer[BUFFER_LENGTH];


 Slave_Comm_TypeDef    g_SlaveComm;

/************************************************************************
 * function   : I2C_Init
 * Description: I2C Initiation. 
 ************************************************************************/ 
void User_I2C_Init(void)
{	
	I2C_InitTypeDef I2C1_InitStruc;
	GPIO_InitTypeDef GPIO_Handle;
	
	 /* Enable Clock */
	System_Module_Enable(EN_I2C1);
	System_Module_Enable(EN_GPIOAB);
    /* GPIO Config */
	/* I2C1 SDA ->PB7 I2C1 SCL ->PB6 */
	GPIO_Handle.Pin            = GPIO_PIN_6 | GPIO_PIN_7;
	GPIO_Handle.Mode           = GPIO_MODE_AF_PP;
	GPIO_Handle.Pull           = GPIO_PULLUP;
	GPIO_Handle.Alternate      = GPIO_FUNCTION_6;
	GPIO_Init(GPIOB, &GPIO_Handle);        
	/* NVIC Config */
	NVIC_ClearPendingIRQ(I2C1_IRQn);
	NVIC_EnableIRQ(I2C1_IRQn);
	/* I2C Config */
    I2C1_InitStruc.I2C_Mode            = I2C_MODE_SLAVE;
    I2C1_InitStruc.I2C_Tx_Auto_En      = TX_AUTO_EN_ENABLE;
	I2C1_InitStruc.I2C_No_Stretch_Mode = NO_STRETCH_MODE_NOSTRETCH;
	I2C1_InitStruc.I2C_Own_Address     = SLAVE_ADDRESS;
    I2C1_InitStruc.I2C_ClockSpeed      = CLOCK_SPEED_STANDARD;
	
    I2C_Init(I2C1,&I2C1_InitStruc);
	
	/* Enable I2C1 */
	I2C_Cmd(I2C1,ENABLE);
}


/*----------------------- I2C Slave Polling Test------------------------------*/
/************************************************************************
 * function   : I2C_Slave_Polling_Test
 * Description: I2C Slave Polling Test. 
 ************************************************************************/ 
void I2C_Slave_Polling_Test(void)
{
    uint32_t i;
    uint32_t lu32_RxLength = 0;
    uint32_t lu32_TxLength = 0;
    
    User_I2C_Init();

    while (1) 
    {
        printfS("I2C Slave Test is Ready (Polling Mode)--> \r\n");

        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            gu8_TxBuffer[i] = 0;
            gu8_RxBuffer[i] = 0;
        }
        
        while(I2C_OK != I2C_Slave_Receive(USER_I2C, gu8_RxBuffer, BUFFER_LENGTH, 1000));

        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            gu8_TxBuffer[i] = gu8_RxBuffer[i];
        }
		
        I2C_Slave_Transmit(USER_I2C, gu8_TxBuffer, BUFFER_LENGTH, 1000);
        
       
        printfS("I2C Slave Test End (Polling Mode)!!! \r\n");
		printfS("---------------------------------------------- \r\n");
    }
}






/************************************************************************
 * function   : I2C_Slave_Interrupt_Test
 * Description: I2C Slave Interrupt Test. 
 ************************************************************************/ 
void I2C_Slave_Interrupt_Test(void)
{
    uint32_t i;
    
    User_I2C_Init();

    while (1) 
    {
        printfS("I2C Slave Test is Ready(Interrupt Mode)!!! \r\n");

        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            gu8_TxBuffer[i] = 0;
            gu8_RxBuffer[i] = 0;
        }

        I2C_Slave_Receive_IT(USER_I2C, &g_SlaveComm,gu8_RxBuffer, BUFFER_LENGTH);
        while (g_SlaveComm.Slave_RxState != SLAVE_RX_STATE_IDLE);
	
        
        for (i = 0; i < g_SlaveComm.Rx_Count; i++)
        {
            gu8_TxBuffer[i] = gu8_RxBuffer[i];
        }


        I2C_Slave_Transmit_IT(USER_I2C, &g_SlaveComm,gu8_RxBuffer, g_SlaveComm.Rx_Count);
        while(g_SlaveComm.Slave_TxState != SLAVE_TX_STATE_IDLE);
		

        printfS("Rx Count: %d, Tx Count: %d \r\n", g_SlaveComm.Rx_Count, g_SlaveComm.Tx_Count);

        printfS("I2C Slave Test End (Interrupt Mode)!!! \r\n");
		printfS("---------------------------------------------- \r\n");
    }
}

/*----------------------- I2C Slave DMA Test------------------------------*/
static volatile uint8_t gu8_RX_Complete;

#define I2Cx_DMA_Channel    DMA_Channel0
	

/************************************************************************
 * function   : I2C_STOPF_Callback
 * Description: I2C STOPF Callback. 
 ************************************************************************/
void I2C_STOPF_Callback(void)
{
    gu8_RX_Complete = 1;
    
    g_SlaveComm.Rx_Count = g_SlaveComm.Rx_Size - (I2Cx_DMA_Channel->CTRL & 0xFFF);
    
	DMA_Cmd(DMA_Channel0, DISABLE);
}

/*********************************************************************************
* Function    : I2Cx_Receive_DMA
* Description : Set I2C Recv Data from DMA
* Input       : RecvBuff: Receive Data Buff
* Input       : Size: Receive Data Length
* Output      : None
**********************************************************************************/
void I2Cx_Receive_DMA(uint8_t *RecvBuff, uint32_t Size)
{    
	
	DMA_InitTypeDef  DMA_InitStructure;
	
    /* DMA channel0 configuration */
    DMA_DeInit(DMA_Channel0);
    DMA_InitStructure.Request_ID = REQ10_I2C1_RECV;
    DMA_InitStructure.SrcAddr = (uint32_t)(&USER_I2C->DR);
    DMA_InitStructure.DstAddr = (uint32_t)RecvBuff;
    DMA_InitStructure.Data_Flow = DMA_DATA_FLOW_P2M;
    DMA_InitStructure.DMA_BufferSize = Size;
    DMA_InitStructure.Source_Inc = DMA_SOURCE_ADDR_INCREASE_DISABLE;
    DMA_InitStructure.Desination_Inc = DMA_DST_ADDR_INCREASE_ENABLE;
    DMA_InitStructure.Source_Width = DMA_SRC_WIDTH_BYTE;
    DMA_InitStructure.Desination_Width = DMA_DST_WIDTH_BYTE;
    DMA_InitStructure.DMA_Mode = DMA_NORMAL;
    DMA_Init(DMA_Channel0, &DMA_InitStructure);	
	
	g_SlaveComm.Rx_Count =0;
	
	/* Clear STOPF Interrupt Flag */
	USER_I2C->SR = READ_BIT(USER_I2C->SR, I2C_SR_STOPF);
	/* STOPF Interrupt Enable */
	SET_BIT(USER_I2C->CR, I2C_CR_STOPF_INTEN);
			
	//I2C1 DMA Recv
	I2C_DMACmd(USER_I2C, ENABLE);
	
	/* Enable DMA Channel0 transfer */
	DMA_Cmd(DMA_Channel0, ENABLE);
}


/************************************************************************
 * function   : I2C_Slave_DMA_Test
 * Description: I2C Slave DMA Test
 ************************************************************************/ 
void I2C_Slave_DMA_Test(void)
{
    uint32_t i;
	uint8_t Status;
    
    User_I2C_Init();

     /* Enable DMA Module */
    System_Module_Enable(EN_DMA);
	
	g_SlaveComm.I2C_STOPF_Callback = (void *)I2C_STOPF_Callback;

    while (1) 
    {
        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            gu8_TxBuffer[i] = 0;
            gu8_RxBuffer[i] = 0;
        }
        
        printfS("I2C Slave Test is Ready (DMA Mode)!!! \r\n");

        g_SlaveComm.Rx_Size = BUFFER_LENGTH ;

		I2Cx_Receive_DMA(gu8_RxBuffer,g_SlaveComm.Rx_Size);
		
        while (gu8_RX_Complete != 1);

        gu8_RX_Complete = 0;
		
        for (i = 0; i < g_SlaveComm.Rx_Count; i++)
        {
			printfS("gu8_RxBuffer[%d]=0x%x\r\n",i,gu8_RxBuffer[i]);
        }

        printfS("Rx Count: %d\r\n", g_SlaveComm.Rx_Count);
        
        printfS("I2C Slave Test End (DMA Mode)!!! \r\n");
    }
}




/************************************************************************
 * function   : I2C_Slave_Test
 * Description: I2C Slave Test. 
 ************************************************************************/ 
void I2C_Slave_Test(enum_TEST_MODE_t fe_Mode)
{

    printfS("---------- I2C Slave Test ----------\r\n");
    
    switch (fe_Mode)
    {
        /* Polling Mode */
        case TEST_SLAVE_POLLING: 
            I2C_Slave_Polling_Test();
            break;
        
        /* Interrupt Mode */
        case TEST_SLAVE_INTERRUPT: 
            I2C_Slave_Interrupt_Test();
            break;
        
        /* DMA Mode */
        case TEST_SLAVE_DMA: 
            I2C_Slave_DMA_Test();
            break;
        
        default: 
            break; 
    }

}

