/*
  ******************************************************************************
  * Copyright (c)  2008 - 2024, Shanghai AisinoChip Co.,Ltd .
  * @file    APP.c 
  * @version V1.0.0
  * @date    2024
  * @author  Aisinochip Firmware Team  
  * @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;

#define USERKEY_PORT	GPIOC
#define USERKEY_PIN		GPIO_PIN_13

/*********************************************************************************
* Function    : UserKEY_Init
* Description : User key initialize
* Input       : 
* Output      : 
**********************************************************************************/
void UserKEY_Init(void)
{
	GPIO_InitTypeDef    KEY_Handle;
    System_Module_Enable(EN_GPIOCD);
    
    KEY_Handle.Pin       = USERKEY_PIN;
    KEY_Handle.Mode      = GPIO_MODE_INPUT;
    KEY_Handle.Pull      = GPIO_PULLUP;
    KEY_Handle.Alternate = GPIO_FUNCTION_0;

    GPIO_Init(USERKEY_PORT, &KEY_Handle);
}

/*********************************************************************************
* Function    : UserKEY_Get
* Description : detection button is pressed
* Input       : 
* Output      : 
**********************************************************************************/
bool UserKEY_Get(void)
{
    if (Bit_RESET == GPIO_ReadInputDataBit(USERKEY_PORT, USERKEY_PIN)) 
    {
        System_Delay_MS(20);
        
        if (Bit_RESET == GPIO_ReadInputDataBit(USERKEY_PORT, USERKEY_PIN)) 
        {
            return true;
        }
    }

    return false;
}

/************************************************************************
 * function   : I2C_Init
 * Description: I2C Initiation. 
 ************************************************************************/ 
void User_I2C_Init(void)
{	
	#if 0
	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);
	#else
	I2C_InitTypeDef I2C2_InitStruc;
	GPIO_InitTypeDef GPIO_Handle;
	
	 /* Enable Clock */
	System_Module_Enable(EN_I2C2);
	System_Module_Enable(EN_GPIOAB);
    /* GPIO Config */
	/* I2C2 SDA ->PB14 I2C2 SCL ->PB13 */
	GPIO_Handle.Pin            = GPIO_PIN_14 | GPIO_PIN_13;
	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(I2C2_IRQn);
	NVIC_EnableIRQ(I2C2_IRQn);
	/* I2C Config */
    I2C2_InitStruc.I2C_Mode            = I2C_MODE_SLAVE;
    I2C2_InitStruc.I2C_Tx_Auto_En      = TX_AUTO_EN_ENABLE;
	I2C2_InitStruc.I2C_No_Stretch_Mode = NO_STRETCH_MODE_NOSTRETCH;
	I2C2_InitStruc.I2C_Own_Address     = SLAVE_ADDRESS;
    I2C2_InitStruc.I2C_ClockSpeed      = CLOCK_SPEED_STANDARD;
	
    I2C_Init(I2C2,&I2C2_InitStruc);
	
	/* Enable I2C2 */
	I2C_Cmd(I2C2,ENABLE);
	
	#endif
}


/*----------------------- I2C Slave Polling Test------------------------------*/
/************************************************************************
 * function   : I2C_Slave_Polling_Test
 * Description: I2C Slave Polling Test. 
 ************************************************************************/ 
void I2C_Slave_Polling_Test(void)
{
    uint32_t i;
    
    User_I2C_Init();
    printfS("---------- Please press the USR_PB button ----------\r\n");
    
    while(false == UserKEY_Get());
    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();
    printfS("---------- Please press the USR_PB button ----------\r\n");
    
    while(false == UserKEY_Get());
    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_TxBuffer, 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);

}
void print_reg(uint32_t addr,uint32_t size)
{
	uint8_t i;
	for(i=0;i<size/sizeof(uint32_t);i++)
	{
		printf("addr=0x%08x,data=0x%08x\r\n",addr+i*4,*(uint32_t*)(addr+i*4));
	}
	printf("\r\n");
}
/*********************************************************************************
* 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 = REQ12_I2C2_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 ret;

    User_I2C_Init();

     /* Enable DMA Module */
    System_Module_Enable(EN_DMA);
	
	g_SlaveComm.I2C_STOPF_Callback = I2C_STOPF_Callback;
    printfS("---------- Please press the USR_PB button ----------\r\n");
    
    while(false == UserKEY_Get());
    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);
		printfS("rx cnt =%d\r\n",g_SlaveComm.Rx_Count);

        gu8_RX_Complete = 0;
		
        for (i = 0; i < g_SlaveComm.Rx_Count; i++)
        {
            gu8_TxBuffer[i] = gu8_RxBuffer[i];
        }

		USER_I2C->DR=gu8_TxBuffer[0];
        ret=I2C_Slave_Transmit(USER_I2C, gu8_TxBuffer+1, g_SlaveComm.Rx_Count-1, 0);
		printfS("ret =%d\r\n",ret);
		
//        I2C_Slave_Transmit_IT(USER_I2C, &g_SlaveComm,gu8_TxBuffer, g_SlaveComm.Rx_Count);
//        while(g_SlaveComm.Slave_TxState != SLAVE_TX_STATE_IDLE);
		
        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");
	UserKEY_Init();
    
    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; 
    }

}

/************************************************************************
 * function   : I2C1_IRQHandler
 * Description: I2C1 Interrupt Handler. 
 ************************************************************************/ 
void I2C2_IRQHandler(void)
{
    _I2Cx_IRQHandler(USER_I2C,&g_SlaveComm);
}





