
/**
 ******************************************************************************
 *
 * @file        LCDDEMO_KEY_API.c
 *
 * @brief       This file provides firmware functions to manage the following 
 *              functionalities of the ADC peripheral:
 *
 * @par         Project
 *              MG32
 * @version     V1.01
 * @date        2021/06/01
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2016 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 "LCDDEMO_KEY_API.H"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef    hadc;

/* Private function prototypes -----------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/


/**
 * @name	Set channel0 duty cycle
 *   		
 */ 
///@{ 
/**
 *******************************************************************************
 * @brief       Initial LCD demo board's Key matrix.
 * @param[in]   none
 * @return		none
 * @note 
 * @par         Example
 * @code
    API_Key_Init();
 * @endcode
 *******************************************************************************
 */
void API_Key_Init(void)
{
    // ------------------------------------------------------------------------
    ADC_WindowDetectTypeDef     ADCWinDet;
    ADC_ConversionDef           ADCConMOD;


    // ------------------------------------------------------------------------
    // 1. ADC initial
    hadc.Instance = ADC0;
    ADC_BaseStructure_Init(&hadc.Init);
    {   // modify parameter (48M/30/16 ~ 100ksps)
        hadc.Init.ADC_IntCK_Div = ADC_IntDIV16;
    }
    MID_ADC_Init(&hadc);

    // ------------------------------------------------------------------------
    // 2. ADC Conversion initial
    {   // modify parameter (48M/(30+255)/16 ~ 10ksps)
        ADCConMOD.ADCTypeMDS = ADC_SingleMode;
        ADCConMOD.ADCConversioMDS = LoopMode;       // it don't need trigger to conversion
//        ADCConMOD.ADCConversioMDS = ADCMode;
//        ADCConMOD.ADCConversioMDS = ScanMode;
        ADCConMOD.ExtendSampling = 255;
        ADCConMOD.ScanChannelMSK = ADC_MskAIN10 | ADC_MskAIN11 | ADC_MskAIN12;
        ADCConMOD.CalibrationState = MID_ADC_UnCalibrate;
        ADCConMOD.ActivePGA = DISABLE;
//        ADCConMOD.PGAGain = 0;
//        ADCConMOD.PGAoffset = 0;
        ADCConMOD.TriggerSrcSel = ADC_START;
    }
    MID_ADC_Conversion_Init(&hadc, &ADCConMOD);
    
    // ------------------------------------------------------------------------
    // 3. Window Detect initial
    {   // modify parameter (48M/30/16 ~ 100ksps)
        ADCWinDet.WindowHighThreshold = 3000;
        ADCWinDet.WindowLowThreshold = 0;
        ADCWinDet.ApplyMode = ADC_WINDAll;
    }
    MID_ADC_WindowDetect_Init(&hadc, &ADCWinDet);
    MID_ADC_WindowDetect_Start(&hadc);
    MID_ADC_WindowDetectIT_Start(&hadc, ADC_WDI_IE);

    // ------------------------------------------------------------------------
    // 4. Trigger ADC Conversion if in Loop mode
    if (ADCConMOD.ADCConversioMDS == LoopMode)
    {
        if(ADCConMOD.TriggerSrcSel == ADC_START)
            ADC_SoftwareConversion_Cmd(ADC0, ENABLE);
    }
}

/**
 *******************************************************************************
 * @brief       Get LCD demo board's Key.
 * @param[in]   none
 * @return		MatrixKeyDef:
 *  @arg\b	    SKey1~SKey12 : 
 *	@arg\b	    PKey1~PKey6 : the clock from CK_LS 
 * @note 
 * @par         Example
 * @code
    API_Key_Init();
 * @endcode
 *******************************************************************************
 */
MatrixKeyDef API_ReadKey(void)
{
    // ------------------------------------------------------------------------
//    ADC_ClearFlag(hadc.Instance, ADC_WDIF | ADC_WDHF);
    
    if(hadc.State == MID_ADC_PRESS_KEY)
    {
//                printf("\nchannel=%d\n",hadc.PressChannel);
//                printf("value=%d\n",hadc.ADCData);
        switch(hadc.PressChannel)
        {
        case 10:
            // PA10 (serial)
            if(hadc.ADCData < (521/2))          // 0
                return SKey1;
            else if ((hadc.ADCData > (512/2)) && (hadc.ADCData <= ((512+1080)/2)))  // 512
                return SKey2;
            else if ((hadc.ADCData > ((512+1080)/2)) && (hadc.ADCData <= ((1080+1552)/2)))
                return SKey3;
            else if ((hadc.ADCData > ((1080+1552)/2)) && (hadc.ADCData <= ((1552+2048)/2)))
                return SKey4;
            else if ((hadc.ADCData > ((1552+2048)/2)) && (hadc.ADCData <= ((2048+2544)/2)))
                return SKey5;
            else if ((hadc.ADCData > ((2048+2544)/2)) && (hadc.ADCData <= 3000))
                return SKey6;
            break;
        case 11:
            // PA11 (serial)
            if(hadc.ADCData < (521/2))          // 0
                return SKey7;
            else if ((hadc.ADCData > (512/2)) && (hadc.ADCData <= ((512+1080)/2)))  // 512
                return SKey8;
            else if ((hadc.ADCData > ((512+1080)/2)) && (hadc.ADCData <= ((1080+1552)/2)))
                return SKey9;
            else if ((hadc.ADCData > ((1080+1552)/2)) && (hadc.ADCData <= ((1552+2048)/2)))
                return SKey10;
            else if ((hadc.ADCData > ((1552+2048)/2)) && (hadc.ADCData <= ((2048+2544)/2)))
                return SKey11;
            else if ((hadc.ADCData > ((2048+2544)/2)) && (hadc.ADCData <= 3000))
                return SKey12;
            break;
        case 12:
            // PA12 (parallel)
            if(hadc.ADCData < (720/2))          // 372
                return PKey1;
            else if ((hadc.ADCData > (720/2)) && (hadc.ADCData <= ((720+1303)/2)))  // 512
                return PKey2;
            else if ((hadc.ADCData > ((720+1303)/2)) && (hadc.ADCData <= ((1303+1862)/2)))
                return PKey3;
            else if ((hadc.ADCData > ((1303+1862)/2)) && (hadc.ADCData <= ((1862+2420)/2)))
                return PKey4;
            else if ((hadc.ADCData > ((1862+2420)/2)) && (hadc.ADCData <= ((2420+2942)/2)))
                return PKey5;
            else if ((hadc.ADCData > ((2420+2942)/2))  && (hadc.ADCData <= 3000) )
                return PKey6;
            break;
        default:
//            hadc.State = MID_ADC_STATE_RESET;
            return NoPressKey;
        }
    }
    return NoPressKey;
}

/**
 * @name	ADC_IRQHandler
 *   		
 */ 
///@{
//void ADC_IRQHandler(void)
void ADC_IRQ(void)
{
    static uint16_t debounce_CNT = 0;
    
//    printf("STA=%08X DAT0=%08X", ADC0->STA.W, ADC0->DAT0.W);
    
    // copy ADC information (conversion,column)
    if(ADC_GetSingleFlagStatus(ADC0, ADC_WDIF) == DRV_Happened)
    {   
//        printf("\t+");
        
        if(debounce_CNT == 0)
        {   
            /* set window detect for single channel */        
            ADC_WindowDetectRange_Select(hadc.Instance, ADC_WINDSingle);
       
            /* specify the channel */        
            hadc.PressChannel = ADC_GetDAT0Channel(hadc.Instance);  // Get current ADC channel
            ADC_ExternalChannel_Select(hadc.Instance, (ADC_ExtChannelDef) hadc.PressChannel);
            
            // change debounce_CNT to 1
            debounce_CNT = 1;
            
            /* Enable Window detect (High Event) for single channel */
            MID_ADC_WindowDetectIT_Start(&hadc, ADC_WDH_IE);
            
            // clear WDI+WDH flag
            ADC_ClearFlag(hadc.Instance, ADC_WDIF | ADC_WDHF);
            
            return;
        }
        else 
        {
            if(debounce_CNT < 100)          // ~40ms
            {
//                printf("%d\n", debounce_CNT);
                debounce_CNT ++;
                
                // clear WDI+WDH flag
                ADC_ClearFlag(hadc.Instance, ADC_WDIF | ADC_WDHF);
                return;
            }
            else
            {
                // set state when ADC entry WDI_Event
                hadc.State = MID_ADC_PRESS_KEY;
                hadc.ADCData = ADC_GetDAT0Data(hadc.Instance);
                
                /* Disable Window detect (middle Event) for single channel */
                MID_ADC_WindowDetectIT_Stop(&hadc, ADC_WDI_IE);
                
                /* Enable Window detect (High Event) for single channel */
                MID_ADC_WindowDetectIT_Start(&hadc, ADC_WDH_IE);
                
//                printf("\nchannel=%d\n",hadc.PressChannel);
//                printf("value=%d\n",hadc.ADCData);
//                printf("\n\n\n**** key in ***\n\n\n");
                
                // clear WDI+WDH flag
                ADC_ClearFlag(hadc.Instance, ADC_WDIF | ADC_WDHF);
                
                return;
            }
        }
    }
    
    if(ADC_GetSingleFlagStatus(ADC0, ADC_WDHF) == DRV_Happened)
    {
//        printf("\t-");
        hadc.State = MID_ADC_STATE_RESET;
        
        hadc.PressChannel = 0xFF;
        debounce_CNT = 0;
        
        /* only WDI IE */        
        MID_ADC_WindowDetectIT_Stop(&hadc, ADC_WDH_IE);
        MID_ADC_WindowDetectIT_Start(&hadc, ADC_WDI_IE);
        
        /* set window detect for all channel */        
        ADC_WindowDetectRange_Select(hadc.Instance, ADC_WINDAll);
        
        // clear flag
        ADC_ClearFlag(hadc.Instance, ADC_WDIF | ADC_WDHF);
    }
    
//    printf("Exit\n");
}

