/*!
 * @file        bmp561_gpio.c
 *
 * @brief       This file provides all the GPIO firmware functions
 *
 * @version     V1.0.0
 *
 * @date        2025-01-01
 *
 * @attention
 *
 *  Copyright (C) 2025 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.
 */

#include "bmp561_gpio.h"
#include "bmp561_sysctrl.h"

/** @addtogroup Peripherals_Library Standard Peripheral Library
  @{
*/

/** @addtogroup GPIO_Driver GPIO Driver
  @{
*/

/** @addtogroup GPIO_Functions Functions
  @{
*/

/*!
 * @brief     Resets the GPIO peripheral registers to their default reset values.
 *
 * @param     None
 *
 * @retval    None
 *
 */
void GPIO_Reset(void)
{
    SYSCTRL_Unlock();
    SYSCTRL_EnableAHBPeriphReset(SYSCTRL_AHB_GPIO);
    SYSCTRL_DisableAHBPeriphReset(SYSCTRL_AHB_GPIO);
    SYSCTRL_Lock();
}

/*!
 * @brief     Configures the GPIO peripheral according to the specified parameters in the gpioConfig.
 *
 * @param     gpioConfig: pointer to a GPIO_Config_T structure.
 *
 * @retval    None
 *
 */
void GPIO_Config(GPIO_Config_T* gpioConfig)
{
    GPIO->MDR &= ~(GPIO_MODE << ((gpioConfig->pin) * 2));
    GPIO->MDR |= ((uint32_t)gpioConfig->mode << (gpioConfig->pin * 2));

    if(gpioConfig->pullEn == ENABLE)
    {
        GPIO->PUPDR |= (GPIO_PUE << (gpioConfig->pin * 2));
    }
    else
    {
        GPIO->PUPDR &= ~(GPIO_PUE << (gpioConfig->pin * 2));
    }

    GPIO->PUPDR &= ~(GPIO_PUS << ((gpioConfig->pin) * 2));
    GPIO->PUPDR |= ((uint32_t)gpioConfig->polarity << (gpioConfig->pin * 2 + 1));

    GPIO->OTR &= ~(GPIO_OT << gpioConfig->pin);
    GPIO->OTR |= ((uint32_t)gpioConfig->type << gpioConfig->pin);

    GPIO->OSR &= ~(GPIO_OS << gpioConfig->pin);
    GPIO->OSR |= ((uint32_t)gpioConfig->speed << gpioConfig->pin);

    GPIO->DSR &= ~(GPIO_DS << gpioConfig->pin);
    GPIO->DSR |= ((uint32_t)gpioConfig->drive << gpioConfig->pin);
}

/*!
 * @brief     Fills each GPIO_Config_T member with its default value.
 *
 * @param     adcConfig: pointer to a GPIO_Config_T structure which will be initialized.
 *
 * @retval    None
 *
 */
void GPIO_ConfigStructInit(GPIO_Config_T* gpioConfig)
{
    gpioConfig->pin = GPIO_PIN_0;
    gpioConfig->mode = GPIO_MODE_AN;
    gpioConfig->speed = GPIO_OS_HIGH;
    gpioConfig->type = GPIO_OT_PP;
    gpioConfig->pullEn = DISABLE;
    gpioConfig->polarity = GPIO_POL_UP;
    gpioConfig->drive = GPIO_DS_HIGH;
}

/*!
 * @brief     Configures the GPIO mode
 *
 * @param     pin: select specifies pin.
 *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @param     mode: select mode.
 *                  This parameter can be one of the following values:
 *                  @arg GPIO_MODE_AN : analog mode
 *                  @arg GPIO_MODE_IN : input mode
 *                  @arg GPIO_MODE_OUT: output mode
 *                  @arg GPIO_MODE_AF : alternate function mode
 *
 * @retval    None
 *
 */
void GPIO_ConfigMode(GPIO_PIN_T pin, GPIO_MODE_T mode)
{
    GPIO->MDR &= ~(GPIO_MODE << (pin * 2));
    GPIO->MDR |= ((uint32_t)mode << (pin * 2));
}

/*!
 * @brief     Enables GPIO pull up/down
 *
 * @param     pin: select specifies pin.
 *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @retval    None
 *
 */
void GPIO_EnablePull(GPIO_PIN_T pin)
{
    GPIO->PUPDR |= (GPIO_PUE << (pin * 2));
}

/*!
 * @brief     Disables GPIO pull up/down
 *
 * @param     pin: select specifies pin.
 *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @retval    None
 *
 */
void GPIO_DisablePull(GPIO_PIN_T pin)
{
    GPIO->PUPDR &= ~(GPIO_PUE << (pin * 2));
}

/*!
 * @brief     Configures the GPIO pull up/down
 *
 * @param     pin: select specifies pin.
 *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @param     polarity: select polarity.
 *                      This parameter can be one of the following values:
 *                      @arg GPIO_POL_UP  : pull up
 *                      @arg GPIO_POL_DOWN: pull down
 *
 * @retval    None
 *
 */
void GPIO_ConfigPull(GPIO_PIN_T pin, GPIO_POL_T polarity)
{
    GPIO->PUPDR &= ~(GPIO_PUS << (pin * 2));
    GPIO->PUPDR |= ((uint32_t)polarity << (pin * 2 + 1));
}

/*!
 * @brief     Configures the GPIO output type
 *
 * @param     pin: select specifies pin.
 *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @param     type: select output type.
 *                  This parameter can be one of the following values:
 *                  @arg GPIO_OT_PP: PP mode
 *                  @arg GPIO_OT_OD: OD mode
 *
 * @retval    None
 *
 */
void GPIO_ConfigOutputType(GPIO_PIN_T pin, GPIO_OT_T type)
{
    GPIO->OTR &= ~(GPIO_OT << pin);
    GPIO->OTR |= ((uint32_t)type << pin);
}

/*!
 * @brief     Configures the GPIO output speed
 *
 * @param     pin: select specifies pin.
 *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @param     speed: select output type.
 *                   This parameter can be one of the following values:
 *                   @arg GPIO_OS_HIGH: high speed
 *                   @arg GPIO_OS_LOW : low speed
 *
 * @retval    None
 *
 */
void GPIO_ConfigSpeedMode(GPIO_PIN_T pin, GPIO_OS_T speed)
{
    GPIO->OSR &= ~(GPIO_OS << pin);
    GPIO->OSR |= ((uint32_t)speed << pin);
}

/*!
 * @brief     Configures the GPIO drive force
 *
 * @param     pin: select specifies pin.
 *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @param     drive: select drive force.
 *                   This parameter can be one of the following values:
 *                   @arg GPIO_DS_HIGH: high drive force
 *                   @arg GPIO_DS_LOW : low drive force
 *
 * @retval    None
 *
 */
void GPIO_ConfigDriveForce(GPIO_PIN_T pin, GPIO_DS_T drive)
{
    GPIO->DSR &= ~(GPIO_DS << pin);
    GPIO->DSR |= ((uint32_t)drive << pin);
}

/*!
 * @brief     Reads GPIO input port pin
 *
 * @param     pin: select specifies pin.
 *                 This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @retval    Input bit value.
 *
 */
uint16_t GPIO_ReadBit(GPIO_PIN_T pin)
{
    return (GPIO->DINR & (0x01 << pin)) ? BIT_SET : BIT_RESET;
}

/*!
 * @brief     Reads GPIO input port
 *
 * @param     pin: select specifies pin.
 *                 This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @retval    Input bit value.
 *
 */
uint16_t GPIO_ReadPort(void)
{
    return GPIO->DINR;
}

/*!
 * @brief     Set GPIO output port pin
 *
 * @param     pin: select specifies pin.
 *                 This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @retval    None
 *
 */
void GPIO_SetBit(GPIO_PIN_T pin)
{
    GPIO->DOUTR |= ((uint32_t)0x01 << pin);
}

/*!
 * @brief     Reset GPIO output port pin
 *
 * @param     pin: select specifies pin.
 *                 This parameter can be one of GPIO_PIN_x( x can be from 0 to 9).
 *
 * @retval    None
 *
 */
void GPIO_ResetBit(GPIO_PIN_T pin)
{
    GPIO->DOUTR &= ~((uint32_t)0x01 << pin);
}

/*!
 * @brief     Writes GPIO output port
 *
 * @param     portVal: port value.
 *
 * @retval    None
 *
 */
void GPIO_WritePort(uint16_t portVal)
{
    GPIO->DOUTR = portVal;
}

/*!
 * @brief     Configures GPIO reuse.
 *
 * @param     pin: select specifies pin.
 *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 5).
 *
 * @param     reuse: select GPIO reuse.
 *                   This parameter can be one of the following values:
 *                   @arg GPIO_REUSE_AF0: reuse function 0
 *                   @arg GPIO_REUSE_AF1: reuse function 1
 *                   @arg GPIO_REUSE_AF2: reuse function 2
 *                   @arg GPIO_REUSE_AF3: reuse function 3
 *
 * @retval    None
 *
 */
void GPIO_ConfigPinReuse(GPIO_PIN_T pin, GPIO_REUSE_T reuse)
{
    GPIO->AFSELR &= ~(GPIO_AF << (pin * 2));
    GPIO->AFSELR |= ((uint32_t)reuse << (pin * 2));
}

/**@} end of group GPIO_Functions*/
/**@} end of group GPIO_Driver*/
/**@} end of group Peripherals_Library*/
