/**
 *******************************************************************************
 * @file    dpm32m0xx_eval.c
 *
 * @brief   firmware functions to manage leds, keys, COM ports
 *
 * @author  DPM
 *
 * @version V1.0.0, firmware update for DPM32M08x
 *
 * @date    2024-05-16
 *******************************************************************************/

/*
    Copyright (c) 2024, DP Microelectronics Inc.

    Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors
       may be used to endorse or promote products derived from this software without
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/

#include "dpm32m0xx_eval.h"

/* private variables */
static GPIO_Type* GPIO_PORT[LEDn] =
{
  LED1_GPIO_PORT,
  LED2_GPIO_PORT,
  LED3_GPIO_PORT,
  LED4_GPIO_PORT
};

static uint32_t GPIO_PIN[LEDn] =
{
  LED1_PIN,
  LED2_PIN,
  LED3_PIN,
  LED4_PIN
};

static GPIO_Type* KEY_PORT[KEYn] =
{
  KEY_UP_GPIO_PORT,
  KEY1_GPIO_PORT,
  KEY2_GPIO_PORT,
  KEY3_GPIO_PORT
};

static uint32_t KEY_PIN[KEYn] =
{
  KEY_UP_PIN,
  KEY1_PIN,
  KEY2_PIN,
  KEY3_PIN
};
static GPIO_PuPdEnum KEY_PUPD[KEYn] =
{
  KEY_UP_PUPD,
  KEY1_PUPD,
  KEY2_PUPD,
  KEY3_PUPD
};

static IRQn_Type KEY_IRQn[KEYn] =
{
  KEY_UP_GPIO_IRQn,
  KEY1_GPIO_IRQn,
  KEY2_GPIO_IRQn,
  KEY3_GPIO_IRQn
};

static GPIO_IntTypeEnum KEY_IRQType[KEYn] =
{
  KEY_UP_IRQ_TYPE,
  KEY1_IRQ_TYPE,
  KEY2_IRQ_TYPE,
  KEY3_IRQ_TYPE
};

/**
 *******************************************************************************
 * @brief   Configure led GPIO.
 * @param   [in]  lednum: specify the Led to be configured.
 *                This parameter can be a value of @ref EVAL_LedEnum.
 *                  @arg LED1.
 *                  @arg LED2.
 *                  @arg LED3.
 *                  @arg LED4.
 * @retval  None.
 ******************************************************************************/
void EVAL_LedInit(EVAL_LedEnum lednum)
{
  /* enable the led clock */
  RCC_Unlock();
  RCC_AHBPeriphClockCmd(RCC_AHB_PERIPH_GPIO, ENABLE);
  RCC_Lock();

  /* configure led GPIO port */
  GPIO_InitTypeStruct GPIO_InitStruct;
  GPIO_StructInit(&GPIO_InitStruct);
  GPIO_InitStruct.GPIO_Mode = GPIO_MODE_OUTPUT;
  GPIO_InitStruct.GPIO_Speed = GPIO_SPEED_HIGH;
  GPIO_InitStruct.GPIO_OType =  GPIO_OTYPE_PP;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PUPD_NOPULL;
  GPIO_InitStruct.GPIO_Pin =  GPIO_PIN[lednum];
  GPIO_Init(GPIO_PORT[lednum], &GPIO_InitStruct);

  GPIO_ResetBit(GPIO_PORT[lednum], GPIO_PIN[lednum]);
}

/**
 *******************************************************************************
 * @brief   Turn on selected led.
 * @param   [in]  lednum: specify the Led to be turned on.
 *                This parameter can be a value of @ref EVAL_LedEnum.
 *                  @arg LED1.
 *                  @arg LED2.
 *                  @arg LED3.
 *                  @arg LED4.
 * @retval  None.
 ******************************************************************************/
void EVAL_LedOn(EVAL_LedEnum lednum)
{
  GPIO_SetBit(GPIO_PORT[lednum], GPIO_PIN[lednum]);
}


/**
 *******************************************************************************
 * @brief   Turn off selected led.
 * @param   [in]  lednum: specify the Led to be turned off.
 *                This parameter can be a value of @ref EVAL_LedEnum.
 *                  @arg LED1.
 *                  @arg LED2.
 *                  @arg LED3.
 *                  @arg LED4.
 * @retval  None.
 ******************************************************************************/
void EVAL_LedOff(EVAL_LedEnum lednum)
{
  GPIO_ResetBit(GPIO_PORT[lednum], GPIO_PIN[lednum]);
}

/**
 *******************************************************************************
 * @brief   Toggle selected led.
 * @param   [in]  lednum: specify the Led to be toggled.
 *                This parameter can be a value of @ref EVAL_LedEnum.
 *                  @arg LED1.
 *                  @arg LED2.
 *                  @arg LED3.
 *                  @arg LED4.
 * @retval  None.
 ******************************************************************************/
void EVAL_LedToggle(EVAL_LedEnum lednum)
{
  GPIO_ToggleBit(GPIO_PORT[lednum], GPIO_PIN[lednum]);
}

/**
 *******************************************************************************
 * @brief   Configure key.
 * @param   [in]  keynum: specify the key to be configured.
 *                This parameter can be a value of @ref EVAL_KeyEnum.
 *                  @arg KEY_UP.
 *                  @arg KEY1.
 *                  @arg KEY2.
 *                  @arg KEY3.
 * @param   [in]  key_mode: specify button mode.
 *                This parameter can be a value of @ref EVAL_KeyModeEnum.
 *                  @arg KEY_MODE_GPIO.
 *                  @arg KEY_MODE_IRQ.
 * @retval  None.
 ******************************************************************************/
void EVAL_KeyInit(EVAL_KeyEnum keynum, EVAL_KeyModeEnum key_mode)
{
  /* enable the key clock */
  RCC_Unlock();
  RCC_AHBPeriphClockCmd(RCC_AHB_PERIPH_GPIO, ENABLE);
  RCC_Lock();

  /* configure button pin as input */
  GPIO_InitTypeStruct GPIO_InitStruct;
  GPIO_StructInit(&GPIO_InitStruct);
  GPIO_InitStruct.GPIO_Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.GPIO_Speed = GPIO_SPEED_HIGH;
  GPIO_InitStruct.GPIO_PuPd = KEY_PUPD[keynum];
  GPIO_InitStruct.GPIO_Pin = KEY_PIN[keynum];
  GPIO_Init(KEY_PORT[keynum], &GPIO_InitStruct);

  if(key_mode == KEY_MODE_IRQ)
  {
    /* enable and set key interrupt to the lowest priority */
    NVIC_SetPriority(KEY_IRQn[keynum], 2U);
    NVIC_EnableIRQ(KEY_IRQn[keynum]);

    /* configure GPIO interrupt */
    GPIO_IntConfig(KEY_PORT[keynum], KEY_PIN[keynum], KEY_IRQType[keynum]);
    GPIO_IntCmd(KEY_PORT[keynum], KEY_PIN[keynum], ENABLE);
    GPIO_ClearIntFlag(KEY_PORT[keynum], KEY_PIN[keynum]);
  }
}

/**
 *******************************************************************************
 * @brief   Return the selected button state.
 * @param   [in]  keynum: specify the key to be configured.
 *                This parameter can be a value of @ref EVAL_KeyEnum.
 *                  @arg KEY_UP.
 *                  @arg KEY1.
 *                  @arg KEY2.
 *                  @arg KEY3.
 * @retval  None.
 ******************************************************************************/
uint8_t EVAL_KeyStateGet(EVAL_KeyEnum keynum)
{
  return GPIO_ReadInputBit(KEY_PORT[keynum], KEY_PIN[keynum]);
}

/**
 *******************************************************************************
 * @brief   Configure COM port.
 * @param   None.
 * @retval  None.
 ******************************************************************************/
void EVAL_ComInit(void)
{
  /* enable GPIO clock */
  RCC_Unlock();
  RCC_AHBPeriphClockCmd(RCC_AHB_PERIPH_GPIO, ENABLE);
  RCC_APBPeriphClockCmd(EVAL_COM0_CLK, ENABLE);
  RCC_Lock();

  /* connect port to UARTx Pin */
  GPIO_InitTypeStruct GPIO_InitStruct;
  GPIO_StructInit(&GPIO_InitStruct);
  GPIO_InitStruct.GPIO_Mode = GPIO_MODE_ALT_FUNC;
  GPIO_InitStruct.GPIO_Speed = GPIO_SPEED_HIGH;
  GPIO_InitStruct.GPIO_OType =  GPIO_OTYPE_PP;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PUPD_NOPULL;

  GPIO_InitStruct.GPIO_Pin =  EVAL_COM0_TX_PIN | EVAL_COM0_RX_PIN;
  GPIO_Init(EVAL_COM_GPIO_PORT, &GPIO_InitStruct);
  GPIO_AltFuncConfig(EVAL_COM_GPIO_PORT, EVAL_COM0_TX_PIN | EVAL_COM0_RX_PIN, EVAL_COM_AF);

  /* UART configure */
  UART_DeInit(EVAL_COM0);
  UART_InitTypeStruct UART_InitStruct;
  UART_StructInit(&UART_InitStruct);
  UART_InitStruct.UART_BaudRate = 115200;
  UART_InitStruct.UART_DataLen = UART_DATA_LEN_8;
  UART_InitStruct.UART_StopBits = UART_STOP_BITS_1;
  UART_InitStruct.UART_Parity = UART_PARITY_NO;
  UART_InitStruct.UART_Mode = UART_MODE_RX_TX;
  UART_Init(EVAL_COM0, &UART_InitStruct);
  UART_Cmd(EVAL_COM0, ENABLE);
}
