/**
 ******************************************************************************
 *
 * @file        Sample_I2C_ByteMode.c
 *
 * @brief       This is the C code format driver file.
 *
 * @par         Project
 *              MG32
 * @version     V1.00
 * @date        2019/01/18
 * @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. 
 ******************************************************************************
 ******************************************************************************
 */



#include "Sample_I2C_ByteMode.h"



Sample_I2C_HandleTypeDef gSI2C0;
Sample_I2C_HandleTypeDef gSI2C1;



/**
 *******************************************************************************
 * @brief       Initialize the I2C0 peripheral for byte-mode
 * @details     1. I2C Initialze
 *      \n      2. Check Target device Ready
 *      \n      3. Write Data to Target device.
 *      \n      4. Read Data from Target device.
 *
 * @return      No
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_ByteMode_Init(&I2C0_Init);
 * @endcode     
 * @par         Modify
 *              DRV_Return Sample_I2C_ByteMode_Init(Sample_I2C_InitTypeDef *sI2C)
 *******************************************************************************
 */
void Sample_I2C0_ByteMode(void)
{
    uint8_t const String0[] = {"Welcome use MEGAWIN ARM Coretex-M0 Series MG32x02z Product"};
    uint8_t lDataBuffer[80];
    
    gSI2C0.Instance = I2C0;
    gSI2C0.Init.CK_I2C_PR_Frequency = 12000000;
    gSI2C0.Init.SCL_Clock = 1000000;
    gSI2C0.Init.OwnAddress1 = 0x04;

//    DRV_Return Sample_I2C_ByteMode_Init(Sample_I2C_InitTypeDef *sI2C);
    Sample_I2C_ByteMode_Init(&gSI2C0);

//    printf("I2C_IsDeviceReady\n\r");

//    DRV_Return Sample_I2C_IsDeviceReady(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint32_t Trials)
    if(Sample_I2C_IsDeviceReady(&gSI2C0, (uint16_t)0x04, 10) != DRV_Success)
        printf("Target device is not ready\n\r");

//    DRV_Return Sample_I2C_ByteMode_MasterTransmit(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
    if(Sample_I2C_ByteMode_MasterTransmit(&gSI2C0, (uint16_t)0x04, (uint8_t *)String0, (sizeof(String0)-1)) != DRV_Success)
        printf("Mater transmited data fail\n\r");

//    DRV_Return Sample_I2C_IsDeviceReady(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint32_t Trials)
    if(Sample_I2C_IsDeviceReady(&gSI2C0, (uint16_t)0x04, 10) != DRV_Success)
        printf("Target device is not ready\n\r");

//    DRV_Return Sample_I2C_ByteMode_MasterReceive(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
    if(Sample_I2C_ByteMode_MasterReceive(&gSI2C0, (uint16_t)0x04, (uint8_t *)lDataBuffer, 80) != DRV_Success)
        printf("Mater received data fail\n\r");

//    DRV_Return Sample_I2C_ByteMode_SlaveReceive(Sample_I2C_HandleTypeDef *SI2C, uint8_t *pData, uint16_t Lenth)
    if(Sample_I2C_ByteMode_SlaveReceive(&gSI2C0, (uint8_t *)lDataBuffer, 80) != DRV_Success)
        printf("Slave received data fail\n\r");

//    DRV_Return Sample_I2C_ByteMode_SlaveTransmit(Sample_I2C_HandleTypeDef *SI2C, uint8_t *pData, uint16_t Lenth)
    if(Sample_I2C_ByteMode_SlaveTransmit(&gSI2C0, (uint8_t *)String0, (sizeof(String0)-1)) != DRV_Success)
        printf("Slave transmited data fail\n\r");
}



/**
 *******************************************************************************
 * @brief       Initialize the I2C1 peripheral for byte-mode
 * @details     1. I2C Initialze
 *      \n      2. Check Target device Ready
 *      \n      3. Write Data to Target device.
 *      \n      4. Read Data from Target device.
 *
 * @return      No
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_ByteMode_Init(&I2C1_Init);
 * @endcode     
 * @par         Modify
 *              DRV_Return Sample_I2C_ByteMode_Init(Sample_I2C_InitTypeDef *sI2C)
 *******************************************************************************
 */
void Sample_I2C1_ByteMode(void)
{
    uint8_t const String0[] = {"Welcome use MEGAWIN ARM Coretex-M0 Series MG32x02z Product"};
    uint8_t lDataBuffer[80];
    
    gSI2C1.Instance = I2C1;
    gSI2C1.Init.CK_I2C_PR_Frequency = 12000000;
    gSI2C1.Init.SCL_Clock = 400000;
    gSI2C1.Init.OwnAddress1 = 0x02;
//  DRV_Return Sample_I2C_ByteMode_Init(Sample_I2C_InitTypeDef *sI2C);
    Sample_I2C_ByteMode_Init(&gSI2C1);

//    printf("I2C_IsDeviceReady\n\r");

////    DRV_Return Sample_I2C_IsDeviceReady(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint32_t Trials)
    if(Sample_I2C_IsDeviceReady(&gSI2C1, (uint16_t)0x04, 10) != DRV_Success)
        printf("Target device is not ready\n\r");

//    DRV_Return Sample_I2C_ByteMode_MasterTransmit(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
    if(Sample_I2C_ByteMode_MasterTransmit(&gSI2C1, (uint16_t)0x04, (uint8_t *)String0, (sizeof(String0)-1)) != DRV_Success)
        printf("Mater transmited data fail\n\r");

////    DRV_Return Sample_I2C_IsDeviceReady(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint32_t Trials)
    if(Sample_I2C_IsDeviceReady(&gSI2C1, (uint16_t)0x04, 10) != DRV_Success)
        printf("Target device is not ready\n\r");

//    DRV_Return Sample_I2C_ByteMode_MasterReceive(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
    if(Sample_I2C_ByteMode_MasterReceive(&gSI2C1, (uint16_t)0x04, (uint8_t *)lDataBuffer, 80) != DRV_Success)
        printf("Mater received data fail\n\r");

//    DRV_Return Sample_I2C_ByteMode_SlaveReceive(Sample_I2C_HandleTypeDef *SI2C, uint8_t *pData, uint16_t Lenth)
    if(Sample_I2C_ByteMode_SlaveReceive(&gSI2C1, (uint8_t *)lDataBuffer, 80) != DRV_Success)
        printf("Slave received data fail\n\r");

//    DRV_Return Sample_I2C_ByteMode_SlaveTransmit(Sample_I2C_HandleTypeDef *SI2C, uint8_t *pData, uint16_t Lenth)
    if(Sample_I2C_ByteMode_SlaveTransmit(&gSI2C1, (uint8_t *)String0, (sizeof(String0)-1)) != DRV_Success)
        printf("Slave transmited data fail\n\r");
}



/**
 *******************************************************************************
 * @brief  	    DeInitialize I2C peripheral
 * @details     Enable CSC to SPI clock
 *
 * @param[in]   SI2C : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified I2C.
 * @return	    DRV_Return
 * @note        
 * @par         Example
 * @code
                Sample_I2C_DeInit(&I2C0_Init);
                Sample_I2C_DeInit(&I2C1_Init);
 * @endcode
 *******************************************************************************
 */
DRV_Return Sample_I2C_DeInit(Sample_I2C_HandleTypeDef *SI2C)
{
    if(__I2C_GetFlagStatus(SI2C->Instance, I2C_FLAG_BUSYF))
        return DRV_Busy;

    __I2C_Disable(SI2C->Instance);

    SI2C->Instance->CR0.W = 0;
    SI2C->Instance->STA.W = (~(I2C_FLAG_EVENTF | I2C_FLAG_TXF));
    SI2C->Instance->INT.W = 0;
    SI2C->Instance->CLK.W = 0;
    SI2C->Instance->CR1.W = 0;
    SI2C->Instance->CR2.W = 0;
    SI2C->Instance->SADR.W = 0;
    SI2C->Instance->TMOUT.W = 0;
    SI2C->Instance->CR0.W = 0;

    return DRV_Success;
}



/**
 *******************************************************************************
 * @brief       Initialize the I2C peripheral for byte-mode
 * @details     1. GPIO Initial
 *      \n      1.1 CSC for GPIO Config
 *      \n      1.2 GPIO Config
 *      \n      2. I2C Initial
 *      \n      2.1 CSC for I2C Config
 *      \n      2.2 I2C Output Clock Config 
 *      \n      2.3 I2C Opration Mode Config
 *      \n      2.4 I2C Interrupt Config
 *      \n      2.5 I2C Timeout Config
 *      \n      2.6 I2C Enable
 *
 * @param[in]   SI2C : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified I2C.
 * @return      DRV_Return
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_ByteMode_Init(&I2C0_Init);
                Sample_I2C_ByteMode_Init(&I2C1_Init);
 * @endcode     
 * @par         Modify
 *              DRV_Return Sample_I2C_ByteMode_Init(Sample_I2C_InitTypeDef *SI2C)
 *******************************************************************************
 */
DRV_Return Sample_I2C_ByteMode_Init(Sample_I2C_HandleTypeDef *SI2C)
{
//    PIN_InitTypeDef PINX_InitStruct;
    uint16_t lI2C_Pre = 1;
    uint16_t lI2C_DIV = 1;
    uint16_t lI2C_HT_LT = 0;
    uint16_t lI2C_LT;
    uint16_t lI2C_HT;

    //===== Check I2C Busy =====//
    if(__I2C_GetFlagStatus(SI2C->Instance, I2C_FLAG_BUSYF))
        return DRV_Busy;

    __I2C_Disable(SI2C->Instance);

//    //===== GPIO Initial =====//
//      //===== CSC for GPIO Config =====//
//    UnProtectModuleReg(CSCprotect);                                             // Unprotect CSC module
//    CSC_PeriphOnModeClock_Config(CSC_ON_PortB, ENABLE);		                    // Enable PortB clock
//    CSC_PeriphOnModeClock_Config(CSC_ON_PortC, ENABLE);		                    // Enable PortC clock
////    CSC_PeriphOnModeClock_Config(CSC_ON_PortD, ENABLE);		                    // Enable PortD clock
////    CSC_PeriphOnModeClock_Config(CSC_ON_PortE, ENABLE);		                    // Enable PortE clock
//    ProtectModuleReg(CSCprotect);                                               // protect CSC module

//      //===== GPIO Config =====//
//    PINX_InitStruct.PINX_Mode	            = PINX_Mode_OpenDrain_O;            // Pin select pusu pull mode
//    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Disable;         // Enable pull up resistor
//    PINX_InitStruct.PINX_Speed              = PINX_Speed_High;           
//    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

//    if(sI2C->Instance == I2C0)
//    {
//        GPIO_PinMode_Config(PINB(10),&PINX_InitStruct);                         // I2C0 SCL setup at PB10
//        GPIO_PinMode_Config(PINB(11),&PINX_InitStruct);                         // I2C0 SDA setup at PB11

////        GPIO_PinMode_Config(PINC(4),&PINX_InitStruct);                          // I2C0 SCL setup at PC4
////        GPIO_PinMode_Config(PINC(5),&PINX_InitStruct);                          // I2C0 SDA setup at PC5

////        GPIO_PinMode_Config(PINC(8),&PINX_InitStruct);                          // I2C0 SCL setup at PC8
////        GPIO_PinMode_Config(PINC(9),&PINX_InitStruct);                          // I2C0 SDA setup at PC9

////        GPIO_PinMode_Config(PIND(5),&PINX_InitStruct);                          // I2C0 SCL setup at PD5
////        GPIO_PinMode_Config(PIND(6),&PINX_InitStruct);                          // I2C0 SDA setup at PD6

////        GPIO_PinMode_Config(PINE(0),&PINX_InitStruct);                          // I2C0 SCL setup at PE0
////        GPIO_PinMode_Config(PINE(1),&PINX_InitStruct);                          // I2C0 SDA setup at PE1
//    }

//    if(sI2C->Instance == I2C1)
//    {
//        GPIO_PinMode_Config(PINC(10),&PINX_InitStruct);                         // I2C1 SCL setup at PC10
//        GPIO_PinMode_Config(PINC(11),&PINX_InitStruct);                         // I2C1 SDA setup at PC11

////        GPIO_PinMode_Config(PIND(8),&PINX_InitStruct);                          // I2C1 SCL setup at PD8
////        GPIO_PinMode_Config(PIND(9),&PINX_InitStruct);                          // I2C1 SDA setup at PD9

////        GPIO_PinMode_Config(PINE(2),&PINX_InitStruct);                          // I2C1 SCL setup at PE2
////        GPIO_PinMode_Config(PINE(3),&PINX_InitStruct);                          // I2C1 SDA setup at PE3
//    }

//    //===== I2C Initial =====//
//      //=== CSC for I2C Config ===//
//    UnProtectModuleReg(CSCprotect);                                             // Unprotect CSC module
//    if(sI2C->Instance == I2C0)
//        CSC_PeriphOnModeClock_Config(CSC_ON_I2C0, ENABLE);                      // Enable SPI0 module clock
//    if(sI2C->Instance == I2C1)
//        CSC_PeriphOnModeClock_Config(CSC_ON_I2C1, ENABLE);                      // Enable SPI0 module clock
//    ProtectModuleReg(CSCprotect);                                               // protect CSC module

      //=== I2C Config ===//
    //===== I2C Output Clock Config =====//
    // CK_I2C_PR
    // SCL Output Clock
    // HT + LT, <= 32 >=9, CK_I2C_PR / SCL Clock / Prescaler / DIV

  #if defined(MG32F02A132) || defined(MG32F02A072) 
    do{
        lI2C_HT_LT = SI2C->Init.CK_I2C_PR_Frequency / SI2C->Init.SCL_Clock / lI2C_Pre / lI2C_DIV;
        if((lI2C_HT_LT >= 32) || (lI2C_HT_LT <=9)) 
        {
            lI2C_Pre ++;
            if(lI2C_Pre > 8)
            {
                lI2C_Pre = 1;
                lI2C_DIV ++;
            }
        }
    }while((lI2C_HT_LT >= 32) || (lI2C_HT_LT <=9));
  #else
    do{
        lI2C_HT_LT = SI2C->CK_I2C_PR_Frequency / SI2C->SCL_Clock / lI2C_Pre / lI2C_DIV;
        if((lI2C_HT_LT >= 64) || (lI2C_HT_LT <=9)) 
        {
            lI2C_Pre ++;
            if(lI2C_Pre > 8)
            {
                lI2C_Pre = 1;
                lI2C_DIV ++;
            }
        }
    }while((lI2C_HT_LT >= 64) || (lI2C_HT_LT <=9));
  #endif

    lI2C_LT = (lI2C_HT_LT >> 1);
    lI2C_HT = lI2C_HT_LT - lI2C_LT;

    __I2C_SetClockSource(SI2C->Instance, I2C_CLK_SRC_PROC);
    __I2C_SetClockPrescaler(SI2C->Instance, lI2C_Pre - 1);
    __I2C_SetClockDivider(SI2C->Instance, lI2C_DIV - 1);
    __I2C_SetSCLHighTime(SI2C->Instance, lI2C_HT - 1);
    __I2C_SetSCLLowTime(SI2C->Instance, lI2C_HT - 1);

    //===== I2C Opration Mode Config =====//
    if(SI2C->Init.SCL_Clock > 450000)
        __I2C_SetPreDriveTime(SI2C->Instance, I2C_PDRV_1T);
    else
        __I2C_SetPreDriveTime(SI2C->Instance, I2C_PDRV_0T);

    __I2C_GeneralCallAddress_Disable(SI2C->Instance);
    __I2C_SlaveAddressDetect_Disable(SI2C->Instance, I2C_SADR_2);

    __I2C_SetSlaveAddress1(SI2C->Instance, SI2C->Init.OwnAddress1);
  #if defined(MG32F02A132) || defined(MG32F02A072) 
  #else
    __I2C_SlaveAddress1Mask(SI2C->Instance, 0xFE);
  #endif
    __I2C_SlaveAddressDetect_Enable(SI2C->Instance, I2C_SADR_1);

    __I2C_Set_STA_STO_AA_000(SI2C->Instance);

    //===== I2C Interrupt Config =====//
    if(SI2C->Instance == I2C0)
    {
        NVIC_EnableIRQ(I2C0_IRQn);
        NVIC_SetPriority(I2C0_IRQn, 1);                                         // Suggest SYSTICK Priority = 0
                                                                                //           Other Priority > 0
    }

    if(SI2C->Instance == I2C1)
    {
        NVIC_EnableIRQ(I2Cx_IRQn);
        NVIC_SetPriority(I2Cx_IRQn, 1);                                         // Suggest SYSTICK Priority = 0
                                                                                //           Other Priority > 0
    }

    __I2C_ITEA_Disable(SI2C->Instance);
    __I2C_IT_Disable(SI2C->Instance, (I2C_IT_TMOUT | I2C_IT_EVENT | I2C_IT_ERR | I2C_IT_BUF ));

    //===== I2C Timeout Config =====//
    __I2C_TMO_Disable(SI2C->Instance);
    __I2C_SetTimeOutClockSource(SI2C->Instance, I2C_TMO_CKS_DIV64);
    __I2C_SetTimeOutDetectionMode(SI2C->Instance, I2C_TMO_MDS_GENERAL);
    __I2C_SetTimeOutCount(SI2C->Instance, I2C_TMO_MDS_GENERAL);

    //===== I2C Enable =====//
    __I2C_Enable(SI2C->Instance);
    return DRV_Success;
}



/**
 *******************************************************************************
 * @brief       for I2C Dlelay
 * @details     ms Delay.
 *              
 * @param[in]   Delay : Delay Time. unit ms.
 * @return      No
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_Delay(20);
                Sample_I2C_Delay(5);
 * @endcode     
 * @par         Modify
 *              void Sample_I2C_Delay(uint32_t Delay)
 *******************************************************************************
 */
void Sample_I2C_Delay(uint32_t Delay)
{
    // to do ...
}



/**
 *******************************************************************************
 * @brief       I2C Is Device Ready
 * @details     Checks if target device is ready for communication.
 * @param[in]   SI2C : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified I2C.
 * @param[in]   DevAddress : Target device address: The device 7 bits address
 *              value in datasheet must be shift at right before call interface.
 * @param[in]   Trials : Number of trials
 * @return      DRV status
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                if(Sample_I2C_IsDeviceReady(&gSI2C0, 0xA0, (uint8_t *)&DataBuffer, 256) != DRV_Success)
 * @endcode     
 * @par         Modify
 *              DRV_Return Sample_I2C_IsDeviceReady(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint32_t Trials)
 *******************************************************************************
 */
DRV_Return Sample_I2C_IsDeviceReady(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint32_t Trials)
{
//-----Check I2C Busy ------------------
    if(__I2C_GetFlagStatus(SI2C->Instance, I2C_FLAG_BUSYF) != CLR)
        return DRV_Busy;

//-----Set_Config-----------------------
    SI2C->State.W = 0;
    SI2C->SlaveAddress = DevAddress & 0xFFFE;
    SI2C->pData = 0x00000000;
    SI2C->Length = 0;
    SI2C->Count = 0;
    SI2C->Control.W = Sample_I2C_XferNext_STOP;

//-----Start----------------------------
    do{
        SI2C->State.W = 0;
        Set_STA_STO_AA_100(SI2C->Instance);
        do{
            Sample_I2C_ByteMode_Handle(SI2C);
        }while(SI2C->State.MBit.Done == 0);

        if((SI2C->State.W & (Sample_I2C_State_BusError | \
                             Sample_I2C_State_ArbitrationLost | \
                             Sample_I2C_State_NACK |\
                             Sample_I2C_State_Length)) == 0)
            return DRV_Success;

        Sample_I2C_Delay(1);
        
    }while(-- Trials > 0);

    return DRV_Failure;
}



/**
 *******************************************************************************
 * @brief       I2C Byte Mode Master Transmit
 * @details     Transmits in master mode an amount of data in blocking mode.
 * @param[in]   SI2C : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified I2C.
 * @param[in]   DevAddress : Target device address: The device 7 bits address
 *              value in datasheet must be shift at right before call interface.
 * @param[in]   pData : Pointer to data buffer.
 * @param[in]   Lenth : Amount of data to be sent.
 * @return      DRV status
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_ByteMode_MasterTransmit(&gSI2C0, 0xA0, (uint8_t *)&DataBuffer, 256);
 * @endcode     
 * @par         Modify
 *              DRV_Return Sample_I2C_ByteMode_MasterTransmit(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
 *******************************************************************************
 */
DRV_Return Sample_I2C_ByteMode_MasterTransmit(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
{
//-----Check----------------------------
    if(__I2C_GetFlagStatus(SI2C->Instance, I2C_FLAG_BUSYF) != CLR)
        return DRV_Busy;

//-----Set_Config-----------------------
    SI2C->State.W = 0;
    SI2C->SlaveAddress = DevAddress & 0xFFFE;
    SI2C->pData = pData;
    SI2C->Length = Lenth;
    SI2C->Count = 0;
    SI2C->Control.W = Sample_I2C_XferNext_STOP;

//-----Start----------------------------
    Set_STA_STO_AA_100(SI2C->Instance);
    do{
        Sample_I2C_ByteMode_Handle(SI2C);
    }while(SI2C->State.MBit.Done == 0);

    if((SI2C->State.W & (Sample_I2C_State_BusError | \
                         Sample_I2C_State_ArbitrationLost | \
                         Sample_I2C_State_NACK |\
                         Sample_I2C_State_Length)) != 0)
        return DRV_Failure;
    return DRV_Success;
}



/**
 *******************************************************************************
 * @brief       I2C Byte Mode Master Receive
 * @details     Receives in master mode an amount of data in blocking mode.
 *              
 * @param[in]   SI2C : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified I2C.
 * @param[in]   DevAddress : Target device address: The device 7 bits address
 *              value in datasheet must be shift at right before call interface.
 * @param[in]   pData : Pointer to data buffer.
 * @param[in]   Lenth : Amount of data to be sent.
 * @return      DRV status
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_ByteMode_MasterReceive(&gSI2C0, 0xA0, (uint8_t *)&DataBuffer, 256);
 * @endcode     
 * @par         Modify
 *              DRV_Return Sample_I2C_ByteMode_MasterReceive(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
 *******************************************************************************
 */
DRV_Return Sample_I2C_ByteMode_MasterReceive(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
{
//-----Check----------------------------
    if(__I2C_GetFlagStatus(SI2C->Instance, I2C_FLAG_BUSYF) != CLR)
        return DRV_Busy;

//-----Set_Config-----------------------
    SI2C->State.W = 0;
    SI2C->SlaveAddress = DevAddress | 0x0001;
    SI2C->pData = pData;
    SI2C->Length = Lenth;
    SI2C->Count = 0;
    SI2C->Control.W = Sample_I2C_XferNext_STOP;

//-----Start----------------------------
    Set_STA_STO_AA_100(SI2C->Instance);
    do{
        Sample_I2C_ByteMode_Handle(SI2C);
    }while(SI2C->State.MBit.Done == 0);

    if((SI2C->State.W & (Sample_I2C_State_BusError | \
                         Sample_I2C_State_ArbitrationLost | \
                         Sample_I2C_State_NACK |\
                         Sample_I2C_State_Length)) != 0)
        return DRV_Failure;

    return DRV_Success;
}



/**
 *******************************************************************************
 * @brief       I2C Byte Mode Slave Receive
 * @details     Receives in master mode an amount of data in blocking mode.
 *              
 * @param[in]   SI2C : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified I2C.
 * @param[in]   DevAddress : Target device address: The device 7 bits address
 *              value in datasheet must be shift at right before call interface.
 * @param[in]   pData : Pointer to data buffer.
 * @param[in]   Lenth : Amount of data to be sent.
 * @return      DRV status
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_ByteMode_SlaveReceive(&gSI2C0, 0xA0, (uint8_t *)&DataBuffer, 256);
 * @endcode     
 * @par         Modify
 *              DRV_Return Sample_I2C_ByteMode_SlaveReceive(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
 *******************************************************************************
 */
DRV_Return Sample_I2C_ByteMode_SlaveReceive(Sample_I2C_HandleTypeDef *SI2C, uint8_t *pData, uint16_t Lenth)
{
//-----Check----------------------------
    if(__I2C_GetFlagStatus(SI2C->Instance, I2C_FLAG_BUSYF) != CLR)
        return DRV_Busy;

//-----Set_Config-----------------------
    SI2C->State.W = 0;
    SI2C->pData = pData;
    SI2C->Length = Lenth;
    SI2C->Count = 0;
    SI2C->Control.W = Sample_I2C_XferNext_STOP;

//-----Start----------------------------
    Set_STA_STO_AA_001(SI2C->Instance);
    do{
        Sample_I2C_ByteMode_Handle(SI2C);
    }while(SI2C->State.MBit.Done == 0);
    SI2C->Count  --;

    if((SI2C->State.W & (Sample_I2C_State_BusError | \
                         Sample_I2C_State_ArbitrationLost | \
                         Sample_I2C_State_NACK)) != 0)
        return DRV_Failure;
    return DRV_Success;
}



/**
 *******************************************************************************
 * @brief       I2C Byte Mode Slave Transmit
 * @details     Transmits in master mode an amount of data in blocking mode.
 * @param[in]   SI2C : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified I2C.
 * @param[in]   DevAddress : Target device address: The device 7 bits address
 *              value in datasheet must be shift at right before call interface.
 * @param[in]   pData : Pointer to data buffer.
 * @param[in]   Lenth : Amount of data to be sent.
 * @return      DRV status
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_ByteMode_SlaveTransmit(&gSI2C0, 0xA0, (uint8_t *)&DataBuffer, 256);
 * @endcode     
 * @par         Modify
 *              DRV_Return Sample_I2C_ByteMode_SlaveTransmit(Sample_I2C_HandleTypeDef *SI2C, uint16_t DevAddress, uint8_t *pData, uint16_t Lenth)
 *******************************************************************************
 */
DRV_Return Sample_I2C_ByteMode_SlaveTransmit(Sample_I2C_HandleTypeDef *SI2C, uint8_t *pData, uint16_t Lenth)
{
//-----Check----------------------------
    if(__I2C_GetFlagStatus(SI2C->Instance, I2C_FLAG_BUSYF) != CLR)
        return DRV_Busy;

//-----Set_Config-----------------------
    SI2C->State.W = 0;
    SI2C->pData = pData;
    SI2C->Length = Lenth;
    SI2C->Count = 0;
    SI2C->Control.W = Sample_I2C_XferNext_STOP;

//-----Start----------------------------
    Set_STA_STO_AA_001(SI2C->Instance);
    do{
        Sample_I2C_ByteMode_Handle(SI2C);
    }while((SI2C->State.MBit.Done == 0) || ((__I2C_GetEventCode(SI2C->Instance) & 0xF8) != 0xF8));
    SI2C->Count  --;

    if((SI2C->State.W & (Sample_I2C_State_BusError | \
                         Sample_I2C_State_ArbitrationLost | \
                         Sample_I2C_State_NACK)) != 0)
        return DRV_Failure;

    return DRV_Success;
}



/**
 *******************************************************************************
 * @brief       I2C ByteMode Handle
 * @details     
 *              
 * @param[in]   Sample_I2C : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
                             structure that contains the configuration 
                             information for the specified I2C.
 * @return      No
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_I2C_ByteMode_Handle(Sample_I2C_HandleTypeDef &gSI2C0);
 * @endcode     
 * @par         Modify
 *              void Sample_I2C_ByteMode_Handle(Sample_I2C_HandleTypeDef *Sample_I2C);
 *******************************************************************************
 */
void Sample_I2C_ByteMode_Handle(Sample_I2C_HandleTypeDef *Sample_I2C)
{
    uint8_t lState;

    if(__I2C_GetEventFlag(Sample_I2C->Instance) == 0)
        return;

    lState = __I2C_GetEventCode(Sample_I2C->Instance);
    switch(lState){
        case 0x00:  // Bus Error
            __I2C_ClearFlag(Sample_I2C->Instance, I2C_FLAG_BERRF | I2C_FLAG_ERRF);
            Sample_I2C->State.W |= Sample_I2C_State_BusError | \
                                   Sample_I2C_State_Done;;
            break;
//-------------------------------------
        case 0x08:  // SLA+W sent and ACK received 
        case 0x10:  // Repeated start condition
            Set_STA_STO_AA_000(Sample_I2C->Instance);
            __I2C_SendSBUF(Sample_I2C->Instance, ((uint8_t)Sample_I2C->SlaveAddress));
            break;

        case 0x18:  // MT SLA+W sent and ACK received
        case 0x28:  // MT DATA sent and ACK received
            if(Sample_I2C->Count == Sample_I2C->Length)
            {
                Set_STA_STO_AA_010(Sample_I2C->Instance);
                __I2C_ClearStateFlag(Sample_I2C->Instance);
                while(__I2C_GetStatusCode(Sample_I2C->Instance) == lState);
                lState = __I2C_GetStatusCode(Sample_I2C->Instance);
                Sample_I2C->State.W |= Sample_I2C_State_Done;
                return;
            }
            __I2C_SendSBUF(Sample_I2C->Instance, ((uint8_t)*Sample_I2C->pData));
            Sample_I2C->pData ++;
            Sample_I2C->Count ++;
            break;

        case 0x20:  // MT SLA+W sent NACK received 
        case 0x30:  // MT DATA sent NACK received
        case 0x48:  // MR SLA+R sent NACK received
            Set_STA_STO_AA_010(Sample_I2C->Instance);
            __I2C_ClearFlag(Sample_I2C->Instance, I2C_FLAG_NACKF | I2C_FLAG_ERRF);
            __I2C_ClearEventFlag(Sample_I2C->Instance);
            while(__I2C_GetEventCode(Sample_I2C->Instance) == lState);
            lState = __I2C_GetEventCode(Sample_I2C->Instance);
            Sample_I2C->State.W |= Sample_I2C_State_NACK | \
                                   Sample_I2C_State_Done;
            return;
//-------------------------------------
        case 0x38:  // Arbitration lost
            Set_STA_STO_AA_000(Sample_I2C->Instance);
            __I2C_ClearFlag(Sample_I2C->Instance, I2C_FLAG_ALOSF | I2C_FLAG_ERRF);
            Sample_I2C->State.W |= Sample_I2C_State_ArbitrationLost | \
                                   Sample_I2C_State_Done;
            break;
//-------------------------------------
        case 0x40:  // SLA+R sent and ACK received
            Set_STA_STO_AA_001(Sample_I2C->Instance);
        case 0x50:  // Data Received and ACK sent
            if(Sample_I2C->Count >= (Sample_I2C->Length - 1))
                Set_STA_STO_AA_000(Sample_I2C->Instance);
            *Sample_I2C->pData = __I2C_ReceiveSBUF(Sample_I2C->Instance);
            Sample_I2C->Count++;
            Sample_I2C->pData++;
            break;

        case 0x58:  // Data Received and NACK sent
            if((Sample_I2C->Control.W & Sample_I2C_XferNext_Mask) == Sample_I2C_XferNext_RepeatStart)
                Set_STA_STO_AA_100(Sample_I2C->Instance);
            else
                Set_STA_STO_AA_010(Sample_I2C->Instance);

            Sample_I2C->State.W |= Sample_I2C_State_Done;
            break;

//-------------------------------------
        case 0x68:  // Arbitration lost in SLA+R/W as master,
                    // Own SLA+W has been Received ACK has bee returned
        case 0x78:  // Arbitration lost in SLA+R/W as master,
                    // General Call address has been received ACK has been returned
            Sample_I2C->State.W |= Sample_I2C_State_ArbitrationLost;

        case 0x60:  // Own SLA+W has bee Received ACK has been returned
        case 0x70:  // General Call address has been received ACK has been returned
        case 0x80:  // Data byte has been received ACK has been return
        case 0x90:  // Previously address with General Call address
                    // Data byte has been received ACK has been return
            if(Sample_I2C->Count >= (Sample_I2C->Length - 1))
                Set_STA_STO_AA_000(Sample_I2C->Instance);
            *Sample_I2C->pData = __I2C_ReceiveSBUF(Sample_I2C->Instance);
            Sample_I2C->Count++;
            Sample_I2C->pData++;
            break;

        case 0xA0:  // A STOP or repeated START has been received while will addressed as SLV/REC
                Sample_I2C->Count--;
                Sample_I2C->pData--;

            if (Sample_I2C->Count == 0)
                break;

            if(Sample_I2C->Count != Sample_I2C->Length)
                Sample_I2C->State.W |= Sample_I2C_State_Length;

        case 0x88:  // Data byte has been received Not ACK has been return
        case 0x98:  // Previously address with General Call address
                    // Data byte has been received Not ACK has been return
            Sample_I2C->State.W |= Sample_I2C_State_Done;
            break;

//-------------------------------------
        case 0xB0:  // Arbitration lost in SLA+R/W as master,
                    // Own SLA+R has been Received ACK has bee returned
            Sample_I2C->State.W |= Sample_I2C_State_ArbitrationLost;

        case 0xA8:  // Own SLA+R has bee Received ACK has been returned
        case 0xB8:  // Data byte in SIDAT has been transmitted ACK has been received
            if(Sample_I2C->Count >= Sample_I2C->Length)
            {
                Set_STA_STO_AA_000(Sample_I2C->Instance);
                __I2C_SendSBUF(Sample_I2C->Instance, 0xFF);
            }
            else
            {
                __I2C_SendSBUF(Sample_I2C->Instance, ((uint8_t)*Sample_I2C->pData));
                Sample_I2C->pData ++;
            }
            Sample_I2C->Count ++;
            break;

        case 0xC0:  // Data byte or Last data byte in SIDAT has been transmitted Not ACK has been received
            Sample_I2C->State.W |= Sample_I2C_State_NACK;

        case 0xC8:  // Last Data byte in SIDAT has been transmitted ACK has been received
            Sample_I2C->State.W |= Sample_I2C_State_Done;
            break;

//-------------------------------------
//        case 0xD0: 
//        case 0xD8:
//        case 0xE0:
//        case 0xE8:
//        case 0xF0:
//-------------------------------------      
        case 0xF8:  // Bus Idle

        default:
            break;
    }
    __I2C_ClearEventFlag(Sample_I2C->Instance);
    //while(__I2C_GetEventFlag(Sample_I2C->Instance) != 0);
}


