
/**
 ******************************************************************************
 *
 * @file        MG0404A_BSP.c
 * @brief       MG0404A Board Support routine. 
 *
 * @par         Project
 *              MG32x02z
 * @version     V1.02
 * @date        2022/09/26
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 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.
 *******************************************************************************
 *******************************************************************************
 */


/* Includes ------------------------------------------------------------------*/
#include "MG0404A_BSP.h"
#include "MG32x02z_EncoderEC11_API.h"

/* Exported functions --------------------------------------------------------*/
extern void API_DS1621_Init(void);

/* Exported variables --------------------------------------------------------*/
extern uint32_t SystemCoreClock;

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
//DMA_HandleTypeDef mDMA_ADC;
//DMA_HandleTypeDef mDMA_DAC;
//DMA_HandleTypeDef mDMA_USB;

//DMA_HandleTypeDef mDMA_SPI0RX;  // SPI0 RX to Memory EMB
//DMA_HandleTypeDef mDMA_SPI0Rx_to_URT0Tx; // SPI0 RX to URT0 SPI Mode
static EMB_HandleTypeDef mEMB;

//IWDT_HandleTypeDef mIWDT;


//SPI_HandleTypeDef mSPI0;
static SPI_HandleTypeDef mURT0SPI;
//SPI_HandleTypeDef mURT2SPI;

RTC_HandleTypeDef mRTC;
static I2C_HandleTypeDef mI2C1;
URT_HandleTypeDef mURT4;
EXIC_HandleTypeDef mEXIC_PA;

/* Private function prototypes -----------------------------------------------*/
void DMACopyAgain(DMA_HandleTypeDef *mDMA);
void BSP_Interrupt_Init(void);
void BSP_EXIC_Init(void);
void BSP_LCD_EMB_Init(void);
void BSP_RTC_Init(void);
void BSP_URT_Init(void);
void BSP_SPI_Init(void);
uint32_t BSP_BLE_SPI_Init(void);
void BSP_I2C_Init(void);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/





/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void DMACopyAgain(DMA_HandleTypeDef *mDMA)
{
    __DRV_DMA_DISABLE_ITEA(mDMA);
//    MID_DMA_Start(mDMA, (uint32_t ) &SrcData2, (uint32_t ) &DestArea, 10);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
//void BSP_DMA_Init()
//{
//    mDMA.Instance = DMA;
//    mDMA.PriorityMode = DMA_LEVEL;
//    mDMA.ExtraGPL_Channel = NULL;
//}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_Interrupt_Init(void)
{
    MID_NVIC_SetPriority(USB_IRQn, 1);
    MID_NVIC_SetPriority(SPI0_IRQn, 1);
    MID_NVIC_SetPriority(TM20_IRQn, 2);
    MID_NVIC_SetPriority(TM3x_IRQn, 2);
    MID_NVIC_SetPriority(EXINT0_IRQn, 2);
    MID_NVIC_SetPriority(DMA_IRQn, 3);

    MID_NVIC_EnableIRQ(USB_IRQn);
    MID_NVIC_EnableIRQ(SPI0_IRQn);
    MID_NVIC_EnableIRQ(EXINT0_IRQn);
    MID_NVIC_EnableIRQ(TM3x_IRQn);
    MID_NVIC_EnableIRQ(EXINT0_IRQn);
    MID_NVIC_EnableIRQ(DMA_IRQn);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void MID_MspInit(void)
{
    GPIO_InitTypeDef mGPIO;

  // ICKO
    mGPIO.Pin           = CLKOUT_ICKO_Pin;
    mGPIO.Alternate     = CLKOUT_ICKO_AFS;
    mGPIO.Mode          = GPIO_MODE_PUSHPULL_O;
    mGPIO.Pull          = GPIO_NOPULLUP;
    mGPIO.Speed         = GPIO_SPEED_HIGH;
    mGPIO.Inverse       = GPIO_INVERSE_DISABLE;
    mGPIO.OUTDrive      = GPIO_OUTDRIVE_LEVEL0;
    mGPIO.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;
    MID_GPIO_Init(CLKOUT_ICKO_Port, &mGPIO);

    mGPIO.Mode          = GPIO_MODE_OPENDRAIN_O;
    mGPIO.Pin           = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    MID_GPIO_Init(IOMA, &mGPIO);

  // Debug for GPIO PE12 / 13 / 14 / 15 / PC13 / 14
    PE12 = PE13 = PE14 = PE15 = PC13 = PC14 = 1;
    mGPIO.Pin           = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    mGPIO.Alternate     = 0;
    mGPIO.Mode          = GPIO_MODE_PUSHPULL_O;
    MID_GPIO_Init(IOME, &mGPIO);

    mGPIO.Pin           = GPIO_Pin_13 | GPIO_Pin_14;
    MID_GPIO_Init(IOMC, &mGPIO);

    MID_NVIC_SetPriority(SysTick_IRQn, 0);
    MID_NVIC_SetPriority(SYS_IRQn, 1);
    MID_NVIC_SetPriority(DMA_IRQn, 3);

    MID_NVIC_EnableIRQ(SysTick_IRQn);
    MID_NVIC_EnableIRQ(SYS_IRQn);
    MID_NVIC_SetPriority(DMA_IRQn, 3);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
//void BSP_CSC_Init()
//{
//}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void MID_EXIC_MspInit( EXIC_HandleTypeDef* MEXIC_PX)
{
    GPIO_InitTypeDef mEXICEC11_GPIO;

    ((void)(MEXIC_PX));
    
    mEXICEC11_GPIO.Pull          = GPIO_NOPULLUP;
    mEXICEC11_GPIO.Speed         = GPIO_SPEED_HIGH;
    mEXICEC11_GPIO.Inverse       = GPIO_INVERSE_DISABLE;
    mEXICEC11_GPIO.OUTDrive      = GPIO_OUTDRIVE_LEVEL0;
    mEXICEC11_GPIO.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;

  // EC11
    // SW
    mEXICEC11_GPIO.Pin           = EC11_EXIC_SW_Pin;
    mEXICEC11_GPIO.Alternate     = EC11_EXIC_AFS;
    mEXICEC11_GPIO.Mode          = EC11_TM36_Mode;
    MID_GPIO_Init(EC11_TM36_Port, &mEXICEC11_GPIO);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_EXIC_Init(void)
{
    //EXIC Inital
    mEXIC_PA.Instance    = EXIC_PA;                         // Set mEXIC_PA to control external PortA input interrupt.
    mEXIC_PA.AND_Mask    = 0x0000;                          // Set AND mask = 0x03 ( If PA10 & PA14 trigger event happen at the same time , into interrupt. 
    mEXIC_PA.OR_Mask     = EXIC_PX_PIN14 | EXIC_PX_PIN10;   // Set OR mask = 0x0C (If PA10 or PA14 trigger event happen , into interrupt.
    mEXIC_PA.AND_UnMatch = DISABLE;                         // Disable AND flag status inverse. 
    mEXIC_PA.Interrupt   = EXIC_INTERRUPT_ENABLE;           // Enable Interrupt.

    MID_EXIC_PxTriggerMode_Config(&mEXIC_PA, EXIC_TRGS_PIN14, EXIC_TRIGGER_LEVEL);  // PA14 trigger event = Low Level.
    MID_EXIC_PxTriggerMode_Config(&mEXIC_PA, EXIC_TRGS_PIN10, EXIC_TRIGGER_EDGE);   // PA10 trigger event = falling edge.
    MID_EXIC_PxTrigger_Init(&mEXIC_PA);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void MID_EMB_MspInit(EMB_HandleTypeDef* MspInit_mEMB)
{
    GPIO_InitTypeDef mEMB_GPIO;

    ((void)(MspInit_mEMB));
    
    mEMB_GPIO.Pull          = GPIO_NOPULLUP;
    mEMB_GPIO.Speed         = GPIO_SPEED_HIGH;
    mEMB_GPIO.Inverse       = GPIO_INVERSE_DISABLE;
    mEMB_GPIO.OUTDrive      = GPIO_OUTDRIVE_LEVEL0;
    mEMB_GPIO.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;

  // LCD 
    // LCD BL
  #if defined(MG0404)
    mEMB_GPIO.Pin           = (LCD1st_BL_Pin | LCD2nd_BL_Pin);
    mEMB_GPIO.Alternate     = LCD1st_BL_AFS;
    mEMB_GPIO.Mode          = LCD1st_BL_Mode;
    MID_GPIO_Init(LCD1st_BL_Port, &mEMB_GPIO);
  #else
    mEMB_GPIO.Pin           = LCD_BL_Pin;
    mEMB_GPIO.Alternate     = LCD_BL_AFS;
    mEMB_GPIO.Mode          = LCD_BL_Mode;
    MID_GPIO_Init(LCD_BL_Port, &mEMB_GPIO);
  #endif

    // LCD RSTN
    mEMB_GPIO.Pin           = LCD_RSTN_Pin;
    mEMB_GPIO.Alternate     = LCD_RSTN_AFS;
    mEMB_GPIO.Mode          = LCD_RSTN_Mode;
    MID_GPIO_Init(LCD_RSTN_Port, &mEMB_GPIO);

  // LCD 1st use EMB
    // DB0[0:7] DIN
    mEMB_GPIO.Pin           = (LCD1st_D0_Pin | LCD1st_D1_Pin | LCD1st_D2_Pin | LCD1st_D3_Pin | LCD1st_D4_Pin | LCD1st_D5_Pin | LCD1st_D6_Pin | LCD1st_D7_Pin);
    mEMB_GPIO.Alternate     = LCD1st_D0_7_AFS;
    mEMB_GPIO.Mode          = LCD1st_D0_7_Mode;
    MID_GPIO_Init(LCD1st_D0_7_Port, &mEMB_GPIO);

    // DB[8:15] DIN
    mEMB_GPIO.Pin           = (LCD1st_D8_Pin | LCD1st_D9_Pin | LCD1st_D10_Pin | LCD1st_D11_Pin | LCD1st_D12_Pin | LCD1st_D13_Pin | LCD1st_D14_Pin | LCD1st_D15_Pin);
    mEMB_GPIO.Alternate     = LCD1st_D8_15_AFS;
    mEMB_GPIO.Mode          = LCD1st_D8_15_Mode;
    MID_GPIO_Init(LCD1st_D8_15_Port, &mEMB_GPIO);

    // MCS, MRD, MWR
    mEMB_GPIO.Pin           = (LCD1st_RD_Pin | LCD1st_WR_Pin | LCD1st_CS_Pin);
    mEMB_GPIO.Alternate     = LCD1st_CTL_AFS;
    mEMB_GPIO.Mode          = LCD1st_CTL_Mode;
    MID_GPIO_Init(LCD1st_CTL_Port, &mEMB_GPIO);

    // RS / DC
    mEMB_GPIO.Pin           = LCD1st_RS_Pin;
    mEMB_GPIO.Alternate     = LCD1st_RS_AFS;
    mEMB_GPIO.Mode          = LCD1st_RS_Mode;
    MID_GPIO_Init(LCD1st_RS_Port, &mEMB_GPIO);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_LCD_EMB_Init(void)
{
    mEMB.Instance = EMB;
    mEMB.Init.DeviceAccess = EMB_DEVICE_ACCESS_ASYNCHRONOUS;
    mEMB.Init.WriteSignal = EMB_WRITE_SIGNAL_TOGGLE;
    mEMB.Init.ReadSignal = EMB_READ_SIGNAL_TOGGLE;
    mEMB.Init.DataAddressMux = EMB_DATA_ADDRESS_MUX_DISABLE;
    mEMB.Init.DataAddressMuxMode = EMB_DATA_ADDRESS_MULTIPLEX_1ALE;
    mEMB.Init.AddressRange = EMB_ADDRESS_RANGE_16BIT;
    mEMB.Init.WriteAccess = EMC_WRITE_ACCESS_ENABLE;
  #if defined(MG32_3RD)
    mEMB.Init.DeviceDataWidth = EMB_DEVICE_DATA_BUS_WIDTH_16;
    mEMB.Init.AddressMAM1 = EMB_ADDRESS_MAM1_SIGNAL_DISABLE;
    mEMB.Init.WriteByteAccess = EMB_WRITE_BYTE_ACCESS_DISABLE;
    mEMB.Extended.MADBusByteSwap = EMB_MAD_BYTE_SWAP_DISABLE;
    mEMB.Extended.MADBusReverse = EMB_MAD_REVERSE_DISABLE;
  #endif
    mEMB.Extended.MABusReverse = EMB_MA_REVERSE_DISABLE;
    mEMB.Extended.MCLK_Inverse = EMB_MCLK_INVERSE_DISABLE;
    mEMB.Extended.MALE2_Inverse = EMB_MALE2_INVERSE_DISABLE;
    mEMB.Extended.MALE_Inverse = EMB_MALE_INVERSE_DISABLE;
    mEMB.Extended.MCE_Inverse = EMB_MCE_INVERSE_DISABLE;
    mEMB.CLKPrescaler = 1;
    mEMB.AddressSetupTime = 0;
    mEMB.AddressPulseTime = 1;
    mEMB.AddressHoldTime = 0;
    mEMB.DataSetupTime = 1;
    mEMB.DataAccessTime = 2;
    mEMB.DataHoldTime = 1;
    mEMB.IdleTime = 0;
    EMB_Init(&mEMB);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_RTC_Init(void)
{
    mRTC.Instance = RTC;
    mRTC.Init.RTC_CK_SEL = RTC_CLK_LS;         //RTC clock source select
    mRTC.Init.RTC_RLR = 0x00000000;             //RTC reload register set 0~0xFFFFFFFE, 0xFFFFFFFF  forbidden.
    mRTC.Init.HourFormat = RTC_HOURFORMAT_12;
    mRTC.sDate.Year = 2021U;
    mRTC.sDate.Month = July;
    mRTC.sDate.Date = 20U;
    mRTC.sTime.Hours = 12U;
    mRTC.sTime.Minutes = 00U;
    mRTC.sTime.Seconds = 00U;
    MID_RTC_Init(&mRTC);

    __DRV_RTC_WRITEPROTECT_DISABLE(&mRTC);
    __DRV_RTC_ENABLE_IT(&mRTC, RTC_IT_PC);
    __DRV_RTC_WRITEPROTECT_ENABLE(&mRTC);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void MID_RTC_MspInit(RTC_HandleTypeDef* MspInit_mRTC)
{
    ((void)(MspInit_mRTC));
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void MID_TM_Encoder_MspInit(TM_HandleTypeDef* mTM)
{
    GPIO_InitTypeDef mTM36EC11_GPIO;

    mTM36EC11_GPIO.Pull          = GPIO_NOPULLUP;
    mTM36EC11_GPIO.Speed         = GPIO_SPEED_HIGH;
    mTM36EC11_GPIO.Inverse       = GPIO_INVERSE_DISABLE;
    mTM36EC11_GPIO.OUTDrive      = GPIO_OUTDRIVE_LEVEL0;
    mTM36EC11_GPIO.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;

    if(mTM->Instance == TM36)
    {
      // EC11
        // A, B
        mTM36EC11_GPIO.Pin           = (EC11_TM36_A_Pin | EC11_TM36_B_Pin);
        mTM36EC11_GPIO.Alternate     = EC11_TM36_AFS;
        mTM36EC11_GPIO.Mode          = EC11_TM36_Mode;
        MID_GPIO_Init(EC11_TM36_Port, &mTM36EC11_GPIO);

        MID_NVIC_SetPriority(TM3x_IRQn, 2);
        MID_NVIC_EnableIRQ(EXINT3_IRQn);
    }
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void MID_URT_MspInit(URT_HandleTypeDef* MURT)
{
    GPIO_InitTypeDef mURT_GPIO;

    mURT_GPIO.Pull          = GPIO_NOPULLUP;
    mURT_GPIO.Speed         = GPIO_SPEED_HIGH;
    mURT_GPIO.Inverse       = GPIO_INVERSE_DISABLE;
    mURT_GPIO.OUTDrive      = GPIO_OUTDRIVE_LEVEL0;
    mURT_GPIO.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;

    if(MURT->Instance == URT0)
    {
        // Clcok Config
        // GPIO Config
        // DMA Channel Config
        // Interrupt Config
    }
    if(MURT->Instance == URT1)
    {
        // Clcok Config
        // GPIO Config
        // DMA Channel Config
        // Interrupt Config
    }
    if(MURT->Instance == URT2)
    {
        // Clcok Config
        // GPIO Config
        // DMA Channel Config
        // Interrupt Config
    }
    if(MURT->Instance == URT4) // for Debug on GPIO PE0 / 1
    {
      // Clcok Config
      // GPIO Config
        // URT TX
        mURT_GPIO.Pin           = URT4_TX_Pin;
        mURT_GPIO.Alternate     = URT4_AFS;
        mURT_GPIO.Mode          = URT4_TX_Mode;
        MID_GPIO_Init(URT4_Port, &mURT_GPIO);

        // URT RX
        mURT_GPIO.Pin           = URT4_RX_Pin;
        mURT_GPIO.Mode          = URT4_RX_Mode;
        MID_GPIO_Init(URT4_Port, &mURT_GPIO);

      // DMA Channel Config
      // Interrupt Config
    }
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_URT_Init(void)
{
    mURT4.Instance = URT4;
    mURT4.Init.Mode = URT_TX_RX;
//    mURT4.Init.BaudRate = 921600;
    mURT4.Init.BaudRate = 115200;
//    mURT4.Init.BaudRate = 57600;
//    mURT4.Init.BaudRate = 9600;
//    mURT4.Init.BaudRate = 4800;
//    mURT4.Init.BaudRate = 1200;
    mURT4.Init.WordLength = UART_WORDLENGTH_8B;
    mURT4.Init.Parity = URT_PARITY_NO;
    mURT4.Init.StopBits = URT_STOPBIT_1_0;
    mURT4.Init.HWFlowCtrl = URT_HWCONTROL_NONE;
    mURT4.Init.OneBitSampling = URT_ONEBIT_SAMPLE_SINGLE;
    mURT4.AdvancedInit.AdvFeatureInit = URT_ADVFEATURE_NO_INIT;
    MID_URT_Init(&mURT4);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void MID_SPI_MspInit(SPI_HandleTypeDef *mSPI)
{
    GPIO_InitTypeDef mSPIFlash_GPIO;

    mSPIFlash_GPIO.Pull          = GPIO_NOPULLUP;
    mSPIFlash_GPIO.Speed         = GPIO_SPEED_HIGH;
    mSPIFlash_GPIO.Inverse       = GPIO_INVERSE_DISABLE;
    mSPIFlash_GPIO.OUTDrive      = GPIO_OUTDRIVE_LEVEL0;
    mSPIFlash_GPIO.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;

    if(mSPI->Instance == SPI_SPI0)
    {
      // Flash use SPI0
        // CEn
        mSPIFlash_GPIO.Pin = FLASH_SPI0_CEN_Pin;
        mSPIFlash_GPIO.Alternate = FLASH_SPI0_CEN_AFS;
        mSPIFlash_GPIO.Mode = FLASH_SPI0_Mode;
        MID_GPIO_Init(FLASH_SPI0_Port, &mSPIFlash_GPIO);

        // SCK, DO, D3, 
        mSPIFlash_GPIO.Pin = (FLASH_SPI0_SCK_Pin | FLASH_SPI0_DO_Pin | FLASH_SPI0_D3_Pin);
        mSPIFlash_GPIO.Alternate = FLASH_SPI0_AFS;
        mSPIFlash_GPIO.Mode = FLASH_SPI0_Mode;
        MID_GPIO_Init(FLASH_SPI0_Port, &mSPIFlash_GPIO);

        // D2
        mSPIFlash_GPIO.Pin = (FLASH_SPI0_D2_Pin | FLASH_SPI0_DI_Pin);
        mSPIFlash_GPIO.Alternate     = FLASH_SPI0_AFS_B;
        MID_GPIO_Init(FLASH_SPI0_Port, &mSPIFlash_GPIO);
    }

    if(mSPI->Instance == SPI_URT0)
    {
      // LCD 2nd use URT0
        // DO, CLK, CSn
        mSPIFlash_GPIO.Pin           = (LCD2nd_URT0SPI_SDO_Pin | LCD2nd_URT0SPI_SCK_Pin | LCD2nd_URT0SPI_CS2_Pin);
        mSPIFlash_GPIO.Alternate     = LCD2nd_URT0SPI_AFS;
        mSPIFlash_GPIO.Mode          = LCD2nd_URT0SPI_Mode;
        MID_GPIO_Init(LCD2nd_URT0SPI_Port, &mSPIFlash_GPIO);

        // DI
        mSPIFlash_GPIO.Pin           = LCD2nd_URT0SPI_SDI_Pin;
        mSPIFlash_GPIO.Alternate     = LCD2nd_URT0SPI_AFS;
        mSPIFlash_GPIO.Mode          = LCD2nd_URT0SPI_SDI_Mode;
        MID_GPIO_Init(LCD2nd_URT0SPI_Port, &mSPIFlash_GPIO);
    }
  #if !defined(MG0404)
    if(mSPI->Instance == SPI_URT2)
    {
        // Clcok Config
        // GPIO Config
        mSPIFlash_GPIO.Pin           = BLE_CSN_Pin;
        mSPIFlash_GPIO.Alternate     = BLE_CSN_AFS;
        mSPIFlash_GPIO.Mode          = BLE_CSN_Mode;
        MID_GPIO_Init(BLE_CSN_Port, &mSPIFlash_GPIO);

        mSPIFlash_GPIO.Pin           = BLE_SCK_Pin;
        mSPIFlash_GPIO.Alternate     = BLE_SCK_AFS;
        mSPIFlash_GPIO.Mode          = BLE_SCK_Mode;
        MID_GPIO_Init(BLE_SCK_Port, &mSPIFlash_GPIO);

        mSPIFlash_GPIO.Pin           = BLE_MO_Pin;
        mSPIFlash_GPIO.Alternate     = BLE_MO_AFS;
        mSPIFlash_GPIO.Mode          = BLE_MO_Mode;
        MID_GPIO_Init(BLE_MO_Port, &mSPIFlash_GPIO);

        mSPIFlash_GPIO.Pin           = BLE_MI_Pin;
        mSPIFlash_GPIO.Alternate     = BLE_MI_AFS;
        mSPIFlash_GPIO.Mode          = BLE_MI_Mode;
        MID_GPIO_Init(BLE_MI_Port, &mSPIFlash_GPIO);

        mSPIFlash_GPIO.Pin           = BLE_IRQ_Pin;
        mSPIFlash_GPIO.Alternate     = BLE_IRQ_AFS;
        mSPIFlash_GPIO.Mode          = BLE_IRQ_Mode;
        MID_GPIO_Init(BLE_IRQ_Port, &mSPIFlash_GPIO);

        mSPIFlash_GPIO.Pin           = BLE_LED_Pin;
        mSPIFlash_GPIO.Alternate     = BLE_LED_AFS;
        mSPIFlash_GPIO.Mode          = BLE_LED_Mode;
        MID_GPIO_Init(BLE_LED_Port, &mSPIFlash_GPIO);

        // DMA Channel Config
        // Interrupt Config
    }
  #endif
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_SPI_Init(void)
{
//    mSPI0.Instance = SPI_SPI0;
//    mSPI0.Init.Mode = SPI_MODE_MASTER_NSS;
//    mSPI0.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
//    mSPI0.Init.NSS = SPI_NSS_HARDWARE;
//    mSPI0.Init.DataLine = SPI_STANDARD_SPI;
//    mSPI0.Init.DataSize = SPI_DATASIZE_8BIT;
//    mSPI0.Init.CLKPolarity = SPI_POLARITY_LOW;
//    mSPI0.Init.CLKPhase = SPI_PHASE_1EDGE;
//    mSPI0.Init.ClockDivider = SPI_CLOCKDIVIDER_4;
//    mSPI0.Init.FirstBit = SPI_FIRSTBIT_MSB;
//    mSPI0.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
//    if (MID_SPI_Init(&mSPI0) != MID_OK)                 // When SPI initial failure, stop at there.
//    {
//        while(1){__NOP();}
//    }

    mURT0SPI.Instance = SPI_URT0;
    mURT0SPI.Init.Mode = SPI_MODE_MASTER_NSS;
    mURT0SPI.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    mURT0SPI.Init.NSS = SPI_NSS_OUT_HARDWARE;
    mURT0SPI.Init.DataLine = SPI_STANDARD_SPI;
    mURT0SPI.Init.DataSize = SPI_DATASIZE_8BIT;
    mURT0SPI.Init.CLKPolarity = SPI_POLARITY_LOW;
    mURT0SPI.Init.CLKPhase = SPI_PHASE_1EDGE;
    mURT0SPI.Init.ClockDivider = SPI_CLOCKDIVIDER_2;
    mURT0SPI.Init.FirstBit = SPI_FIRSTBIT_MSB;
    mURT0SPI.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    if (MID_SPI_Init(&mURT0SPI) != MID_OK)                 // When SPI initial failure, stop at there.
    {
        while(1){__NOP();}
    }
    NVIC_DisableIRQ((IRQn_Type)mURT0SPI.SPI_IRQ);
    SPI0->CR0.MBIT.RX_CTL = 1;              // SPI RX at next edge.
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
uint32_t BSP_BLE_SPI_Init(void)
{
//    volatile ctype    URT_RecData;              /* volatile */
    volatile uint8_t  tmp;                      /* volatile */
    volatile uint8_t  CNT;                      /* volatile */
    volatile uint32_t DIV;                      /* volatile */
    volatile uint32_t SPI_Clock;                /* volatile */

    PINB(0)->CR.W = PX_CR_AFS_af0_w | PX_CR_IOM_ppo_w | PX_CR_HS_enable_w | PX_CR_PU_disable_w | PX_CR_ODC_level0_w | PX_CR_INV_disable_w | PX_CR_FDIV_bypass_w | PX_CR_LCK_un_locked_w;
    PINB(1)->CR.W = PX_CR_AFS_af10_w | PX_CR_IOM_ppo_w | PX_CR_HS_enable_w | PX_CR_PU_disable_w | PX_CR_ODC_level0_w | PX_CR_INV_disable_w | PX_CR_FDIV_bypass_w | PX_CR_LCK_un_locked_w;
    PINB(3)->CR.W = PX_CR_AFS_af4_w | PX_CR_IOM_ppo_w | PX_CR_HS_enable_w | PX_CR_PU_disable_w | PX_CR_ODC_level0_w | PX_CR_INV_disable_w | PX_CR_FDIV_bypass_w | PX_CR_LCK_un_locked_w;
    PINE(8)->CR.W = PX_CR_AFS_af3_w | PX_CR_IOM_din_w | PX_CR_HS_enable_w | PX_CR_PU_disable_w | PX_CR_ODC_level0_w | PX_CR_INV_disable_w | PX_CR_FDIV_bypass_w | PX_CR_LCK_un_locked_w;
    PINA(10)->CR.W = PX_CR_AFS_af0_w | PX_CR_IOM_din_w | PX_CR_HS_enable_w | PX_CR_PU_disable_w | PX_CR_ODC_level0_w | PX_CR_INV_disable_w | PX_CR_FDIV_bypass_w | PX_CR_LCK_un_locked_w;
    PINC(14)->CR.W = PX_CR_AFS_af0_w | PX_CR_IOM_ppo_w | PX_CR_HS_enable_w | PX_CR_PU_disable_w | PX_CR_ODC_level0_w | PX_CR_INV_disable_w | PX_CR_FDIV_bypass_w | PX_CR_LCK_un_locked_w;
//    // When CK_AHB > 12MHz
//    if(ProcessClockRate > 12000000)
//    {
//        CPU_CLK_FAST_ENABLE = TRUE;
//    }
//    else
//    {
//        CPU_CLK_FAST_ENABLE = FALSE;
//    }

    /* Get Prescaler setting */
    DIV = 0xFF;
    CNT = 0;
    do
    {
        CNT++;
        SPI_Clock = SystemCoreClock;
        SPI_Clock = (SPI_Clock /(CNT+1)) ;
        if((SPI_Clock >= 6000000) && (SPI_Clock < 10000000))        // When SPI clock range in 6M ~ 10M
        {
            DIV = CNT;                                              // Store DIV 
        }
    }while(CNT<8);                                                  // When 

    if(DIV > 8)                                                     // When not get DIV
        return 1;

    //=====Set Clock=====//
    //---Set BaudRate---//
    BLE_SPI->CLK.W = (BLE_SPI->CLK.W & ~(URT_CLK_BR_MDS_mask_w | URT_CLK_CK_SEL_mask_w)) |
                         URT_CLK_CK_SEL_proc_w | URT_CLK_BR_MDS_separated_w;
    BLE_SPI->RLR.B[0] = 0;
    BLE_SPI->RLR.B[1] = 0;
    BLE_SPI->CLK.W = ((BLE_SPI->CLK.W & (~URT_CLK_BR_EN_mask_w)) |
                          URT_CLK_BR_EN_mask_w);

    //---TX/RX Clock---//
    BLE_SPI->CLK.W = ((BLE_SPI->CLK.W & ~(URT_CLK_TX_CKS_mask_w | URT_CLK_RX_CKS_mask_w)) | 
                          URT_CLK_TX_CKS_internal_w | URT_CLK_RX_CKS_internal_w);
    BLE_SPI->CR1.B[3] = (uint8_t)DIV;
    BLE_SPI->CR1.B[1] = (uint8_t)DIV;
    BLE_SPI->CR0.W = ((BLE_SPI->CR0.W & ~(URT_CR0_OS_MDS_mask_w)) | 
                          URT_CR0_OS_MDS_three_w);
    BLE_SPI->CR2.W = ((BLE_SPI->CR2.W & ~(URT_CR2_TX_EN_mask_w | URT_CR2_RX_EN_mask_w)) | 
                          URT_CR2_TX_EN_enable_w | URT_CR2_RX_EN_enable_w);

    BLE_SPI->CR1.B[2] = URT_CR1_TXDSIZE_8bit_b2 | URT_CR1_TXMSB_EN_enable_b2 | URT_CR1_TXPAR_EN_disable_b2 | URT_CR1_TXSTP_LEN_1bit_b2;
    BLE_SPI->CR1.B[0] = URT_CR1_RXDSIZE_8bit_b0 | URT_CR1_RXMSB_EN_enable_b0 | URT_CR1_RXPAR_EN_disable_b0 | URT_CR1_RXSTP_LEN_1bit_b0;

    tmp = BLE_SPI->CR4.B[0] & (~(URT_CR4_RDAT_INV_mask_b0|URT_CR4_TDAT_INV_mask_b0));
    tmp = tmp | URT_CR4_RDAT_INV_disable_b0 | URT_CR4_TDAT_INV_disable_b0;
    BLE_SPI->CR4.B[0] = tmp;

    // Set Mode Select
    BLE_SPI->CR0.W = (BLE_SPI->CR0.W & (~URT_CR0_MDS_mask_w) ) | URT_CR0_MDS_sync_w; 
//    BLE_SPI->MUTE.W = BLE_MODULE->MUTE.W & (~URT_MUTE_MUTE_EN_mask_w);

    // Set DataLine Select
    BLE_SPI->CR0.W = ((BLE_SPI->CR0.W & (~URT_CR0_DAT_LINE_mask_w)) | URT_CR0_DAT_LINE_2_w);
    BLE_SPI->CR3.W = ((BLE_SPI->CR3.W & (~URT_CR3_CPHA_mask_w)) | URT_CR3_CPHA_leading_edge_w);
    BLE_SPI->CR3.W = ((BLE_SPI->CR3.W & (~URT_CR3_CPOL_mask_w)) | URT_CR3_CPOL_low_w);

    // Flash_nCS = FLASH_nCS_NoACTIVE;
    BLE_CSN = 1;

    // Set Data Control
    BLE_SPI->CR3.B[2] = 0;

    // Enable CLK(SYSCLK)
    BLE_SPI->CLK.W = (( BLE_SPI->CLK.W & (~URT_CLK_CLK_EN_mask_w)) | URT_CLK_CLK_EN_mask_w);

    // Swap TX and RX pins
    BLE_SPI->CR0.W |= URT_CR0_IO_SWP_enable_w;

    // Enable URT
    BLE_SPI->CR0.W = ((BLE_SPI->CR0.W & (~URT_CR0_EN_mask_w)) | URT_CR0_EN_mask_w);

    return 0;
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void MID_I2C_MspInit(I2C_HandleTypeDef *mI2C)
{
    GPIO_InitTypeDef mI2CEEPROM_GPIO;

    mI2CEEPROM_GPIO.Pull          = GPIO_NOPULLUP;
    mI2CEEPROM_GPIO.Speed         = GPIO_SPEED_HIGH;
    mI2CEEPROM_GPIO.Inverse       = GPIO_INVERSE_DISABLE;
    mI2CEEPROM_GPIO.OUTDrive      = GPIO_OUTDRIVE_LEVEL0;
    mI2CEEPROM_GPIO.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;

//    if(mI2C->Instance == I2C0)
//    {
//      // Clcok Config
//      // GPIO Config
//      // DMA Channel Config
//      // Interrupt Config
//    }

    if(mI2C->Instance == I2C1)
    {
      // Clcok Config
      // GPIO Config
        // EEPROM
        mI2CEEPROM_GPIO.Pin           = (EEPROM_I2C1_SDA_Pin | EEPROM_I2C1_SCL_Pin);
        mI2CEEPROM_GPIO.Alternate     = EEPROM_I2C1_AFS;
        mI2CEEPROM_GPIO.Mode          = EEPROM_I2C1_Mode;
        MID_GPIO_Init(EEPROM_I2C1_Port, &mI2CEEPROM_GPIO);

      // DMA Channel Config
      // Interrupt Config
    }
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_I2C_Init(void)
{
    mI2C1.Instance = I2C1;
    mI2C1.Init.Timing = MID_I2C_GetInitTiming(&mI2C1, 1000000);
    mI2C1.Init.OwnAddress1 = 0x20;
    mI2C1.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
    mI2C1.Init.OwnAddress2 = 0x80;
    mI2C1.Init.GeneralCallMode = I2C_GENERALCALL_ENABLE;
    MID_I2C_Init(&mI2C1);
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
//void MID_IWDT_MspInit(IWDT_HandleTypeDef *MspInit_mIWDT)
//{

//}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_IWDT_Init(void)
{
    //mIWDT.Instance = IWDT;                                          //Mapping IWDT base address
    //mIWDT.Init.Interrupt = (IWDT_IT_TIE);   //ENABLE IWDT
    //mIWDT.Init.Prescaler = IWDT_PRESCALER_4096;
    //mIWDT.Init.Prescaler = IWDT_PRESCALER_256;
    //mIWDT.Init.Prescaler = IWDT_PRESCALER_128;
    //if (MID_IWDT_Init(&mIWDT) != MID_OK)
    //{
        //IWDT_Error_Handler(&mIWDT);
    //}

    /*=== 1. Configure IWDT clock ===*/
    UnProtectModuleReg(IWDTprotect);                                // Unprotect IWDT module
    IWDT_Divider_Select(IWDT_DIV_128);                              // DIV output = CK_IWDT /128

    /*=== 2. Configure RST module ===*/                         
    UnProtectModuleReg(RSTprotect);                                 // Unprotect RST moduel register
    RST_WRstSource_Config(RST_IWDT_WE, ENABLE);                     // Enable IWDT event trigger warm reset
    ProtectModuleReg(RSTprotect);                                   // Protect RST moduel register

    IWDT_IT_Config(IWDT_INT_TF, ENABLE);                            // Enable IWDT timeout interupt 
    NVIC_EnableIRQ(SYS_IRQn);
    SYS_ITEA_Cmd(ENABLE);                                           // Enable SYS interupt in NVIC
    IWDT_ClearFlag(IWDT_TF);                                        // Clear IWDT timeout flag

    /*=== 3. Enable IWDT module ===*/
    IWDT_Cmd(ENABLE);                                               // Enable IWDT module
    ProtectModuleReg(IWDTprotect);                                  // Protect IWDT module

    /*=== 4. Check flag action ===*/
    while(IWDT_GetSingleFlagStatus(IWDT_EW1F) == DRV_UnHappened);   // Wait IWDT early wakeup-1 happened
    IWDT_ClearFlag(IWDT_EW1F);                                      // Clear EW1F flag 

    while(IWDT_GetSingleFlagStatus(IWDT_EW0F) == DRV_UnHappened);   // Wait IWDT early wakeup-0 happened
    IWDT_ClearFlag(IWDT_EW0F);                                      // Clear EW0F flag

    IWDT_RefreshCounter();                                          // Clear IWDT timer
}

/**
 *******************************************************************************
 * @brief       
 * @details     
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code
 * @endcode
 *******************************************************************************
 */
void BSP_Init(void)
{
    // Chip
    // Debug use URT4
    BSP_URT_Init();

    // Initial
    // LCD use EMB 
    BSP_LCD_EMB_Init();

    // LCD use URT0(with SPI Mode)
    // Flash MX25 SPI0 QSPI Mode
    BSP_SPI_Init();          // URT0 SPI Mode and SPI0
    BSP_BLE_SPI_Init();     // URT2 SPI Mode

    //__DRV_SYS_ENABLE_IT(SYS_INT_IEA_mask_w);
    SYS->INT.W = SYS_INT_IEA_mask_w;
    BSP_RTC_Init();

    // EEPROM I2C1 24C08
    BSP_I2C_Init();

    // Encoder EC11
    API_EncoderEC11_Init();
    BSP_EXIC_Init();

    // Interrupt, NVIC
    MID_Init();
    BSP_Interrupt_Init();
}


