/**
 ******************************************************************************
 *
 * @file        MG32_IEC60730_GPIO.c
 *
 * @brief       This is the C code format driver head file.
 *
 * @par         Project
 *              MG32
 * @version     V1.01
 * @date        2021/01/22
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2018 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. 
 ******************************************************************************
 ******************************************************************************
 */ 

 
#include "MG32_IEC60730_Common.h"


#if IEC60730_GPIO_Option == 1

#include "MG32_IEC60730_GPIO.h"
#include MG32_GPIO_FILENAME




#if TST_PAO_MSK == 1 || TST_PAO_MSK == 1 || TST_PAO_MSK == 1 || TST_PAO_MSK == 1 || TST_PAO_MSK 
static uint16_t const GPIOutput_Table[TST_TOTAL_PORT][2] = {
                                                           {TST_PAOX_MSK,TST_PAO_LVL},
                                                           {TST_PBOX_MSK,TST_PBO_LVL},
                                                           {TST_PCOX_MSK,TST_PCO_LVL},
                                                           {TST_PDOX_MSK,TST_PDO_LVL},
                                                           {TST_PEOX_MSK,TST_PEO_LVL}
                                                        };
#endif
#if TST_PAI_MSK == 1 || TST_PBI_MSK == 1 || TST_PCI_MSK == 1 || TST_PDI_MSK == 1 || TST_PEI_MSK                                                    
static uint16_t const GPIOInput_Table[TST_TOTAL_PORT][2] = {
                                                           {TST_PAIX_MSK,TST_PAI_EXPECT},
                                                           {TST_PBIX_MSK,TST_PBI_EXPECT},
                                                           {TST_PCIX_MSK,TST_PCI_EXPECT},
                                                           {TST_PDIX_MSK,TST_PDI_EXPECT},
                                                           {TST_PEIX_MSK,TST_PEI_EXPECT}
                                                        };
#endif
  

/**
 *******************************************************************************
 * @brief       
 * @details  
 * @param[in]    
 * @return      
 * @exception   No   
 * @note        
 *******************************************************************************
 */
IEC60730_Ret MG32_GPIOutput_Test(void)
{
    #if TST_PAO_MSK == 1 || TST_PAO_MSK == 1 || TST_PAO_MSK == 1 || TST_PAO_MSK == 1 || TST_PAO_MSK

        GPIO_Struct* GPIOX = {0};
        BitAction    TST_TRG;
        uint8_t      PortCnt;
        uint16_t     Test_pattern;
        uint16_t     Cmp_pattern;
        

        for( PortCnt = 0; PortCnt < TST_TOTAL_PORT ; PortCnt++)
        {
            TST_TRG = SET;
            switch(PortCnt)
            {
                #if TST_PAO_MSK == 1 
                case IEC60730_PORTA:
                                    GPIOX = GPIOA;
                                    break;
                #endif
                #if TST_PBO_MSK == 1 
                case IEC60730_PORTB:
                                    GPIOX = GPIOB;
                                    break;
                #endif
                #if TST_PCO_MSK == 1 
                case IEC60730_PORTC:
                                    GPIOX = GPIOC;
                                    break;
                #endif
                #if TST_PDO_MSK == 1 
                case IEC60730_PORTD:
                                    GPIOX = GPIOD;
                                    break;
                #endif
                #if TST_PEO_MSK == 1 
                case IEC60730_PORTE:
                                    GPIOX = GPIOE;
                                    break;
                #endif
                default:
                                    TST_TRG = CLR;
                                    break;
            }
            if(TST_TRG==SET)
            {
                Test_pattern = GPIO_ReadPort(GPIOX);
                Test_pattern = Test_pattern & (~(GPIOutput_Table[PortCnt][0]));
                Test_pattern = Test_pattern | (GPIOutput_Table[PortCnt][0]|GPIOutput_Table[PortCnt][1]);
                GPIO_WritePort(GPIOA,Test_pattern);
                Cmp_pattern = GPIO_ReadPort(GPIOX);
                if((Test_pattern & GPIOutput_Table[PortCnt][0]) !=(Cmp_pattern & GPIOutput_Table[PortCnt][0]))
                {
                    return(IEC60730_TEST_FAILURE);
                } 
            }
        }
        
        
    #endif
    
    return(IEC60730_TEST_SUCCESS);
    
} 

/**
 *******************************************************************************
 * @brief       
 * @details  
 * @param[in]    
 * @return      
 * @exception   No   
 * @note        
 *******************************************************************************
 */
IEC60730_Ret MG32_GPIOInput_Test(void)
{
    #if TST_PAI_MSK == 1 || TST_PBI_MSK == 1 || TST_PCI_MSK == 1 || TST_PDI_MSK == 1 || TST_PEI_MSK

        GPIO_Struct* GPIOX = {0};
        BitAction    TST_TRG;
        uint8_t      PortCnt;
        uint16_t     Test_pattern;


        for( PortCnt = 0; PortCnt < TST_TOTAL_PORT ; PortCnt++)
        {
            TST_TRG = SET;
            switch(PortCnt)
            {
                #if TST_PAI_MSK == 1 
                case IEC60730_PORTA:
                                    GPIOX = GPIOA;
                                    break;
                #endif
                #if TST_PBI_MSK == 1 
                case IEC60730_PORTB:
                                    GPIOX = GPIOB;
                                    break;
                #endif
                #if TST_PCI_MSK == 1 
                case IEC60730_PORTC:
                                    GPIOX = GPIOC;
                                    break;
                #endif
                #if TST_PDI_MSK == 1 
                case IEC60730_PORTD:
                                    GPIOX = GPIOD;
                                    break;
                #endif
                #if TST_PEI_MSK == 1 
                case IEC60730_PORTE:
                                    GPIOX = GPIOE;
                                    break;
                #endif
                default:
                                    TST_TRG = CLR;
                                    break;
            }
            if(TST_TRG==SET)
            {
                Test_pattern = GPIO_ReadPort(GPIOX);
                
                
                if((Test_pattern & GPIOInput_Table[PortCnt][0]) !=(GPIOInput_Table[PortCnt][1] & GPIOInput_Table[PortCnt][0]))
                {
                    return(IEC60730_TEST_FAILURE);
                } 
            }
        }
        
        
    #endif
        
    return(IEC60730_TEST_SUCCESS);
}
/**
 *******************************************************************************
 * @brief       
 * @details  
 * @param[in]    
 * @return      
 * @exception   No   
 * @note        
 *******************************************************************************
 */
#define TST_GPIO_TABLE_TOTAL    ((sizeof(GPIO_CFG))/4 - 1)/2
IEC60730_Ret IEC60730_TestGPIO(void)
{
    #if TST_PA_MSK == 1 || TST_PB_MSK == 1 || TST_PC_MSK == 1 || TST_PD_MSK == 1 || TST_PE_MSK == 1
        
    
        BitAction  TST_TRG = CLR;
        uint32_t   TST_TABLE_CNT;
        uint32_t   PortADR_CMP = 0;
        uint32_t   TSTPin_Cmp = 0;
        uint32_t   PinInt_Cmp;
        uint32_t   PinADR;
        uint32_t   PinMDS_CNT = TST_GPIO_TABLE_TOTAL;
        //====================================
        //GPIO Mode Inital.
        #ifndef _MG32_GPIO_Init_H
            #error "<<< Please include MG32_GPIO_Init.h file or being setted GPIO mode by self.>>>"
    
            //If no want to use MG32_GPIO_Init.h you can use GPIO_PinMode_Config or GPIO_PortMode_Config to set that you want setting.
        #else
            #if MG32_GPIOInit_ENMask
                #error "<<< MG32_GPIO_Init.h file no any GPIO mode setting.>>>"
            #else
                UnProtectModuleReg(CSCprotect);
                
                for(TST_TABLE_CNT = 0; TST_TABLE_CNT < PinMDS_CNT; TST_TABLE_CNT++)
                {   
                    PinInt_Cmp =  GPIO_CFG[TST_TABLE_CNT*2];          
                    PinADR = (PinInt_Cmp & TST_PORT_MSK);
                    
                    if(PinADR!=PortADR_CMP)
                    {
                        PortADR_CMP = PinADR;
                        TST_TRG = SET;
                        switch(PinADR)
                        {
                            #if TST_PA_MSK == 1
                            case PA0_CR_ADR:
                                            TSTPin_Cmp = TST_PINA_MSK;
                                            CSC_PeriphOnModeClock_Config(CSC_ON_PortA, ENABLE);
                                            break;
                            #endif
                            #if TST_PB_MSK == 1
                            case PB0_CR_ADR:
                                            TSTPin_Cmp = TST_PINB_MSK;
                                            CSC_PeriphOnModeClock_Config(CSC_ON_PortB, ENABLE);
                                            break;
                            #endif
                            #if TST_PC_MSK == 1
                            case PC0_CR_ADR:
                                            TSTPin_Cmp = TST_PINC_MSK;
                                            CSC_PeriphOnModeClock_Config(CSC_ON_PortC, ENABLE);
                                            break;
                            #endif
                            #if TST_PD_MSK == 1
                            case PD0_CR_ADR:
                                            TSTPin_Cmp = TST_PIND_MSK;
                                            CSC_PeriphOnModeClock_Config(CSC_ON_PortD, ENABLE);
                                            break;
                            #endif
                            #if TST_PE_MSK == 1
                            case PE0_CR_ADR:
                                            TSTPin_Cmp = TST_PINE_MSK;
                                            CSC_PeriphOnModeClock_Config(CSC_ON_PortE, ENABLE);
                                            break;
                            #endif
                            default:
                                            TSTPin_Cmp = CLR;
                                            break;
                        }
                    }
                    
                    if(TST_TRG == SET)
                    {
                        PinInt_Cmp = ((PinInt_Cmp & TST_PIN_MSK) / 4);
                        PinInt_Cmp = 0x00000001 << PinInt_Cmp;
                        
                        if((TSTPin_Cmp & PinInt_Cmp)!=0)
                        {
                            *((volatile uint32_t*)((uint32_t)GPIO_CFG[TST_TABLE_CNT*2])) = ( GPIO_CFG[TST_TABLE_CNT*2+1] & (~PX_CR_AFS_mask_w));           
                        }
                    }                
                }
                ProtectModuleReg(CSCprotect);
            #endif
        #endif

        //====================================
        //IEC60730 GPIO Test Gode.
        if(MG32_GPIOutput_Test()==IEC60730_TEST_FAILURE)
        {
            return(IEC60730_TEST_FAILURE);
        }
        if(MG32_GPIOInput_Test()==IEC60730_TEST_FAILURE)
        {
            return(IEC60730_TEST_FAILURE);
        }
        
    #endif
    
    return(IEC60730_TEST_SUCCESS);
} 
 
#endif










