


/**
 ******************************************************************************
 *
 * @file        BSP_Common_MG04_06.c
 * @brief       
 
 * @par         Project
 *              MG32
 * @version     V1.01
 * @date        2022/08/01
 * @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 "BSP_Common_MG04_06.h"
#include "BSP_ARGB.h"
#include "BSP_UARTCOM.h"
#include "BSP_SARADCKey.h"
#include "BSP_TouchKey.h"
#include "BSP_SPIFlash.h"
#include "BSP_SPILCD.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define BSP_AHB_FREQ       24000000                 /*!< Device AHB clock frequence.*/

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static __IO uint32_t SysTickCnt;           


/* Private function prototypes -----------------------------------------------*/
void SysTick_Handler(void);

static void BSP_InitTick( uint32_t TickPriority);
static void BSP_ADC_StartCalibration(void);    

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


/**
 * @name  SysTick
 */
///@{
/**
 *******************************************************************************
 * @brief	    Systick interrupt handler 
 * @details     
 * @return      
 * @exception   No
 * @note
 *******************************************************************************
 */
//void SysTick_Handler(void)
//{
//    BSP_IncTick(); 
//    
//    
//}
/**
 *******************************************************************************
 * @brief	    Provides a tick value
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */ 
uint32_t BSP_GetTick(void)
{
    return(SysTickCnt);
}
/**
 *******************************************************************************
 * @brief	    Provides a tick value
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */ 
void BSP_IncTick(void)
{
    SysTickCnt++;
}

/**
 *******************************************************************************
 * @brief       This function configures the source of the time base. 
 *              The time source is configured  to have 1ms time base with a dedicated 
 *              Tick interrupt priority.
 * @param       TickPriority Tick interrupt priority.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void BSP_InitTick( uint32_t BSP_TickPriority)
{
    /*Cofig the SysTick to have interrupt in 1ms time basis.*/
    SysTick_Config((BSP_AHB_FREQ/1000));
    
    /*Configure the SysTick IRQ priority.*/
    NVIC_SetPriority(SysTick_IRQn,BSP_TickPriority);
    
}

///@}

/**
 *******************************************************************************
 * @brief       This function provides accurate delay based 
 *              on variable incremented.
 * @param[in]   BSP_DelayTime: specifies the delay time length in SysTick basis time.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */ 
void BSP_Delay( uint32_t BSP_DelayTime)
{
    uint32_t Delay_tickstart = BSP_GetTick();
    uint32_t Delay_wait = BSP_DelayTime;
    
    if (Delay_wait < 0xFFFFFFFF)
    {
       Delay_wait++;
    }
  
    while((BSP_GetTick() - Delay_tickstart) < Delay_wait)
    {
        __NOP();
    }  
}

/**
 *******************************************************************************
 * @brief	    BSP GPIO initial
 * @details     Pin mode initial
 * @param[in]   PinName: PINA(n) ~ PIND(n) (n = 0 ~ 15)
 * @param[in]   PinMode: 
 *   @arg\b     Analog_Mode: IO mode control.
 *   @arg\b     Data_DIR_OUT_QB      : Quasi-Birdirectional output.
 *   @arg\b     Data_DIR_OUT_OD_NoRU : Open drain output and disable internal pull-up resister.
 *   @arg\b     Data_DIR_OUT_OD_RU   : Open drain output with internal pull-up resister.
 *   @arg\b     Data_DIR_OUT_PP      : Push pull output.
 *   @arg\b     Data_DIR_IN_NoRU     : Digital input and disable internal pull-up resister.
 *   @arg\b     Data_DIR_IN_RU       : Digital input with internal pull-up resister.
 * @param[in]   PinAFS: Pin alternate function select.
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */ 
void BSP_GPIO_PinConfig(Pin_Struct* PinName , GPIO_Mode_TypeDef PinMode , uint8_t PinAFS)
{
    PIN_InitTypeDef                 PINX_InitStruct;
    
    
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Enable;
    PINX_InitStruct.PINX_Speed              = PINX_Speed_High;
    
    if( PinMode == Data_DIR_OUT_QB)
    {
        PINX_InitStruct.PINX_Mode               = PINX_Mode_Quasi_IO;
    }
    else if( PinMode == Data_DIR_OUT_OD_NoRU)
    {
        PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Disable;
        PINX_InitStruct.PINX_Mode				= PINX_Mode_OpenDrain_O;
    }
    else if( PinMode == Data_DIR_OUT_OD_RU)
    {
        PINX_InitStruct.PINX_Mode				= PINX_Mode_OpenDrain_O;
    }
    else if( PinMode == Data_DIR_OUT_PP)
    {
         PINX_InitStruct.PINX_Mode				 = PINX_Mode_PushPull_O;
    }
    else if( PinMode == Data_DIR_IN_NoRU)
    {
        PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Disable;
        PINX_InitStruct.PINX_Mode				= PINX_Mode_Digital_I;
        PINX_InitStruct.PINX_Speed              = PINX_Speed_Low;
    }
    else if( PinMode == Data_DIR_IN_RU)
    {
        PINX_InitStruct.PINX_Mode				= PINX_Mode_Digital_I;
        PINX_InitStruct.PINX_Speed              = PINX_Speed_Low;
    }
    else 
    {
        PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Disable;
        PINX_InitStruct.PINX_Mode				= PINX_Mode_Analog_IO;
        PINX_InitStruct.PINX_Speed              = PINX_Speed_Low;
    }

    PINX_InitStruct.PINX_OUTDrive           = PINX_OUTDrive_Level0;
    PINX_InitStruct.PINX_FilterDivider      = PINX_FilterDivider_Bypass;
    PINX_InitStruct.PINX_Inverse            = PINX_Inverse_Disable;
    PINX_InitStruct.PINX_Alternate_Function = PinAFS;
    GPIO_PinMode_Config(PinName,&PINX_InitStruct);  
}


/**
 *******************************************************************************
 * @brief	    BSP initial
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */ 
void BSP_Init(void)
{
    /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
    BSP_InitTick(0);
    
    /* ADC Initial */
    // config clock
    MG04_06_ADC->CLK.MBIT.CK_SEL2   = ADC_CKADC;
    MG04_06_ADC->CLK.MBIT.CK_DIV    = ADC_IntDIV2;
    MG04_06_ADC->CLK.MBIT.CK_DIV2   = ADC_PLLDIV2;
    
    // ADC data alignment
    MG04_06_ADC->CR1.MBIT.ALIGN_SEL = ADC_RightJustified;
    // ADC conversion resolution
    MG04_06_ADC->CR0.MBIT.RES_SEL   = ADC_12BitData;
    // ADC data overwritten or keep mode
    MG04_06_ADC->CR1.MBIT.OVR_MDS   = ADC_DataOverWritten;
    // Select ADC conversion time with 24 ADCK. 
    MG04_06_ADC->ANA.MBIT.CONV_TIME = ADC_FastCONV;
    // ADC operation bias.
    MG04_06_ADC->ANA.MBIT.BIAS      = ADC_BIAS_LVL3;
    // ADC discharge function in ADC sample and hold state.
    MG04_06_ADC->ANA.MBIT.DISCHR_EN = ENABLE;
    // ADC sample and hold clock phase state.
    MG04_06_ADC->CLK.MBIT.CK_DLY    = ADC_CK_PHASE2;
    
    //Enable ADC
    __BSP_ADC_ENABLE();

    //Configure ADC mode
    //One-shot 
    MG04_06_ADC->START.MBIT.CONV_MDS  = ADC_OneShot;         /*!< One shot(1-time) conversion.*/
    MG04_06_ADC->START.MBIT.TRG_CONT  = DISABLE;             /*!< ADC start trigger continuous control disable.*/
    

    //Clear all flag
    __BSP_ADC_CLEARFLAG(0xFFFFFFFF);
    
    //Start calibration
    BSP_ADC_StartCalibration();
    
    //Input channel Mux is external channel.
    MG04_06_ADC->START.MBIT.CH_SEL = ADC_ExternalChannel;
    
    //Trigger source select
    MG04_06_ADC->START.MBIT.START_SEL = ADC_START;


    /* URT CON Initial*/
    BSP_UARTCom_Init();
    
    /*Flash*/
    BSP_Flash_Init();
    BSP_Flash_CheckFlashRDID();      //Check Flash RDID.
    
    /*LCD Initial*/
    BSP_LCD_Init();
    
    /*ARGB Initial*/
    BSP_ARGB_Init();
    
    /*KEY ( SARADC) Button Initial*/
    BSP_SARADCKey_Init();
    
    /*Touch Key Initial*/
    BSP_TouchKey_Init();
    
    /*User parameter Initial*/
    BSP_InitCallback();
    
}
/**
 *******************************************************************************
 * @brief	   BSP Initial callback function 
 * @details     
 * @return      
 * @exception   
 * @note                        
 *******************************************************************************
 */
static void BSP_ADC_StartCalibration(void)
{
    int16_t  ADC_CONV;
    uint8_t  i, OFFT_ADC_MinIDX;
    uint32_t rADC_MSK, rADC_START, rADC_CR0, rADC_CR1;
    uint32_t rSUM0, rSUM1, rSUM2;
   

    /*RESAVE*/
    rADC_MSK   = MG04_06_ADC->MSK.W;
    rADC_START = MG04_06_ADC->START.W;
    rADC_CR0   = MG04_06_ADC->CR0.W;  
    rADC_CR1   = MG04_06_ADC->CR1.W;  
    rSUM0      = MG04_06_ADC->SUM0.W;
    rSUM1      = MG04_06_ADC->SUM1.W;
    rSUM2      = MG04_06_ADC->SUM2.W;
   
    /*Reset SUM_NUM & window detect*/
    MG04_06_ADC->CR1.W &= ~(ADC_CR1_SUM_NUM_mask_w | ADC_CR1_WIND_EN_enable_w);

    /*Config ADC mode for calibration*/
    // ADC mode
    MG04_06_ADC->START.MBIT.CONV_MDS  = ADC_OneShot;         /*!< One shot(1-time) conversion.*/
    MG04_06_ADC->START.MBIT.TRG_CONT  = DISABLE;             /*!< ADC start trigger continuous control disable.*/
    // ADC trigger source : software setting to convert.
    MG04_06_ADC->START.MBIT.START_SEL = ADC_START;
    // ADC conversion data resolution is 12 bit
    MG04_06_ADC->CR0.MBIT.RES_SEL     = ADC_12BitData;

    // ------------------------------------------------------------------------
    // start calibration - Offset issue
    // ------------------------------------------------------------------------
    // Select interanl channel VSSA
    MG04_06_ADC->START.B[1] = ADC_INT_VSSA;
   
    OFFT_ADC_MinIDX = 0;

    // ------------------------------------------------------------------------
    // 1. Scan minimum index when ADC sample not equal '0'
    // ------------------------------------------------------------------------
    while(1)
    {
        // set ADC_GAIN_OFFT
        MG04_06_ADC->GAIN.MBIT.OFFT_ADC = OFFT_ADC_MinIDX;

        // sample internal VSS
        __BSP_ADC_START_SW();
        while((MG04_06_ADC->STA.W & ADC_E1CNVF)==0);
        __BSP_ADC_CLEARFLAG((ADC_E1CNVF | ADC_ESMPF));
        ADC_CONV = __BSP_ADC_GETDATA();

        // check ADC_CONV data (search ADC_CONV==1 or 2)  
        if (ADC_CONV == 0)
        {
            OFFT_ADC_MinIDX ++;
        }
        else 
        {
            if(OFFT_ADC_MinIDX < 2)     // No trimming range in this issue
            {
                OFFT_ADC_MinIDX = 0;
                break;         
            }
            OFFT_ADC_MinIDX -= 2;
            break;
        }
        //
        if (OFFT_ADC_MinIDX == 31) break;
    }
    // ------------------------------------------------------------------------
    // 2. average ADC conversion data -> decide the optimum
    // ------------------------------------------------------------------------
    while(1)
    {
        // set ADC_GAIN_OFFT
        MG04_06_ADC->GAIN.MBIT.OFFT_ADC = OFFT_ADC_MinIDX;
               
        // Average ADC conversion
        for (i=0, ADC_CONV=0 ; i<8; i++)
        {
            __BSP_ADC_START_SW();
            while((MG04_06_ADC->STA.W & ADC_E1CNVF)==0);
            __BSP_ADC_CLEARFLAG((ADC_E1CNVF | ADC_ESMPF));
            ADC_CONV += __BSP_ADC_GETDATA();
        }        
       
        // check ADC_CONV data (search ADC_CONV==1 or 2)  
        if (ADC_CONV == 0)
        {
            OFFT_ADC_MinIDX ++;
        }
        else if (ADC_CONV < 8)
        {
            break;
        }
        else
        {
            if(OFFT_ADC_MinIDX == 0) break;         // No trimming range in this issue
            OFFT_ADC_MinIDX --;         // make sure -> ADC can convert '0'
            break;
        }
        //
        if (OFFT_ADC_MinIDX > 31) break;
       
    }
    // desire ADC_GAIN_OFFT
    MG04_06_ADC->GAIN.MBIT.OFFT_ADC = OFFT_ADC_MinIDX;
    
    // restore
    MG04_06_ADC->MSK.W   = rADC_MSK;
    MG04_06_ADC->START.W = rADC_START;
    MG04_06_ADC->CR0.W   = rADC_CR0;    
    MG04_06_ADC->CR1.W   = rADC_CR1;    
    MG04_06_ADC->SUM0.W  = rSUM0;
    MG04_06_ADC->SUM1.W  = rSUM1;
    MG04_06_ADC->SUM2.W  = rSUM2; 

}    
/**
 *******************************************************************************
 * @brief	   BSP Initial callback function 
 * @details     
 * @return      
 * @exception   
 * @note                        
 *******************************************************************************
 */
__WEAK void BSP_InitCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modifyed, when the 
    //       callback is needed, the MID_URT_RxCpltCallback 
    //       can be implemented in the user file.

}







