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

#define BUFFER_LENGTH    (256)

#define SLAVE_ADDRESS    (0xA6)

uint8_t TxBuffer[BUFFER_LENGTH];
uint8_t RxBuffer[BUFFER_LENGTH];

I2C_Handler_t hi2c;

/************************************************************************
 * function   : User_I2C_Init
 * Description: I2C Initiation. 
 ************************************************************************/ 
void I2C1_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_Handle;
	
	 /* Enable GPIO Clock */
    __RCC_GPIOB_CLK_ENABLE();
    
	GPIO_Handle.Pin            = GPIO_PIN_6 | GPIO_PIN_7;
	GPIO_Handle.Mode           = GPIO_MODE_AF_PP;
	GPIO_Handle.Pull           = GPIO_PULLUP;
    GPIO_Handle.Drive          = GPIO_DRIVE_LEVEL3;
	GPIO_Handle.Alternate      = GPIO_FUNCTION_5;
	GPIO_Init(GPIOB, &GPIO_Handle);
    
    printfS("I2C1 PINs selected:\r\n");
    printfS("SCL:PB6\r\n");
    printfS("SDA:PB7\r\n\r\n");
    
}

void I2C1_Init(void)
{
    I2C_InitTypeDef I2C_InitStruct;
    
    __RCC_I2C1_CLK_ENABLE();
    
    I2C_InitStruct.Clock_Speed = CLOCK_SPEED_STANDARD;
                  
    I2C_InitStruct.I2C_Mode = I2C_MODE_MASTER;
                  
    I2C_InitStruct.Stretch_Mode = STRETCH_MODE_DISABLE;
                  
    I2C_InitStruct.Own_Address = 0;
                  
    I2C_InitStruct.Tx_Auto_En = TX_AUTO_ENABLE;
                  
    I2C_InitStruct.filter_enable = FILTER_ALGO_DISABLE;

    I2C_Init(I2C1, &I2C_InitStruct);
    
    NVIC_ClearPendingIRQ(I2C1_IRQn);
    NVIC_EnableIRQ(I2C1_IRQn);

    /* I2C module enable */
    I2C_Cmd(I2C1, ENABLE);
}

void printf_buff_byte(uint8_t* buff, uint32_t length)
{
	uint32_t i;

	for(i=0;i<length;i++)
	{
		printf("%.2x ",buff[i]);	
	}
	printf("\n");
}

/*************************For I2C Master Test******************/ 
void I2C_Master_Comm_LOOP(void)
{
    uint32_t i;
    uint32_t Length  = 1;
    uint32_t COM_OK  = 0;
    uint32_t COM_Err = 0;
    uint8_t Status;

    I2C1_Init();
    
    I2C1_GPIO_Init();
    
    
    while (1) 
    {        
        if (Length > BUFFER_LENGTH) 
        {
            Length = 1;
        }
        
        for (i = 0; i < Length; i++)
        {
            TxBuffer[i] = i + 1;
        }
        
        printfS("I2C Master Comm LOOP Demo.\r\n");
        
        do
        {
            Status = I2C_Master_Transmit(I2C1, SLAVE_ADDRESS, TxBuffer, Length, 1000);
        }while(Status != I2C_OK);
        
        DelayMs(500);
        
        do
        {
            Status = I2C_Master_Receive(I2C1, SLAVE_ADDRESS, RxBuffer, Length,10000);
        }while(Status != I2C_OK);
        
        for (i = 0; i < Length; i++)
        {
            if (TxBuffer[i] != RxBuffer[i]) 
            {
                printfS("There is one mistake : TxBuffer[%d] != RxBuffer[%d] \r\n", i, i);
                
                COM_Err++;
            }
            else 
            {
                COM_OK++;
            }
        }
        
        printfS("I2C Master Test OK count %d times \r\n",  COM_OK);
        printfS("I2C Master Test Err count %d times \r\n", COM_Err);
        
        printfS("I2C Master Test End!!! \r\n");

        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            TxBuffer[i] = 0;
            RxBuffer[i] = 0;
        }

        COM_Err  = 0;
        COM_OK   = 0;

        Length++;

        DelayMs(500);
    }
}

void I2C_Master_Comm_IT(void)
{
	
	uint32_t i;
    uint32_t Length  = 1;
    uint32_t COM_OK  = 0;
    uint32_t COM_Err = 0;
    uint8_t Status;
    
    printfS("I2C Master IT Demo. (should connect to another board running I2C Slave Comm Demo, & Slave should run first)\r\n\r\n");
    
    I2C1_Init();
    
    I2C1_GPIO_Init();
    
//    printfS("Please press the USR_PB button to continue......\r\n\r\n");
//    
//    while(GPIO_PIN_SET == BSP_PB_GetState());
    
    while (1) 
    {
        if (Length > BUFFER_LENGTH) 
        {
            Length = 1;
        }

        for (i = 0; i < Length; i++)
        {
            TxBuffer[i] = 1 + i;
        }
        
        printfS("I2C Master Test is Ready!!! \r\n");
        
        do
        {
            Status = I2C_Master_Transmit_IT(I2C1, SLAVE_ADDRESS, &hi2c, TxBuffer, Length);
        }while(Status != I2C_OK);
        
        while(hi2c.state != I2C_STATE_IDLE);
        DelayMs(100);
        
        do
        {
            Status = I2C_Master_Receive_IT(I2C1, SLAVE_ADDRESS, &hi2c, RxBuffer, Length);
        }while(Status != I2C_OK);
        
        while(hi2c.state != I2C_STATE_IDLE);
        
        for (i = 0; i < Length; i++)
        {
            if (TxBuffer[i] != RxBuffer[i]) 
            {
                printfS("ERROR@ %x \r\n", i);
            
                COM_Err++;
                goto end2;
            }
            else 
            {
                COM_OK++;
            }
        }
        
        
        
        printfS("I2C Master Test OK count %d times \r\n",  COM_OK);
        printfS("I2C Master Test Err count %d times \r\n", COM_Err);
        
        printfS("I2C Master Test End!!! \r\n");

        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            TxBuffer[i] = 0;
            RxBuffer[i] = 0;
        }

        COM_Err  = 0;
        COM_OK   = 0;

        Length++;

        DelayMs(100);
    }
end2:    
    printf_buff_byte(RxBuffer, Length);
}

/*************************For I2C EEprom Test******************/ 
#define AT24_I2C                I2C1
#define AT24_DEV_ADDRESS        0xA0

#define I2C_EEWR_WRITE_READ_LENGTH  128

uint8_t I2C_EEWR_Test(void)
{

    uint8_t i;
    uint8_t wr_buff[128], rd_buff[128];

    for(i = 0; i < 128; i++)
    {
        wr_buff[i] = i+2;
    }
    printfS("iic write data\n");
    IC_AT24_WriteBytes(AT24_I2C, AT24_DEV_ADDRESS, 0x02, wr_buff, I2C_EEWR_WRITE_READ_LENGTH,1000);

    printfS("iic read data\n");
    IC_AT24_ReadBytes(AT24_I2C, AT24_DEV_ADDRESS, 0x02, rd_buff, I2C_EEWR_WRITE_READ_LENGTH,1000);  

    for(i = 0; i < I2C_EEWR_WRITE_READ_LENGTH; i++)
    {
        printfS("wr_buff[%d]= 0x%x,rd_buff[%d]= 0x%x \n", i, wr_buff[i], i, rd_buff[i]);
    }
		
    if (0 == memcmp(wr_buff, rd_buff, I2C_EEWR_WRITE_READ_LENGTH))
    {
        printfS("PASS\n"); 
        return 0;  
    }
    else
    {
        printfS("FAIL\n");  
        return 1;   
    }
}


/************************************************************************
 * function   : I2C_EEprom_Test
 * Description: I2C EEprom Test. 
 ************************************************************************/ 
void I2C_EEprom_Test(void)
{
    uint32_t test_times, total_times;
    
    test_times = 0;
    total_times = 5;
    printfS("I2C EEPROM Demo\r\n");
    
    I2C1_Init();
    
    I2C1_GPIO_Init();

    while(test_times < 5)
    {
        if (0 != I2C_EEWR_Test())     
        {
            break; 
        }
        else
        {
            test_times++;
        }
    }
    printfS("iic write eeprom test ends, success times:%d, total test times:%d!\n", test_times, total_times);
}


/************************************************************************
 * function   : I2C_Master_Test
 * Description: I2C Master Test. 
 ************************************************************************/ 
void I2C_Master_Test(enum_TEST_MODE_t fe_Mode)
{
    switch (fe_Mode)
    {
        case TEST_MASTER_COMM: 
            I2C_Master_Comm_LOOP();
            break; 
        
        case TEST_MASTER_COMM_IT:
            I2C_Master_Comm_IT();
            break;
        
        case TEST_MASTER_EEPROM: 
            I2C_EEprom_Test();
            break;
        
        default: break;     
    }
}