/**
 * @file        apm32f4xx_smc_cfg.c
 *
 * @brief       This file provides configuration support for SMC
 *
 * @version     V1.0.0
 *
 * @date        2023-12-01
 *
 * @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_smc_cfg.h"

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

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

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

/* Private variables ******************************************************/
SRAM_HandleTypeDef hsram;
SMC_NORSRAM_TimingTypeDef SRAM_Timing;

/* Private function prototypes ********************************************/

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

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

/**
  * @brief  SRAM MSP Init.
  * @param  hsram pointer to a SRAM_HandleTypeDef structure that contains
  *                the configuration information for SRAM module.
  * @retval None
  */
void DAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* Enable GPIO clock */
    __DAL_RCM_GPIOD_CLK_ENABLE();
    __DAL_RCM_GPIOE_CLK_ENABLE();
    __DAL_RCM_GPIOF_CLK_ENABLE();
    __DAL_RCM_GPIOG_CLK_ENABLE();

    /* Enable SMC clock */
    __DAL_RCM_EMMC_CLK_ENABLE();

    /** GPIO configuration for SMC */
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | \
                          GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_9 | \
                          GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SMC;
    DAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | \
                          GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | \
                          GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SMC;
    DAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    /* PG0(A10) -> LCD RS */
    /* PG10(NE3) -> LCD CS */
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SMC;
    DAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

    /* GPIO configuration for LCD */
    GPIO_InitStruct.Pin = LCD_RST_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    DAL_GPIO_Init(LCD_RST_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = LCD_BK_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    DAL_GPIO_Init(LCD_BK_GPIO_PORT, &GPIO_InitStruct);
}

/**
  * @brief  SRAM MSP DeInit.
  * @param  hsram pointer to a SRAM_HandleTypeDef structure that contains
  *                the configuration information for SRAM module.
  * @retval None
  */
void DAL_SRAM_MspDeInit(SRAM_HandleTypeDef *hsram)
{
    /* Reset peripheral */
    __DAL_RCM_EMMC_FORCE_RESET();
    __DAL_RCM_EMMC_RELEASE_RESET();

    /* GPIO configuration for SMC */
    DAL_GPIO_DeInit(GPIOD, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | \
                          GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_9 | \
                          GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);

    DAL_GPIO_DeInit(GPIOE, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | \
                          GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | \
                          GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

    DAL_GPIO_DeInit(GPIOG, GPIO_PIN_0 | GPIO_PIN_10);

    /* GPIO configuration for LCD */
    DAL_GPIO_DeInit(LCD_RST_GPIO_PORT, LCD_RST_GPIO_PIN);
    DAL_GPIO_DeInit(LCD_BK_GPIO_PORT, LCD_BK_GPIO_PIN);
}

/**
 * @brief   SMC configuration
 *
 * @param   None
 *
 * @retval  None
 */
void DAL_SMC_Config(void)
{
    hsram.Instance = SMC_NORSRAM_DEVICE;
    hsram.Extended = SMC_NORSRAM_EXTENDED_DEVICE;

    /* SRAM device configuration */
    /* Timing configuration derived from system clock (up to 168Mhz)
       for 60ns as SRAM access time */
    SRAM_Timing.AddressSetupTime = 4;
    SRAM_Timing.AddressHoldTime = 0;
    SRAM_Timing.DataSetupTime = 2;
    SRAM_Timing.BusTurnAroundDuration = 0;
    SRAM_Timing.CLKDivision = 1;
    SRAM_Timing.DataLatency = 2;
    SRAM_Timing.AccessMode = SMC_ACCESS_MODE_B;

    hsram.Init.NSBank = SMC_NORSRAM_BANK3;
    hsram.Init.DataAddressMux = SMC_DATA_ADDRESS_MUX_DISABLE;
    hsram.Init.MemoryType = SMC_MEMORY_TYPE_NOR;
    hsram.Init.MemoryDataWidth = SMC_NORSRAM_MEM_BUS_WIDTH_16;
    hsram.Init.BurstAccessMode = SMC_BURST_ACCESS_MODE_DISABLE;
    hsram.Init.WaitSignalPolarity = SMC_WAIT_SIGNAL_POLARITY_LOW;
    hsram.Init.WrapMode = SMC_WRAP_MODE_DISABLE;
    hsram.Init.WaitSignalActive = SMC_WAIT_TIMING_BEFORE_WS;
    hsram.Init.WriteOperation = SMC_WRITE_OPERATION_ENABLE;
    hsram.Init.WaitSignal = SMC_WAIT_SIGNAL_DISABLE;
    hsram.Init.ExtendedMode = SMC_EXTENDED_MODE_DISABLE;
    hsram.Init.AsynchronousWait = SMC_ASYNCHRONOUS_WAIT_DISABLE;
    hsram.Init.WriteBurst = SMC_WRITE_BURST_DISABLE;
    hsram.Init.ContinuousClock = SMC_CONTINUOUS_CLOCK_SYNC_ASYNC;

    /* Initialize the SRAM controller */
    if (DAL_SRAM_Init(&hsram, &SRAM_Timing, &SRAM_Timing) != DAL_OK)
    {
        Error_Handler();
    }
}
