/**
 * @file        apm32f4xx_i2c_cfg.c
 *
 * @brief       This file provides configuration support for I2C
 *
 * @version     V1.0.0
 *
 * @date        2023-07-31
 *
 * @attention
 *
 *  Copyright (C) 2023 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

/* Includes ***************************************************************/
#include "apm32f4xx_i2c_cfg.h"

/* Private includes *******************************************************/

/* Private macro **********************************************************/

/* Private typedef ********************************************************/

/* Private variables ******************************************************/
I2C_HandleTypeDef hi2c1;

/* Private function prototypes ********************************************/
static void I2C1_ErrorHandler(uint8_t addr);

/* External variables *****************************************************/

/* External functions *****************************************************/

/**
 * @brief  Initialize the I2C MSP
 *
 * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
 *         the configuration information for the specified I2C
 *
 * @retval None
 */
void DAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    if (hi2c->Instance == I2C1)
    {
        /* Enable peripheral GPIO clock */
        __DAL_RCM_GPIOB_CLK_ENABLE();

        /* I2C1 pin configuration */
        GPIO_InitStruct.Pin         = GPIO_PIN_8 | GPIO_PIN_9;
        GPIO_InitStruct.Mode        = GPIO_MODE_AF_OD;
        GPIO_InitStruct.Pull        = GPIO_NOPULL;
        GPIO_InitStruct.Speed       = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate   = GPIO_AF4_I2C1;
        DAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        /* Enable peripheral clock */
        __DAL_RCM_I2C1_CLK_ENABLE();
    }
}

/**
 * @brief  DeInitialize the I2C MSP
 *
 * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
 *         the configuration information for the specified I2C
 *
 * @retval None
 */
void DAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
{
    if (hi2c->Instance == I2C1)
    {
        /* Disable peripheral clock */
        __DAL_RCM_I2C1_CLK_DISABLE();

        /* I2C1 GPIO configuration */
        DAL_GPIO_DeInit(GPIOB, GPIO_PIN_8 | GPIO_PIN_9);
    }
}

/**
 * @brief   I2C1 configuration
 *
 * @param   None
 *
 * @retval  None
 */
void DAL_I2C1_Config(void)
{
    /* Configure the I2C1 */
    hi2c1.Instance              = I2C1;
    hi2c1.Init.ClockSpeed       = 100000U;
    hi2c1.Init.AddressingMode   = I2C_ADDRESSINGMODE_7BIT;
    hi2c1.Init.OwnAddress1      = 0U;
    hi2c1.Init.OwnAddress2      = 0U;
    hi2c1.Init.DutyCycle        = I2C_DUTYCYCLE_2;
    hi2c1.Init.DualAddressMode  = I2C_DUALADDRESS_DISABLE;
    hi2c1.Init.GeneralCallMode  = I2C_GENERALCALL_DISABLE;
    hi2c1.Init.NoStretchMode    = I2C_NOSTRETCH_DISABLE;
    if (DAL_I2C_Init(&hi2c1) != DAL_OK)
    {
        Error_Handler();
    }
}

/**
 * @brief   Writes a data
 *
 * @param   addr: I2C address
 *
 * @param   regAddr: Reg address 
 *
 * @param   regVal: Data to be written
 *
 * @retval  None
 */
void I2C1_WriteData(uint8_t addr, uint8_t regAddr, uint8_t regVal)
{
    if(DAL_I2C_Mem_Write(&hi2c1, \
                         addr, \
                         (uint16_t)regAddr, \
                         I2C_MEMADD_SIZE_8BIT, \
                         &regVal, \
                         1U, \
                         I2C_TIMEOUT) != DAL_OK)
    {
        I2C1_ErrorHandler(addr);
    }
}

/**
 * @brief   Reads a data
 *
 * @param   addr: I2C address
 *
 * @param   regAddr: Reg address
 *
 * @param   regVal: Pointer to the register value
 *
 * @retval  None
 */
void I2C1_ReadData(uint8_t addr, uint8_t regAddr, uint8_t *regVal)
{
    if(DAL_I2C_Mem_Read(&hi2c1, \
                        addr, \
                        regAddr, \
                        I2C_MEMADD_SIZE_8BIT, \
                        regVal, \
                        1U, \
                        I2C_TIMEOUT) != DAL_OK)
    {
        I2C1_ErrorHandler(addr);
    }
}

/**
 * @brief   I2C error handler
 *
 * @param   addr: I2C address
 *
 * @retval  None
 */
static void I2C1_ErrorHandler(uint8_t addr)
{
    /* De-initialize the I2C */
    DAL_I2C_DeInit(&hi2c1);

    /* Re-Initiaize the I2C */
    DAL_I2C1_Config();
}
