/*************************************************************************//** 
 * @file     main.c 
 * @version  V1.00 
 * @brief    A project template for M480 MCU. 
 * 
 * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. 
*****************************************************************************/ 
#include <stdio.h> 
#include "NuMicro.h" 
 
#define ADC_PDMA_CH                                         (4) 
#define ADC_PDMA_OPENED_CH                           (1 << ADC_PDMA_CH) 
#define ADC_DMA_SAMPLE_COUNT                         (4) 
 
uint16_t pdmaConvertedData[ADC_DMA_SAMPLE_COUNT] = {0}; 
 
 
enum 
{ 
    ADC0_CH0 = 0, 
    ADC0_CH1, 
    ADC0_CH2, 
    ADC0_CH3, 
    ADC0_CH4, 
    ADC0_CH5, 
    ADC0_CH6, 
    ADC0_CH7, 
    ADC0_CH8, 
    ADC0_CH9, 
    ADC0_CH10, 
    ADC0_CH11, 
    ADC0_CH12, 
    ADC0_CH13, 
    ADC0_CH14, 
    ADC0_CH15, 
 
    ADC0_CH16_BAND_GAP_VOLT, 
    ADC0_CH17_TEMP_SENSOR, 
    ADC0_CH18_VBAT, 
 
    ADC_CH_DEFAULT 
} ADC_CH_TypeDef; 
 
typedef enum 
{ 
 
    flag_ADC_Band_GAP = 0, 
    flag_ADC_Data_Ready, 
    flag_ADC_Sensor_Ready, 
 
    flag_PDMA_Trans_Data_Ready, 
 
    flag_DEFAULT 
} Flag_Index; 
 
uint32_t BitFlag = 0; 
#define BitFlag_ON(flag)                                                        (BitFlag|=flag) 
#define BitFlag_OFF(flag)                                                        (BitFlag&=~flag) 
#define BitFlag_READ(flag)                                                        ((BitFlag&flag)?1:0) 
#define ReadBit(bit)                                                                (uint32_t)(1<<bit) 
 
#define is_flag_set(idx)                                                        (BitFlag_READ(ReadBit(idx))) 
#define set_flag(idx,en)                                                        ( (en == 1) ? (BitFlag_ON(ReadBit(idx))) : (BitFlag_OFF(ReadBit(idx)))) 
 
void ReloadPDMA(void) 
{ 
    /* transfer width is half word(16 bit) and transfer count is ADCDatalenght+1 */ 
    PDMA_SetTransferCnt(PDMA, ADC_PDMA_CH, PDMA_WIDTH_16, ADC_DMA_SAMPLE_COUNT); 
 
    /* Select PDMA request source as ADC RX */ 
    PDMA_SetTransferMode(PDMA, ADC_PDMA_CH, PDMA_EADC0_RX, FALSE, (uint32_t) 0); 
} 
 
void PDMA_IRQHandler(void) 
{ 
    uint32_t status = PDMA_GET_INT_STATUS(PDMA); 
 
    if (status & PDMA_INTSTS_ABTIF_Msk)   /* abort */ 
    { 
#if 0 
        PDMA_CLR_ABORT_FLAG(PDMA, PDMA_GET_ABORT_STS(PDMA)); 
#else 
        if (PDMA_GET_ABORT_STS(PDMA) & ADC_PDMA_OPENED_CH) 
        { 
            printf("ABTSTS\r\n"); 
        } 
        PDMA_CLR_ABORT_FLAG(PDMA, ADC_PDMA_OPENED_CH); 
 
#endif 
    } 
    else if (status & PDMA_INTSTS_TDIF_Msk)     /* done */ 
    { 
        if(PDMA_GET_TD_STS(PDMA) & ADC_PDMA_OPENED_CH) 
        { 
            //insert process 
            set_flag(flag_PDMA_Trans_Data_Ready, ENABLE); 
            printf("TDIF\r\n"); 
        } 
 
        /* Clear PDMA transfer done interrupt flag */ 
        PDMA_CLR_TD_FLAG(PDMA, ADC_PDMA_OPENED_CH); 
    } 
    else if (status & (PDMA_INTSTS_REQTOF1_Msk))     /* Check the DMA time-out interrupt flag */ 
    { 
        PDMA_CLR_TMOUT_FLAG(PDMA, ADC_PDMA_CH); 
        printf("REQTOF\r\n"); 
 
    } 
    else 
    { 
 
    } 
 
} 
 
 
void PDMA_Init(void) 
{ 
    SYS_ResetModule(PDMA_RST); 
 
    /* Configure PDMA peripheral mode form ADC to memory */ 
    /* Open PDMA Channel 1 based on ADC_PDMA_CH setting*/ 
//    PDMA_Open(PDMA, BIT0 << ADC_PDMA_CH); 
    PDMA_Open(PDMA, 0); 
 
    /* transfer width is half word(16 bit) and transfer count is ADCDatalenght+1 */ 
    PDMA_SetTransferCnt(PDMA, ADC_PDMA_CH, PDMA_WIDTH_16, ADC_DMA_SAMPLE_COUNT); 
 
    /* Set source address as ADC data register (no increment) and destination address as g_i32ConversionData array (increment) */ 
    PDMA_SetTransferAddr(PDMA, ADC_PDMA_CH, (uint32_t) & (EADC->CURDAT), PDMA_SAR_FIX, (uint32_t)pdmaConvertedData, PDMA_DAR_INC); 
 
    /* Select PDMA request source as ADC RX */ 
    PDMA_SetTransferMode(PDMA, ADC_PDMA_CH, PDMA_EADC0_RX, FALSE, 0); 
 
    /* Set PDMA as single request type for ADC */ 
    PDMA_SetBurstType(PDMA, ADC_PDMA_CH, PDMA_REQ_SINGLE, PDMA_BURST_128); 
 
    PDMA_EnableInt(PDMA, ADC_PDMA_CH, PDMA_INT_TRANS_DONE); 
    NVIC_EnableIRQ(PDMA_IRQn); 
 
    PDMA_Trigger(PDMA, ADC_PDMA_CH); 
 
    /* ADC enable PDMA transfer */ 
    EADC_ENABLE_PDMA(EADC); 
} 
 
void EADC00_IRQHandler(void) 
{ 
//    printf(" EADC00_IRQHandler\r\n"); 
    EADC_CLR_INT_FLAG(EADC, EADC_STATUS2_ADIF0_Msk);      /* Clear the A/D ADINT0 interrupt flag */ 
} 
 
 
void ADC_Convert_Ext_Channel(void) 
{ 
 
    /* Set input mode as single-end, and Single mode*/ 
    EADC_Open(EADC, EADC_CTL_DIFFEN_SINGLE_END); 
 
    EADC_SetExtendSampleTime(EADC, 0x0f, 0x3F); 
 
    EADC_ConfigSampleModule(EADC, 0, EADC_ADINT0_TRIGGER, 0); 
    EADC_ConfigSampleModule(EADC, 1, EADC_ADINT0_TRIGGER, 1); 
    EADC_ConfigSampleModule(EADC, 2, EADC_ADINT0_TRIGGER, 2); 
    EADC_ConfigSampleModule(EADC, 3, EADC_ADINT0_TRIGGER, 3); 
 
 
    EADC_CLR_INT_FLAG(EADC, EADC_STATUS2_ADIF0_Msk); 
    EADC_ENABLE_INT(EADC, (BIT0 << 0)); 
 
    EADC_ENABLE_SAMPLE_MODULE_INT(EADC, 0, 0x7FF); 
 
    NVIC_EnableIRQ(EADC00_IRQn); 
 
    PDMA_Init(); 
 
    EADC_START_CONV(EADC, 0x0F); 
 
} 
 
 
void SYS_Init(void) 
{ 
    /*---------------------------------------------------------------------------------------------------------*/ 
    /* Init System Clock                                                                                       */ 
    /*---------------------------------------------------------------------------------------------------------*/ 
    /* Unlock protected registers */ 
    SYS_UnlockReg(); 
 
    /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */ 
    PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk); 
 
    /* Enable External XTAL (4~24 MHz) */ 
    CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk); 
 
    /* Waiting for 12MHz clock ready */ 
    CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk); 
 
    /* Set core clock as PLL_CLOCK from PLL */ 
    CLK_SetCoreClock(FREQ_192MHZ); 
    /* Set PCLK0/PCLK1 to HCLK/2 */ 
    CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2); 
 
    /* Enable UART clock */ 
    CLK_EnableModuleClock(UART0_MODULE); 
 
    /* Select UART clock source from HXT */ 
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HXT, CLK_CLKDIV0_UART0(1)); 
 
    /* Enable EADC module clock */ 
    CLK_EnableModuleClock(EADC_MODULE); 
 
    /* EADC clock source is 96MHz, set divider to 8, EADC clock is 96/8 MHz */ 
    CLK_SetModuleClock(EADC_MODULE, 0, CLK_CLKDIV0_EADC(8)); 
 
    CLK_EnableModuleClock(PDMA_MODULE); 
 
    /* Update System Core Clock */ 
    /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */ 
    SystemCoreClockUpdate(); 
 
    /* Set GPB multi-function pins for UART0 RXD and TXD */ 
    SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk); 
    SYS->GPB_MFPH |= (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD); 
 
    PB->MODE &= ~(GPIO_MODE_MODE0_Msk | GPIO_MODE_MODE1_Msk | GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk); 
    SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB0MFP_Msk | SYS_GPB_MFPL_PB1MFP_Msk | SYS_GPB_MFPL_PB2MFP_Msk | SYS_GPB_MFPL_PB3MFP_Msk); 
    SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB0MFP_EADC0_CH0 | SYS_GPB_MFPL_PB1MFP_EADC0_CH1 | SYS_GPB_MFPL_PB2MFP_EADC0_CH2 | SYS_GPB_MFPL_PB3MFP_EADC0_CH3); 
    GPIO_DISABLE_DIGITAL_PATH(PB, BIT0 | BIT1 | BIT2 | BIT3); 
 
 
 
    /* Set reference voltage to external pin (3.3V) */ 
    SYS_SetVRef(SYS_VREFCTL_VREF_PIN); 
 
    /* Lock protected registers */ 
    SYS_LockReg(); 
} 
 
/* 
 * This is a template project for M480 series MCU. Users could based on this project to create their 
 * own application without worry about the IAR/Keil project settings. 
 * 
 * This template application uses external crystal as HCLK source and configures UART0 to print out 
 * "Hello World", users may need to do extra system configuration based on their system design. 
 */ 
 
int main() 
{ 
 
    SYS_Init(); 
    /* Init UART to 115200-8n1 for print message */ 
    UART_Open(UART0, 115200); 
 
    printf("\r\nCLK_GetCPUFreq : %8d\r\n", CLK_GetCPUFreq()); 
    printf("CLK_GetHXTFreq : %8d\r\n", CLK_GetHXTFreq()); 
    printf("CLK_GetLXTFreq : %8d\r\n", CLK_GetLXTFreq()); 
    printf("CLK_GetPCLK0Freq : %8d\r\n", CLK_GetPCLK0Freq()); 
    printf("CLK_GetPCLK1Freq : %8d\r\n", CLK_GetPCLK1Freq()); 
 
    ADC_Convert_Ext_Channel(); 
 
    /* Got no where to go, just loop forever */ 
    while(1) 
    { 
 
 
        pdmaConvertedData[0] = EADC_GET_CONV_DATA(EADC, 0); 
        pdmaConvertedData[1] = EADC_GET_CONV_DATA(EADC, 1); 
        pdmaConvertedData[2] = EADC_GET_CONV_DATA(EADC, 2); 
        pdmaConvertedData[3] = EADC_GET_CONV_DATA(EADC, 3); 
 
        printf("%04d,%04d,%04d,%04d \r\n", pdmaConvertedData[0], pdmaConvertedData[1], pdmaConvertedData[2], pdmaConvertedData[3] ); 
 
    } 
} 
 
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ 
 
 
 |   
 
 
 
 |