T168_111\core\N32903文件:第1~14个文件

context.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define CONTEXT_C

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <string.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "Common.h"
#include "XCore.h"
#include "XNutOS.h"
#include "..\ARM.h"
#include <stdio.h>
#include <stdlib.h>

__asm int __get_CPSR(void)
 {
     mrs r0,cpsr
     bx lr
 }
     
 __asm void __disable_interrupt(void)
 {
aa     mrs r0,cpsr
     orr r0,r0,#0xc0
     msr cpsr_c,r0
     mrs r0,cpsr
     ands r0,r0,#0xc0
     beq aa
     bx lr
 }
  __asm void __enable_interrupt(void)
 {
     mrs r0,cpsr
     bic r0,r0,#0xc0
     msr cpsr_c,r0
     bx lr
 }
#if defined(NUTOS)

/******************************************************************************
 *                                                                            *
 *                         L O C A L   D E F I N E S                          *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *                        L O C A L   T Y P E D E F S                         *
 *                                                                            *
 ******************************************************************************/

/*!
 * \brief Context switch frame layout.
 *
 * This is the layout of the stack after a thread's context has been
 * switched-out. The stack pointer is stored in the thread info and
 * points to this structure.
 */
typedef struct {
    u_long csf_cpsr;
    u_long csf_r4;
    u_long csf_r5;
    u_long csf_r6;
    u_long csf_r7;
    u_long csf_r8;
    u_long csf_r9;
    u_long csf_r10;
    u_long csf_r11;             /* AKA fp */
    u_long csf_lr;
} SWITCHFRAME;

/*!
 * \brief Thread entry frame layout.
 *
 * This is the stack layout being build to enter a new thread.
 */
typedef struct {
    u_long cef_r0;
    u_long cef_pc;
} ENTERFRAME;

/******************************************************************************
 *                                                                            *
 *             L O C A L   F U N C T I O N   P R O T O T Y P E S              *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *    L O C A L   I N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *    L O C A L   U N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

/*!
 * \brief Enter a new thread.
 */
 
static __asm void NutThreadEntry(void) __attribute__ ((naked));
__asm void NutThreadEntry(void)
{
    /* Load argument in r0 and jump to thread entry. */
//    asm volatile ("ldmfd   sp!, {r0, lr}\n\tbx lr":::"r0", "lr");
    ldmfd   sp!, {r0, lr}
    BX LR
}

__asm void SaveStackPointer(uptr_t *pointer)
{
    str     sp, [r0]
    BX LR
}

__asm void RestoreStackPointer(uptr_t *pointer)
{
    ldr     sp, [r0]
    BX LR
}

/*!
 * \brief Switch to another thread.
 *
 * Stop the current thread, saving its context. Then start the
 * one with the highest priority, which is ready to run.
 *
 * Application programs typically do not call this function.
 *
 * \note CPU interrupts must be disabled before calling this function.
 *
 */
void __asm NutThreadSwitch_1(void) __attribute__ ((naked));
void __asm NutThreadSwitch_1(void)
{
    mov        r1,lr
    ldmia   sp!, {r4, lr}
    stmfd   sp!, {r4-r11, lr}
    mrs     r0, cpsr
    stmfd   sp!, {r0}
    BX r1
}
void __asm NutThreadSwitch_2(void) __attribute__ ((naked));
void __asm NutThreadSwitch_2(void)
{
    ldmfd   sp!, {r0}
    bic     r0, r0, #0xC0
    msr     SPSR_cxsf, r0
    ldmfd   sp!, {r4-r11, lr}
    BX LR
}//CPSR_cxsf?SPSR_cxsf
void NutThreadSwitch(void) __attribute__ ((naked));
void NutThreadSwitch(void)
{
//    asm("ldmia   sp!, {r4, lr}");

//    __asm__ __volatile__
//        /* Save CPU context. */
//     ("@ Save context\n\t"
//      /* Save registers. */
//      "stmfd   sp!, {r4-r11, lr}\n\t"
//      /* Save status. */
//      "mrs     r0, cpsr\n\t"
//      /* */
//      "stmfd   sp!, {r0}\n\t"
//      /* Save stack pointer. */
//      "str     sp, %[td_sp]"
//      /* Output. */
//      :
//      /* Input. */
//      :[td_sp] "o"(runningThread->td_sp)
//      /* Clobbers. */
//      :"r0", "memory");
/*
    asm("stmfd   sp!, {r4-r11, lr}");    // Save registers. 
    asm("mrs     r0, cpsr");            // Save status. 
    asm("stmfd   sp!, {r0}");*/
    NutThreadSwitch_1();
    SaveStackPointer(&runningThread->td_sp);

    /* Select thread on top of the run queue. */
    runningThread = runQueue;
    runningThread->td_state = TDS_RUNNING;

//    __asm__ __volatile__
//        /* Restore context. */
//     ("@ Reload context\n\t"
//      /* Restore stack pointer. */
//      "ldr     sp, %[td_sp]\n\t"
//      /* Get saved status... */
//      "ldmfd   sp!, {r0}\n\t"
//      /* ...enable interrupts */
//      "bic     r0, r0, #0xC0\n\t"
//      /* ...and save in spsr. */
//      "msr     spsr, r0\n\t"
//      /* Restore registers. */
//      "ldmfd   sp!, {r4-r11, lr}\n\t"
//      /* Restore status and return. */
//      "movs    pc, lr"
//      /* Output. */
//      :
//      /* Input. */
//      :[td_sp] "m"(runningThread->td_sp)
//      /* Clobbers. */
//      :"r0", "memory");

    RestoreStackPointer(&runningThread->td_sp);
/*
    asm("ldmfd   sp!, {r0}");            // Get saved status... 
    asm("bic     r0, r0, #0xC0");        // ...enable interrupts
    asm("msr     spsr, r0");            // ...and save in spsr. 
    asm("ldmfd   sp!, {r4-r11, lr}");    // Restore registers. 
    asm("movs    pc, lr");                // Restore status and return. 
*/
    NutThreadSwitch_2();
}

/*!
 * \brief Create a new thread.
 *
 * If the current thread's priority is lower or equal than the default
 * priority (64), then the current thread is stopped and the new one
 * is started.
 *
 * \param name      String containing the symbolic name of the new thread,
 *                  up to 8 characters long.
 * \param fn        The thread's entry point, typically created by the
 *                  THREAD macro.
 * \param arg       Argument pointer passed to the new thread.
 * \param stackSize Number of bytes of the stack space allocated for
 *                  the new thread.
 *
 * \note The thread must run in ARM mode. Thumb mode is not supported.
 *
 * \return Pointer to the NUTTHREADINFO structure or 0 to indicate an
 *         error.
 */
   extern void led_led(void);
void __asm NutThreadCreate_1(void) __attribute__ ((naked));
 void __asm NutThreadCreate_1(void)
 {
         ldmfd   sp!, {r0}
        bic     r0, r0, #0xC0
        msr     SPSR_cxsf, r0
        ldmfd   sp!, {r4-r11, lr}
        BX LR
 }
NUTHANDLE NutThreadCreate(char * name, void (*fn) (void *), void *arg, size_t stackSize)
{
    u_char *threadMem;
    SWITCHFRAME *sf;
    ENTERFRAME *ef;
    NUTTHREADINFO *td;

// ch_20211229
#ifdef DEBUG_NUTOS
    sysprintf("Enter NutThreadCreate()...\n");
#endif        

    /*
     * Allocate stack and thread info structure in one block.
     * We sill setup the following layout:
     *
     * Upper memory addresses.
     *
     *              +--------------------+
     *              I                    I
     *              I   NUTTHREADINFO    I
     *              I                    I
     * td ->        +-----+--------------+ <- Stack top
     *              I     I              I
     *              I  T  I   ENTERFRAME I
     *              I  H  I              I
     * ef ->        I  R  +--------------+
     *              I  E  I              I    ^
     *              I  A  I  SWITCHFRAME I    I
     *              I  D  I              I    I  pop moves up
     * sf ->        I     +--------------+ <- Initial stack pointer
     *              I  S  I              I    I  push moves down
     *              I  T  I Application  I    I
     *              I  A  I Stack        I    V
     *              I  C  I              I
     *              I  K  I              I
     * threadMem -> +-----+--------------+ <- Stack bottom
     *
     * Lower memory addresses.
     */

    
    if ((threadMem = NutHeapAlloc(stackSize + sizeof(NUTTHREADINFO))) == 0) {
        return 0;
    }

    td = (NUTTHREADINFO *) (threadMem + stackSize);
    ef = (ENTERFRAME *) ((uptr_t) td - sizeof(ENTERFRAME));
    sf = (SWITCHFRAME *) ((uptr_t) ef - sizeof(SWITCHFRAME));

    /* 
     * Set predefined values at the stack bottom. May be used to detect
     * stack overflows.
     */
    *((u_long *) threadMem) = DEADBEEF;
    *((u_long *) (threadMem + 4)) = DEADBEEF;
    *((u_long *) (threadMem + 8)) = DEADBEEF;
    *((u_long *) (threadMem + 12)) = DEADBEEF;

    /*
     * Setup the entry frame to simulate C function entry.
     */
    ef->cef_pc = (uptr_t) fn;
    ef->cef_r0 = (uptr_t) arg;

    /*
     * Setup the switch frame.
     */
    sf->csf_lr = (uptr_t) NutThreadEntry;
    sf->csf_cpsr = ARM_CPSR_I_BIT | ARM_CPSR_F_BIT | ARM_MODE_SYS;

    /*
     * Initialize the thread info structure and insert it into the 
     * thread list and the run queue.
     */
    memcpy(td->td_name, name, sizeof(td->td_name) - 1);
    td->td_name[sizeof(td->td_name) - 1] = 0;
    td->td_state = TDS_READY;
    td->td_sp = (uptr_t) sf;
    td->td_priority = 64;
    td->td_memory = threadMem;
    td->td_timer = 0;
    td->td_queue = 0;
    NutEnterCritical();
    td->td_next = nutThreadList;
    nutThreadList = td;
    NutThreadAddPriQueue(td, (NUTTHREADINFO **) & runQueue);

    // ch_20211229
#ifdef DEBUG_NUTOS
        while (td) 
        {
            sysprintf("%s\t", td->td_name);
            td = td->td_next;
        }    
        sysprintf("\n");
#endif
    
    /*
     * If no thread is running, then this is the first thread ever 
     * created. In Nut/OS, the idle thread is created first.
     */
    if (runningThread == 0) {
        /* This will never return. */
        runningThread = runQueue;
        runningThread->td_state = TDS_RUNNING;

    //    __asm__ __volatile__
    //        /* Load initial idle thread context. */
    //     ("@ Load context\n\t"
    //      /* Restore stack pointer. */
    //      "ldr     sp, %[td_sp]\n\t"
    //      /* Get saved status... */
    //      "ldmfd   sp!, {r0}\n\t"
    //      /* ...enable interrupts */
    //      "bic     r0, r0, #0xC0\n\t"
    //      /* ...and save in spsr. */
    //      "msr     spsr, r0\n\t"
    //      /* Restore registers. */
    //      "ldmfd   sp!, {r4-r11, lr}\n\t"
    //      /* Restore status and return. */
    //      "movs    pc, lr"
    //      /* Input. */
    //      :
    //      /* Output. */
    //      :[td_sp] "m" (runningThread->td_sp)
    //      /* Clobbers. */
    //      :"r0", "memory");
        RestoreStackPointer(&runningThread->td_sp);
        NutThreadCreate_1();
/*
        asm("ldmfd   sp!, {r0}");            // Get saved status... 
        asm("bic     r0, r0, #0xC0");        // ...enable interrupts
        asm("msr     spsr, r0");            // ...and save in spsr. 
        asm("ldmfd   sp!, {r4-r11, lr}");    // Restore registers. 
        asm("movs    pc, lr");                // Restore status and return. 
        */
    }

    /*
     * If current context is not in front of the run queue (highest 
     * priority), then switch to the thread in front.
     */
    if (runningThread != runQueue) {
        runningThread->td_state = TDS_READY;
        NutThreadSwitch();
    }
    NutExitCritical();

    return td;
}

#endif



DMA.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Common.h"
#include "XCore.h"
#include "XProFile.h"
#include "XAppVer.h"
#include "XPrtEng.h"
#include "XParser.h"
#include "XComm.h"
#include "../device/USB/Device/N32903/UsbLibry.h"


#define DBG_PRINTF    sysprintf
volatile unsigned int count=0;
static DMA_CALLBACK DMA_CallbackTab[4] = {0};
__align(32) UINT8 data[200];
void DMATest(void);


#define TEST_SIZE    1 * 1024
STATIC __align(4096) UINT8 WriteBuffer[TEST_SIZE];


UINT8 previous = 0;
UINT32 count_A = 0;
UINT8 flag = 0;


void DMA_ISR() {

    if (inp32(REG_VDMA_ISR) & BIT31) {
        sysPutChar('f');
        if (inp32(REG_VDMA_ISR) & INTR1) {
            if (inp32(REG_PDMA_ISR1) & EDMABLKD_IF) {
                previous = 0;
                outp32(REG_PDMA_ISR1, inp32(REG_PDMA_ISR1) | EDMABLKD_IF);
                if (DMA_CallbackTab[0] != NULL) {
                    DMA_CallbackTab[0]();
                }
                
            } else if (inp32(REG_PDMA_ISR1) & EDMATABORT_IF) {
                outp32(REG_PDMA_ISR1, EDMATABORT_IF);
            }

        } else if (inp32(REG_VDMA_ISR) & INTR2) {
            if (inp32(REG_PDMA_ISR2) & EDMABLKD_IF) {
                outp32(REG_PDMA_ISR2, EDMABLKD_IF);
                DMA_CallbackTab[1]();
            }
        } else if (inp32(REG_VDMA_ISR) & INTR3) {
            if (inp32(REG_PDMA_ISR3) & EDMABLKD_IF) {
                outp32(REG_PDMA_ISR3, EDMABLKD_IF);
                DMA_CallbackTab[2]();
            }
        } else if (inp32(REG_VDMA_ISR) & INTR4) {
            if (inp32(REG_PDMA_ISR4) & EDMABLKD_IF) {
                outp32(REG_PDMA_ISR4, EDMABLKD_IF);
                DMA_CallbackTab[3]();
            }
        }
        
    }

}

void DMA_Init() {

    sysInstallISR(IRQ_LEVEL_7, IRQ_EDMA, (PVOID)DMA_ISR);
    sysSetInterruptType(IRQ_EDMA, HIGH_LEVEL_SENSITIVE);
    sysEnableInterrupt(IRQ_EDMA);
    
}

void DMA_Channel_Init(UINT8 channel,DMA_APB_DEVICE dev, DMA_APB_RW rw, DMA_DIRECTION_SELECT srcDir, DMA_DIRECTION_SELECT desDir) {
    
    UINT32 u32SFR;
    UINT8 shift;
    UINT8 nShift;

    outp32(REG_VDMA_CSR + channel * 0x100, inp32(REG_VDMA_CSR + channel * 0x100)  | EDMACEN| TRIG_EN);

    outp32(REG_AHBCLK, inp32(REG_AHBCLK) | (0x00000400 << channel));// open clk
    //spiIoctl(0, SPI_SET_CLOCK, 48, 16000);
    
    u32SFR = REG_VDMA_CSR + channel * 0x100;
    outp32(u32SFR,(inp32(u32SFR) & ~APB_TWS) | (1 << 19));//8 bit
    
    if (rw == DMA_WRITE_APB) {
        outp32(u32SFR,(inp32(u32SFR) & ~MODE_SEL) | (2 << 2));//memory to device
        shift = ((channel - 1) * 4 + 16);
        nShift = ((channel - 1) * 4);
    } else if (rw == DMA_READ_APB) {
        outp32(u32SFR,(inp32(u32SFR) & ~MODE_SEL) | (1 << 2));//device to memory
        shift = ((channel - 1) * 4);
        nShift = ((channel - 1) * 4 + 16);
    }


    outp32(u32SFR, inp32(u32SFR) & ~EDMASG_EN);// disable scatter-gather function

    outp32(u32SFR, inp32(u32SFR) & (~(3<<6)));
    outp32(u32SFR, inp32(u32SFR) | (desDir << 6));

    outp32(u32SFR, inp32(u32SFR) & (~(3<<4)));
    outp32(u32SFR, inp32(u32SFR) | (srcDir << 4));

    outp32(REG_EDSSR, inp32(REG_EDSSR) | (7 << nShift));
    outp32(REG_EDSSR, inp32(REG_EDSSR) & (~(7 << shift)));//clear
    outp32(REG_EDSSR, inp32(REG_EDSSR) | (dev << shift));// set channel

}


void DMA_Transfer_Init(UINT8 channel, UINT32 src, UINT32 dest, UINT32 len, DMA_CALLBACK callback) {

    unsigned char *pSrc;

    pSrc = (UINT8 *)((UINT32)WriteBuffer | NON_CACHE_BIT);
    
    outp32(REG_VDMA_SAR + channel * 0x100, (UINT32)pSrc);
    outp32(REG_VDMA_DAR + channel * 0x100, dest);
    outp32(REG_VDMA_BCR + channel * 0x100, len);

    outp32(REG_VDMA_IER + channel * 0x100, BLKD_IE);
    DMA_CallbackTab[channel - 1] = callback;
}


void DMA_Transfer(UINT8 channel, DMA_APB_DEVICE dev, DMA_APB_RW rw) {

    switch(dev) {
        case DMA_SPIMS0:
                if (rw == DMA_READ_APB) {
                    
                    outp32(REG_SPI0_EDMA, 0x03 | EDMA_GO);
                    outp32(REG_SPI0_CNTRL, inp32(REG_SPI0_CNTRL) |GO_BUSY);
                    
                } else if (rw == DMA_WRITE_APB) {

                    outp32(REG_SPI0_EDMA, 0x01 | EDMA_GO);
                    outp32(REG_SPI0_CNTRL, inp32(REG_SPI0_CNTRL) |GO_BUSY);
                }
            break;
    }
}

void DMA_TransferClose(UINT8 channel) {

    outp32(REG_VDMA_ISR + channel * 0x100, inp32(REG_VDMA_ISR + channel * 0x100) | (EDMASG_IF | EDMABLKD_IF | EDMATABORT_IF));
    outp32(REG_VDMA_IER + channel * 0x100, inp32(REG_VDMA_IER + channel * 0x100) & ~(SG_IEN | WAR_IE | BLKD_IE | EDMATABORT_IE));
    outp32(REG_VDMA_CSR + channel * 0x100, inp32(REG_VDMA_CSR + channel * 0x100) & ~EDMACEN);
    outp32(REG_AHBCLK,inp32(REG_AHBCLK) & ~(0x00000400 << channel));
}

void SPI_Init() {

    UINT16 loop = 500;
    
    outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS0_CKE);    // turn on SPI clk
    outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI0RST);
    outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI0RST);

    while (loop --);
    
    outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | (1 << 11));//clk idle high
    outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & (~(1 << 10)));//MSB first
    outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) &  (~(0x1f << 3)));
    outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | (8 << 3));//8 BIT
    outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & (~(1 << 2)));//tx on rising
    spiIoctl(0, SPI_SET_CLOCK, 96, 8000);
    spiTxLen(0, 0, 8);

    
}

void DMACb() {

    unsigned short val;
    UINT32 loop = 1280 * 2;
    //sysprintf("f\n");
    //count_A --;
    while(loop --);
    TPH_SpiEnd();
    TPH_SpiStart((UINT32)data, 108, 1,DMACb);
    sysPutChar('b');
    sysPutChar('\n');
    //DMA_Transfer_Init(1, (UINT32)data, REG_SPI0_TX0, 108, DMACb);
    //DMA_Transfer(1, DMA_SPIMS0, DMA_WRITE_APB);
}


void TIME_cb() {
    //sysprintf("TIME_CB\n");
}

void Test()
{    
    UINT32 loop = 1280;
    //sysPutChar('e');
    //sysprintf("e\n");
    //DMA_Transfer_Init(1, (UINT32)data, REG_SPI0_TX0, 108, DMACb);
    //DMA_Transfer(1, DMA_SPIMS0, DMA_WRITE_APB);
    while(loop --);
    TPH_SpiStart((UINT32)data, 108, 1,DMACb);
    sysPutChar('a');
    //while(loop --);
    //sysprintf("%d\n", count_A);
    //sysPutChar('0' + count_A);
    //count_A ++;
}

void t1_cb() {
    static UINT32 count = 0;
    count ++;
}

void DemoAPI_Timer0(void)
{
    //    unsigned int volatile i;
    volatile unsigned int btime, etime, tmp, tsec;
    volatile UINT32 u32TimeOut = 0;
    UINT32 u32ExtFreq;
    
    u32ExtFreq = sysGetExternalClock()*1000;
    DBG_PRINTF("Timer 0 Test...\n");    
    sysSetTimerReferenceClock(TIMER0, u32ExtFreq); //External Crystal
    sysStartTimer(TIMER0, 10000, PERIODIC_MODE);            /* 100 ticks/per sec ==> 1tick/10ms */
    tmp = sysSetTimerEvent(TIMER0, 25, (PVOID)Test);    /* 100 ticks = 1s call back */

    sysSetTimerReferenceClock(TIMER1, u32ExtFreq); //External Crystal
    sysStartTimer(TIMER1, 1000, PERIODIC_MODE);            /* 100 ticks/per sec ==> 1tick/10ms */
    tmp = sysSetTimerEvent(TIMER1, 10, (PVOID)t1_cb);    /* 100 ticks = 1s call back */


}


void DMATest(void) {

    
    UINT16 index;
    UINT32 u32ExtFreq;
    DemoAPI_Timer0();

/*    
    for (index = 0; index < 1024; index ++) {
        data[index] = 0x55;
    }
*/    
    SPI_Init();
    DMA_Init();
    
    //DMA_Channel_Init(1, DMA_SPIMS0, DMA_WRITE_APB, DMA_DIRECTION_INCREMENTED, DMA_DIRECTION_FIXED);
    //DMA_Transfer_Init(1, (UINT32)data, REG_SPI0_TX0, 108, DMACb);
    //DMA_Transfer(1, DMA_SPIMS0, DMA_WRITE_APB);

}



DMA.H  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

#ifndef __DMA_H__
#define __DMA_H__


typedef enum
{
    DMA_SPIMS0=0,
    DMA_SPIMS1,  
    DMA_UART0,      
    DMA_UART1,
    DMA_ADC,
    DMA_DIS
}DMA_APB_DEVICE;


typedef enum
{
    DMA_READ_APB=0,    
    DMA_WRITE_APB  
}DMA_APB_RW;


typedef enum
{
    DMA_DIRECTION_INCREMENTED =0,
    DMA_DIRECTION_DECREMENTED,
    DMA_DIRECTION_FIXED,
    DMA_DIRECTION_WRAPAROUND
}DMA_DIRECTION_SELECT;


typedef void (*DMA_CALLBACK)();


void DMA_Init(void);
void DMA_Channel_Init(UINT8 channel,DMA_APB_DEVICE dev, DMA_APB_RW rw, DMA_DIRECTION_SELECT srcDir, DMA_DIRECTION_SELECT desDir);
void DMA_Transfer_Init(UINT8 channel, UINT32 src, UINT32 dest, UINT32 len, DMA_CALLBACK callback);
void DMA_Transfer(UINT8 channel, DMA_APB_DEVICE dev, DMA_APB_RW rw); 
void DMA_TransferClose(UINT8 channel);
void SPI_Init(void);

#endif


DrvEDMA.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/****************************************************************
 *                                                              *
 * Copyright (c) Nuvoton Technology Corp. All rights reserved. *
 *                                                              *
 ****************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include "wblib.h"
#include "DrvEDMA.h"

static PFN_DRVEDMA_CALLBACK  g_pfnEDMACallback[MAX_CHANNEL_NUM+1][4]  = {
                                {0,0,0,0},
                                {0,0,0,0},
                                {0,0,0,0},
                                {0,0,0,0},
                                {0,0,0,0}                                                            
};                                


#define    MAX_GS_TRANSFER_SIZE    32*1024

void DrvEDMA_EnableScatterGather(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

  
void DrvEDMA_DisableScatterGather(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

UINT32  
DrvEDMA_Open(void)
{
    // 1.Check I/O pins. If I/O pins are used by other IPs, return error code.
    // 2.Enable IPˇs clock --> Enable Channel clock in DrvEDMA_SetCHOperation( ) function
    // 3.Reset IP
    // 4.Configure IP according to inputted arguments.
    // 5.Enable IP I/O pins
    // 6.Return 0 to present success
    return E_SUCCESS;    
}

void DrvEDMA_Close(void)
{
    UINT32 u32Mask;
    
    // 1.Disable IP I/O pins
    // 2.Disable IPˇs clock --> Disable Channel Clock in DrvEDMA_SetCHOperation( ) function
    u32Mask = EDMA0_CKE | EDMA1_CKE | EDMA2_CKE | EDMA3_CKE | EDMA4_CKE;
    outp32(REG_AHBCLK,inp32(REG_AHBCLK) & ~u32Mask);                    
    
}

// Get Channel Enable/Disable status
BOOL  
DrvEDMA_IsCHBusy(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT;    
    
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
    
    if (inp32(u32SFR) &  TRIG_EN)
        return TRUE;
    else
        return FALSE;    
}

// Set Channel Enable/Disable & Enable Channel Clock
void DrvEDMA_EnableCH(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_OPERATION eOP
)
{
    UINT32 u32SFR,u32Mask;    
    
    u32Mask = 0x00000400 << eChannel;
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;

    if (eOP == eDRVEDMA_DISABLE)
    {            
        outp32(u32SFR, inp32(u32SFR) & ~EDMACEN);     
        outp32(REG_AHBCLK,inp32(REG_AHBCLK) & ~u32Mask);                    // Disable Channel Clock
    }        
    else 
    {
        outp32(REG_AHBCLK,inp32(REG_AHBCLK) | u32Mask);                        // Enable Channel Clock        
        outp32(u32SFR, inp32(u32SFR) | EDMACEN);            
    }        
        
    
}


// Get Channel Enable/Disable status
BOOL  
DrvEDMA_IsEnabledCH(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT;    
    
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
    
    return inp32(u32SFR) & EDMACEN;
}

// Set Source/Destination Address and Direction and Transfer Length for Channelx
ERRCODE  
DrvEDMA_SetTransferSetting(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    S_DRVEDMA_CH_ADDR_SETTING* psSrcAddr, 
    S_DRVEDMA_CH_ADDR_SETTING* psDestAddr, 
    UINT32 u32TransferLength
)
{
    UINT32 u32SFR, u32Value; 
    
    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT;    
    
    DrvEDMA_DisableScatterGather(eChannel);
    
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
    u32Value = inp32(u32SFR);        
        
    outp32(REG_VDMA_SAR + eChannel * 0x100, psSrcAddr->u32Addr);   
    u32Value = (u32Value & ~SAD_SEL) | (psSrcAddr->eAddrDirection << SOURCE_DIRECTION_BIT);
    
    outp32(REG_VDMA_DAR + eChannel * 0x100, psDestAddr->u32Addr);
    u32Value = (u32Value & ~DAD_SEL) | (psDestAddr->eAddrDirection << DESTINATION_DIRECTION_BIT);
    outp32(u32SFR,u32Value);

    if (u32TransferLength > MAX_TRANSFER_BYTE_COUNT)
        return E_DRVEDMA_FALSE_INPUT;
        
    outp32(REG_VDMA_BCR + eChannel * 0x100,u32TransferLength);
    
    return E_SUCCESS;     
}

// Get Source/Destination Address and Direction from Channelx
ERRCODE    
DrvEDMA_GetTransferSetting(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_TARGET eTarget, 
    UINT32* pu32Addr, 
    E_DRVEDMA_DIRECTION_SELECT* peDirection
)
{
    UINT32 u32SFR, u32Value;

    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT;     
    
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
    
    if ((eTarget != eDRVEDMA_TARGET_SOURCE) && (eTarget != eDRVEDMA_TARGET_DESTINATION))
        return E_DRVEDMA_FALSE_INPUT;
    
    u32Value = inp32(u32SFR);
    
    if (eTarget == eDRVEDMA_TARGET_SOURCE)
    {
        *pu32Addr = inp32(REG_VDMA_SAR + eChannel * 0x100);
        *peDirection = (u32Value & SAD_SEL) >> SOURCE_DIRECTION_BIT;
    }
    else
    {
        *pu32Addr = inp32(REG_VDMA_DAR + eChannel * 0x100);
        *peDirection = (u32Value & DAD_SEL) >> DESTINATION_DIRECTION_BIT;        
    }
    
    return E_SUCCESS;     
}

// Get Transfer Length from Channelx
ERRCODE    
DrvEDMA_GetTransferLength(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    UINT32* pu32TransferLength
)
{
    UINT32 u32SFR;
    
    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT; 
            
    u32SFR = REG_VDMA_BCR + eChannel * 0x100;
    
    *pu32TransferLength = inp32(u32SFR);
    
    return E_SUCCESS;       
}


// Set APB Transfer Width for Channelx
ERRCODE  
DrvEDMA_SetAPBTransferWidth(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_TRANSFER_WIDTH eTransferWidth
)
{
    UINT32 u32SFR;
    
    if ((eChannel > MAX_CHANNEL_NUM) || (eChannel ==0))
        return E_DRVEDMA_FALSE_INPUT; 
            
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
    outp32(u32SFR,(inp32(u32SFR) & ~APB_TWS) | (eTransferWidth << TRANSFER_WIDTH_BIT));
        
    return E_SUCCESS;     
}

// Get Transfer Width from Channelx
ERRCODE    
DrvEDMA_GetAPBTransferWidth(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_TRANSFER_WIDTH* peTransferWidth
)
{
    UINT32 u32SFR;
    
    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT; 
            
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
    *peTransferWidth = (inp32(u32SFR) & APB_TWS) >> TRANSFER_WIDTH_BIT;    
    
    return E_SUCCESS;    
}

// Select EDMA channel for APB Device
ERRCODE  
DrvEDMA_SetCHForAPBDevice(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_APB_DEVICE eDevice,
    E_DRVEDMA_APB_RW eRWAPB    
)
{
    UINT32 u32Value,u32Mask,i,u32OrMask; 
    UINT32 u32SFR;       
    
    if ((eChannel > MAX_CHANNEL_NUM) || (eChannel ==0))
        return E_DRVEDMA_FALSE_INPUT; 
            
    if ((eRWAPB == eDRVEDMA_WRITE_APB) && (eDevice == eDRVEDMA_ADC))
        return E_DRVEDMA_FALSE_INPUT;
                
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
                    
    // Let Tx and Rx does not use the same channel             
    if (eRWAPB == eDRVEDMA_WRITE_APB)
    {
        outp32(u32SFR,(inp32(u32SFR) & ~MODE_SEL) | (eDRVEDMA_MEMORY_TO_DEVICE << MODE_SELECT_BIT));    
        u32Mask = 0x000F0000 << ((eChannel-1)*4);
        u32OrMask = 0x0007 << ((eChannel-1)*4);
    }        
    else
    {
        outp32(u32SFR,(inp32(u32SFR) & ~MODE_SEL) | (eDRVEDMA_DEVICE_TO_MEMORY << MODE_SELECT_BIT));      
        u32Mask = 0x0000000F << ((eChannel-1)*4);
        u32OrMask = 0x00070000 << ((eChannel-1)*4);        
    }        

    u32Value = inp32(REG_EDSSR) & ~u32Mask;
    
    if ((eDevice == eDRVEDMA_SPIMS0) || (eDevice == eDRVEDMA_SPIMS1))
        u32Value &= ~u32OrMask;    
    else
        u32Value |= u32OrMask;

    // let Tx or Rx does not use two channel concurrently    
    if (eRWAPB == eDRVEDMA_WRITE_APB)
    {
        u32Mask = 0x070000;
           for(i=1;i<=4;i++)
           {
               if (i != eChannel)
               {
                   if (((u32Value & u32Mask)>>((i-1)*4+16)) == eDevice)
                   {
                       u32Value |= u32Mask;
                       
                       if ((eDevice == eDRVEDMA_SPIMS0) || (eDevice == eDRVEDMA_SPIMS1))
                           u32Value |=  0x07 << ((i-1)*4);                       
                }                       
            }                   
               u32Mask <<= 4;    
        }        
        

           u32Value |=  eDevice << ((eChannel-1)*4 + 16);
           
           // TX and RX use same channel for SPIM0 & 1 
           if ((eDevice == eDRVEDMA_SPIMS0) || (eDevice == eDRVEDMA_SPIMS1))
               u32Value |=  eDevice << ((eChannel-1)*4);
    }
    else
    {
        u32Mask = 0x07;
           for(i=1;i<=4;i++)
           {
               if (i != eChannel)
               {
                  if (((u32Value & u32Mask)>>(i-1)*4) == eDevice)
                  {
                       u32Value |= u32Mask;
                       
                       if ((eDevice == eDRVEDMA_SPIMS0) || (eDevice == eDRVEDMA_SPIMS1))
                           u32Value |=  0x070000 << ((i-1)*4);                             
                }                           
               }    
               u32Mask <<= 4;    
        }  
            
        u32Value |=  eDevice << ((eChannel-1)*4);    
        
        // TX and RX use same channel for SPIM0 & 1 
           if ((eDevice == eDRVEDMA_SPIMS0) || (eDevice == eDRVEDMA_SPIMS1))
               u32Value |=  eDevice << ((eChannel-1)*4+16);        
    }

    outp32(REG_EDSSR,u32Value);
        
    return E_SUCCESS;     
}

// Get EDMA channel for APB Device
E_DRVEDMA_CHANNEL_INDEX  
DrvEDMA_GetCHForAPBDevice(
    E_DRVEDMA_APB_DEVICE eDevice,
    E_DRVEDMA_APB_RW eRWAPB    
)
{
    UINT32 u32Value,i;
    
    if ((eDevice < eDRVEDMA_SPIMS0) || (eDevice > eDRVEDMA_ADC))
        return E_DRVEDMA_FALSE_INPUT;
        
    if (eRWAPB == eDRVEDMA_WRITE_APB)
    {
        u32Value = inp32(REG_EDSSR)>>16;
    }
    else
    {
        u32Value = inp32(REG_EDSSR);
    }
    
       for(i=1;i<=4;i++)
       {
           if (((u32Value >> (i-1)*4) & 0x07) == eDevice)
               return i;
    }     
    
       return 0;  
}

// Set Wrap Around Transfer Byte count interrupt Select for Channelx
ERRCODE  
DrvEDMA_SetWrapIntType(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_WRAPAROUND_SELECT eType
)
{
    UINT32 u32SFR;
    
    if ((eChannel > MAX_CHANNEL_NUM) || (eChannel == 0))
        return E_DRVEDMA_FALSE_INPUT;
            
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
    
    if (eType > 0x0F)  
        return E_DRVEDMA_FALSE_INPUT;    
        
    outp32(u32SFR,(inp32(u32SFR) & ~WAR_BCR_SEL) | (eType<<12));    
    
    return E_SUCCESS;  
}

// Get Wrap Around Transfer Byte count interrupt Select from Channelx
E_DRVEDMA_WRAPAROUND_SELECT  
DrvEDMA_GetWrapIntType(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    if ((eChannel > MAX_CHANNEL_NUM) || (eChannel == 0))
        return E_DRVEDMA_FALSE_INPUT;
            
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;  
    
    return (inp32(u32SFR) & WAR_BCR_SEL )>> 12;  
}

// Software reset Channelx
ERRCODE  
DrvEDMA_CHSoftwareReset(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT;
            
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;  
    
    outp32(u32SFR, inp32(u32SFR) | SW_RST);  
    
    return E_SUCCESS;     
}

// Enable EDMA data read or write Transfer
ERRCODE  
DrvEDMA_CHEnablelTransfer(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT;
            
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;  
    
    outp32(u32SFR, inp32(u32SFR) | TRIG_EN | EDMACEN);  
    
    return E_SUCCESS;      
}

// Get Current Source Address from Channelx
UINT32  
DrvEDMA_GetCurrentSourceAddr(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_CSAR + eChannel * 0x100;   
    
    return inp32(u32SFR);      
}

// Get Current Destination Address from Channelx
UINT32  
DrvEDMA_GetCurrentDestAddr(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_CDAR + eChannel * 0x100;   
    
    return inp32(u32SFR);      
}

// Get Current Transfer Count from Channelx
UINT32  
DrvEDMA_GetCurrentTransferCount(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_CBCR + eChannel * 0x100;   
    
    return inp32(u32SFR);   
}

// Enable Interrupt for Channelx
ERRCODE  
DrvEDMA_EnableInt(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_ENABLE eIntSource
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_IER + eChannel * 0x100;        
    
    if ((eIntSource <1) || (eIntSource >15)) 
        return E_DRVEDMA_FALSE_INPUT;

    outp32(u32SFR, inp32(u32SFR) | eIntSource);  
    
    return E_SUCCESS;      
}

// Disable Interrupt for Channelx
void DrvEDMA_DisableInt(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_ENABLE eIntSource
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_IER + eChannel * 0x100;        
    
    outp32(u32SFR, inp32(u32SFR) & ~eIntSource);  
              
}

// Check if the specified interrupt source is enabled in Channelx
UINT32  
DrvEDMA_IsIntEnabled(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_INT_ENABLE eIntSource    
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_ISR + eChannel * 0x100;    
    
    switch(eIntSource)
    {
        case eDRVEDMA_TABORT:
            return inp32(u32SFR) & EDMATABORT_IE;         
            break;
        case eDRVEDMA_BLKD:
            return inp32(u32SFR) & BLKD_IE;         
            break;
        case eDRVEDMA_WAR:
            return inp32(u32SFR) & WAR_IE;         
            break;
        case eDRVEDMA_SG:
            return inp32(u32SFR) & SG_IEN;         
            break;            
        default :
            return E_DRVEDMA_FALSE_INPUT;                    
    }    
}

// Clear Interrupt Status for Channelx
void DrvEDMA_ClearInt(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_FLAG eIntFlag
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_ISR + eChannel * 0x100;    
    
    outp32(u32SFR, eIntFlag);
}

BOOL
DrvEDMA_PollInt(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_FLAG eIntFlag
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_ISR + eChannel * 0x100;    
    
    return inp32(u32SFR) & eIntFlag;
}

// Set Color Format Transform for Channel0
ERRCODE  
DrvEDMA_SetColorTransformFormat(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_COLOR_FORMAT eSourceFormat,
    E_DRVEDMA_COLOR_FORMAT eDestFormat
)
{ 
    UINT32 u32SFR;

     if ((eChannel > MAX_CHANNEL_NUM) || (eChannel == 1) || (eChannel == 2) || (eChannel == 3) || (eChannel == 4))
            return E_DRVEDMA_FALSE_INPUT;
    
        u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
    
    outp32(u32SFR, (inp32(u32SFR) & ~(SOUR_FORMAT | DEST_FORMAT)) | eSourceFormat<<24 | eDestFormat<<16);
    return E_SUCCESS;  
}

// Get Color Format Transform from Channel0
void DrvEDMA_GetColorTransformFormat(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_COLOR_FORMAT* peSourceFormat,
    E_DRVEDMA_COLOR_FORMAT* peDestFormat
)
{
    UINT32 u32SFR;     
    
        u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
        
    *peSourceFormat = (inp32(u32SFR) & SOUR_FORMAT) >> 24;
    *peDestFormat = (inp32(u32SFR) & DEST_FORMAT) >> 16;    
}

ERRCODE  
DrvEDMA_SetColorTransformOperation(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_OPERATION eColorSpaceTran,
    E_DRVEDMA_OPERATION eStrideMode
)
{ 
    UINT32 u32SFR;

     if ((eChannel > MAX_CHANNEL_NUM) || (eChannel == 1) || (eChannel == 2) || (eChannel == 3) || (eChannel == 4))
            return E_DRVEDMA_FALSE_INPUT;
    
        u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
        
    outp32(u32SFR, (inp32(u32SFR) & ~(COL_TRA_EN | STRIDE_EN)) | eColorSpaceTran<<1 | eStrideMode);
    return E_SUCCESS;  
}

void DrvEDMA_GetColorTransformOperation(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_OPERATION* peColorSpaceTran,
    E_DRVEDMA_OPERATION* peStrideMode
)
{ 
    UINT32 u32SFR;     
    
        u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
    
    *peColorSpaceTran = (inp32(u32SFR) & COL_TRA_EN) >> 1;
    *peStrideMode = inp32(u32SFR) & STRIDE_EN ;    
}

// Set Source Stride Transfer Byte Count & Offset Byte Length
// Only Channel0 support this function
ERRCODE  
DrvEDMA_SetSourceStride(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32 u32StrideByteCount,
    UINT32 u32OffsetByteLength
)
{
    UINT32 u32SFR;

     if ((eChannel > MAX_CHANNEL_NUM) || (eChannel == 1) || (eChannel == 2) || (eChannel == 3) || (eChannel == 4))
            return E_DRVEDMA_FALSE_INPUT;
    
        u32SFR = REG_VDMA_SASOCR + eChannel * 0x100;
    
    outp32(u32SFR,(u32StrideByteCount<<16) |u32OffsetByteLength);   
    
    return E_SUCCESS;     
}

// Get Source/Destination Stride Transfer Byte Count & Offset Byte Length
void DrvEDMA_GetSourceStride(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32* pu32StrideByteCount,
    UINT32* pu32OffsetByteLength
)
{
    UINT32 u32SFR;    
    
        u32SFR = REG_VDMA_SASOCR + eChannel * 0x100;
     
    *pu32StrideByteCount = (inp32(u32SFR) & STBC) >> 16;   
    *pu32OffsetByteLength = (inp32(u32SFR) & SASTOBL);     
}

// Set Destination Stride Transfer Byte Count & Offset Byte Length
// Only Channel0 support this function
ERRCODE  
DrvEDMA_SetDestinationStrideOffset(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32 u32OffsetByteLength
)
{
    UINT32 u32SFR;

     if ((eChannel > MAX_CHANNEL_NUM) || (eChannel == 1) || (eChannel == 2) || (eChannel == 3) || (eChannel == 4))
            return E_DRVEDMA_FALSE_INPUT;
    
        u32SFR = REG_VDMA_DASOCR + eChannel * 0x100;
    
    outp32(u32SFR,u32OffsetByteLength & DASTOBL);   
    
    return E_SUCCESS;     
}

// Get Destination Stride Offset Byte Length
void DrvEDMA_GetDestinationStrideOffset(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32* pu32OffsetByteLength
)
{
     UINT32 u32SFR;    
    
        u32SFR = REG_VDMA_DASOCR + eChannel * 0x100;
        
    *pu32OffsetByteLength = (inp32(u32SFR) & DASTOBL);     
}

// Set Channel0 Clamping function 
ERRCODE
DrvEDMA_SetClamping(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_OPERATION eOP
)
{
    UINT32 u32SFR;

     if ((eChannel > MAX_CHANNEL_NUM) || (eChannel == 1) || (eChannel == 2) || (eChannel == 3) || (eChannel == 4))
            return E_DRVEDMA_FALSE_INPUT;
    
        u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
    
    if (eOP == eDRVEDMA_DISABLE)
        outp32(u32SFR, inp32(u32SFR) & ~CLAMPING_EN);     
    else 
        outp32(u32SFR, inp32(u32SFR) | CLAMPING_EN);      

    return E_SUCCESS; 
}

// Get Channel0 Clamping status
E_DRVEDMA_OPERATION  
DrvEDMA_GetClamping(
E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;     
    
        u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
        
    return (inp32(u32SFR) & CLAMPING_EN) >> 7;
}

// Get Channel 1 ~ 4 Internal Buffer Pointer
UINT32  
DrvEDMA_GetInternalBufPointer(
    E_DRVEDMA_CHANNEL_INDEX eChannel
)
{
    UINT32 u32SFR;
    
    //if ((eChannel > MAX_CHANNEL_NUM) || (eChannel == 0))
    //    return E_DRVEDMA_FALSE_INPUT;    
    
    u32SFR = REG_PDMA_POINT1 + (eChannel-1) * 0x100; 
    
    return (inp32(u32SFR) & PDMA_POINT);
}

// Get Shared Buffer Content from Channelx
UINT32  
DrvEDMA_GetSharedBufData(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    UINT32 u32BufIndex
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_EDMA_SBUF0_C0 + eChannel * 0x100 + u32BufIndex * 4;
    
    return inp32(u32SFR);
    
    
}

// EDMA ISR
void DrvEDMA_ISR(void)
{
    UINT32 u32IntStatus;
    UINT32 u32WraparoundStatus;
    
    if (inp32(REG_VDMA_ISR) & BIT31)
    {
        if (inp32(REG_VDMA_ISR) & INTR0)
        {
            u32IntStatus = inp32(REG_VDMA_ISR) & inp32(REG_VDMA_IER);
            if (u32IntStatus & EDMATABORT_IF)
            {
                outp32(REG_VDMA_ISR,EDMATABORT_IF);
                if (g_pfnEDMACallback[0][0] != 0)
                    (*g_pfnEDMACallback[0][0])(0);                
            }                
            else 
            {
                if (u32IntStatus & EDMABLKD_IF)
                {
                    outp32(REG_VDMA_ISR,EDMABLKD_IF);
                    if (g_pfnEDMACallback[0][1] != 0)
                        (*g_pfnEDMACallback[0][1])(0);                                        
                }
                else if (u32IntStatus & EDMASG_IF)
                {
                outp32(REG_VDMA_ISR,EDMASG_IF);
                    if (g_pfnEDMACallback[0][3] != 0)
                        (*g_pfnEDMACallback[0][3])(0);                                        
                }
                                    
            }
        }
        else if (inp32(REG_VDMA_ISR) & INTR1)
        {
            if (inp32(REG_PDMA_IER1) & WAR_IE)
                u32IntStatus = inp32(REG_PDMA_ISR1) & (inp32(REG_PDMA_IER1) | 0x0F00);
            else
                u32IntStatus = inp32(REG_PDMA_ISR1) & inp32(REG_PDMA_IER1);            
            
            if (u32IntStatus & EDMATABORT_IF)
            {
                outp32(REG_PDMA_ISR1,EDMATABORT_IF);
                if (g_pfnEDMACallback[1][0] != 0)            
                    (*g_pfnEDMACallback[1][0])(0);                
            }                
            else
            {
                if (u32IntStatus & EDMABLKD_IF)
                {
                    outp32(REG_PDMA_ISR1,EDMABLKD_IF);    
                    if (g_pfnEDMACallback[1][1] != 0)                
                        (*g_pfnEDMACallback[1][1])(0);                                    
                }       
                else if (u32IntStatus & EDMASG_IF)
                {
                    outp32(REG_PDMA_ISR1,EDMASG_IF);
                    if (g_pfnEDMACallback[1][3] != 0)
                        (*g_pfnEDMACallback[1][3])(0);                                    
                }                             
                else
                {
                    u32WraparoundStatus = inp32(REG_PDMA_ISR1) & 0x0F00;
                    if (u32WraparoundStatus)
                    {
                        if (u32WraparoundStatus & 0x0200)
                            u32WraparoundStatus = 0x0200;
                        else if (u32WraparoundStatus & 0x0400)
                            u32WraparoundStatus = 0x0400;
                        else  if (u32WraparoundStatus & 0x0800)
                            u32WraparoundStatus = 0x0800;
                        else           
                            u32WraparoundStatus = 0x0100;     

                    outp32(REG_PDMA_ISR1,u32WraparoundStatus);                
                        if (g_pfnEDMACallback[1][2] != 0)                                    
                            (*g_pfnEDMACallback[1][2])(u32WraparoundStatus); 
                                                               
                    }
                }                    
            }        
        }
        else if (inp32(REG_VDMA_ISR) & INTR2)
        {
            if (inp32(REG_PDMA_IER2) & WAR_IE)
                u32IntStatus = inp32(REG_PDMA_ISR2) & (inp32(REG_PDMA_IER2) | 0x0F00);
            else
                u32IntStatus = inp32(REG_PDMA_ISR2) & inp32(REG_PDMA_IER2);            
            
            if (u32IntStatus & EDMATABORT_IF)
            {
                outp32(REG_PDMA_ISR2,EDMATABORT_IF);
                if (g_pfnEDMACallback[2][0] != 0)            
                    (*g_pfnEDMACallback[2][0])(0);                
            }                
            else 
            {
                if (u32IntStatus & EDMABLKD_IF)
                {
                    outp32(REG_PDMA_ISR2,EDMABLKD_IF);
                    if (g_pfnEDMACallback[2][1] != 0)                
                        (*g_pfnEDMACallback[2][1])(0);                                        
                }    
                else if (u32IntStatus & EDMASG_IF)
                {
                    outp32(REG_PDMA_ISR2,EDMASG_IF);
                    if (g_pfnEDMACallback[2][3] != 0)
                        (*g_pfnEDMACallback[2][3])(0);                                    
                }                                    
                else
                {
                    u32WraparoundStatus = inp32(REG_PDMA_ISR2) & 0x0F00;
                    if (u32WraparoundStatus)
                    {
                        if (u32WraparoundStatus & 0x0200)
                            u32WraparoundStatus = 0x0200;
                        else if (u32WraparoundStatus & 0x0400)
                            u32WraparoundStatus = 0x0400;
                        else  if (u32WraparoundStatus & 0x0800)
                            u32WraparoundStatus = 0x0800;
                        else           
                            u32WraparoundStatus = 0x0100;     

                    outp32(REG_PDMA_ISR2,u32WraparoundStatus);        
                        if (g_pfnEDMACallback[2][2] != 0)                                    
                            (*g_pfnEDMACallback[2][2])(u32WraparoundStatus);                                                                
                    }
                }                    
            }         
        }
        else if (inp32(REG_VDMA_ISR) & INTR3)
        {
            if (inp32(REG_PDMA_IER3) & WAR_IE)
                u32IntStatus = inp32(REG_PDMA_ISR3) & (inp32(REG_PDMA_IER3) | 0x0F00);
            else
                u32IntStatus = inp32(REG_PDMA_ISR3) & inp32(REG_PDMA_IER3);            
            
            if (u32IntStatus & EDMATABORT_IF)
            {
                outp32(REG_PDMA_ISR3,EDMATABORT_IF);
                if (g_pfnEDMACallback[3][0] != 0)            
                    (*g_pfnEDMACallback[3][0])(0);                
            }                
            else 
            {
                if (u32IntStatus & EDMABLKD_IF)
                {
                    outp32(REG_PDMA_ISR3,EDMABLKD_IF);
                    if (g_pfnEDMACallback[3][1] != 0)                
                        (*g_pfnEDMACallback[3][1])(0);                                        
                }        
                else if (u32IntStatus & EDMASG_IF)
                {
                    outp32(REG_PDMA_ISR3,EDMASG_IF);
                    if (g_pfnEDMACallback[3][3] != 0)
                        (*g_pfnEDMACallback[3][3])(0);                                    
                }                        
                else
                {
                    u32WraparoundStatus = inp32(REG_PDMA_ISR3) & 0x0F00;
                    if (u32WraparoundStatus)
                    {
                        if (u32WraparoundStatus & 0x0200)
                            u32WraparoundStatus = 0x0200;
                        else if (u32WraparoundStatus & 0x0400)
                            u32WraparoundStatus = 0x0400;
                        else  if (u32WraparoundStatus & 0x0800)
                            u32WraparoundStatus = 0x0800;
                        else           
                            u32WraparoundStatus = 0x0100;     

                    outp32(REG_PDMA_ISR3,u32WraparoundStatus);                
                        if (g_pfnEDMACallback[3][2] != 0)                                    
                            (*g_pfnEDMACallback[3][2])(u32WraparoundStatus);                                                                
                    }
                }                    
            }         
        }
        else 
        {
            if (inp32(REG_PDMA_IER4) & WAR_IE)
                u32IntStatus = inp32(REG_PDMA_ISR4) & (inp32(REG_PDMA_IER4) | 0x0F00);
            else
                u32IntStatus = inp32(REG_PDMA_ISR4) & inp32(REG_PDMA_IER4);            
            
            if (u32IntStatus & EDMATABORT_IF)
            {
                outp32(REG_PDMA_ISR4,EDMATABORT_IF);
                if (g_pfnEDMACallback[4][0] != 0)            
                    (*g_pfnEDMACallback[4][0])(0);                
            }                
            else 
            {
                if (u32IntStatus & EDMABLKD_IF)
                {
                    outp32(REG_PDMA_ISR4,EDMABLKD_IF);
                    if (g_pfnEDMACallback[4][1] != 0)                
                        (*g_pfnEDMACallback[4][1])(0);                                        
                }    
                else if (u32IntStatus & EDMASG_IF)
                {
                    outp32(REG_PDMA_ISR4,EDMASG_IF);
                    if (g_pfnEDMACallback[4][3] != 0)
                        (*g_pfnEDMACallback[4][3])(0);                                    
                }                        
                else
                {
                    u32WraparoundStatus = inp32(REG_PDMA_ISR4) & 0x0F00;
                    if (u32WraparoundStatus)
                    {
                        if (u32WraparoundStatus & 0x0200)
                            u32WraparoundStatus = 0x0200;
                        else if (u32WraparoundStatus & 0x0400)
                            u32WraparoundStatus = 0x0400;
                        else  if (u32WraparoundStatus & 0x0800)
                            u32WraparoundStatus = 0x0800;
                        else           
                            u32WraparoundStatus = 0x0100;     

                    outp32(REG_PDMA_ISR4,u32WraparoundStatus);                
                        if (g_pfnEDMACallback[4][2] != 0)                                    
                            (*g_pfnEDMACallback[4][2])(u32WraparoundStatus);                                                                
                    }
                }                    
            }         
        }        
    }
}
void DrvEDMA_Spi(PFN_DRVEDMA_CALLBACK irq1)
{
    g_pfnEDMACallback[1][1] = irq1;
    sysInstallISR(IRQ_LEVEL_2, IRQ_EDMA, (PVOID)DrvEDMA_ISR);
}
// Install Call Back Function for Channelx & Interrupt source
ERRCODE  
DrvEDMA_InstallCallBack(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_ENABLE eIntSource,
    PFN_DRVEDMA_CALLBACK pfncallback,    
    PFN_DRVEDMA_CALLBACK *pfnOldcallback      
)
{
    UINT32 u32SFR, index;
    
    u32SFR = REG_VDMA_IER + eChannel * 0x100;        
    
    if (eChannel > MAX_CHANNEL_NUM)
        return E_DRVEDMA_FALSE_INPUT;
            
    if ((eIntSource !=1) && (eIntSource !=2) && (eIntSource !=4) && (eIntSource !=8)) 
        return E_DRVEDMA_FALSE_INPUT;
/*    
    if (*pfnOldcallback != 0)
        *pfnOldcallback = g_pfnEDMACallback[eChannel][eIntSource>>1];
    ///g_pfnEDMACallback[eChannel][eIntSource>>1] = pfncallback;
    for(i=0; i<4; i++)
    {
        if((eIntSource>>i) & 0x01)
            g_pfnEDMACallback[eChannel][i] = pfncallback;
    }
*/    
    for (index=0; index<4; index++)
        if ((1<<index) == eIntSource)
            break;
    if (pfnOldcallback != NULL)
        *pfnOldcallback = g_pfnEDMACallback[eChannel][index];
    g_pfnEDMACallback[eChannel][index] = pfncallback;
    sysInstallISR(IRQ_LEVEL_1, IRQ_EDMA, (PVOID)DrvEDMA_ISR);
    sysSetInterruptType(IRQ_EDMA, HIGH_LEVEL_SENSITIVE);
    sysEnableInterrupt(IRQ_EDMA);    
        
    return E_SUCCESS;      
}

// Get Information about Scatter Gather Descript Table size and Max Transfer Size per Descript Table  
void DrvEDMA_GetScatterGatherInfo(
    UINT32 *pu32TblSize,
    UINT32 *pu32MaxTransferBytePerTbl
)
{
    *pu32TblSize = sizeof(S_DRVEDMA_DESCRIPT_FORMAT);
    *pu32MaxTransferBytePerTbl = MAX_GS_TRANSFER_SIZE;
    
    return;
}

// Set Scatter Gather Descript Format Table Start Address
void DrvEDMA_SetScatterGatherTblStartAddr(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    UINT32    u32TblStartAddr
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_SGAR + eChannel * 0x100;    
    outp32(u32SFR, u32TblStartAddr);
}    

// Enable Scatter Gather Function  
void DrvEDMA_EnableScatterGather(
    E_DRVEDMA_CHANNEL_INDEX eChannel 
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;    
    outp32(u32SFR, inp32(u32SFR)| EDMASG_EN);
}

// Disable Scatter Gather Function
void DrvEDMA_DisableScatterGather(
    E_DRVEDMA_CHANNEL_INDEX eChannel 
)
{
    UINT32 u32SFR;
    
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;    
    outp32(u32SFR, inp32(u32SFR) & ~EDMASG_EN);
}

// Set Descript Format for Scatter Gather
// This function only support Order =0 
ERRCODE 
DrvEDMA_SetScatterGatherSetting(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32 u32SGTblStartAddr,
    S_DRVEDMA_DESCRIPT_SETTING* psDescript
)
{
    UINT32 u32SFR, u32Value;     
    S_DRVEDMA_DESCRIPT_FORMAT *psSGFmt;
    UINT32 u32TranferByte=0;
    UINT32 u32TotalByteCount;
    UINT32 u32NewSrcAddr, u32NewDestAddr, u32AddSrcAddr, u32AddDestAddr;    
    E_DRVEDMA_COLOR_FORMAT eSrcFormat, eDestFormat;
    UINT32 u32MaxTxfBytePerTbl;    
    
    if ((int)psDescript->u32TransferByteCount <=0)
        return E_DRVEDMA_FALSE_INPUT;
    
    u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
        
    eSrcFormat = (inp32(u32SFR) & SOUR_FORMAT) >> 24;
    eDestFormat = (inp32(u32SFR) & DEST_FORMAT) >> 16;            
        
    u32SFR = REG_VDMA_CSR + eChannel * 0x100;
    u32Value = inp32(u32SFR);         
    u32Value = (u32Value & ~SAD_SEL) | (psDescript->eSrcDirection << SOURCE_DIRECTION_BIT);    
    u32Value = (u32Value & ~DAD_SEL) | (psDescript->eDestDirection << DESTINATION_DIRECTION_BIT);
    outp32(u32SFR,u32Value); 
            
    DrvEDMA_EnableScatterGather(eChannel);
    DrvEDMA_SetScatterGatherTblStartAddr(eChannel, u32SGTblStartAddr);
    psSGFmt = (S_DRVEDMA_DESCRIPT_FORMAT *)u32SGTblStartAddr;
    u32TotalByteCount = psDescript->u32TransferByteCount;
    u32NewSrcAddr = psDescript->u32SourceAddr;
    u32NewDestAddr = psDescript->u32DestAddr;    
    u32AddSrcAddr=0;
    u32AddDestAddr=0;    
    
    // Update TransferByteCount for stride mode    
    u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
    
    if ((psDescript->u32Stride) && (inp32(u32SFR) & STRIDE_EN))
        u32MaxTxfBytePerTbl = MAX_GS_TRANSFER_SIZE / psDescript->u32Stride * psDescript->u32Stride;    
    else    
        u32MaxTxfBytePerTbl = MAX_GS_TRANSFER_SIZE;
    
    do {
        // Set Phsyical Source Address and Destination Address
        // Set WrapAround and Fixed Direction in Scatter Gather as Fixed Direction    
        if (psDescript->eSrcDirection == eDRVEDMA_DIRECTION_INCREMENTED)
        {
            psSGFmt->u32SourceAddr = u32NewSrcAddr + u32AddSrcAddr;
            u32NewSrcAddr += u32AddSrcAddr;
        } 
        else 
        {
            if (psDescript->eSrcDirection == eDRVEDMA_DIRECTION_DECREMENTED)
            {
                psSGFmt->u32SourceAddr    = u32NewSrcAddr - u32AddSrcAddr;
                u32NewSrcAddr -= u32AddSrcAddr;                
            }  
            else    
                psSGFmt->u32SourceAddr    = u32NewSrcAddr;                
        }
        
        if (psDescript->eDestDirection == eDRVEDMA_DIRECTION_INCREMENTED)
        {
            psSGFmt->u32DestAddr = u32NewDestAddr + u32AddDestAddr;
            u32NewDestAddr += u32AddDestAddr;
        } 
        else
        {
            if (psDescript->eDestDirection == eDRVEDMA_DIRECTION_DECREMENTED)
            {
                psSGFmt->u32DestAddr = u32NewDestAddr - u32AddDestAddr; 
                 u32NewDestAddr -= u32AddDestAddr;           
            }             
            else    
                psSGFmt->u32DestAddr = u32NewDestAddr;                
        }
        
        if (u32TotalByteCount >= u32MaxTxfBytePerTbl)
        {
            u32TranferByte = u32MaxTxfBytePerTbl;
            u32TotalByteCount -= u32MaxTxfBytePerTbl;            
        }            
        else
        {
            u32TranferByte = u32TotalByteCount;      
            u32TotalByteCount = 0;      
        }      
        
        // Src/Dest format must be set before DrvEDMA_SetScatterGatterSetting() function to calcuate the next address
        u32SFR = REG_VDMA_CTCSR + eChannel * 0x100;
        if ((psDescript->u32Stride) && (inp32(u32SFR) & STRIDE_EN) && (eChannel ==0))
        {   // Calculate the next Src/Destination for Stride mode
            u32AddSrcAddr = (u32TranferByte / psDescript->u32Stride) * (psDescript->u32SrcOffset + psDescript->u32Stride) + 
                            u32TranferByte % psDescript->u32Stride;

            if (eSrcFormat == eDRVEDMA_RGB888)
            {
                if (eDestFormat== eDRVEDMA_RGB888)
                    u32AddDestAddr = (u32TranferByte / psDescript->u32Stride) * (psDescript->u32DestOffset + psDescript->u32Stride) + 
                            u32TranferByte % psDescript->u32Stride;    
                else    
                    u32AddDestAddr = (u32TranferByte / psDescript->u32Stride) * (psDescript->u32DestOffset + psDescript->u32Stride/2) + 
                            u32TranferByte % psDescript->u32Stride/2;
            }
            else
            {
                if (eDestFormat== eDRVEDMA_RGB888)
                    u32AddDestAddr = (u32TranferByte / psDescript->u32Stride) * (psDescript->u32DestOffset + psDescript->u32Stride*2) + 
                            u32TranferByte % psDescript->u32Stride*2;
                else    
                    u32AddDestAddr = (u32TranferByte / psDescript->u32Stride) * (psDescript->u32DestOffset + psDescript->u32Stride) + 
                            u32TranferByte % psDescript->u32Stride;            
            }
              
        }
        else
        {   // Calculate the next Src/Destination for non-Stride mode
            u32AddSrcAddr = u32TranferByte;
            
            if (eChannel ==0)
            {
                if (eSrcFormat == eDRVEDMA_RGB888)
                {
                    if (eDestFormat== eDRVEDMA_RGB888)
                        u32AddDestAddr = u32TranferByte;
                    else    
                        u32AddDestAddr = u32TranferByte/2;
                }
                else
                {
                    if (eDestFormat== eDRVEDMA_RGB888)
                        u32AddDestAddr = u32TranferByte*2;
                    else    
                        u32AddDestAddr =u32TranferByte;        
                }
            }
            else
            {
                u32AddDestAddr = u32TranferByte;
            }            
        }          
        
        // Set Stride Transfer Byte Count & Byte Count    
        psSGFmt->u32StrideAndByteCount   = ((psDescript->u32Stride & 0x7FFF) << 17) | u32TranferByte;
        
        // Set Source Offset Byte Length and Destination Offset Byte Length
             psSGFmt->u32Offset = ((psDescript->u32DestOffset & 0x7FFF) << 16) |
                                   (psDescript->u32SrcOffset & 0x7FFF);          
                                   
        // Set EOT for last Descript Format                                   
        if (u32TotalByteCount == 0)
            psSGFmt->u32Offset |= 0x80000000;
            
        // Set Next Scatter Gether Table Address    
        psSGFmt->u32NextSGTblAddr = (UINT32)(psSGFmt+1);     
        
        psSGFmt++;        
             
    } while(u32TotalByteCount > 0);    
    
    return E_SUCCESS;  
}


DrvEDMA.h  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/****************************************************************
 *                                                             *
 * Copyright (c) Nuvoton Technology Corp. All rights reserved. *
 *                                                              *
 ****************************************************************/
 /****************************************************************
 Total:
     
 Revision History:
     05/26/2009, first creation
 ****************************************************************/
 
#ifndef __DRVEDMA_H__
#define __DRVEDMA_H__

#include "wbio.h"
#include "w55fa93_reg.h"

#ifdef  __cplusplus
extern "C"
{
#endif

#define    E_SUCCESS    0

#define DESTINATION_DIRECTION_BIT   6
#define SOURCE_DIRECTION_BIT        4
#define TRANSFER_WIDTH_BIT          19
#define MODE_SELECT_BIT             2

#define MAX_TRANSFER_BYTE_COUNT     0x00FFFFFF
#define MAX_CHANNEL_NUM   4

#define ERRCODE               UINT32
#define     ERR_EDMA                (0xFFFF0000 | ((EDMA_BA>>16) & 0xFF00) |((EDMA_BA>>8) & 0xFF))

#define E_DRVEDMA_FALSE_INPUT          (ERR_EDMA | 00)

// For interrupt CallBack Function
typedef void (*PFN_DRVEDMA_CALLBACK)(UINT32);

/****************************************************************
    Enumerate Type
 ****************************************************************/
typedef enum
{
    eDRVEDMA_DISABLE =0,
    eDRVEDMA_ENABLE
}E_DRVEDMA_OPERATION;

typedef enum
{
    eDRVEDMA_CHANNEL_0 =0,
    eDRVEDMA_CHANNEL_1,
    eDRVEDMA_CHANNEL_2,
    eDRVEDMA_CHANNEL_3,
    eDRVEDMA_CHANNEL_4    
}E_DRVEDMA_CHANNEL_INDEX;

typedef enum
{
    eDRVEDMA_TARGET_SOURCE =0,
    eDRVEDMA_TARGET_DESTINATION
}E_DRVEDMA_TARGET;


typedef enum
{
    eDRVEDMA_WRAPAROUND_NO_INT =0,    
    eDRVEDMA_WRAPAROUND_EMPTY,                // empty
    eDRVEDMA_WRAPAROUND_THREE_FOURTHS,        // 3/4 
    eDRVEDMA_WRAPAROUND_HALF=4,             // 1/2 
    eDRVEDMA_WRAPAROUND_QUARTER=8           // 1/4 
}E_DRVEDMA_WRAPAROUND_SELECT;

typedef enum
{
    eDRVEDMA_TABORT_FLAG =1,
    eDRVEDMA_BLKD_FLAG,
    eDRVEDMA_SG_FLAG=8,    
    eDRVEDMA_WRA_EMPTY_FLAG=0x100,              // empty        
    eDRVEDMA_WRA_THREE_FOURTHS_FLAG=0x200,      // 3/4 
    eDRVEDMA_WRA_HALF_FLAG=0x400,             // 1/2 
    eDRVEDMA_WRA_QUARTER_FLAG=0x800           // 1/4 
}E_DRVEDMA_INT_FLAG;

typedef enum
{
    eDRVEDMA_DIRECTION_INCREMENTED =0,
    eDRVEDMA_DIRECTION_DECREMENTED,
    eDRVEDMA_DIRECTION_FIXED,
    eDRVEDMA_DIRECTION_WRAPAROUND
}E_DRVEDMA_DIRECTION_SELECT;

typedef enum
{
    eDRVEDMA_WIDTH_32BITS=0,    
    eDRVEDMA_WIDTH_8BITS,
    eDRVEDMA_WIDTH_16BITS
}E_DRVEDMA_TRANSFER_WIDTH;

typedef enum
{
    eDRVEDMA_TABORT =1,
    eDRVEDMA_BLKD,
    eDRVEDMA_WAR=4,            
    eDRVEDMA_SG=8        
}E_DRVEDMA_INT_ENABLE;

typedef enum
{
    eDRVEDMA_RGB888=1,    
    eDRVEDMA_RGB555=2,  
    eDRVEDMA_RGB565=4,      
    eDRVEDMA_YCbCr422=8
}E_DRVEDMA_COLOR_FORMAT;

typedef enum
{
    eDRVEDMA_SPIMS0=0,    
    eDRVEDMA_SPIMS1,  
    eDRVEDMA_UART0,      
    eDRVEDMA_UART1,
    eDRVEDMA_ADC
}E_DRVEDMA_APB_DEVICE;

typedef enum
{
    eDRVEDMA_READ_APB=0,    
    eDRVEDMA_WRITE_APB  
}E_DRVEDMA_APB_RW;

typedef enum
{
    eDRVEDMA_MEMORY_TO_MEMORY =0,
    eDRVEDMA_DEVICE_TO_MEMORY,
    eDRVEDMA_MEMORY_TO_DEVICE
}E_DRVEDMA_MODE_SELECT;

typedef struct {
    UINT32 u32Addr;
    E_DRVEDMA_DIRECTION_SELECT eAddrDirection;
}S_DRVEDMA_CH_ADDR_SETTING;

typedef struct {
    UINT32 u32SourceAddr;
    E_DRVEDMA_DIRECTION_SELECT eSrcDirection;    
    UINT32 u32DestAddr;
    E_DRVEDMA_DIRECTION_SELECT eDestDirection;     
    UINT32 u32TransferByteCount;
    UINT32 u32Stride;
    UINT32 u32SrcOffset;
    UINT32 u32DestOffset;    
}S_DRVEDMA_DESCRIPT_SETTING;

typedef struct {
    UINT32 u32SourceAddr;
    UINT32 u32DestAddr;
    UINT32 u32StrideAndByteCount;
    UINT32 u32Offset;
    UINT32 u32NextSGTblAddr;
}S_DRVEDMA_DESCRIPT_FORMAT;

/****************************************************************
// APIs declaration
 ****************************************************************/
UINT32  
DrvEDMA_Open(void);

void DrvEDMA_Close(void);

BOOL  
DrvEDMA_IsCHBusy(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

void DrvEDMA_EnableCH(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_OPERATION eOP
);

BOOL  
DrvEDMA_IsEnabledCH(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

ERRCODE  
DrvEDMA_SetTransferSetting(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    S_DRVEDMA_CH_ADDR_SETTING* psSrcAddr, 
    S_DRVEDMA_CH_ADDR_SETTING* psDestAddr, 
    UINT32 u32TransferLength
);

ERRCODE  
DrvEDMA_GetTransferSetting(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_TARGET eTarget, 
    UINT32* pu32Addr, 
    E_DRVEDMA_DIRECTION_SELECT* peDirection
);

ERRCODE  
DrvEDMA_GetTransferLength(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    UINT32* pu32TransferLength
);

ERRCODE  
DrvEDMA_SetAPBTransferWidth(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_TRANSFER_WIDTH eTransferWidth
);

ERRCODE  
DrvEDMA_GetAPBTransferWidth(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_TRANSFER_WIDTH* peTransferWidth
);

ERRCODE  
DrvEDMA_SetCHForAPBDevice(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_APB_DEVICE eDevice,
    E_DRVEDMA_APB_RW eRWAPB    
);

E_DRVEDMA_CHANNEL_INDEX  
DrvEDMA_GetCHForAPBDevice(
    E_DRVEDMA_APB_DEVICE eDevice,
    E_DRVEDMA_APB_RW eRWAPB    
);

ERRCODE  
DrvEDMA_SetWrapIntType(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_WRAPAROUND_SELECT eType
);

E_DRVEDMA_WRAPAROUND_SELECT  
DrvEDMA_GetWrapIntType(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

ERRCODE  
DrvEDMA_CHSoftwareReset(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

ERRCODE  
DrvEDMA_CHEnablelTransfer(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

UINT32  
DrvEDMA_GetCurrentSourceAddr(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

UINT32  
DrvEDMA_GetCurrentDestAddr(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

UINT32  
DrvEDMA_GetCurrentTransferCount(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

ERRCODE  
DrvEDMA_EnableInt(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_ENABLE eIntSource
);

void DrvEDMA_DisableInt(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_ENABLE eIntSource
);

UINT32  
DrvEDMA_IsIntEnabled(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_INT_ENABLE eIntSource    
);

void DrvEDMA_ClearInt(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_FLAG eIntFlag
);

BOOL
DrvEDMA_PollInt(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_FLAG eIntFlag
);

ERRCODE  
DrvEDMA_SetColorTransformFormat(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_COLOR_FORMAT u32SourceFormat,
    E_DRVEDMA_COLOR_FORMAT u32DestFormat
);

void DrvEDMA_GetColorTransformFormat(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_COLOR_FORMAT* pu32SourceFormat,
    E_DRVEDMA_COLOR_FORMAT* pu32DestFormat
);


ERRCODE  
DrvEDMA_SetColorTransformOperation(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_OPERATION eColorSpaceTran,
    E_DRVEDMA_OPERATION eStrideMode
);

void DrvEDMA_GetColorTransformOperation(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_OPERATION* peColorSpaceTran,
    E_DRVEDMA_OPERATION* peStrideMode
);

ERRCODE  
DrvEDMA_SetSourceStride(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32 u32StrideByteCount,
    UINT32 u32OffsetByteLength
);

void DrvEDMA_GetSourceStride(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32* pu32StrideByteCount,
    UINT32* pu32OffsetByteLength
);

ERRCODE  
DrvEDMA_SetDestinationStrideOffset(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32 u32OffsetByteLength
);

void DrvEDMA_GetDestinationStrideOffset(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32* pu32OffsetByteLength
);

ERRCODE
DrvEDMA_SetClamping(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    E_DRVEDMA_OPERATION eOP
);

E_DRVEDMA_OPERATION  
DrvEDMA_GetClamping(
E_DRVEDMA_CHANNEL_INDEX eChannel
);

UINT32  
DrvEDMA_GetInternalBufPointer(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

UINT32  
DrvEDMA_GetSharedBufData(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    UINT32 u32BufIndex
);

ERRCODE  
DrvEDMA_InstallCallBack(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    E_DRVEDMA_INT_ENABLE eIntSource,
    PFN_DRVEDMA_CALLBACK pfncallback,    
    PFN_DRVEDMA_CALLBACK *pfnOldcallback      
);

void DrvEDMA_GetScatterGatherInfo(
    UINT32 *pu32TblSize,
    UINT32 *pu32MaxTransferBytePerTbl
);
  
ERRCODE 
DrvEDMA_SetScatterGatherSetting(
    E_DRVEDMA_CHANNEL_INDEX eChannel,
    UINT32 u32SGTblStartAddr,
    S_DRVEDMA_DESCRIPT_SETTING* psDescript
);

void DrvEDMA_EnableScatterGather(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

  
void DrvEDMA_DisableScatterGather(
    E_DRVEDMA_CHANNEL_INDEX eChannel
);

void DrvEDMA_SetScatterGatherTblStartAddr(
    E_DRVEDMA_CHANNEL_INDEX eChannel, 
    UINT32    u32TblStartAddr
);

UINT32  
DrvEDMA_GetVersion(void);


#ifdef  __cplusplus
}
#endif

#endif    // __DRVEDMA_H__



fmi.c   。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential                                       */
/*                                                                                   */
/* Copyright (c) 2008 by Nuvoton Technology Corporation                              */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
#ifdef ECOS
    #include "drv_api.h"
    #include "diag.h"
    #include "Common.h"
    #include "wbio.h"
    #define IRQ_SD   16
#else
    #define IRQ_SD  IRQ_SIC
    #include "wblib.h"
#endif

#include "w55fa93_reg.h"
#include "w55fa93_sic.h"

#include "fmi.h"
//#include "nvtfat.h"

#ifdef ECOS
cyg_interrupt  /* dmac_interrupt, */ fmi_interrupt;
cyg_handle_t   /* dmac_interrupt_handle, */ fmi_interrupt_handle;
#endif


// global variable
//UINT32 _fmi_uFMIReferenceClock;
BOOL volatile _fmi_bIsSDDataReady=FALSE, _fmi_bIsSMDataReady=FALSE;

typedef void (*fmi_pvFunPtr)();   /* function pointer */
void (*fmiSD0RemoveFun)() = NULL;
void (*fmiSD0InsertFun)() = NULL;

extern PDISK_T *pDisk_SD0;
extern PDISK_T *pDisk_SD1;
extern PDISK_T *pDisk_SD2;

#ifdef _SIC_USE_INT_
#ifdef ECOS
static cyg_uint32 fmiIntHandler(cyg_vector_t vector, cyg_addrword_t data)
#else
VOID fmiIntHandler()
#endif
{
    unsigned int volatile isr;

    // FMI data abort interrupt
    if (inpw(REG_FMIISR) & FMI_DAT_IF)
    {
        /* fmiResetAllEngine() */
        outpw(REG_FMICR, inpw(REG_FMICR) | FMI_SWRST);
        outpw(REG_FMIISR, FMI_DAT_IF);
    }

    // SD interrupt status
    isr = inpw(REG_SDISR);
    if (isr & SDISR_BLKD_IF)        // block down
    {
        _fmi_bIsSDDataReady = TRUE;
        outpw(REG_SDISR, SDISR_BLKD_IF);
    }

    if (isr & SDISR_CD_IF)    // port 0 card detect
    {
        if (inpw(REG_SDISR) & SDISR_CD_Card)
        {
            pSD0->bIsCardInsert = FALSE;
            if (fmiSD0RemoveFun != NULL)
                (*fmiSD0RemoveFun)(pDisk_SD0);
        }
        else
        {
            pSD0->bIsCardInsert = TRUE;
            if (fmiSD0InsertFun != NULL)
                (*fmiSD0InsertFun)();
        }
        outpw(REG_SDISR, SDISR_CD_IF);
    }

    // SM interrupt status
    isr = inpw(REG_SMISR);
    if (isr & SMISR_DMA_IF)
    {
        _fmi_bIsSMDataReady = TRUE;
        outpw(REG_SMISR, SMISR_DMA_IF);
    }

#ifdef ECOS
    cyg_drv_interrupt_acknowledge(IRQ_SD);
    return CYG_ISR_HANDLED;
#endif
}
#endif    //_SIC_USE_INT_

VOID fmiSetCallBack(UINT32 uCard, PVOID pvRemove, PVOID pvInsert)
{
    switch (uCard)
    {
        case FMI_SD_CARD:
            fmiSD0RemoveFun = (fmi_pvFunPtr)pvRemove;
            fmiSD0InsertFun = (fmi_pvFunPtr)pvInsert;
            break;
    }
}


VOID fmiInitDevice()
{
    // Enable SD Card Host Controller operation and driving clock.
    outpw(REG_AHBCLK, inpw(REG_AHBCLK) | HCLK3_CKE | SIC_CKE | SD_CKE | NAND_CKE);

#ifdef _SIC_USE_INT_
    /* Install ISR */
#ifdef ECOS
    cyg_drv_interrupt_create(IRQ_SD, 10, 0, fmiIntHandler, NULL,
                                &fmi_interrupt_handle, &fmi_interrupt);
    cyg_drv_interrupt_attach(fmi_interrupt_handle);
#else
    sysInstallISR(IRQ_LEVEL_1, IRQ_SD, (PVOID)fmiIntHandler);
#endif

#ifndef ECOS
    /* enable CPSR I bit */
    sysSetLocalInterrupt(ENABLE_IRQ);
#endif
#endif    //_SIC_USE_INT_

    // DMAC Initial
    outpw(REG_DMACCSR, DMAC_SWRST | DMAC_EN);
    outpw(REG_DMACCSR, DMAC_EN);

#ifdef _SIC_USE_INT_
#ifdef ECOS
    cyg_drv_interrupt_unmask(IRQ_SD);
#else
    sysEnableInterrupt(IRQ_SD);
#endif
#endif    //_SIC_USE_INT_

    outpw(REG_FMICR, FMI_SWRST);        // reset FMI engine
    while(inpw(REG_FMICR)&FMI_SWRST);
}

VOID fmiSetFMIReferenceClock(UINT32 uClock)
{
    _fmi_uFMIReferenceClock = uClock;    // kHz
}




fmi.h  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。



#ifndef _FMI_H
#define _FMI_H

#include <stdio.h>
#include "wbio.h"

// define DATE FMI_DATE_CODE and show it when running to make maintaining easy.
#define FMI_DATE_CODE   "20161207"

//#define _SIC_USE_INT_
//#define DEBUG
#define TIMER0  0

#define printf    sysprintf

//#define _USE_DAT3_DETECT_

//-- function return value
#define    Successful  0
#define    Fail        1

//--- define type of SD card or MMC
#define FMI_TYPE_UNKNOWN                0
#define FMI_TYPE_SD_HIGH                1
#define FMI_TYPE_SD_LOW                 2
#define FMI_TYPE_MMC                    3   // MMC access mode: Byte mode for capacity <= 2GB
#define FMI_TYPE_MMC_SECTOR_MODE        4   // MMC access mode: Sector mode for capacity > 2GB

#ifdef ECOS
#define sysGetTicks(TIMER0)  cyg_current_time()
//#define printf    diag_printf
#endif

// extern global variables
extern UINT32 _fmi_uFMIReferenceClock;
extern BOOL volatile _fmi_bIsSDDataReady;

#define STOR_STRING_LEN 32

/* we allocate one of these for every device that we remember */
typedef struct disk_data_t
{
    struct disk_data_t  *next;           /* next device */

    /* information about the device -- always good */
    unsigned int  totalSectorN;
    unsigned int  diskSize;         /* disk size in Kbytes */
    int           sectorSize;
    char          vendor[STOR_STRING_LEN];
    char          product[STOR_STRING_LEN];
    char          serial[STOR_STRING_LEN];
} DISK_DATA_T;


// function declaration

// SD functions
INT  fmiSDCommand(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg);
INT  fmiSDCmdAndRsp(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg, INT nCount);
INT  fmiSDCmdAndRsp2(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg, UINT *puR2ptr);
INT  fmiSDCmdAndRspDataIn(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg);
INT  fmiSD_Init(FMI_SD_INFO_T *pSD);
INT  fmiSelectCard(FMI_SD_INFO_T *pSD);
VOID fmiGet_SD_info(FMI_SD_INFO_T *pSD, DISK_DATA_T *_info);
INT  fmiSD_Read_in(FMI_SD_INFO_T *pSD, UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr);
INT  fmiSD_Write_in(FMI_SD_INFO_T *pSD, UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr);
INT  fmiSD_CardStatus(void);

#endif  // end of _FMI_H


hwsetup.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

//*----------------------------------------------------------------------------
//*         ATMEL Microcontroller Software Support  -  ROUSSET  -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name           : HwSetup.c
//* Object              : Low level initialisations written in C
//* Creation            : FB   23/10/2002
//* Modify              : SBb  10/06/2005
//*
//*----------------------------------------------------------------------------

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define HWSETUP_C

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <string.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "Common.h"
#include "XCore.h"

/******************************************************************************
 *                                                                            *
 *                         L O C A L   D E F I N E S                          *
 *                                                                            *
 ******************************************************************************/


/******************************************************************************
 *                                                                            *
 *                        L O C A L   T Y P E D E F S                         *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *             L O C A L   F U N C T I O N   P R O T O T Y P E S              *
 *                                                                            *
 ******************************************************************************/


/******************************************************************************
 *                                                                            *
 *    L O C A L   I N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *    L O C A L   U N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

//*----------------------------------------------------------------------------
//* \fn    EnableMainOscillator
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
VOID EnableMainOscillator(VOID)
{


}

//*----------------------------------------------------------------------------
//* \fn    WaitForMainClockFrequency
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
BOOL WaitForMainClockFrequency(VOID)
{

    return TRUE;
}

//*----------------------------------------------------------------------------
//* \fn    InitClocks
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
VOID InitClocks(VOID)
{
    
}


VOID InitPIO(VOID)
{
    outpw(REG_GPDFUN , inpw(REG_GPDFUN) &~ (0xFF0003FF));
    outpw(REG_GPDFUN , inpw(REG_GPDFUN)|(0xFF000000));
    
    
    //RF_RST
    gpio_configure(GPIO_PORTB,5);//B5
    gpio_setportdir(GPIO_PORTB, BIT5, BIT5);//Êä³ö
    gpio_setportval(GPIO_PORTB, BIT5, BIT5);//Êä³ö0


    //³õʼ»¯´òÓ¡Í·Òý½Å
    outpw(REG_GPBFUN , inpw(REG_GPBFUN) &(~BIT19) | BIT18); //B9 spi_clk---TPH_CLK
    outpw(REG_GPBFUN , inpw(REG_GPBFUN) &(~BIT25) | BIT24); //B12 spi_do---TPH_DAT
    outpw(REG_GPBFUN , inpw(REG_GPBFUN) &(~BIT21) | BIT20); //B10 cs0    
    gpio_setportdir(GPIO_PORTB, BIT9|BIT10|BIT12, BIT9|BIT10|BIT12);//Êä³ö
    gpio_setportval(GPIO_PORTB, BIT9|BIT10|BIT12, BIT9|BIT10|BIT12);//Êä³ö1
#if 1
    //FLASH SPI 
    outpw(REG_GPDFUN , inpw(REG_GPDFUN) | BIT25 | BIT24); //D12 spi_clk
    outpw(REG_GPDFUN , inpw(REG_GPDFUN) | BIT31 | BIT30); //D15 spi_do
    outpw(REG_GPDFUN , inpw(REG_GPDFUN) | BIT27 | BIT26);//D13 cs0    
    gpio_setportdir(GPIO_PORTD, BIT12|BIT13|BIT15, BIT12|BIT13|BIT15);//Êä³ö
    gpio_setportval(GPIO_PORTD, BIT12|BIT13|BIT15, BIT12|BIT13|BIT15);//Êä³ö1
#endif
        
    //Ëø´æÒý½Å
    gpio_configure(GPIO_PORTB,10); //B10---TPH_LTACH
    gpio_setportdir(GPIO_PORTB, BIT10, BIT10);//Êä³ö
    gpio_setportval(GPIO_PORTB, BIT10, BIT10);//Êä³ö1
    
    //TPH_POWER
    gpio_configure(GPIO_PORTB,11);//B11
    gpio_setportdir(GPIO_PORTB, BIT11, BIT11);
    gpio_setportval(GPIO_PORTB, BIT11, 0);
    

    //STB2 
    gpio_configure(GPIO_PORTB,7);//B7 
    gpio_setportdir(GPIO_PORTB, BIT7, BIT7);
    gpio_setportval(GPIO_PORTB, BIT7, BIT7);
    gpio_setportpull(GPIO_PORTB, BIT7, BIT7);

    //STB1
    gpio_configure(GPIO_PORTB,8);//B8 
    gpio_setportdir(GPIO_PORTB, BIT8, BIT8);
    gpio_setportval(GPIO_PORTB, BIT8, BIT8);
    gpio_setportpull(GPIO_PORTB, BIT8, BIT8);


    //adc sw IO
    gpio_configure(GPIO_PORTA,5); //A5_ADC_SW01
    gpio_configure(GPIO_PORTA,6); //A6_ADC_SW02
    gpio_setportdir(GPIO_PORTA, BIT5|BIT6, BIT5|BIT6);//OUT PUT
    gpio_setportval(GPIO_PORTA, BIT5|BIT6, 0);//OUT 0

    //cutter
    gpio_configure(GPIO_PORTE,1); //CUT_EN-->E1
    gpio_configure(GPIO_PORTE,0); //CUT_PH-->E0
    gpio_setportdir(GPIO_PORTE, BIT1|BIT0, BIT1|BIT0);
    
    gpio_configure(GPIO_PORTC,15);//CUT_SENSOR --> C15
    gpio_setportdir(GPIO_PORTC, BIT15, 0);

    //set sensor intension control IO
    gpio_configure(GPIO_PORTD,8);//GAP0 --> D8
    gpio_setportdir(GPIO_PORTD, BIT8, BIT8);

    gpio_configure(GPIO_PORTD,7);//GAP1 --> D7
    gpio_setportdir(GPIO_PORTD, BIT7, BIT7);


    gpio_configure(GPIO_PORTE,11);//GAP2 --> E11
    gpio_setportdir(GPIO_PORTE, BIT11, BIT11);
    
    gpio_configure(GPIO_PORTE,10);//GAP4 --> E10
    gpio_setportdir(GPIO_PORTE, BIT10, BIT10);

    gpio_configure(GPIO_PORTD,5);//BLINE0 --> D5
    gpio_setportdir(GPIO_PORTD, BIT5, BIT5);

    gpio_configure(GPIO_PORTD,6);//BLINE1 --> D6
    gpio_setportdir(GPIO_PORTD, BIT6, BIT6);


    //KEY 
    gpio_configure(GPIO_PORTC,12);// KEY_1 -> C12
    gpio_setportdir(GPIO_PORTC, BIT12, 0); // input

//    gpio_configure(GPIO_PORTC,11);// KEY_2 ->C11 // ch_20220120
//    gpio_setportdir(GPIO_PORTC, BIT11, 0); // input // ch_20220120

//    gpio_configure(GPIO_PORTC,10);// KEY_3 ->C10
//    gpio_setportdir(GPIO_PORTC, BIT10, 0); // input
    
//    gpio_configure(GPIO_PORTC,9);// KEY_4 ->C9
//    gpio_setportdir(GPIO_PORTC, BIT9, 0); // input    

//    gpio_configure(GPIO_PORTC,8);// KEY_5 ->C8 // ch_20220120
//    gpio_setportdir(GPIO_PORTC, BIT8, 0); // input // ch_20220120    


    //led
    gpio_configure(GPIO_PORTC,13); // LED_GREEN -> C13
    gpio_setportdir(GPIO_PORTC, BIT13, 0/*BIT13*/); // ch_20211221
    gpio_configure(GPIO_PORTC,14); //LED_RED -> C14
    gpio_setportdir(GPIO_PORTC, BIT14, 0/*BIT14*/); // ch_20211221


    //Carriage
    gpio_configure(GPIO_PORTE,8);// HEAD -> E8
    gpio_setportdir(GPIO_PORTE, BIT8, 0);
    gpio_setportpull(GPIO_PORTE, BIT8, BIT8);


    //setp motor
#if ORIGIN_STEP_MOTOR_DRIVE
    gpio_configure(GPIO_PORTA,2);//PH1 -> A2
    gpio_setportdir(GPIO_PORTA,BIT2, BIT2);
    gpio_setportpull(GPIO_PORTA, BIT2, BIT2); // ch_20220127
    gpio_setportval(GPIO_PORTA,BIT2,BIT2);

    gpio_configure(GPIO_PORTA,4);//PH2 -> A4
    gpio_setportdir(GPIO_PORTA,BIT4,BIT4);
    gpio_setportpull(GPIO_PORTA, BIT4, BIT4); // ch_20220127
    gpio_setportval(GPIO_PORTA,BIT4,BIT4);
#endif

    gpio_configure(GPIO_PORTA,3);//MD_EN -> A3
    gpio_setportdir(GPIO_PORTA,BIT3,BIT3);
    gpio_setportval(GPIO_PORTA,BIT3,0);

#if NEW_STEP_MOTOR_DRIVE
    // ch_20220120
//    gpio_configure(GPIO_PORTC, 7);
//    gpio_configure(GPIO_PORTC, 8);
//    gpio_setportdir(GPIO_PORTC, BIT8|BIT7, BIT8|BIT7); // drive Step motor.
//    gpio_setportpull(GPIO_PORTC, BIT8, BIT8); // ch_20220127
//    gpio_setportval(GPIO_PORTC, BIT7, 0);
//    gpio_setportval(GPIO_PORTC, BIT8, BIT8);
//    gpio_configure(GPIO_PORTC, 10);
//    gpio_configure(GPIO_PORTC, 11);
//    gpio_setportdir(GPIO_PORTC, BIT11|BIT10, BIT11|BIT10); // drive Step motor.
//    gpio_setportpull(GPIO_PORTC, BIT11, BIT11); // ch_20220127
//    gpio_setportval(GPIO_PORTC, BIT10, 0);
//    gpio_setportval(GPIO_PORTC, BIT11, BIT11);    
    gpio_configure(GPIO_PORTC, 0); // ch_20220130
    gpio_configure(GPIO_PORTC, 3); // ch_20220130
    gpio_configure(GPIO_PORTC, 6);
    gpio_configure(GPIO_PORTC, 8);
    gpio_configure(GPIO_PORTC, 9);
    gpio_configure(GPIO_PORTC, 11);
    gpio_setportdir(GPIO_PORTC, BIT11|BIT9|BIT8|BIT6|BIT3|BIT0, BIT11|BIT9|BIT8|BIT6|BIT3|BIT0); // drive Step motor.    
#if FULL_STEP_FULL_CURRENT
    gpio_setportpull(GPIO_PORTC, BIT11|BIT8, BIT11|BIT8); // ch_20220127
    gpio_setportval(GPIO_PORTC, BIT11|BIT8, BIT11|BIT8);
    gpio_setportval(GPIO_PORTC, BIT9|BIT6|BIT3|BIT0, ~(BIT9|BIT6|BIT3|BIT0));
#elif HALF_STEP_FULL_CURRENT
    gpio_setportpull(GPIO_PORTC, BIT11|BIT9|BIT8|BIT6, BIT11|BIT9|BIT8|BIT6); // ch_20220127
    gpio_setportval(GPIO_PORTC, BIT11|BIT9|BIT8|BIT6, BIT11|BIT9|BIT8|BIT6);
    gpio_setportval(GPIO_PORTC, BIT3|BIT0, ~(BIT3|BIT0));
#elif HALF_STEP_PART_CURRENT
    gpio_setportpull(GPIO_PORTC, BIT11|BIT9|BIT8|BIT6|BIT3|BIT0, BIT11|BIT9|BIT8|BIT6|BIT3|BIT0); // ch_20220127
    gpio_setportval(GPIO_PORTC, BIT11|BIT9|BIT8|BIT6|BIT3|BIT0, BIT11|BIT9|BIT8|BIT6|BIT3|BIT0);
#endif    

#endif

    //DC motor
    gpio_configure(GPIO_PORTA,0);//DC_MOTOR_PHASE -> A0
    gpio_setportdir(GPIO_PORTA,BIT0,BIT0);
    gpio_setportval(GPIO_PORTA,BIT0,0); 
    
    gpio_configure(GPIO_PORTD,0);//DC_MOTOR_PWM -> D0
    gpio_setportdir(GPIO_PORTD,BIT0,BIT0);
    gpio_setportval(GPIO_PORTD,BIT0,0); 

    gpio_configure(GPIO_PORTE,9);//RIBBON_SENSER --> E9
    gpio_setportdir(GPIO_PORTE, BIT9, 0);


    //PEEL
    gpio_configure(GPIO_PORTB,4);//PEEL_EN -> B4
    gpio_setportdir(GPIO_PORTB, BIT4, BIT4);
    gpio_setportpull(GPIO_PORTB, BIT4, BIT4);    

    gpio_configure(GPIO_PORTB,3);//PEEL_SW -> B4
    gpio_setportdir(GPIO_PORTB, BIT3, BIT3);
    gpio_setportpull(GPIO_PORTB, BIT3, BIT3);    

    //power down
    gpio_configure(GPIO_PORTB,2);//power down -> B2
    gpio_setportdir(GPIO_PORTB, BIT2, 0);
    gpio_setportpull(GPIO_PORTB, BIT2, 0);


    //I2C_SDA
    gpio_configure(GPIO_PORTB,14);//B14
    gpio_setportdir(GPIO_PORTB, BIT14, BIT14);
    gpio_setportval(GPIO_PORTB, BIT14, BIT14);
    gpio_setportpull(GPIO_PORTB, BIT14, BIT14);

    //I2C_SCL
    gpio_configure(GPIO_PORTB,13);//B13
    gpio_setportdir(GPIO_PORTB, BIT13, BIT13);
    gpio_setportval(GPIO_PORTB, BIT13, BIT13);
    gpio_setportpull(GPIO_PORTB, BIT13, BIT13);

    //SD DET
    gpio_configure(GPIO_PORTA,1);//A1
    gpio_setportdir(GPIO_PORTA, BIT1, 0);

    //HUART
    outpw(REG_GPDFUN, inpw(REG_GPDFUN) & (~BIT3)| BIT2);// HUR_TX-> D1
    outpw(REG_GPDFUN, inpw(REG_GPDFUN) & (~BIT5)| BIT4);// HUR_RX-> D2
    
    //gpio_configure(GPIO_PORTA,7);// HUR_RTS-> A7    
    //gpio_setportdir(GPIO_PORTA, BIT7, BIT7);// RTS->OUT PUT
    
    //gpio_configure(GPIO_PORTD,4);// HUR_CTS-> D3    
    //gpio_setportdir(GPIO_PORTD, BIT4, 0);// CTS->IN PUT

    //UART
    outpw(REG_GPAFUN, inpw(REG_GPAFUN) | BIT21 | BIT20);//UART_TX -> A10
    outpw(REG_GPAFUN, inpw(REG_GPAFUN) | BIT23 | BIT22);//UART_RX -> A11    
    
    //gpio_configure(GPIO_PORTB,5);// UART_RTS-> B5 
    //gpio_setportdir(GPIO_PORTB, BIT5, BIT5);// RTS->OUT PUT

    //gpio_configure(GPIO_PORTB,6);// UART_CTS-> B6 
    //gpio_setportdir(GPIO_PORTB, BIT6, 0);// CTS->IN PUT    
}                                                                   

//*----------------------------------------------------------------------------
//* \fn    LowLevelInit
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
INT __low_level_init(VOID)
{
       InitPIO();

    /*==================================*/
    /* Choose if segment initialization */
    /* should be done or not.           */
    /* Return: 0 to omit seg_init       */
    /*         1 to run seg_init        */
    /*==================================*/
    return (1);
}

    

hwsetup.h  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

//*----------------------------------------------------------------------------
//*         ATMEL Microcontroller Software Support  -  ROUSSET  -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name           : init.h
//* Object              : Low level initialisations written in C
//* Create              : SBb   10/06/2005
//*
//*----------------------------------------------------------------------------

#ifndef HWSETUP_H

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define HWSETUP_H

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#ifdef __cplusplus
extern "C" {            /* Assume C declarations for C++ */
#endif    /* __cplusplus */

/******************************************************************************
 *                                                                            *
 *                        G L O B A L   D E F I N E S                         *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *                 S T R U C T U R E   D E F I N I T I O N S                  *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *    G L O B A L   V A R I A B L E S   -   N O   I N I T I A L I Z E R S     *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *       G L O B A L   V A R I A B L E S   -   I N I T I A L I Z E R S        *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *                   F U N C T I O N   P R O T O T Y P E S                    *
 *                                                                            *
 ******************************************************************************/

#ifdef __cplusplus
}                       /* End of extern "C" { */
#endif    /* __cplusplus */

#endif    



libadc.c   。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/****************************************************************************
*                                                                           *
* Copyright (c) 2009 Nuvoton Tech. Corp. All rights reserved.               *
*                                                                           *
*****************************************************************************/

/****************************************************************************
* FILENAME
*   libadc.c
*
* VERSION
*   1.0
*
* DESCRIPTION
*   ADC touch screen library source file
*
* DATA STRUCTURES
*   None
*
* FUNCTIONS
*
* HISTORY
*
* REMARK
*   None
****************************************************************************/
#include "W55fa93_adc.h"

#include "W55fa93_reg.h"

/* Verbose debug information */
#define DBG_PRINTF(...)        //sysprintf 

#define SORT_FIFO            6    

/* Define the operation state machine */
#define E_ADC_UNINIT    0
#define E_ADC_INIT        1
#define E_ADC_OPEN    2

#define ADC_STATE_WT        0  // waiting for trigger mode
#define ADC_STATE_AUTO    1  // auto

static unsigned char _opened = E_ADC_UNINIT;
// These two will always store the latest sampled value
static unsigned short  _hr, _vr;
static unsigned char volatile _state;
static INT32 i32_x=0, i32_y=0;

typedef enum{ 
    eADC_BAND_P0P5 = 0,                                             
    eADC_BAND_P0P75
}E_ADC_UPBAND;
    
typedef enum{ 
    eADC_BAND_N0P5 = 0,                                             
    eADC_BAND_N0P75
}E_ADC_DOWNBAND;   

typedef enum{ 
    eADC_PRE_P0 = 0,                                             
    eADC_PRE_P8,
    eADC_PRE_P14,
    eADC_PRE_P20
}E_ADC_PREGAIN;  

typedef enum{ 
    eADC_NG_N30 = 0,                                             
    eADC_NG_N36,
    eADC_NG_N42,
    eADC_NG_N48
}E_ADC_NOISEGATE;  

typedef enum{ 
    eADC_POST_N12 = 0,                                             
    eADC_POST_N11P25,
    eADC_POST_N10P5,
    eADC_POST_N9P75,
    eADC_POST_N9,
    eADC_POST_N8P25,
    eADC_POST_N7P5,    
    eADC_POST_N6P75,
    eADC_POST_N6,
    eADC_POST_N5P25,
    eADC_POST_N4P5,
    eADC_POST_N3P75,
    eADC_POST_N3,
    eADC_POST_N2P25,
    eADC_POST_N1P5,
    eADC_POST_N0P75,
    
    eADC_POST_P0,
    eADC_POST_P0P75,
    eADC_POST_P1P5,
    eADC_POST_P2P25,
    eADC_POST_P3,
    eADC_POST_P3P75,
    eADC_POST_P4P5,
    eADC_POST_P5P25,
    eADC_POST_P6,
    eADC_POST_P6P75,
    eADC_POST_P7P5,
    eADC_POST_P8P25,
    eADC_POST_P9,
    eADC_POST_P9P75,
    eADC_POST_P10P5,
    eADC_POST_P11P25,
    
    eADC_POST_P12,
    eADC_POST_P12P75,
    eADC_POST_P13P5,
    eADC_POST_P14P25,
    eADC_POST_P15,
    eADC_POST_P15P75,
    eADC_POST_P16P5,
    eADC_POST_P17P25,
    eADC_POST_P18,
    eADC_POST_P18P75,
    eADC_POST_P19P5,
    eADC_POST_P20P25,
    eADC_POST_P21,
    eADC_POST_P21P75,
    eADC_POST_P22P5,
    eADC_POST_P23P25,
    
    eADC_POST_P24,
    eADC_POST_P24P75,
    eADC_POST_P25P5,
    eADC_POST_P26P25,
    eADC_POST_P27,
    eADC_POST_P27P75,
    eADC_POST_P28P5,
    eADC_POST_P29P25,
    eADC_POST_P30,
    eADC_POST_P30P75,
    eADC_POST_P31P5,
    eADC_POST_P32P25,
    eADC_POST_P33,
    eADC_POST_P33P75,
    eADC_POST_P34P5,
    eADC_POST_P35P25
}E_ADC_POSTGAIN;

typedef enum{                            
    eADC_TSCREEN_4WIRE = 0,               
    eADC_TSCREEN_5WIRE,     /* FA93 reserved for the item*/
    eADC_TSCREEN_8WIRE,    /* FA93 reserved for the item*/
    eADC_TSCREEN_UNUSED   /* FA93 reserved for the item*/                                                  
}E_ADC_TSC_TYPE; 

typedef void (*PFN_ADC_CALLBACK)(VOID);    
static PFN_ADC_CALLBACK g_psADCCallBack[4]={0, 0, 0, 0};


static __inline VOID DrvADC_PollingADC(VOID)
{
    while( (inp32(REG_ADC_CON) & ADC_INT) != ADC_INT);    /* Wait until ADC INT */ 
     outp32(REG_ADC_CON, (inp32(REG_ADC_CON) &       /* Clean the ADC interrupt */         
                                ~(WT_INT | LVD_INT)) |  
                                (WT_INT |ADC_INT));
}
static __inline VOID DrvADC_PollingWT(VOID)
{
    while( (inp32(REG_ADC_CON) & WT_INT) != WT_INT);    /* Wait until ADC INT */ 
    outp32(REG_ADC_CON, (inp32(REG_ADC_CON) &    /* Clean the touch panel interrupt */    
                                    ~WT_INT) );
    outp32(REG_ADC_CON, (inp32(REG_ADC_CON) &    /* Clean the touch panel interrupt */    
                                ~(LVD_INT | ADC_INT)) |  
                                (WT_INT |ADC_INT));
}
static __inline BOOL DrvADC_IsPenDown(VOID)
{
    if ( (inp32(REG_ADC_TSC) & ADC_UD) == ADC_UD)
        return TRUE;    //Pen down;
    else
        return FALSE;    //Pen up;        
}
/* =============================== sorting =============================== */
void swap(UINT16 *x,UINT16 *y) 
{   
    UINT16 temp; 
    temp = *x; 
    *x = *y; 
    *y = temp; 
} 
UINT16 choose_pivot(UINT16 i,UINT16 j ) 
{ 
    return((i+j) /2); 
} 
void quicksort(UINT16 list[],int m,int n) 
{    
    int key,i,j,k; 
    if( m < n) 
    { 
        k = choose_pivot(m,n); 
        swap(&list[m],&list[k]); 
        key = list[m]; 
        i = m+1; 
        j = n; 
        while(i <= j) 
        { 
            while((i <= n) && (list[i] <= key)) 
                i++; 
            while((j >= m) && (list[j] > key))                 
                j--; 
            if( i < j) 
                swap(&list[i],&list[j]); 
        } 
        // swap two elements 
        swap(&list[m],&list[j]); 
        // recursively sort the lesser list 
        quicksort(list,m,j-1); 
        quicksort(list,j+1,n);
    } 
} 

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* FUNCTION                                                                                                */
/*         DrvADC_EnableInt()                                                                                         */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*         enable ADC interrupt and setup callback function                                                    */
/*                                                                                                         */
/* INPUTS                                                                                                  */
/*      callback                                                                                           */
/*          The callback funciton                                                                          */
/*                                                                                                         */
/*      u32UserData                                                                                        */
/*          The user's data to pass to the callback function                                               */
/*                                                                                                         */
/* OUTPUTS                                                                                                 */
/*      none                                                                                                */
/*                                                                                                         */
/* RETURN                                                                                                  */
/*      none                                                                                               */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
UINT32  
adc_enableInt(
    E_ADC_INT eIntType
    )
{
    /* Enable adc interrupt */
#ifdef USING_INT    
    switch(eIntType)
    {
        case eADC_ADC_INT: 
             outp32(REG_ADC_CON, inp32(REG_ADC_CON) | ADC_INT_EN);                                                     
            break; 
           case eADC_AUD_INT:
               outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) | AUDIO_INT_EN);     
               break;
        case eADC_LVD_INT:
            outp32(REG_ADC_CON, inp32(REG_ADC_CON) | LVD_INT_EN);     
            break;
        case eADC_WT_INT:     
            outp32(REG_ADC_CON, inp32(REG_ADC_CON) | WT_INT_EN);     
            break;    
        default:
            return -1;
    }            
#endif    
    return Successful;
}

UINT32 adc_disableInt(E_ADC_INT eIntType)
{
    /* Enable adc interrupt */
    switch(eIntType)
    {
            case eADC_ADC_INT:
                outp32(REG_ADC_CON, inp32(REG_ADC_CON) & ~ADC_INT_EN);                                          
                break; 
           case eADC_AUD_INT:
               outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) & ~AUDIO_INT_EN);     
               break;
        case eADC_LVD_INT:
            outp32(REG_ADC_CON, inp32(REG_ADC_CON) & ~LVD_INT_EN);    
            break;
        case eADC_WT_INT:
            outp32(REG_ADC_CON, inp32(REG_ADC_CON) & ~WT_INT_EN);     
            break;    
        default:
            return -1;//E_DRVADC_INVALID_INT;
    }            
    return Successful;
}

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* FUNCTION                                                                                                */
/*         DrvADC_SetTouchScreen()                                                                                 */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*         Set the parameter for TSC                                                                           */
/*                                                                                                         */
/* INPUTS                                                                                                  */
/*      eTscMode        Normal mode, Semi-Auto, Auto or Wait for trigger                                      */
/*      eTscWire         4 wire, 5 wire, 8 wire or unused                                                         */
/*      bIsPullup        Control the internal pull up PMOS in switch box                                       */
/*      bMAVFilter      Enable or disable MAV filter in TSC auto mode                                      */
/* OUTPUTS                                                                                                 */
/*      none                                                                                                */
/*                                                                                                         */
/* RETURN                                                                                                  */
/*      none                                                                                               */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
void adc_setTouchScreen(
    E_ADC_TSC_MODE eTscMode,
    UINT32 u32DleayCycle,
    BOOL bIsPullup,
    BOOL bMAVFilter    
    )
{                  
    //Change mode should reset ADC IP. otherwise, the ADC will hang-up
    outp32(REG_APBIPRST, inp32(REG_APBIPRST) | ADCRST);
    outp32(REG_APBIPRST, inp32(REG_APBIPRST) & ~ADCRST);    
    
    if(eTscMode==eADC_TSCREEN_AUTO)
        _state = ADC_STATE_AUTO;
    else if(eTscMode==eADC_TSCREEN_TRIG)
        _state = ADC_STATE_WT;
    outp32(REG_ADC_CON, inp32(REG_ADC_CON) & ~ADC_CON_ADC_EN);//打开ADC
    outp32(REG_ADC_CON, (inp32(REG_ADC_CON) & ~(ADC_TSC_MODE | ADC_MUX)) |     
                   (eTscMode << 14) );//设置模式
                                                          
    outp32(REG_ADC_DLY, u32DleayCycle);                 
    outp32(REG_ADC_TSC, (inp32(REG_ADC_TSC) & ~(ADC_TSC_TYPE | ADC_PU_EN | ADC_TSC_MAV_EN)) |     
                    ( (((eADC_TSCREEN_4WIRE << 1) & ADC_TSC_TYPE) | ((bIsPullup <<3) & ADC_PU_EN)) |
                    ((bMAVFilter<<9) & ADC_TSC_MAV_EN) ));    
    outp32(REG_ADC_CON, inp32(REG_ADC_CON) | ADC_CON_ADC_EN);                                              
}   
void DrvADC_Conversion(void)
{
    outp32(REG_ADC_CON, inp32(REG_ADC_CON) | ADC_CONV);    
}

void DrvADC_GetNormalData(PUINT16 pu16Data)
{          
    *pu16Data = inp32(REG_ADC_XDATA);                                                                                                                                                                                                                 
}

void DrvADC_GetTscData(
    PUINT16     pu16XData,
    PUINT16     pu16YData
    )
{          
    *pu16XData = inp32(REG_ADC_XDATA);
    *pu16YData = inp32(REG_ADC_YDATA);                                                                                                                                                                                                                 
}

static BOOL g_bIsADCInt =FALSE;
static BOOL g_bIsWTInt =FALSE;
static BOOL g_bIsAudioInt =FALSE;

static void adc_isr(void)
{
    UINT32 u32Reg;
    
    u32Reg = inp32(REG_ADC_CON);
    
    /* Process ADC interrupt */
    if( (u32Reg & (ADC_INT_EN | ADC_INT)) == (ADC_INT_EN | ADC_INT))
    {//ADC interrupt
    if(g_psADCCallBack[eADC_ADC_INT]!=0)
                g_psADCCallBack[eADC_ADC_INT]();   
        g_bIsADCInt = TRUE;                           
        outp32(REG_ADC_CON, (inp32(REG_ADC_CON) &       /* Clean the ADC interrupt */         
                        ~(WT_INT | LVD_INT)) |  
                        (WT_INT |ADC_INT));
        return;
    }      
    if( (u32Reg & (LVD_INT_EN | LVD_INT)) == (LVD_INT_EN | LVD_INT))
    {//LVD interrupt
        if(g_psADCCallBack[eADC_LVD_INT]!=0)
                g_psADCCallBack[eADC_LVD_INT]();           
        outp32(REG_ADC_CON, (inp32(REG_ADC_CON) &      /* Clean the LVD interrupt */
                        ~(WT_INT | ADC_INT)) |  
                        LVD_INT);    
        return;
    }  
    if( (u32Reg & (WT_INT_EN | WT_INT)) == (WT_INT_EN | WT_INT))
    {//Wait for trigger    
        /*Disable WT int  */
        if((inp32(REG_ADC_CON) & ADC_TSC_MODE)==ADC_TSC_MODE)
            adc_disableInt(eADC_WT_INT);    
                        
        if(g_psADCCallBack[eADC_WT_INT]!=0)
                g_psADCCallBack[eADC_WT_INT]();
        g_bIsWTInt = TRUE;           
        outp32(REG_ADC_CON, (inp32(REG_ADC_CON) &    /* Clean the touch panel interrupt */    
                        ~(LVD_INT | ADC_INT)) |  
                        (WT_INT |ADC_INT));
        return;
    }    
    u32Reg = inp32(REG_AUDIO_CON);
    if( (u32Reg & (AUDIO_INT_EN | AUDIO_INT)) == (AUDIO_INT_EN | AUDIO_INT))
    {//Audio record interrupt
        if(g_psADCCallBack[eADC_AUD_INT]!=0)
                g_psADCCallBack[eADC_AUD_INT]();        
        g_bIsAudioInt = TRUE;                
        outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) | AUDIO_INT);    /* Clean the record interrupt */
    }   
}


UINT32  
adc_installCallback(
    E_ADC_INT eIntType,
    PFN_ADC_CALLBACK pfnCallback,
    PFN_ADC_CALLBACK* pfnOldCallback
    )
{
    switch(eIntType)
        {
            case eADC_ADC_INT:
                *pfnOldCallback = g_psADCCallBack[eADC_ADC_INT];
                g_psADCCallBack[eADC_ADC_INT] = pfnCallback;                                           
                   break; 
           case eADC_AUD_INT:
               *pfnOldCallback = g_psADCCallBack[eADC_AUD_INT];
                g_psADCCallBack[eADC_AUD_INT] = pfnCallback;      
               break;
        case eADC_LVD_INT:
            *pfnOldCallback = g_psADCCallBack[eADC_LVD_INT];
                g_psADCCallBack[eADC_LVD_INT] = pfnCallback; 
            break;
        case eADC_WT_INT:
            *pfnOldCallback = g_psADCCallBack[eADC_WT_INT];
                g_psADCCallBack[eADC_WT_INT] = pfnCallback;  
            break;    
        default:
            return E_ADC_INVALID_INT;
    }            
    return Successful;
}

void adc_setWorkingFreq(UINT32 u32WorkingFreq)
{
    UINT32 u32WorkingKHz, u32UpllKHz, u32ApllKHz;
    UINT32 u32Div, u32Div0, u32Div1;
    UINT32 u32ADCSrc;
    
    u32WorkingKHz = sysGetExternalClock();
    u32UpllKHz = sysGetPLLOutputKhz(eSYS_UPLL, u32WorkingKHz);
    DBG_PRINTF("UPLL output clock = %dMHz\n", u32UpllKHz/1000);
    u32ApllKHz = sysGetPLLOutputKhz(eSYS_APLL, u32WorkingKHz);
    DBG_PRINTF("APLL output clock = %dMHz\n", u32ApllKHz/1000);
    
    if( (u32UpllKHz > 25000) )
    {//>25MHz. 
        u32ADCSrc = 0x18<<16;
        u32Div = u32UpllKHz/u32WorkingFreq;
        if( (u32UpllKHz%u32WorkingFreq) != 0)
            u32Div = u32Div +1;    
        u32WorkingKHz =     u32UpllKHz/u32Div;    
    }
    else if (u32ApllKHz> 25000)        
    {//>25MHz 
        u32ADCSrc = 0x10<<16;
        u32Div = u32ApllKHz/u32WorkingFreq;
        if( (u32ApllKHz%u32WorkingFreq) !=0)
            u32Div = u32Div +1;
        u32WorkingKHz =     u32ApllKHz/u32Div;    
    }
     
    /* Search for fit divider */
    for(u32Div1=1; u32Div1<256; u32Div1=u32Div1+1)
    {
        for(u32Div0=1; u32Div0<8; u32Div0=u32Div0+1)
        {//u32Div0!=0
            if((u32Div0*u32Div1)==u32Div)
                break;
        }
        if((u32Div0*u32Div1)==u32Div)
                break;
    }    
    if(u32Div0>=1)
        u32Div0 = u32Div0 -1; 
    if( u32Div1>=1)
        u32Div1 = u32Div1 -1;         
    DBG_PRINTF("Total divider = %d\n", u32Div);
    DBG_PRINTF("Div0 = %d, Div1 = %d \n", u32Div0, u32Div1);
    
    DBG_PRINTF("ADC working frequency = %d\n", u32WorkingKHz);
    outp32(REG_CLKDIV3, (inp32(REG_CLKDIV3) & ~(ADC_N1 | ADC_S | ADC_N0)) | 
                        ((u32ADCSrc) | ((u32Div0<<16) | (u32Div1<<24))) );

}

/*-----------------------------------------------------------------------------------------------------------
    Function: adc_init                                                               
    The function initialize the ADC IP.
    1. Get the PLL as system clock source.       
    2. Set the working frequency. Max frequency = 25MHz

-----------------------------------------------------------------------------------------------------------*/
void adc_init(void)
{
    //WB_CLKFREQ_T clk;
    //sysGetClockFreq(&clk);
    
    outp32(REG_APBCLK, inp32(REG_APBCLK) | ADC_CKE);    
    adc_setWorkingFreq(100*50);    
    
    outp32(REG_APBIPRST, inp32(REG_APBIPRST) | ADCRST);
    outp32(REG_APBIPRST, inp32(REG_APBIPRST) & ~ADCRST);
    outp32(REG_ADC_CON, inp32(REG_ADC_CON) | ADC_CON_ADC_EN);
    _opened = E_ADC_INIT;
}
/*-----------------------------------------------------------------------------------------------------------
    Function: adc_normalRead                                                               
    The function is use to converse the voltage(analog) to 10 bits gigital data  
    u32Channel = 2, 3, 4.

-----------------------------------------------------------------------------------------------------------*/
UINT32 adc_normalread(UINT32 u32Channel, PUINT16 pu16Data)
{
    if( (u32Channel>4)&&(u32Channel<2) )
        return E_DRVADC_INVALID_CHANNEL;
    if(_state != ADC_STATE_WT)    
        return E_DRVADC_INVALID_TIMING;
    
    adc_disableInt(eADC_WT_INT);    
    adc_setTouchScreen(eADC_TSCREEN_AUTO,            //E_DRVADC_TSC_MODE eTscMode,
                                0x150,
                                TRUE,                    //BOOL bIsPullup,
                                TRUE);
    adc_enableInt(eADC_ADC_INT);    
    
    outp32( REG_ADC_CON,( ADC_CON_ADC_EN | ADC_CONV | ADC_INT 
                        | (u32Channel<<9)) );
    DrvADC_Conversion();    
    //while( (inp32(REG_ADC_CON) & ADC_INT) != ADC_INT);    /* Wait until ADC INT */ 
    DrvADC_PollingADC();
    DrvADC_GetNormalData(pu16Data);        
    
    outp32(REG_ADC_CON, (inp32(REG_ADC_CON) & ~(ADC_TSC_MODE|ADC_MUX))|(ADC_INT | WT_INT));     
    /* set to WT mode */
    adc_setTouchScreen(eADC_TSCREEN_TRIG,                    //E_DRVADC_TSC_MODE eTscMode,
                                0x150,
                                TRUE,                        //BOOL bIsPullup,
                                TRUE);                        //BOOL bMAVFilter
    adc_enableInt(eADC_ADC_INT);                                    
    adc_enableInt(eADC_WT_INT);
    return Successful;                    
}

/*-----------------------------------------------------------------------------------------------------------
    Function: adc_open                                                               
    The function open ADC driver
    1. Set the working frequency. Max frequency = 25MHz


-----------------------------------------------------------------------------------------------------------*/
int adc_open(unsigned char type, unsigned short hr, unsigned short vr)
{

    if(_opened == 0)
        adc_init();
    if(_opened != 1)
        return(-1);
    _opened = 2;
        
    switch (type) 
    {
        
        case ADC_TS_4WIRE:    
            outp32(REG_APBCLK, inp32(REG_APBCLK) | ADC_CKE);        
        #if 0    
            adc_setTouchScreen(eADC_TSCREEN_TRIG,        //E_DRVADC_TSC_MODE eTscMode,                            
                                150,
                                TRUE,                        //BOOL bIsPullup,
                                FALSE);                        //MAV enable 
            adc_setWorkingFreq(100*50);                        //100 KHz
        #else
            adc_setTouchScreen(eADC_TSCREEN_TRIG,        //E_DRVADC_TSC_MODE eTscMode,                            
                                0x180,
                                TRUE,                        //BOOL bIsPullup,
                                FALSE);                        //MAV enable 
            
        #endif    
            break;
            return(-1);    
    }
    _hr = hr;
    outp32(REG_CLKDIV3, (inp32(REG_CLKDIV3) & ~(ADC_N1 | ADC_S | ADC_N0) ) | (1<<24));    //Come from XTAL directly 
    _vr = vr;
    sysInstallISR(IRQ_LEVEL_7, IRQ_ADC, (PVOID)adc_isr);    
    sysEnableInterrupt(IRQ_ADC);
    _opened = E_ADC_OPEN;
    return(0);
}

void adc_close(void)
{
    if(_opened != 2)
        return;
    sysDisableInterrupt(IRQ_ADC);
    
    outp32(REG_ADC_CON, inp32(REG_ADC_CON) & ~ADC_CON_ADC_EN);
    outp32(REG_APBIPRST, inp32(REG_APBIPRST) | ADCRST);
    outp32(REG_APBIPRST, inp32(REG_APBIPRST) & ~ADCRST);
    outp32(REG_APBCLK, inp32(REG_APBCLK) & ~ADC_CKE);    
    
    _opened = E_ADC_UNINIT;    
    return;
}

void printlist(UINT16 list[],int n) 
{   
    int i; 
    for(i=0;i<n;i++)        
        sysprintf("%d\t",list[i]); 
    sysprintf("\n");
} 
/*-----------------------------------------------------------------------------------------------------------
    Function adc_read.
        Get touch panel position. 
    mode: ADC_NONBLOCK or ADC_BLOCK.
    x: X position
    y: Y position 
    
    return 0: No any position.  The (x, y) is unavilable.
          1: Panel was touched. The (x, y) is avilable.  
-----------------------------------------------------------------------------------------------------------*/
int adc_read(unsigned char mode, unsigned short *x, unsigned short *y)
{
    volatile UINT32 u32Idx=0;
    
    UINT16 au16XPos[SORT_FIFO];
    UINT16 au16YPos[SORT_FIFO];
    BOOL bIsXnear, bIsYnear;
    //_state = ADC_STATE_WT;        
    if(_opened != 2)
        return(-1);        
            
    if(mode != ADC_NONBLOCK && mode != ADC_BLOCK) {
        sysDisableInterrupt(IRQ_ADC);     
        return(-1);
    }    
    /*0211 */
    outp32(REG_ADC_CON, (inp32(REG_ADC_CON) & ~ADC_TSC_MODE) | (2 << 14) ); 
    adc_disableInt(eADC_ADC_INT);    
    
    /* set to WT mode */
    adc_setTouchScreen(eADC_TSCREEN_TRIG,                    //E_DRVADC_TSC_MODE eTscMode,
                                0x180,
                                FALSE,                        //BOOL bIsPullup,
                                FALSE);                        //BOOL bMAVFilter                                                                        
    g_bIsWTInt = 0;    
    adc_enableInt(eADC_WT_INT);    
    u32Idx=0x10;
    while(u32Idx--);                
    if(mode == ADC_BLOCK)
    {    
#ifdef USING_INT    
        while(g_bIsWTInt==0);
#else        
        DrvADC_PollingWT();
#endif        
    }    
    /*0211 */      
    else
    {
#ifdef USING_INT    
        if(g_bIsWTInt==0)
#else
        if(DrvADC_IsPenDown()==FALSE)
#endif        
            return 0;    //Means pen up. 
    }
    /*0211 */  
    
    /* set to Auto mode */
    /*0211 */ 
    adc_disableInt(eADC_WT_INT);
    /*0211 */ 
    
    g_bIsADCInt = 0;
    adc_setTouchScreen(eADC_TSCREEN_AUTO,            //E_DRVADC_TSC_MODE eTscMode,
                                0x180,
                                FALSE,                    //BOOL bIsPullup,
                                FALSE);

/*0211 */      
    adc_enableInt(eADC_ADC_INT);    
/*0211 */    

    g_bIsADCInt = 0;
    DrvADC_Conversion();    
#ifdef USING_INT        
    while(g_bIsADCInt==0);                
#else
    DrvADC_PollingADC( );
#endif                                    
    
    u32Idx = 0x2000;
    while(u32Idx--);                                
    for(u32Idx = 0; u32Idx<SORT_FIFO; u32Idx=u32Idx+1)    
    {    

        g_bIsADCInt = 0;                    
        DrvADC_Conversion();    
#ifdef USING_INT                
        while(g_bIsADCInt==0);
#else
        DrvADC_PollingADC( );
#endif        
        DrvADC_GetTscData(&au16XPos[u32Idx],&au16YPos[u32Idx]);    
    }                                                                
        
    quicksort(au16XPos, 0, SORT_FIFO-1); 
        quicksort(au16YPos, 0, SORT_FIFO-1); 
          
    *x = (au16XPos[SORT_FIFO-4]+au16XPos[SORT_FIFO-3]+au16XPos[SORT_FIFO-2])/3;
    *y = (au16YPos[SORT_FIFO-4]+au16YPos[SORT_FIFO-3]+au16YPos[SORT_FIFO-2])/3;
    bIsXnear = ((i32_x-16) <*x ) && (*x <(i32_x+16)); 
    bIsYnear = ((i32_y-16) <*y ) && (*y <(i32_y+16)); 
         
        adc_setTouchScreen(eADC_TSCREEN_TRIG,            //E_DRVADC_TSC_MODE eTscMode,
                                0x20,
                                FALSE,                        //BOOL bIsPullup,
                                FALSE);                        //BOOL bMAVFilter     
          
       i32_x = *x;
     i32_y = *y;  
     u32Idx=0x40000;
    while(u32Idx--);    
    if(mode == ADC_NONBLOCK)    
    {                    
        //if(bIsXnear &&  bIsYnear)
        {            
#ifdef USING_INT            
            if(g_bIsWTInt == 0)
#else
            if(DrvADC_IsPenDown()==FALSE)
#endif        
            {
                sysprintf("Library Pen up\n");    
                return 0;    //Means pen up.
            }    
            else
                return 1;    //Means pen down.
        }        
        return 0;                    
    }    
    else
    {        
        if(bIsXnear &&  bIsYnear)
        {                
            return 1;
        }
        else
            return 0;        
    }    
            
}


/*---------------------------------------------------------------------------------------------------------
                                                                                                         
 FUNCTION                                                                                                
         DrvADC_SetOffsetCancellation()                                                                         
                                                                                                         
 DESCRIPTION                                                                                             
      The function is only for OP offset callcellation                                                    
                                                                                                         
 INPUTS                                                                                                  
      None                                                                                               
                                                                                                         
 OUTPUTS                                                                                                 
      none                                                                                                
                                                                                                         
 RETURN                                                                                                  
      Recording gain in dB.                                                                               
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
void DrvADC_SetOffsetCancellation(
    BOOL bIsMuteEnable,
    BOOL bIsOffsetCalibration,
    BOOL bIsHardwareMode,
    UINT32 u32Offset
    )
{
    outp32(REG_OPOC, (inp32(REG_OPOC) & ~(MUTE_SW | OOC | OPOCM |OPOC_SW)) |
                 ((((bIsMuteEnable ? MUTE_SW:0) |
                 (bIsOffsetCalibration ? OOC:0)) |
                 (bIsHardwareMode ? OPOCM:0)) | 
                 ((u32Offset<<24)&OPOC_SW)) );
}    

void DrvADC_GetOffsetCancellation(
    PBOOL pbIsMuteEnable,
    PBOOL pbIsOffsetCalibration,
    PBOOL pbIsHardwareMode,
    PUINT32 pu32Offset
    )
{
    UINT32 u32RegData = inp32(REG_OPOC);
    *pbIsMuteEnable = (u32RegData & MUTE_SW)>>31;
    *pbIsOffsetCalibration = (u32RegData & OOC)>>30;
    *pbIsHardwareMode = (u32RegData & OPOCM)>>29;
    *pu32Offset = (u32RegData & OPOC_SW)>>24;
}    

void DrvADC_SetOffsetCancellationEx(
    UINT32 u32SampleNumber,
    UINT32 u32DelaySampleCount
    )
{
    outp32(REG_OPOC, (inp32(REG_OPOC) & ~(OPOC_TCSN | OPOC_DSC)) |
                 (((u32SampleNumber<<16) & OPOC_TCSN) |
                 (u32DelaySampleCount & OPOC_DSC)) );
}
void DrvADC_GetOffsetCancellationEx(
    PUINT32 pu32SampleNumber,
    PUINT32 pu32DelaySampleCount
    )
{
    UINT32 u32RegData = inp32(REG_OPOC);    
    *pu32SampleNumber = u32RegData & OPOC_TCSN;
    *pu32DelaySampleCount = u32RegData & OPOC_DSC;
}


/*---------------------------------------------------------------------------------------------------------
                                                                                                         
 FUNCTION                                                                                                
         ADC_SetNoiseGate()                                                                                     
                                                                                                         
 DESCRIPTION                                                                                             
         Set Pre-Amplifer, Post-Amplifer and offset(Offset Cancellation                                       
                                                                                                         
 INPUTS                                                                                                  
      None                                                                                               
                                                                                                         
 OUTPUTS                                                                                                 
      none                                                                                                
                                                                                                         
 RETURN                                                                                                  
      Noise gate Level gain in -24, -30, -36, -42dB.                                                       
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
void ADC_SetNoiseGate(
    BOOL bIsEnable, 
    E_ADC_NOISEGATE eNoiseGateLevel
    )
{

     outp32(REG_AGC_CON, (inp32(REG_AGC_CON) & ~(NG_EN |NG_LEVEL)) | 
                     (((bIsEnable <<31)& NG_EN) |
                     ((eNoiseGateLevel <<12)& NG_LEVEL)) );                                                         
                    
}    

/*---------------------------------------------------------------------------------------------------------
                                                                                                         
 FUNCTION                                                                                                
         ADC_GetNoiseGate()                                                                                     
                                                                                                         
 DESCRIPTION                                                                                             
         Set Pre-Amplifer, Post-Amplifer and offset(Offset Cancellation                                       
                                                                                                         
 INPUTS                                                                                                  
      None                                                                                               
                                                                                                         
 OUTPUTS                                                                                                 
      none                                                                                                
                                                                                                         
 RETURN                                                                                                  
      Noise gate Level gain in -24, -30, -36, -42dB.                                                       
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
void ADC_GetNoiseGate(
    PBOOL pbIsEnable, 
    E_ADC_NOISEGATE* peNoiseGateLevel
    )
{
    UINT32 u32RegData = inp32(REG_AGC_CON);
    *pbIsEnable = (u32RegData & NG_EN)>>31;
    *peNoiseGateLevel = (u32RegData & NG_LEVEL)>>12;                                                 
}    

/*---------------------------------------------------------------------------------------------------------
                                                                                                         
 FUNCTION                                                                                                
         DrvADC_SetAutoGainTiming()                                                                             
                                                                                                         
 DESCRIPTION                                                                                             
         Set the parameter for AGC                                                                           
                                                                                                         
 INPUTS                                                                                                  
      u32Period        Detect max peak in the how many samples                                               
      u32Attack                                                                                                 
      u32Recovery            A band in the uper side from u32OutputLevel+-eUpBand                           
      u32Hold       A band in the buttom side from u32OutputLevel+-eUpBand                               
                                                                                                         
 OUTPUTS                                                                                                 
      none                                                                                                
                                                                                                         
 RETURN                                                                                                  
      none                                                                                               
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
void ADC_SetAutoGainTiming(
    UINT32 u32Period,
    UINT32 u32Attack,
    UINT32 u32Recovery,
    UINT32 u32Hold
    )
{              
     outp32(REG_AGC_CON, ( (inp32(REG_AGC_CON) & ~(PERIOD | ATTACK | RECOVERY| HOLD)) | 
                     ( ((u32Period<<16) & PERIOD) |
                     ((u32Attack<<8) & ATTACK)) ) |                     
                     ( ((u32Recovery <<4)& RECOVERY) | 
                     (u32Hold & HOLD) ) );
                                                                                                                                                                                                                                                             
}    
void ADC_GetAutoGainTiming(
    PUINT32 pu32Period,
    PUINT32 pu32Attack,
    PUINT32 pu32Recovery,
    PUINT32 pu32Hold
    )
{          

    UINT32 u32RegData = inp32(REG_AGC_CON);        
    *pu32Period = (u32RegData & PERIOD) >> 16;
    *pu32Attack = (u32RegData & ATTACK) >> 8;
    *pu32Recovery = (u32RegData & RECOVERY) >> 4;
    *pu32Hold = u32RegData & HOLD;                                                                                                                                                                                                                              
}   
/*---------------------------------------------------------------------------------------------------------
                                                                                                         
 FUNCTION                                                                                                
         ADC_SetGainControl()                                                                                 
                                                                                                         
 DESCRIPTION                                                                                             
         Set Pre-Amplifer and Post-Amplifer                                                                      
                                                                                                         
 INPUTS                                                                                                  
      None                                                                                               
                                                                                                         
 OUTPUTS                                                                                                 
      none                                                                                                
                                                                                                         
 RETURN                                                                                                  
      Recording gain in dB.                                                                               
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
void ADC_SetGainControl(
    E_ADC_PREGAIN ePreGain, 
    E_ADC_POSTGAIN ePostGain
    )
{
     outp32(REG_AGCP1, (inp32(REG_AGCP1) & ~(AUDIO_VOL|PRAGA)) | 
                     ((ePreGain<<8)|ePostGain));                                                      
}    

void ADC_GetGainControl(
    E_ADC_PREGAIN* pePreGain, 
    E_ADC_POSTGAIN* pePostGain
    )
{
    UINT32 u32RegData = inp32(REG_AGCP1);
    *pePreGain =  (u32RegData & PRAGA)>>8;
    *pePostGain = u32RegData & AUDIO_VOL;                                                 
}    

/*---------------------------------------------------------------------------------------------------------
                                                                                                         
 FUNCTION                                                                                                
         ADC_SetAutoGainControl()                                                                                 
                                                                                                         
 DESCRIPTION                                                                                             
         Set the parameter for AGC                                                                           
                                                                                                         
 INPUTS                                                                                                  
      bIsEnable        Enable AGC                                                                           
      u32OutputLevel  Output target level                                                                 
      eUpBand            A band in the uper side from u32OutputLevel+-eUpBand                               
      eDownBand       A band in the buttom side from u32OutputLevel+-eUpBand                               
                                                                                                         
 OUTPUTS                                                                                                 
      none                                                                                                
                                                                                                         
 RETURN                                                                                                  
      none                                                                                               
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
void ADC_SetAutoGainControl(
    BOOL bIsEnable, 
    UINT32 u32OutputLevel,
    E_ADC_UPBAND eAdcUpBand,
    E_ADC_DOWNBAND eAdcDownBand
    )
{
     outp32(REG_AGC_CON, (inp32(REG_AGC_CON) & ~AGC_EN) | 
                     ((bIsEnable <<30)& AGC_EN) );                     
     outp32(REG_AGCP1, ( (inp32(REG_AGCP1) & ~(OTL | UPBAND | DOWNBAND)) | 
                     ((u32OutputLevel<<12) & OTL) ) |
                     (((eAdcUpBand <<11)& UPBAND) | 
                     ((eAdcDownBand <<10)& DOWNBAND)) );                                                                                                                                                                                                                                         
}    
    
/*---------------------------------------------------------------------------------------------------------
                                                                                                         
 FUNCTION                                                                                                
         ADC_GetAutoGainControl()                                                                             
                                                                                                         
 DESCRIPTION                                                                                             
         Set Pre-Amplifer, Post-Amplifer and offset(Offset Cancellation                                       
                                                                                                         
 INPUTS                                                                                                  
      None                                                                                               
 OUTPUTS                                                                                                 
      bIsEnable        Enable AGC                                                                           
      u32OutputLevel  Output target level                                                                 
      eUpBand            A band in the uper side from u32OutputLevel+-eUpBand                               
      eDownBand       A band in the buttom side from u32OutputLevel+-eUpBand                               
                                                                                                         
 RETURN                                                                                                  
      None.                                                                                                  
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
void ADC_GetAutoGainControl(
    PBOOL pbIsEnable, 
    PUINT32 pu32OutputLevel,
    E_ADC_UPBAND* peAdcUpBand,
    E_ADC_DOWNBAND* peAdcDownBand
    )
{
    UINT32 u32RegData = inp32(REG_AGC_CON);
    *pbIsEnable = (u32RegData & AGC_EN)>>30;
    u32RegData = inp32(REG_AGCP1);
    *pu32OutputLevel = (u32RegData & OTL)>>12; 
    *peAdcUpBand =     (u32RegData & UPBAND)>>11;                                          
    *peAdcDownBand = (u32RegData & DOWNBAND)>>10;                                                                                                                            
}    
/*---------------------------------------------------------------------------------------------------------                                                                                                 
 FUNCTION                                                                                                
      Audio_Open()                                                                                       
                                                                                                         
 DESCRIPTION                                                                                             
      Open the ADC conversion or Audio record function                                                     
                                                                                                         
 INPUTS                                                                                                  
      mode:   The work mode of ADC. It could be in normal                                                
              ADC conversion mode or audio recording mode                                                   
                                                                                                         
      u32ConvClock:                                                                                      
              If working in ADC_NORMAL mode, u32ConvClock is the                                         
              conversion rate.                                                                           
              If working in ADC_RECORD mode, u32ConvClock is the                                         
              sampling rate.                                                                             
                                                                                                         
 OUTPUTS                                                                                                 
      none                                                                                               
                                                                                                         
 RETURN                                                                                                  
      E_SUCCESS           Success                                                                           
      E_DRVADC_ARGUMENT   Wrong argument                                                                 
      E_DRVADC_CLOCK      Unable to output a suitable clock                                              
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
BOOL bIsAudioInitialize = FALSE;
INT32 audio_Open(E_SYS_SRC_CLK eSrcClock, UINT32 u32ConvClock)
{
    UINT32 u32PllOutKHz, u32ExtFreq;
    UINT32 u32Tmp;
    UINT32 u32Reg;
    volatile UINT32 u32Dly=0x100;
           
         /* Enable clock and IP reset */
        outp32(REG_APBCLK, inp32(REG_APBCLK) | ADC_CKE);
        outp32(REG_APBIPRST, inp32(REG_APBIPRST) | ADCRST);
       outp32(REG_APBIPRST,  inp32(REG_APBIPRST) & ~ADCRST);
    /* Default to use conv bit to control conversion */
    u32Reg = 0;
    u32Reg = u32Reg | (ADC_CON_ADC_EN); /* Enable ADC */

        /* Use the same clock source as system */
 
    outp32(REG_CLKDIV3, (inp32(REG_CLKDIV3) & ~ADC_S) | 
                    (eSrcClock << 19));                        
    switch(eSrcClock)
    {
        case eSYS_X32K:    
                    return -1;            /* Wrong clock source */            
                    break;
        case eSYS_APLL:                                                
        case eSYS_UPLL:            
                    {
                        UINT32 u32TotalDiv;
                        UINT32 u32IdxN0, u32IdxN1; 
                        UINT32 u32IdxN00, u32IdxN11;                     
                        u32ExtFreq = sysGetExternalClock();                        
                        u32PllOutKHz = sysGetPLLOutputKhz(eSrcClock, u32ExtFreq);    
                        if(u32PllOutKHz==169333)
                            u32PllOutKHz = 169344;                    
                        sysprintf("PLL clock = %d KHz\n", u32PllOutKHz);                                                
                        //if(eDRVADC_Mode == eDRVADC_RECORD)
                            u32TotalDiv = (u32PllOutKHz*1000)/(1280*u32ConvClock);
                        //else
                        //    u32TotalDiv = (u32PllOutKHz/50)/u32ConvClock;    
                        
                        if(u32TotalDiv>(8*256))                        
                            return -1;                        
                                                                                    
                        sysprintf("Total divider = %d\n", u32TotalDiv);    
                        for(u32IdxN1=1;u32IdxN1<=256;u32IdxN1=u32IdxN1+1)
                        {
                            for(u32IdxN0=2;u32IdxN0 <= 8;u32IdxN0=u32IdxN0+1)                                
                            {//u32IdxN0 != 1
                                if(u32TotalDiv==(u32IdxN0*u32IdxN1))
                                {
                                    u32IdxN00 = u32IdxN0;
                                    u32IdxN11 = u32IdxN1;
                                    sysprintf("DIV_N1, DIV_N0  = %d, %d\n", u32IdxN11, u32IdxN00);                                        
                                    break; 
                                }    
                            }                            
                            if(u32TotalDiv==((u32IdxN00)*u32IdxN11))                                            
                                break;
                            
                        }    
                        u32Tmp = (inp32(REG_CLKDIV3) & ~(ADC_N1 | ADC_S | ADC_N0)) | 
                                        ( (((u32IdxN11-1) <<24) | ((u32IdxN00-1) << 16) | (eSrcClock<<19) ));
                        outp32(REG_CLKDIV3, u32Tmp);                                                                                    
                    }                    
                    break;
        case eSYS_EXT:    
                    {
                        UINT32 u32ExtClk, u32AdcDivN1;
                        u32ExtClk = sysGetExternalClock();                                        
                        u32AdcDivN1 = (u32ExtClk)/u32ConvClock;    
                        if(u32AdcDivN1>256)
                            return -1;
                        outp32(REG_CLKDIV3, (inp32(REG_CLKDIV3) & ~(ADC_N1 | ADC_N0)) |
                                        ((u32AdcDivN1-1) <<24) );                                                                                                                    
                    }                                    
                    break;
    }                                                          

    outp32(REG_ADC_CON, u32Reg);

    /* Reset Record Function */    
    outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) | AUDIO_RESET);
    while(u32Dly--);
    outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) & ~(AUDIO_RESET));        
    /* Default to Audio Interrupt Mode 3, op offset:b'1000, interrupt enabled */
    outp32(REG_AUDIO_CON, (AUDIO_HPEN | AUDIO_INT | AUDIO_INT_EN |AUDIO_VOL_EN | AUDIO_RESET));
    outp32(REG_AUDIO_CON, (inp32(REG_AUDIO_CON) & ~(AUDIO_CCYCLE | AUDIO_RESET)) | (0x50<<16));//ADC cycle = 50

    /* Hardware offset calibration */       
    if(bIsAudioInitialize==FALSE)
    {
        bIsAudioInitialize = TRUE;
            outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) | 
                             ( AUDIO_INT | AUDIO_EN ) );
            DrvADC_SetOffsetCancellation(FALSE,   //BOOL bIsMuteEnable,
                                FALSE, //BOOL bIsOffsetCalibration,
                                TRUE, //BOOL bIsHardwareMode,
                                0x10);      //UINT32 u32Offset   
                                                                                              
        DrvADC_SetOffsetCancellationEx(1,            //255 sample
                                    256);//Delay sample count                               
        {
            volatile unsigned int btime, etime;
            btime = etime = sysGetTicks(TIMER0);
            
            while( (etime - btime) <= 10 )
            {                    
                etime = sysGetTicks(TIMER0);                    
            }
        }            
            outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) & ~AUDIO_EN);
               DrvADC_SetOffsetCancellation(FALSE,   //BOOL bIsMuteEnable,
                                                FALSE, //BOOL bIsOffsetCalibration,
                                                FALSE, //BOOL bIsHardwareMode,
                                                0x10);      //UINT32 u32Offset 
    }        
    
    /* Set ADC Parameter for audio recording*/
    
    //outp32(REG_AUDIO_CON, (inp32(REG_AUDIO_CON) & ~(AUDIO_INT_MODE)) | (1<<30));                                                                                                                                                                                                                                                                                                                                                                                     
    outp32(REG_AUDIO_CON, (inp32(REG_AUDIO_CON) & ~(AUDIO_INT_MODE)) );             
    
        ADC_SetNoiseGate(FALSE, eADC_NG_N36);                
    ADC_SetAutoGainTiming(4, //Period
                            4,  //Attack
                            4,
                            4);                                                                                                                
        ADC_SetGainControl(eADC_PRE_P14,            //Pre-gain 14db
                            eADC_POST_P0);    //Post-gain is invalid if enable AGC 
                            
        ADC_SetAutoGainControl(TRUE,                    //AGC enable
                            13,                     //Output target aszOTLArray[13] = -9db 
                                 eADC_BAND_P0P5,
                                 eADC_BAND_N0P5); 
    
    outp32(0xb800E000, inp32(0xb800E000) & ~BIT8); //Audio data src from Audio buffer                                                           
    
    sysInstallISR(IRQ_LEVEL_7, IRQ_ADC, (PVOID)adc_isr);    
    sysEnableInterrupt(IRQ_ADC);    
        
    return 0;    
}
/*----------------------------------------------------------------------------------------------------------
 FUNCTION                                                                                                                    
         adc_StartRecord()                                                                                           
                                                                                                                                 
 DESCRIPTION                                                                                                                 
         Start to record Audio data. This function only can be used in                                              
      ADC_RECORD mode.                                                                                                   
                                                                                                                                 
 INPUTS                                                                                                                      
      none                                                                                
                                                                                                                                 
 OUTPUTS                                                                                                                     
      none                                                                                
                                                                                                                                 
 RETURN                                                                                                                      
      none                                                                                                               
                                                                                                                                 
----------------------------------------------------------------------------------------------------------*/
void adc_StartRecord(void)
{
    //Enable Co-work with EDMA      
    outp32(REG_AGCP1, inp32(REG_AGCP1) | EDMA_MODE);    

    // Clean INT status for safe 
    outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) | 
                    (AUDIO_RESET | AUDIO_INT) );
    outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) & 
                    ~(AUDIO_RESET | AUDIO_INT) );
     //Enable record function 
#if 0     
    outp32(REG_AUDIO_CON, (inp32(REG_AUDIO_CON) & ~AUDIO_INT_MODE) |
                    (((1 << 30) &  AUDIO_INT_MODE) |
                     AUDIO_EN) );
#else
  outp32(REG_AUDIO_CON, (inp32(REG_AUDIO_CON) & ~AUDIO_INT_MODE) |
                    (((0 << 30) &  AUDIO_INT_MODE) |
                     AUDIO_EN) );    
#endif                     
    
}
/*----------------------------------------------------------------------------------------------------------
 FUNCTION                                                                                                                    
         adc_StopRecord()                                                                                            
                                                                                                                                 
 DESCRIPTION                                                                                                                 
         Stop recording Audio data. This function only can be used in                                               
      ADC_RECORD mode.                                                                                                   
                                                                                                                                 
 INPUTS                                                                                                                      
      none                                                                                
                                                                                                                                 
 OUTPUTS                                                                                                                     
      none                                                                                
                                                                                                                                 
 RETURN                                                                                                                      
      none                                                                                                               
                                                                                                                                 
----------------------------------------------------------------------------------------------------------*/
void adc_StopRecord(void)
{
        //Disable record function 
         outp32(REG_AGCP1, inp32(REG_AGCP1) & ~EDMA_MODE);    
    outp32(REG_AUDIO_CON, inp32(REG_AUDIO_CON) & (~AUDIO_EN));
}
/*---------------------------------------------------------------------------------------------------------                                                                                                     
 FUNCTION                                                                                                
         adc_GetRecordData()                                                                               
                                                                                                         
 DESCRIPTION                                                                                             
         Get the converted ADC value in ADC_RECORD mode                                                       
                                                                                                         
 INPUTS                                                                                                  
      none                                                                                               
                                                                                                         
 OUTPUTS                                                                                                 
      none                                                                                                
                                                                                                         
 RETURN                                                                                                  
      The pointer to the record data. The data length is 8 samples                                        
                                                                                                         
---------------------------------------------------------------------------------------------------------*/
PINT16 
adc_GetRecordData(
    void
    )
{
         //Return the base address of converted data. There are 8 samples 
        return (PINT16)REG_AUDIO_BUF0;
}

void ADC_Test2(void) {
    
    UINT16 val;
    UINT32 index;
    
    adc_init();
    adc_open(ADC_TS_4WIRE, 320, 240);
    
    
    while (1) {
        if (adc_normalread(2, &val)==Successful) {
            sysprintf("2:ADC Value = %d\n", val);
        }
        if (adc_normalread(3, &val)==Successful) {
            sysprintf("3:ADC Value = %d\n", val);
        }
        for (index = 0; index < 40000 * 100; index ++);
    }

}




libgpio.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/****************************************************************************
*                                                                           *
* Copyright (c) 2009 Nuvoton Tech. Corp. All rights reserved.                  *
*                                                                           *
*****************************************************************************/

/****************************************************************************
* FILENAME
*   libgpio.c
*
* VERSION
*   1.0
*
* DESCRIPTION
*   GPIO library source code
*
* DATA STRUCTURES
*   None
*
* FUNCTIONS
*
* HISTORY
*
* REMARK
*   None
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "wblib.h"
#include "w55fa93_gpio.h"

// accetiable debounce clock
static const unsigned int _clk[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 2*256, 4*256, 8*256, 16*256, 32*256, 64*256, 128*256};

int gpio_open(unsigned char port)
{

    switch (port) {            
        case GPIO_PORTA:
            outpw(REG_GPAFUN , inpw(REG_GPAFUN) &~ (0xF00000));
            break;            
        case GPIO_PORTD:
            outpw(REG_GPDFUN , inpw(REG_GPDFUN) &~ (0xFF0003FF));
            break;
        case GPIO_PORTE:
            outpw(REG_GPEFUN , inpw(REG_GPEFUN) &~ (0xFF0));
            break;    
        case GPIO_PORTB:                
        case GPIO_PORTC:            
            break;    
        default:
            return(-1);

    }
    return(0);

}

int gpio_configure(unsigned char port, unsigned short num)
{

    switch (port) {            
        case GPIO_PORTA:
            if(num<=11)
                outpw(REG_GPAFUN , inpw(REG_GPAFUN) &~ (0x3 << (num<<1)));
            else
                return(-1);
            break;    
        case GPIO_PORTB:
            outpw(REG_GPBFUN , inpw(REG_GPBFUN) &~ (0x3 << (num<<1)));
            break;
        case GPIO_PORTC:
            outpw(REG_GPCFUN , inpw(REG_GPCFUN) &~ (0x3 << (num<<1)));            
            break;
        case GPIO_PORTD:
            outpw(REG_GPDFUN , inpw(REG_GPDFUN) &~ (0x3 << (num<<1)));            
            break;
        case GPIO_PORTE:
            if(num<=11)
                outpw(REG_GPEFUN , inpw(REG_GPEFUN) &~ (0x3 << (num<<1)));        
            else
                return(-1);
            break;    
            
        default:
            return(-1);

    }
    return(0);

}

int gpio_readport(unsigned char port, unsigned short *val)
{
    switch (port) {
    
        case GPIO_PORTA:
            *val = (inpw(REG_GPIOA_PIN) & 0x0fff);
            break;
        case GPIO_PORTB:
            *val = (inpw(REG_GPIOB_PIN) & 0xffff);
            break;            
        case GPIO_PORTC:
            *val = (inpw(REG_GPIOC_PIN) & 0xffff);
            break;        
        case GPIO_PORTD:
            *val = (inpw(REG_GPIOD_PIN) & 0xffff);
            break;    
        case GPIO_PORTE:
            *val = (inpw(REG_GPIOE_PIN) & 0x0fff);
            break;        
        default:
            return(-1);

    }
    return(0);
}

int gpio_setportdir(unsigned char port, unsigned short mask, unsigned short dir)
{
    switch (port) {

        case GPIO_PORTA:
            outpw(REG_GPIOA_OMD , inpw(REG_GPIOA_OMD) & ~(mask & (mask ^ dir)));
            outpw(REG_GPIOA_OMD , inpw(REG_GPIOA_OMD) | (mask & dir));            
            break;
        case GPIO_PORTB:
            outpw(REG_GPIOB_OMD , inpw(REG_GPIOB_OMD) & ~(mask & (mask ^ dir)));
            outpw(REG_GPIOB_OMD , inpw(REG_GPIOB_OMD) | (mask & dir));    
            break;            
        case GPIO_PORTC:
            outpw(REG_GPIOC_OMD , inpw(REG_GPIOC_OMD) & ~(mask & (mask ^ dir)));
            outpw(REG_GPIOC_OMD , inpw(REG_GPIOC_OMD) | (mask & dir));    
            break;        
        case GPIO_PORTD:
            outpw(REG_GPIOD_OMD , inpw(REG_GPIOD_OMD) & ~(mask & (mask ^ dir)));
            outpw(REG_GPIOD_OMD , inpw(REG_GPIOD_OMD) | (mask & dir));    
            break;    
        case GPIO_PORTE:
            outpw(REG_GPIOE_OMD , inpw(REG_GPIOE_OMD) & ~(mask & (mask ^ dir)));
            outpw(REG_GPIOE_OMD , inpw(REG_GPIOE_OMD) | (mask & dir));    
            break;        
        default:
            return(-1);

    }
    return(0);
    

}

int gpio_setportval(unsigned char port, unsigned short mask, unsigned short val)
{
    switch (port) {
    
        case GPIO_PORTA:
            outpw(REG_GPIOA_DOUT , inpw(REG_GPIOA_DOUT) & ~(mask & (mask ^ val)));
            outpw(REG_GPIOA_DOUT , inpw(REG_GPIOA_DOUT) | (mask & val));            
            break;
        case GPIO_PORTB:
            outpw(REG_GPIOB_DOUT , inpw(REG_GPIOB_DOUT) & ~(mask & (mask ^ val)));
            outpw(REG_GPIOB_DOUT , inpw(REG_GPIOB_DOUT) | (mask & val));
            break;            
        case GPIO_PORTC:
            outpw(REG_GPIOC_DOUT , inpw(REG_GPIOC_DOUT) & ~(mask & (mask ^ val)));
            outpw(REG_GPIOC_DOUT , inpw(REG_GPIOC_DOUT) | (mask & val));
            break;        
        case GPIO_PORTD:
            outpw(REG_GPIOD_DOUT , inpw(REG_GPIOD_DOUT) & ~(mask & (mask ^ val)));
            outpw(REG_GPIOD_DOUT , inpw(REG_GPIOD_DOUT) | (mask & val));
            break;    
        case GPIO_PORTE:
            outpw(REG_GPIOE_DOUT , inpw(REG_GPIOE_DOUT) & ~(mask & (mask ^ val)));
            outpw(REG_GPIOE_DOUT , inpw(REG_GPIOE_DOUT) | (mask & val));
            break;        
        default:
            return(-1);

    }
    return(0);

}

int gpio_setportpull(unsigned char port, unsigned short mask, unsigned short pull)
{
    switch (port) {
    
        case GPIO_PORTA:
            outpw(REG_GPIOA_PUEN , inpw(REG_GPIOA_PUEN) & ~(mask & (mask ^ pull)));
            outpw(REG_GPIOA_PUEN , inpw(REG_GPIOA_PUEN) | (mask & pull));            
            break;
        case GPIO_PORTB:
            outpw(REG_GPIOB_PUEN , inpw(REG_GPIOB_PUEN) & ~(mask & (mask ^ pull)));
            outpw(REG_GPIOB_PUEN , inpw(REG_GPIOB_PUEN) | (mask & pull));    
            break;            
        case GPIO_PORTC:
            outpw(REG_GPIOC_PUEN , inpw(REG_GPIOC_PUEN) & ~(mask & (mask ^ pull)));
            outpw(REG_GPIOC_PUEN , inpw(REG_GPIOC_PUEN) | (mask & pull));    
            break;    
        case GPIO_PORTD:
            outpw(REG_GPIOD_PUEN , inpw(REG_GPIOD_PUEN) & ~(mask & (mask ^ pull)));
            outpw(REG_GPIOD_PUEN , inpw(REG_GPIOD_PUEN) | (mask & pull));    
            break;
        case GPIO_PORTE:
            outpw(REG_GPIOE_PUEN , inpw(REG_GPIOE_PUEN) & ~(mask & (mask ^ pull)));
            outpw(REG_GPIOE_PUEN , inpw(REG_GPIOE_PUEN) | (mask & pull));    
            break;        
        default:
            return(-1);

    }
    return(0);

}

int gpio_setdebounce(unsigned int clk, unsigned char src)
{
    int i;
    
    if(clk > 128*256 || src > 0xf)
        return(-1);
    
    // clk could only be 1, 2, 4, 8, ... 128*256
    for(i = 0 ; i < 16; i++) {
        if(_clk[i] == clk)
            break;
    }
    if(i == 16)
        return(-1);

    outpw(REG_DBNCECON , (i << 4 | src));
        
    return(0);                
}

void gpio_getdebounce(unsigned int *clk, unsigned char *src)
{
    *clk = _clk[(inpw(REG_DBNCECON) >> 4) & 0xf];
    *src = inpw(REG_DBNCECON) & 0xf;
    
    return;
}

int gpio_setsrcgrp(unsigned char port, unsigned short mask, unsigned char irq)
{

    const unsigned int _irq[4] = {0, 0x55555555, 0xaaaaaaaa, 0xffffffff};
    unsigned int _mask = 0;
    int i;
    
    
    if(irq > 3)
        return(-1);    
    
    if(mask > 0xffff)
        return(-1);
        
    for(i = 0; i < 16; i++) {
        if(mask & (1 << i))
            _mask += (3 << (i << 1));    
    }
        
    switch (port) {    
        case GPIO_PORTA:
            outpw(REG_IRQSRCGPA , inpw(REG_IRQSRCGPA) & ~_mask);
            outpw(REG_IRQSRCGPA , inpw(REG_IRQSRCGPA) | (_mask & _irq[irq]));            
            break;
        case GPIO_PORTB:
            outpw(REG_IRQSRCGPB , inpw(REG_IRQSRCGPB) & ~_mask);
            outpw(REG_IRQSRCGPB , inpw(REG_IRQSRCGPB) | (_mask & _irq[irq]));
            break;            
        case GPIO_PORTC:
            outpw(REG_IRQSRCGPC , inpw(REG_IRQSRCGPC) & ~_mask);
            outpw(REG_IRQSRCGPC , inpw(REG_IRQSRCGPC) | (_mask & _irq[irq]));
            break;    
        case GPIO_PORTD:
            outpw(REG_IRQSRCGPD , inpw(REG_IRQSRCGPD) & ~_mask);
            outpw(REG_IRQSRCGPD , inpw(REG_IRQSRCGPD) | (_mask & _irq[irq]));
            break;
        case GPIO_PORTE:
            outpw(REG_IRQSRCGPE , inpw(REG_IRQSRCGPE) & ~_mask);
            outpw(REG_IRQSRCGPE , inpw(REG_IRQSRCGPE) | (_mask & _irq[irq]));
            break;        
        default:
            return(-1);

    }
    return(0);
}

int gpio_getsrcgrp(unsigned char port, unsigned int *val)
{
    switch (port) {    
        case GPIO_PORTA:        
            *val = inpw(REG_IRQSRCGPA);
            break;
        case GPIO_PORTB:
            *val = inpw(REG_IRQSRCGPB);
            break;            
        case GPIO_PORTC:
            *val = inpw(REG_IRQSRCGPC);
            break;    
        case GPIO_PORTD:
            *val = inpw(REG_IRQSRCGPD);
            break;
        case GPIO_PORTE:            
            *val = inpw(REG_IRQSRCGPE);
            break;        
        default:
            return(-1);

    }
    return(0);

}

int gpio_setintmode(unsigned char port, unsigned short mask, unsigned short falling, unsigned short rising)
{
    
    if(mask > 0xffff)
        return(-1);
        
    switch (port) {    
        case GPIO_PORTA:    
            outpw(REG_IRQENGPA , inpw(REG_IRQENGPA) & ~((mask << 16) | mask));
            outpw(REG_IRQENGPA , inpw(REG_IRQENGPA) | (((mask & rising) << 16) | (mask & falling)));            
            break;
        case GPIO_PORTB:
            outpw(REG_IRQENGPB , inpw(REG_IRQENGPB) & ~((mask << 16) | mask));
            outpw(REG_IRQENGPB , inpw(REG_IRQENGPB) | (((mask & rising) << 16) | (mask & falling)));
            break;            
        case GPIO_PORTC:
            outpw(REG_IRQENGPC , inpw(REG_IRQENGPC) & ~((mask << 16) | mask));
            outpw(REG_IRQENGPC , inpw(REG_IRQENGPC) | (((mask & rising) << 16) | (mask & falling)));
            break;    
        case GPIO_PORTD:
            outpw(REG_IRQENGPD , inpw(REG_IRQENGPD) & ~((mask << 16) | mask));
            outpw(REG_IRQENGPD , inpw(REG_IRQENGPD) | (((mask & rising) << 16) | (mask & falling)));
            break;    
        case GPIO_PORTE:
            outpw(REG_IRQENGPE , inpw(REG_IRQENGPE) & ~((mask << 16) | mask));
            outpw(REG_IRQENGPE , inpw(REG_IRQENGPE) | (((mask & rising) << 16) | (mask & falling)));        
            break;        
        default:
            return(-1);

    }
    return(0);        
        
}


int gpio_getintmode(unsigned char port, unsigned short *falling, unsigned short *rising)
{

    switch (port) {    
        case GPIO_PORTA:        
            *rising = inpw(REG_IRQENGPA) >> 16;
            *falling = inpw(REG_IRQENGPA) & 0xffff;
            break;
        case GPIO_PORTB:
            *rising = inpw(REG_IRQENGPB) >> 16;
            *falling = inpw(REG_IRQENGPB) & 0xffff;
            break;            
        case GPIO_PORTC:
            *rising = inpw(REG_IRQENGPC) >> 16;
            *falling = inpw(REG_IRQENGPC) & 0xffff;
            break;    
        case GPIO_PORTD:
            *rising = inpw(REG_IRQENGPD) >> 16;
            *falling = inpw(REG_IRQENGPD) & 0xffff;
            break;
        case GPIO_PORTE:
            *rising = inpw(REG_IRQENGPE)  >> 16;
            *falling = inpw(REG_IRQENGPE) & 0xffff;        
            break;        
        default:
            return(-1);

    }
    return(0);
}


int gpio_setlatchtrigger(unsigned char src)
{
    if(src > 0xf)
        return(-1);

    outpw(REG_IRQLHSEL , src);        
    return(0);

}

void gpio_getlatchtrigger(unsigned char *src)
{

    *src = inpw(REG_IRQLHSEL) & 0xf;
    return;
}

int gpio_getlatchval(unsigned char port, unsigned short *val)
{

    switch (port) {    
        case GPIO_PORTA:        
            *val = inpw(REG_IRQLHGPA) & 0xffff;
            break;
        case GPIO_PORTB:
            *val = inpw(REG_IRQLHGPB) & 0xffff;
            break;            
        case GPIO_PORTC:
            *val = inpw(REG_IRQLHGPC) & 0xffff;
            break;    
        case GPIO_PORTD:
            *val = inpw(REG_IRQLHGPD) & 0xffff;
            break;
        case GPIO_PORTE:
            *val = inpw(REG_IRQLHGPE) & 0xffff;
            break;        
        default:
            return(-1);

    }

    return(0);
}


int gpio_gettriggersrc(unsigned char port, unsigned short *src)
{

    switch (port) {    
        case GPIO_PORTA:        
            *src = inpw(REG_IRQTGSRC0) & 0xffff;                        
            break;
        case GPIO_PORTB:
            *src = (inpw(REG_IRQTGSRC0) & 0xffff0000) >> 16;                        
            break;            
        case GPIO_PORTC:
            *src = inpw(REG_IRQTGSRC1) & 0xffff;                        
            break;    
        case GPIO_PORTD:
            *src = (inpw(REG_IRQTGSRC1) & 0xffff0000) >> 16;                        
            break;    
        case GPIO_PORTE:
            *src = inpw(REG_IRQTGSRC2) & 0xffff;                        
            break;        
        default:
            return(-1);

    }

    return(0);
}

int gpio_cleartriggersrc(unsigned char port)
{

    switch (port) {    
        case GPIO_PORTA:                    
            outpw(REG_IRQTGSRC0 , inpw(REG_IRQTGSRC0) & 0xffff);            
            break;
        case GPIO_PORTB:            
            outpw(REG_IRQTGSRC0 , inpw(REG_IRQTGSRC0) & 0xffff0000);            
            break;            
        case GPIO_PORTC:            
            outpw(REG_IRQTGSRC1 , inpw(REG_IRQTGSRC1) & 0xffff);            
            break;    
        case GPIO_PORTD:            
            outpw(REG_IRQTGSRC1 , inpw(REG_IRQTGSRC1) & 0xffff0000);            
            break;    
        case GPIO_PORTE:            
            outpw(REG_IRQTGSRC2 , inpw(REG_IRQTGSRC2) & 0xffff);            
            break;        
        default:
            return(-1);

    }

    return(0);
}




main.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "wblib.h"
#include "w55fa93_edma.h"
#include "w55fa93_gpio.h"
#include "w55fa93_spi.h"
#include "w55fa93_adc.h"

#include "XTPH.h"
#include "XADC.h"

#define APBCLK    48000000

extern void DemoAPI_Timer0(void);


void ram_size(int Arg2, int Arg3 ) 
{

    while (1)
    {
        VOID *p = malloc(Arg2 * 1024);
        if (p)
        {
                //sysprintf("\r\n Heap space remaining %d KByte", Arg2);
                free(p);
                break;
        }
        Arg2 -= ((Arg2-Arg3) ? Arg3 : 1);
    }
}


static int record = 1;
static int record_index = 1;
void step(int i)
{

    if ((record + 1) != i)
    {
        sysprintf("r=%d\n", record_index);
        sysPutChar('0' + record);
        sysPutChar('0' + i);
        sysPutChar('M');
    }
    record = i;
    if (i == 7)
        record = 1;

    record_index ++;

}
void ii_main(void)
{
    WB_UART_T uart;
    UINT32 u32ExtFreq, u32Item;
    UINT8 u8Item;
    u32ExtFreq = sysGetExternalClock();
    sysSetSystemClock(eSYS_UPLL,     //E_SYS_SRC_CLK eSrcClk,                        
    192000,        //UINT32 u32PllKHz,                         
    192000,        //UINT32 u32SysKHz,                    
    192000,        //UINT32 u32CpuKHz,                      
    96000,        //UINT32 u32HclkKHz,                      
    APBCLK/1000);        //UINT32 u32ApbKHz    
                          

    uart.uiFreq = u32ExtFreq*1000;
    //uart.uiBaudrate = 230400; // ch_20220811
    uart.uiBaudrate = 921600; // ch_20220811
    uart.uiDataBits = WB_DATA_BITS_8;
    uart.uiStopBits = WB_STOP_BITS_1;
    uart.uiParity = WB_PARITY_NONE;
    uart.uiRxTriggerLevel = LEVEL_1_BYTE;
    sysInitializeUART(&uart);    


    ADCInit();
sysprintf("Reg_ADC_Clk = %x\n", inp32(REG_CLKDIV3)); // ch_20220305    

    //while(1);
    //u8Item = sysGetChar(); 
    sysEnableCache(CACHE_WRITE_BACK);
    //sysEnableCache(CACHE_DISABLE);
    sysSetLocalInterrupt(ENABLE_FIQ_IRQ);

    
    
    ram_size(1024*8, 1); 


    //inputTest();
    return;
}



N32903.ini   。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

FUNC void DRAMInit(void)
{
 _WDWORD(0xb0000204, 0xFFFFFFFF);
 _WDWORD(0xb0003000, 0x0013044E);
 _WDWORD(0xb0003030, 0x00001010);
 _WDWORD(0xb0003010, 0x00000003);
 _WDWORD(0xb0003004, 0x00000021);
 _WDWORD(0xb0003004, 0x00000023);
 _WDWORD(0xb0003004, 0x00000027);

 _WDWORD(0xb000301C, 0x00001002);
 _WDWORD(0xb0003018, 0x00000132);
 _WDWORD(0xb0003004, 0x00000027);
 _WDWORD(0xb0003004, 0x0000002B);

 _WDWORD(0xb0003004, 0x0000002B);
 _WDWORD(0xb0003018, 0x00000032);
 _WDWORD(0xb0003004, 0x00000020);
 _WDWORD(0xb0003034, 0x00AAAA00);

 _WDWORD(0xb0003008, 0x00008035);
 _WDWORD(0xb00000A0, 0x00000000);
 _WDWORD(0xb0000224, 0x0000447E);
 _WDWORD(0xb0000204, 0x0001011F);
 _WDWORD(0xb000020C, 0x00000018);
 _WDWORD(0xb000021C, 0x00000100);
 _WDWORD(0xb0003028, 0x094E7425);

 _WDWORD(0xb8001010, 0x00000008);
 _WDWORD(0xb8001018, 0x00000008);
}


DRAMInit();
LOAD %L INCREMENTAL   // Load the .axf Debug file




N32903.sct   。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x00020000 0x7E0000  {    ; load region size_region
  ER_IROM1 0x00020000 0x7E0000  {  ; load address = execution address
   *.o (WB_INIT, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_RAM1 +0  {  ; RW_RAM1 start address is after ER_ROM1
   .ANY (+RW +ZI)
  }
  ZI +0 {
    .ANY (.)
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值