/**
  ******************************************************************************
 *
 * @file        Sample_MID_I2C.c
 *
 * @brief       I2C master transmit and reiceive sample code
 *
 * @par         Project
 *              MG32
 * @version     V1.11
 * @date        2021/05/27
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2020 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.
 *******************************************************************************
 ******************************************************************************
 */

/* Wizard menu ---------------------------------------------------------------*/

/* Includes ------------------------------------------------------------------*/
#include "MG32_MID.h"

/* External vairables --------------------------------------------------------*/

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
void DMA_IRQHandler(void);

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static GPIO_InitTypeDef GPIO_InitStruct;

static DMA_HandleTypeDef       mDMA_I2C0_Tx;
static DMA_HandleTypeDef       mDMA_I2C0_Rx;
static I2C_HandleTypeDef       mI2C0;

#if defined(MG32_2ND)
#else
  static DMA_HandleTypeDef   mDMA_I2C1_Tx;
  static DMA_HandleTypeDef   mDMA_I2C1_Rx;
  static I2C_HandleTypeDef   mI2C1;
#endif

static uint8_t                 I2C0_TxBuffer[80];
static uint8_t                 I2C0_RxBuffer[80];

/* Private function prototypes -----------------------------------------------*/
void Error_Handler(void);

void Sample_MID_I2C_Master(void);
void Sample_MID_I2C_Slave(void);
void Sample_MID_I2C_MEM(void);

void MX_DMA_Init(void);
void MX_I2C0_Init(void);
void MID_I2C_MspInit(I2C_HandleTypeDef *mI2C);

void I2C0_IRQHandler(void);

#if defined(MG32_2ND)
#else
    void I2Cx_IRQHandler(void);
#endif

/**
 *******************************************************************************
 * @brief       I2C master transmit and receive.
 * @details     1.Initial I2C
 *    \n        2.Check Device.
 *    \n        3.Transmit data.
 *    \n        4.Receive data.
 *    \n        5.Transmit data with Interrupt.
 *    \n        6.Receive data with Interrupt.
 * @return      None
 *******************************************************************************
 */
void Sample_MID_I2C_Master(void)
{
    MX_DMA_Init();
    MX_I2C0_Init();

    sprintf((char*)I2C0_TxBuffer, "Welcom use MEGAWIN Product MG32F02A132 with arm cortex-M0");

    MID_I2C_IsDeviceReady(&mI2C0, 0x20, 10, 20);
    MID_I2C_IsDeviceReady(&mI2C0, 0x40, 10, 20);
    MID_I2C_IsDeviceReady(&mI2C0, 0x60, 10, 20);
    MID_I2C_IsDeviceReady(&mI2C0, 0x80, 10, 20);
    MID_I2C_IsDeviceReady(&mI2C0, 0xA0, 10, 20);

//-----------------------------------------------------------------------------
    MID_I2C_Master_Transmit(&mI2C0, 0x20, I2C0_TxBuffer, 40, 25);

    MID_I2C_Master_Receive(&mI2C0, 0x20, I2C0_RxBuffer, 40, 25);

//-----------------------------------------------------------------------------
    MID_I2C_Master_Transmit_IT(&mI2C0, 0x40, I2C0_TxBuffer, 40);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(1);

    MID_I2C_Master_Receive_IT(&mI2C0, 0x40, I2C0_RxBuffer, 40);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(1);

//-----------------------------------------------------------------------------
    MID_I2C_Master_Transmit_DMA(&mI2C0, 0x20, I2C0_TxBuffer, 40);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(1);

    MID_I2C_Master_Receive_DMA(&mI2C0, 0x20, I2C0_RxBuffer, 40);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(1);
}


/**
 *******************************************************************************
 * @brief       I2C Slave transmit and receive.
 * @details     1.Initial I2C
 *    \n        2.Receive data.
 *    \n        3.Transmit data.
 *    \n        4.Receive data with Interrupt.
 *    \n        5.Transmit data with Interrupt.
 * @return      None
 *******************************************************************************
 */
void Sample_MID_I2C_Slave(void)
{
    MX_DMA_Init();
    MX_I2C0_Init();

    sprintf((char*)I2C0_TxBuffer, "Welcom use MEGAWIN Product MG32F02A032 with arm cortex-M0");

    MID_I2C_Slave_Receive(&mI2C0, I2C0_RxBuffer, 40, MID_MAX_DELAY);
    MID_I2C_Slave_Transmit(&mI2C0, I2C0_TxBuffer, 40, MID_MAX_DELAY);

//-----------------------------------------------------------------------------
    MID_I2C_Slave_Receive_IT(&mI2C0, I2C0_RxBuffer, 40);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_I2C_Slave_Transmit_IT(&mI2C0, I2C0_TxBuffer, 40);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);

//-----------------------------------------------------------------------------
    MID_I2C_Slave_Receive_DMA(&mI2C0, I2C0_RxBuffer, 40);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);

    MID_I2C_Slave_Transmit_DMA(&mI2C0, I2C0_TxBuffer, 40);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
}

/**
 *******************************************************************************
 * @brief       I2C Memory Write and Read.
 * @details     1.Initial I2C
 *    \n        2.Check Device.
 *    \n        3.Memory Write.
 *    \n        4.Memory Read.
 *    \n        5.Memory Write with Interrupt.
 *    \n        6.Memory Read with Interrupt.
 * @return      None
 *******************************************************************************
 */
void Sample_MID_I2C_MEM(void)
{
    MX_DMA_Init();
    MX_I2C0_Init();

    sprintf((char*)I2C0_TxBuffer, "Welcom use MEGAWIN Product MG32F02A132 with arm cortex-M0");

    MID_I2C_IsDeviceReady(&mI2C0, 0xA0, 10, 20);

    MID_I2C_Mem_Write(&mI2C0, 0xA0, 0x0010, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer), 8, MID_MAX_DELAY);
    MID_Delay(3); // Page Write Delay Time with 24C
    MID_I2C_Mem_Write(&mI2C0, 0xA0, 0x0018, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 8), 8, MID_MAX_DELAY);
    MID_Delay(3);
    MID_I2C_Mem_Write(&mI2C0, 0xA0, 0x0020, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 16), 8, MID_MAX_DELAY);
    MID_Delay(3);
    MID_I2C_Mem_Write(&mI2C0, 0xA0, 0x0028, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 24), 8, MID_MAX_DELAY);
    MID_Delay(3);
    MID_I2C_Mem_Write(&mI2C0, 0xA0, 0x0030, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 32), 8, MID_MAX_DELAY);
    MID_Delay(3);
    MID_I2C_Mem_Write(&mI2C0, 0xA0, 0x0038, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 40), 8, MID_MAX_DELAY);
    MID_Delay(3);

    MID_I2C_Mem_Read(&mI2C0, 0xA0, 0x0010, I2C_MEMADD_SIZE_8BIT, I2C0_RxBuffer, 48, MID_MAX_DELAY);

//-----------------------------------------------------------------------------
    MID_I2C_Mem_Write_IT(&mI2C0, 0xA0, 0x0080, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_IT(&mI2C0, 0xA0, 0x0088, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 8), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_IT(&mI2C0, 0xA0, 0x0090, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 16), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_IT(&mI2C0, 0xA0, 0x0098, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 24), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_IT(&mI2C0, 0xA0, 0x00A0, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 32), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_IT(&mI2C0, 0xA0, 0x00A8, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 40), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Read_IT(&mI2C0, 0xA0, 0x0080, I2C_MEMADD_SIZE_8BIT, I2C0_RxBuffer, 48);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);

//-----------------------------------------------------------------------------
    MID_I2C_Mem_Write_DMA(&mI2C0, 0xA0, 0x0080, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_DMA(&mI2C0, 0xA0, 0x0088, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 8), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_DMA(&mI2C0, 0xA0, 0x0090, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 16), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_DMA(&mI2C0, 0xA0, 0x0098, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 24), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_DMA(&mI2C0, 0xA0, 0x00A0, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 32), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Write_DMA(&mI2C0, 0xA0, 0x00A8, I2C_MEMADD_SIZE_8BIT, (I2C0_TxBuffer + 40), 8);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
    MID_Delay(3);

    MID_I2C_Mem_Read_DMA(&mI2C0, 0xA0, 0x0080, I2C_MEMADD_SIZE_8BIT, I2C0_RxBuffer, 48);
    while((MID_I2C_GetState(&mI2C0) & MID_I2C_STATE_BUSY) != 0);
}

/**
 ******************************************************************************
 * Enable DMA controller clock
 ******************************************************************************
 */
void MX_DMA_Init(void)
{
    /* DMA Interrupt Init */
    MID_NVIC_SetPriority(DMA_IRQn, 3);
    MID_NVIC_EnableIRQ(DMA_IRQn);
}

/**
 ******************************************************************************
 * @brief I2C0 Initialization Function
 * @retval None
 ******************************************************************************
 */
void MX_I2C0_Init(void)
{
    /* USER CODE BEGIN I2C0_Init 0 */

    /* USER CODE END I2C0_Init 0 */

    /* USER CODE BEGIN I2C0_Init 1 */

    /* USER CODE END I2C0_Init 1 */

    mI2C0.Instance = I2C0;
    mI2C0.Init.Timing = MID_I2C_GetInitTiming(&mI2C0, 100000UL);
    mI2C0.Init.OwnAddress1 = 0x20;
  #if defined(MG32_1ST)
  #else
    mI2C0.Init.OwnAddress1Masks = I2C_OA1_NOMASK;
  #endif
    mI2C0.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
    mI2C0.Init.OwnAddress2 = 0x80;
    mI2C0.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    if (MID_I2C_Init(&mI2C0) != MID_OK)
    {
        /* USER CODE BEGIN Error_Handler_Debug */
        /* User can add his own implementation to report the HAL error return state */
        __NOP();
        /* USER CODE END Error_Handler_Debug */
    }

    MID_I2CEx_ConfigPreDriveTime(&mI2C0, I2C_PDT_1T);
    /* USER CODE BEGIN I2C0_Init 2 */

    /* USER CODE END I2C0_Init 2 */
}

/**
 ******************************************************************************
 * @brief Initialize the I2C MSP(MCU Support Package).
 * @param  mI2C: Pointer to a I2C_HandleTypeDef structure that contains
 *               the configuration information for the specified I2C.
 * @retval None
 ******************************************************************************
 */
void MID_I2C_MspInit(I2C_HandleTypeDef *mI2C)
{
    if(mI2C->Instance == I2C0)
    {
        GPIO_InitStruct.Pin = (GPIO_Pin_10 | GPIO_Pin_11);
        GPIO_InitStruct.Alternate = 2;
        GPIO_InitStruct.Mode = GPIO_MODE_OPENDRAIN_O;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.OUTDrive = GPIO_OUTDRIVE_LEVEL0;
        GPIO_InitStruct.Inverse = GPIO_INVERSE_DISABLE;
        GPIO_InitStruct.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;
        MID_GPIO_Init(IOMB, &GPIO_InitStruct);

      /* I2C0 DMA Init */
        /* I2C0_Tx Init */
        mDMA_I2C0_Tx.Instance = DMA;
        mDMA_I2C0_Tx.DMAChannelIndex = DMAChannel0;
        mDMA_I2C0_Tx.Init.SrcPeri = MID_DMA_MEMORY_READ;       // Source symbol is memory
        mDMA_I2C0_Tx.Init.DesPeri = MID_DMA_I2C0_WRITE;        // Destination symbol is memory
        mDMA_I2C0_Tx.Init.BSize = DMA_BSIZE_1BYTE;             // Burst size is 1 byte
        mDMA_I2C0_Tx.Init.MEMMode = MID_DMA_MEMORY_NORMAL;     // Normal memory access mode    
        mDMA_I2C0_Tx.Init.LoopMode = DMA_LOOP_DISABLE;         // DISABLE Loop mode
      #if defined(MG32_2ND)
      #else
        mDMA_I2C0_Tx.Init.Priority = DMA_PRIORITY_HIGH;
      #endif

        if (MID_DMA_Init(&mDMA_I2C0_Tx) != MID_OK)
        {
            Error_Handler();
        }

        __MID_LINKDMA(mI2C, hdmatx, mDMA_I2C0_Tx);

        /* I2C0_Rx Init */
        mDMA_I2C0_Rx.Instance = DMA;
        mDMA_I2C0_Rx.DMAChannelIndex = DMAChannel1;
        mDMA_I2C0_Rx.Init.SrcPeri = MID_DMA_I2C0_READ;         // Source symbol is memory
        mDMA_I2C0_Rx.Init.DesPeri = MID_DMA_MEMORY_WRITE;      // Destination symbol is memory
        mDMA_I2C0_Rx.Init.BSize = DMA_BSIZE_1BYTE;             // Burst size is 1 byte
        mDMA_I2C0_Rx.Init.MEMMode = MID_DMA_MEMORY_NORMAL;     // Normal memory access mode    
        mDMA_I2C0_Rx.Init.LoopMode = DMA_LOOP_DISABLE;         // DISABLE Loop mode
      #if defined(MG32_2ND)
      #else
        mDMA_I2C0_Rx.PriorityMode = DMA_LEVEL;
        mDMA_I2C0_Rx.Init.Priority = DMA_PRIORITY_HIGH;
      #endif

        if (MID_DMA_Init(&mDMA_I2C0_Rx) != MID_OK)
        {
            Error_Handler();
        }

        __MID_LINKDMA(mI2C, hdmarx, mDMA_I2C0_Rx);

        /* I2C0_IRQn interrupt configuration */
        MID_NVIC_SetPriority(I2C0_IRQn, 2);
        MID_NVIC_EnableIRQ(I2C0_IRQn);
    }
  #if defined(MG32_2ND)
  #else
    else if(mI2C->Instance == I2C1)
    {
        GPIO_InitStruct.Pin = (GPIO_Pin_10 | GPIO_Pin_11);
        GPIO_InitStruct.Alternate = 2;
        GPIO_InitStruct.Mode = GPIO_MODE_OPENDRAIN_O;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.OUTDrive = GPIO_OUTDRIVE_LEVEL0;
        GPIO_InitStruct.Inverse = GPIO_INVERSE_DISABLE;
        GPIO_InitStruct.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;
        MID_GPIO_Init(IOMC, &GPIO_InitStruct);

      /* I2C1 DMA Init */
        /* I2C1_Tx Init */
        mDMA_I2C1_Tx.Instance = DMA;
        mDMA_I2C1_Tx.DMAChannelIndex = DMAChannel0;
        mDMA_I2C1_Tx.Init.SrcPeri = MID_DMA_MEMORY_READ;       // Source symbol is memory
        mDMA_I2C1_Tx.Init.DesPeri = MID_DMA_I2C1_WRITE;        // Destination symbol is memory
        mDMA_I2C1_Tx.Init.BSize = DMA_BSIZE_1BYTE;             // Burst size is 1 byte
        mDMA_I2C1_Tx.Init.MEMMode = MID_DMA_MEMORY_NORMAL;     // Normal memory access mode    
        mDMA_I2C1_Tx.Init.LoopMode = DMA_LOOP_DISABLE;         // DISABLE Loop mode
      #if defined(MG32_2ND)
      #else
        mDMA_I2C0_Tx.Init.Priority = DMA_PRIORITY_HIGH;
      #endif

        if (MID_DMA_Init(&mDMA_I2C1_Tx) != MID_OK)
        {
            Error_Handler();
        }

        __MID_LINKDMA(mI2C, hdmatx, mDMA_I2C1_Tx);

        /* I2C0_Rx Init */
        mDMA_I2C1_Rx.Instance = DMA;
        mDMA_I2C1_Rx.DMAChannelIndex = DMAChannel1;
        mDMA_I2C1_Rx.Init.SrcPeri = MID_DMA_I2C1_READ;         // Source symbol is memory
        mDMA_I2C1_Rx.Init.DesPeri = MID_DMA_MEMORY_WRITE;      // Destination symbol is memory
        mDMA_I2C1_Rx.Init.BSize = DMA_BSIZE_1BYTE;             // Burst size is 1 byte
        mDMA_I2C1_Rx.Init.MEMMode = MID_DMA_MEMORY_NORMAL;     // Normal memory access mode    
        mDMA_I2C1_Rx.Init.LoopMode = DMA_LOOP_DISABLE;         // DISABLE Loop mode
      #if defined(MG32_2ND)
      #else
        mDMA_I2C1_Rx.Init.Priority = DMA_PRIORITY_HIGH;
      #endif

        if (MID_DMA_Init(&mDMA_I2C1_Rx) != MID_OK)
        {
            Error_Handler();
        }

        __MID_LINKDMA(mI2C, hdmarx, mDMA_I2C1_Rx);

        /* I2Cx_IRQn interrupt configuration */
        MID_NVIC_SetPriority(I2Cx_IRQn, 2);
        MID_NVIC_EnableIRQ(I2Cx_IRQn);
    }
  #endif
}


/**
 ******************************************************************************
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 ******************************************************************************
 */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void DMA_IRQHandler(void)
{
    if(__DRV_EXIC_GET_ID8_SOURCE() & EXIC_SRC2_ID8_dma_b0)
    {
        // Middleware level interrupt routine
        MID_DMA_IRQHandler(&mDMA_I2C0_Tx);
        MID_DMA_IRQHandler(&mDMA_I2C0_Rx);
        //MID_DMA_IRQHandler(&mDMA_I2C1_Tx);
        //MID_DMA_IRQHandler(&mDMA_I2C1_Rx);
    }
}


/**
 ******************************************************************************
 * @brief This function handles I2C0 event global interrupt / I2C0 wake-up interrupt through EXTI line 23.
 * @retval None
 ******************************************************************************
 */
void I2C0_IRQHandler(void)
{
    /* USER CODE BEGIN I2C0_IRQn 0 */

    /* USER CODE END I2C0_IRQn 0 */
    MID_I2C_IRQHandler(&mI2C0);
    /* USER CODE BEGIN I2C0_IRQn 1 */

    /* USER CODE END I2C0_IRQn 1 */
}

#if defined(MG32_2ND)
#else
/**
 ******************************************************************************
 * @brief This function handles I2C1 event global interrupt / I2C1 wake-up interrupt through EXTI line 23.
 * @retval None
 ******************************************************************************
 */
void I2Cx_IRQHandler(void)
{
    /* USER CODE BEGIN I2C1_IRQn 0 */

    /* USER CODE END I2C1_IRQn 0 */
    MID_I2C_IRQHandler(&mI2C1);
    /* USER CODE BEGIN I2C1_IRQn 1 */

    /* USER CODE END I2C1_IRQn 1 */
}
#endif


