MODDMA GPDMA Controller New features: transfer pins to memory buffer under periodic timer control and send double buffers to DAC

Dependents:   FirstTest WaveSim IO-dma-memmem DACDMAfuncgenlib ... more

Files at this revision

API Documentation at this revision

Comitter:
AjK
Date:
Tue Nov 23 14:50:39 2010 +0000
Child:
1:9700b9455cbf
Commit message:
0.1

Changed in this revision

CONFIG.h Show annotated file Show diff for this revision Revisions of this file
ChangeLog.c Show annotated file Show diff for this revision Revisions of this file
DATALUTS.cpp Show annotated file Show diff for this revision Revisions of this file
INIT.cpp Show annotated file Show diff for this revision Revisions of this file
MODDMA.cpp Show annotated file Show diff for this revision Revisions of this file
MODDMA.h Show annotated file Show diff for this revision Revisions of this file
SETUP.cpp Show annotated file Show diff for this revision Revisions of this file
example1.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CONFIG.h	Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,96 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#ifdef NOCOMPILE
+
+#ifndef MODDMA_CONFIG_H
+#define MODDMA_CONFIG_H
+
+#include "mbed.h"
+
+namespace AjK {
+
+// Forward reference.
+class MODDMA;
+
+class  MODDMA_Channel_CFG_t {
+public:
+
+    // *****************************************
+    // From GPDMA by NXP MCU SW Application Team
+    // *****************************************
+    
+    uint32_t ChannelNum;        //!< DMA channel number, should be in range from 0 to 7. 
+    uint32_t TransferSize;      //!< Length/Size of transfer 
+    uint32_t TransferWidth;     //!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_m2m only 
+    uint32_t SrcMemAddr;        //!< Physical Src Addr, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::m2p 
+    uint32_t DstMemAddr;        //!< Physical Destination Address, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::p2m 
+    uint32_t TransferType;      //!< Transfer Type
+    uint32_t SrcConn;           ///!< Peripheral Source Connection type, used in case TransferType is chosen as
+    uint32_t DstConn;           //!< Peripheral Destination Connection type, used in case TransferType is chosen as
+    uint32_t DMALLI;            //!< Linker List Item structure data address if there's no Linker List, set as '0'
+    
+    // Mbed specifics.
+    
+    MODDMA_Channel_CFG_t() {
+        isrIntTCStat  = new FunctionPointer;
+        isrIntErrStat = new FunctionPointer;
+    }
+    
+    ~MODDMA_Channel_CFG_t() {
+        delete(isrIntTCStat);
+        delete(isrIntErrStat);
+    }
+        
+    class MODDMA_Channel_CFG_t * channelNum(uint32_t n)    { ChannelNum = n;    return this; }
+    class MODDMA_Channel_CFG_t * transferSize(uint32_t n)  { TransferSize = n;  return this; }
+    class MODDMA_Channel_CFG_t * transferWidth(uint32_t n) { TransferWidth = n; return this; }
+    class MODDMA_Channel_CFG_t * srcMemAddr(uint32_t n)    { SrcMemAddr = n;    return this; }
+    class MODDMA_Channel_CFG_t * dstMemAddr(uint32_t n)    { DstMemAddr = n;    return this; }
+    class MODDMA_Channel_CFG_t * transferType(uint32_t n)  { TransferType = n;  return this; }
+    class MODDMA_Channel_CFG_t * srcConn(uint32_t n)       { SrcConn = n;       return this; }
+    class MODDMA_Channel_CFG_t * dstConn(uint32_t n)       { DstConn = n;       return this; }
+    class MODDMA_Channel_CFG_t * dmaLLI(uint32_t n)        { DMALLI = n;        return this; }
+    
+    uint32_t channelNum(void) { return ChannelNum; }
+    
+    FunctionPointer *isrIntTCStat;                        
+    FunctionPointer *isrIntErrStat;                        
+};
+
+/**
+ * @brief GPDMA Linker List Item structure type definition
+ */
+ /*
+typedef struct {
+    uint32_t SrcAddr;    //!< Source Address 
+    uint32_t DstAddr;    //!< Destination address 
+    uint32_t NextLLI;    //!< Next LLI address, otherwise set to '0' 
+    uint32_t Control;    //!< GPDMA Control of this LLI 
+} GPDMA_LLI_t;
+*/
+
+
+}; // namespace AjK ends.
+
+#endif 
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ChangeLog.c	Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,8 @@
+/* $Id:$
+
+
+1.0 - 22/11/2010
+
+    * First release
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DATALUTS.cpp	Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,147 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#include "MODDMA.h"
+
+#ifndef MBED_H
+#include "mbed.h"
+#endif
+
+#ifndef MODDMA_CONFIG_H
+#include "CONFIG.h"
+#endif
+
+namespace AjK {
+
+uint32_t
+MODDMA::LUTPerAddr(int n)
+{
+	const uint32_t lut[] = { 
+          (uint32_t)&LPC_SSP0->DR         // SSP0 Tx
+        , (uint32_t)&LPC_SSP0->DR         // SSP0 Rx
+        , (uint32_t)&LPC_SSP1->DR         // SSP1 Tx
+        , (uint32_t)&LPC_SSP1->DR         // SSP1 Rx
+        , (uint32_t)&LPC_ADC->ADGDR       // ADC
+        , (uint32_t)&LPC_I2S->I2STXFIFO   // I2S Tx
+        , (uint32_t)&LPC_I2S->I2SRXFIFO   // I2S Rx
+        , (uint32_t)&LPC_DAC->DACR        // DAC
+        , (uint32_t)&LPC_UART0->THR       // UART0 Tx
+        , (uint32_t)&LPC_UART0->RBR       // UART0 Rx
+        , (uint32_t)&LPC_UART1->THR       // UART1 Tx
+        , (uint32_t)&LPC_UART1->RBR       // UART1 Rx
+        , (uint32_t)&LPC_UART2->THR       // UART2 Tx
+        , (uint32_t)&LPC_UART2->RBR       // UART2 Rx
+        , (uint32_t)&LPC_UART3->THR       // UART3 Tx
+        , (uint32_t)&LPC_UART3->RBR       // UART3 Rx
+        , (uint32_t)&LPC_TIM0->MR0        // MAT0.0
+        , (uint32_t)&LPC_TIM0->MR1        // MAT0.1
+        , (uint32_t)&LPC_TIM1->MR0        // MAT1.0
+        , (uint32_t)&LPC_TIM1->MR1        // MAT1.1
+        , (uint32_t)&LPC_TIM2->MR0        // MAT2.0
+        , (uint32_t)&LPC_TIM2->MR1        // MAT2.1
+        , (uint32_t)&LPC_TIM3->MR0        // MAT3.0
+        , (uint32_t)&LPC_TIM3->MR1        // MAT3.1   
+    };
+    return lut[n & 0xFF];	
+}
+
+uint32_t
+MODDMA::Channel_p(int channel)
+{
+    const uint32_t lut[] = {
+          (uint32_t)LPC_GPDMACH0
+        , (uint32_t)LPC_GPDMACH1
+        , (uint32_t)LPC_GPDMACH2
+        , (uint32_t)LPC_GPDMACH3
+        , (uint32_t)LPC_GPDMACH4
+        , (uint32_t)LPC_GPDMACH5
+        , (uint32_t)LPC_GPDMACH6
+        , (uint32_t)LPC_GPDMACH7
+    };
+    return lut[channel & 0xFF];
+}
+
+uint8_t
+MODDMA::LUTPerBurst(int n)
+{
+    const uint8_t lut[] = {
+          (uint8_t)_4       // SSP0 Tx 
+        , (uint8_t)_4       // SSP0 Rx
+        , (uint8_t)_4       // SSP1 Tx
+        , (uint8_t)_4       // SSP1 Rx
+        , (uint8_t)_4       // ADC
+        , (uint8_t)_32      // I2S channel 0
+        , (uint8_t)_32      // I2S channel 1
+        , (uint8_t)_1       // DAC
+        , (uint8_t)_1       // UART0 Tx
+        , (uint8_t)_1       // UART0 Rx
+        , (uint8_t)_1       // UART1 Tx
+        , (uint8_t)_1       // UART1 Rx
+        , (uint8_t)_1       // UART2 Tx
+        , (uint8_t)_1       // UART2 Rx
+        , (uint8_t)_1       // UART3 Tx
+        , (uint8_t)_1       // UART3 Rx
+        , (uint8_t)_1       // MAT0.0
+        , (uint8_t)_1       // MAT0.1
+        , (uint8_t)_1       // MAT1.0
+        , (uint8_t)_1       // MAT1.1
+        , (uint8_t)_1       // MAT2.0
+        , (uint8_t)_1       // MAT2.1
+        , (uint8_t)_1       // MAT3.0
+        , (uint8_t)_1       // MAT3.1
+    };
+    return lut[n & 0xFFF];
+}
+
+uint8_t
+MODDMA::LUTPerWid(int n)
+{
+    const uint8_t lut[] = {
+          (uint8_t)byte      // SSP0 Tx
+        , (uint8_t)byte      // SSP0 Rx
+        , (uint8_t)byte      // SSP1 Tx
+        , (uint8_t)byte      // SSP1 Rx
+        , (uint8_t)word      // ADC
+        , (uint8_t)word      // I2S channel 0
+        , (uint8_t)word      // I2S channel 1
+        , (uint8_t)byte      // DAC
+        , (uint8_t)byte      // UART0 Tx
+        , (uint8_t)byte      // UART0 Rx
+        , (uint8_t)byte      // UART1 Tx
+        , (uint8_t)byte      // UART1 Rx
+        , (uint8_t)byte      // UART2 Tx
+        , (uint8_t)byte      // UART2 Rx
+        , (uint8_t)byte      // UART3 Tx
+        , (uint8_t)byte      // UART3 Rx  
+        , (uint8_t)word      // MAT0.0
+        , (uint8_t)word      // MAT0.1
+        , (uint8_t)word      // MAT1.0
+        , (uint8_t)word      // MAT1.1
+        , (uint8_t)word      // MAT2.0
+        , (uint8_t)word      // MAT2.1
+        , (uint8_t)word      // MAT3.0
+        , (uint8_t)word      // MAT3.1  
+    };
+    return lut[n & 0xFFF];
+}
+
+}; // namespace AjK ends
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/INIT.cpp	Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,69 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#include "MODDMA.h"
+
+namespace AjK {
+
+extern uint32_t oldDMAHandler;
+extern "C" void MODDMA_IRQHandler(void);
+extern class MODDMA *moddma_p;
+
+void
+MODDMA::init(bool isConstructorCalling, int Channels, int Tc, int Err)
+{
+    if (isConstructorCalling) {    
+        if (LPC_SC->PCONP & (1UL << 29)) {
+            if (LPC_GPDMA->DMACConfig & 1) {
+                error("Only one instance of MODDMA can exist.");
+            }
+        }
+        LPC_SC->PCONP |= (1UL << 29);
+        LPC_GPDMA->DMACConfig = 1;
+        moddma_p = this;
+        for (int i = 0; i < 8; i++) {
+            setups[i] = (MODDMA_Config *)NULL;
+        }        
+    }
+    
+    // Reset channel configuration register(s)
+    if (Channels & 0x01) LPC_GPDMACH0->DMACCConfig = 0;
+    if (Channels & 0x02) LPC_GPDMACH1->DMACCConfig = 0;
+    if (Channels & 0x04) LPC_GPDMACH2->DMACCConfig = 0;
+    if (Channels & 0x08) LPC_GPDMACH3->DMACCConfig = 0;
+    if (Channels & 0x10) LPC_GPDMACH4->DMACCConfig = 0;
+    if (Channels & 0x20) LPC_GPDMACH5->DMACCConfig = 0;
+    if (Channels & 0x40) LPC_GPDMACH6->DMACCConfig = 0;
+    if (Channels & 0x80) LPC_GPDMACH7->DMACCConfig = 0;
+
+    /* Clear DMA interrupt and error flag */
+    LPC_GPDMA->DMACIntTCClear = Tc;
+    LPC_GPDMA->DMACIntErrClr  = Err;
+    
+    if (isConstructorCalling) {    
+        oldDMAHandler = NVIC_GetVector(DMA_IRQn);
+        NVIC_SetVector(DMA_IRQn, (uint32_t)MODDMA_IRQHandler);
+        NVIC_EnableIRQ(DMA_IRQn);
+    }
+}
+
+}; // namespace AjK ends
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODDMA.cpp	Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,144 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#include "MODDMA.h"
+
+namespace AjK {
+
+// Create a "hook" for our ISR to make callbacks. Set by init()
+class MODDMA *moddma_p = (class MODDMA *)NULL;
+
+void
+MODDMA::Enable(CHANNELS ChannelNumber)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber );
+    pChannel->DMACCConfig |= _E;
+}
+
+bool
+MODDMA::Enabled(CHANNELS ChannelNumber)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber );
+    return (bool)(pChannel->DMACCConfig & _E);
+}
+
+void
+MODDMA::Disable(CHANNELS ChannelNumber)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber );
+    pChannel->DMACCConfig &= ~(_E);
+}
+
+bool
+MODDMA::isActive(CHANNELS ChannelNumber)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber );
+    return (bool)( pChannel->DMACCConfig & CxConfig_A() ) ;
+}
+
+void 
+MODDMA::haltChannel(CHANNELS ChannelNumber)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber );
+    pChannel->DMACCConfig |= CxConfig_H();
+}
+
+uint32_t oldDMAHandler = 0;
+typedef void (*MODDMA_FN)(void);
+
+extern "C" void MODDMA_IRQHandler(void) {
+    uint32_t channel_mask;
+        
+    if (moddma_p == (class MODDMA *)NULL) {
+        if (oldDMAHandler) {
+            ((MODDMA_FN)oldDMAHandler)();
+            return;
+        }
+        else {
+            error("Interrupt without instance");
+        }
+    }
+    
+    for (int channel_number = 0; channel_number < 8; channel_number++) {
+        channel_mask = (1UL << channel_number);
+        if (LPC_GPDMA->DMACIntStat & channel_mask) {
+            if (LPC_GPDMA->DMACIntTCStat & channel_mask) {
+                if (moddma_p->setups[channel_number] != (MODDMA_Config *)NULL) {
+                    moddma_p->setIrqProcessingChannel((MODDMA::CHANNELS)channel_number);
+                    moddma_p->setIrqType(MODDMA::TcIrq);
+                    moddma_p->setups[channel_number]->isrIntTCStat->call();
+                    moddma_p->isrIntTCStat.call();
+                    // The user callback should clear the IRQ. But if they forget
+                    // then the Mbed will lockup. So, check to see if the IRQ has
+                    // been dismissed, if not, we will dismiss it here.
+                    if (LPC_GPDMA->DMACIntTCStat & channel_mask) {
+                        LPC_GPDMA->DMACIntTCClear = channel_mask;
+                    }
+                    // If the user has left the channel enabled, disable it.
+                    // Not, we don't check Active here as it may block inside
+                    // an ISR, we just shut it down immediately. If the user
+                    // must wait for completion they should implement their
+                    // own ISR.
+                    if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) {
+                        moddma_p->Disable( (MODDMA::CHANNELS)channel_number );
+                    }
+                }            
+            }
+            
+            if (LPC_GPDMA->DMACIntErrStat & channel_mask) {
+                if (moddma_p->setups[channel_number] != (MODDMA_Config *)NULL) {
+                    moddma_p->setIrqProcessingChannel((MODDMA::CHANNELS)channel_number);
+                    moddma_p->setIrqType(MODDMA::ErrIrq);
+                    moddma_p->setups[channel_number]->isrIntErrStat->call();
+                    moddma_p->isrIntErrStat.call();
+                    // The user callback should clear the IRQ. But if they forget
+                    // then the Mbed will lockup. So, check to see if the IRQ has
+                    // been dismissed, if not, we will dismiss it here.
+                    if (LPC_GPDMA->DMACIntErrStat & channel_mask) {
+                        LPC_GPDMA->DMACIntErrClr = channel_mask;
+                    }
+                    // If the user has left the channel enabled, disable it.
+                    // Not, we don't check Active here as it may block inside
+                    // an ISR, we just shut it down immediately. If the user
+                    // must wait for completion they should implement their
+                    // own ISR.
+                    if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) {
+                        moddma_p->Disable( (MODDMA::CHANNELS)channel_number );
+                    }
+                }            
+            }
+        }
+    }
+    
+    /* IRQ should be handled by now, check to make sure. */
+    if (LPC_GPDMA->DMACIntStat) {
+        ((MODDMA_FN)oldDMAHandler)();
+        LPC_GPDMA->DMACIntTCClear = (uint32_t)0xFF; /* If not, clear anyway! */
+    }
+    if (LPC_GPDMA->DMACIntErrStat) {
+        ((MODDMA_FN)oldDMAHandler)();
+        LPC_GPDMA->DMACIntErrClr = (uint32_t)0xFF; /* If not, clear anyway! */
+    }
+}
+
+}; // namespace AjK ends
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODDMA.h	Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,508 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+    
+    @file          MODDMA.h 
+    @purpose       Adds DMA controller and multiple transfer configurations
+    @version       1.0
+    @date          Nov 2010
+    @author        Andy Kirkham    
+*/
+
+#ifndef MODDMA_H
+#define MODDMA_H
+
+/** @defgroup API The MODSERIAL API */
+/** @defgroup MISC Misc MODSERIAL functions */
+/** @defgroup INTERNALS MODSERIAL Internals */
+
+#include "mbed.h"
+
+namespace AjK {
+
+/**
+ * @author Andy Kirkham
+ * @see http://mbed.org/cookbook/MODDMA
+ * @see example1.cpp
+ * @see API 
+ *
+ * <b>MODDMA</b> defines a GPDMA controller and multiple DMA configurations that allow for DMA
+ * transfers from memory to memory, memory to peripheral or peripheral to memory.
+ *
+ * At the heart of the library is the MODDMA class the defines a single instance controller that
+ * manages all the GPDMA hardware registers and interrupts. The controller can accept multiple
+ * configurations that define the transfer. Each configuration specifies the src and dest information
+ * and other associated parts to maintain the transfer process.
+ *
+ * Standard example:
+ * @code
+ * #include "mbed.h"
+ * #include "MODDMA.h"
+ *
+ * DigitalOut led1(LED1);
+ * Serial pc(USBTX, USBRX); // tx, rx
+ * MODDMA dma;
+ *
+ * int main() {
+ *
+ *     // Create a string buffer to send directly to a Uart/Serial
+ *     char s[] = "***DMA*** ABCDEFGHIJKLMNOPQRSTUVWXYZ ***DMA***";
+ *
+ *     // Create a transfer configuarion
+ *     MODDMA_Config *config = new MODDMA_Config;
+ *
+ *     // Provide a "minimal" setup for demo purposes.
+ *     config
+ *      ->channelNum    ( MODDMA::Channel_0 )   // The DMA channel to use.
+ *      ->srcMemAddr    ( (uint32_t) &s )       // A pointer to the buffer to send.
+ *      ->transferSize  ( sizeof(s) )           // The size of that buffer.
+ *      ->transferType  ( MODDMA::m2p )         // Buffer is memory, dest is peripheral
+ *      ->dstConn       ( MODDMA::UART0_Tx )    // Specifically, peripheral is Uart0 TX (USBTX, USBRX)
+ *    ; // config end.
+ *
+ *    // Pass the configuration to the MODDMA controller.
+ *    dma.Setup( config );
+ *
+ *    // Enable the channel and begin transfer.
+ *    dma.Enable( config->channelNum() );
+ *
+ *    while(1) {
+ *         led1 = !led1;
+ *         wait(0.25);
+ *     }
+ * }
+ * @endcode
+ */
+class  MODDMA_Config {
+protected:
+
+    // *****************************************
+    // From GPDMA by NXP MCU SW Application Team
+    // *****************************************
+    
+    uint32_t ChannelNum;        //!< DMA channel number, should be in range from 0 to 7. 
+    uint32_t TransferSize;      //!< Length/Size of transfer 
+    uint32_t TransferWidth;     //!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_m2m only 
+    uint32_t SrcMemAddr;        //!< Physical Src Addr, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::m2p 
+    uint32_t DstMemAddr;        //!< Physical Destination Address, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::p2m 
+    uint32_t TransferType;      //!< Transfer Type
+    uint32_t SrcConn;           //!< Peripheral Source Connection type, used in case TransferType is chosen as
+    uint32_t DstConn;           //!< Peripheral Destination Connection type, used in case TransferType is chosen as
+    uint32_t DMALLI;            //!< Linker List Item structure data address if there's no Linker List, set as '0'
+    
+    // Mbed specifics.
+
+public: 
+   
+    MODDMA_Config() {
+        isrIntTCStat  = new FunctionPointer;
+        isrIntErrStat = new FunctionPointer;
+        ChannelNum    = 0xFFFF;
+        TransferSize  = 0;
+        TransferWidth = 0;
+        SrcMemAddr    = 0;
+        DstMemAddr    = 0;
+        TransferType  = 0;
+        SrcConn       = 0;
+        DstConn       = 0;
+        DMALLI        = 0;
+    }
+    
+    ~MODDMA_Config() {
+        delete(isrIntTCStat);
+        delete(isrIntErrStat);
+    }
+        
+    class MODDMA_Config * channelNum(uint32_t n)    { ChannelNum = n & 0x7;  return this; }
+    class MODDMA_Config * transferSize(uint32_t n)  { TransferSize = n;      return this; }
+    class MODDMA_Config * transferWidth(uint32_t n) { TransferWidth = n;     return this; }
+    class MODDMA_Config * srcMemAddr(uint32_t n)    { SrcMemAddr = n;        return this; }
+    class MODDMA_Config * dstMemAddr(uint32_t n)    { DstMemAddr = n;        return this; }
+    class MODDMA_Config * transferType(uint32_t n)  { TransferType = n;      return this; }
+    class MODDMA_Config * srcConn(uint32_t n)       { SrcConn = n;           return this; }
+    class MODDMA_Config * dstConn(uint32_t n)       { DstConn = n;           return this; }
+    class MODDMA_Config * dmaLLI(uint32_t n)        { DMALLI = n;            return this; }
+    
+    uint32_t channelNum(void)    { return ChannelNum;    }
+    uint32_t transferSize(void)  { return TransferSize;  }
+    uint32_t transferWidth(void) { return TransferWidth; }
+    uint32_t srcMemAddr(void)    { return SrcMemAddr;    }
+    uint32_t dstMemAddr(void)    { return DstMemAddr;    }
+    uint32_t transferType(void)  { return TransferType;  }
+    uint32_t srcConn(void)       { return SrcConn;       }
+    uint32_t dstConn(void)       { return DstConn;       }
+    uint32_t dmaLLI(void)        { return DMALLI;        }
+    
+    FunctionPointer *isrIntTCStat;                        
+    FunctionPointer *isrIntErrStat;                        
+};
+
+/**
+ * @brief GPDMA Linker List Item structure type definition
+ */
+ /*
+typedef struct {
+    uint32_t SrcAddr;    //!< Source Address 
+    uint32_t DstAddr;    //!< Destination address 
+    uint32_t NextLLI;    //!< Next LLI address, otherwise set to '0' 
+    uint32_t Control;    //!< GPDMA Control of this LLI 
+} GPDMA_LLI_t;
+*/
+
+/**
+ * @author Andy Kirkham
+ * @see http://mbed.org/cookbook/MODDMA_Config
+ * @see MODDMA
+ * @see API 
+ *
+ * <b>MODDMA_Config</b> defines a configuration that can be passed to the MODDMA controller
+ * instance to perform a GPDMA data transfer.
+ * transfers from memory to memory, memory to peripheral or peripheral to memory.
+ */
+class MODDMA
+{
+public:
+
+    //! Channel definitions.
+    enum CHANNELS {
+          Channel_0 = 0     /*!< Channel 0 */ 
+        , Channel_1         /*!< Channel 1 */ 
+        , Channel_2         /*!< Channel 2 */ 
+        , Channel_3         /*!< Channel 3 */ 
+        , Channel_4         /*!< Channel 4 */ 
+        , Channel_5         /*!< Channel 5 */ 
+        , Channel_6         /*!< Channel 6 */ 
+        , Channel_7         /*!< Channel 7 */ 
+    };
+    
+    //! Interrupt callback types.
+    enum IrqType_t {
+          TcIrq = 0     /*!< Terminal Count interrupt */
+        , ErrIrq        /*!< Error interrupt */
+    };
+    
+    //! Return status codes.
+    enum Status {
+          Ok            = 0     /*!< Ok, suceeded */
+        , Error         = -1    /*!< General error */
+        , ErrChInUse    = -2    /*!< Specific error, channel in use */
+    };
+    
+    //! DMA Connection number definitions 
+    enum GPDMA_CONNECTION {
+          SSP0_Tx       = 0UL   /*!< SSP0 Tx */
+        , SSP0_Rx       = 1UL   /*!< SSP0 Rx */
+        , SSP1_Tx       = 2UL   /*!< SSP1 Tx */
+        , SSP1_Rx       = 3UL   /*!< SSP1 Rx */
+        , ADC           = 4UL   /*!< ADC */
+        , I2S_Channel_0 = 5UL   /*!< I2S channel 0 */
+        , I2S_Channel_1 = 6UL   /*!< I2S channel 1 */
+        , DAC           = 7UL   /*!< DAC */
+        , UART0_Tx      = 8UL   /*!< UART0 Tx */
+        , UART0_Rx      = 9UL   /*!< UART0 Rx */
+        , UART1_Tx      = 10UL  /*!< UART1 Tx */
+        , UART1_Rx      = 11UL  /*!< UART1 Rx */
+        , UART2_Tx      = 12UL  /*!< UART2 Tx */
+        , UART2_Rx      = 13UL  /*!< UART2 Rx */
+        , UART3_Tx      = 14UL  /*!< UART3 Tx */
+        , UART3_Rx      = 15UL  /*!< UART3 Rx */
+        , MAT0_0        = 16UL  /*!< MAT0.0 */
+        , MAT0_1        = 17UL  /*!< MAT0.1 */
+        , MAT1_0        = 18UL  /*!< MAT1.0 */
+        , MAT1_1        = 19UL  /*!< MAT1.1 */
+        , MAT2_0        = 20UL  /**< MAT2.0 */
+        , MAT2_1        = 21UL  /*!< MAT2.1 */
+        , MAT3_0        = 22UL  /*!< MAT3.0 */
+        , MAT3_1        = 23UL  /*!< MAT3.1 */
+    };
+
+    //! GPDMA Transfer type definitions 
+    enum  GPDMA_TRANSFERTYPE {
+          m2m = 0UL     /*!< Memory to memory - DMA control */
+        , m2p = 1UL     /*!< Memory to peripheral - DMA control */
+        , p2m = 2UL     /*!< Peripheral to memory - DMA control */
+        , p2p = 3UL     /*!< Src peripheral to dest peripheral - DMA control */        
+    };   
+
+    //! Burst size in Source and Destination definitions */
+    enum GPDMA_BSIZE {
+          _1    = 0UL   /*!< Burst size = 1 */
+        , _4    = 1UL   /*!< Burst size = 4 */
+        , _8    = 2UL   /*!< Burst size = 8 */
+        , _16   = 3UL   /*!< Burst size = 16 */
+        , _32   = 4UL   /*!< Burst size = 32 */
+        , _64   = 5UL   /*!< Burst size = 64 */
+        , _128  = 6UL   /*!< Burst size = 128 */
+        , _256  = 7UL   /*!< Burst size = 256 */
+    };
+    
+    //! Width in Src transfer width and Dest transfer width definitions */
+    enum GPDMA_WIDTH {
+          byte     = 0UL    /*!< Width = 1 byte */
+        , halfword = 1UL    /*!< Width = 2 bytes */
+        , word     = 2UL    /*!< Width = 4 bytes */
+    };
+    
+    //! DMA Request Select Mode definitions. */
+    enum GPDMA_REQSEL {
+          uart  = 0UL   /*!< UART TX/RX is selected */
+        , timer = 1UL   /*!< Timer match is selected */
+    };
+
+    //! GPDMA Control register bits.
+    enum Config {
+          _E = 1        /*!< DMA Controller enable */
+        , _M = 2        /*!< AHB Master endianness configuration */
+    };    
+
+    //! GPDMA Channel config register bits.
+    enum CConfig {
+          _CE  = (1UL << 0)     /*!< Channel enable */
+        , _IE  = (1UL << 14)    /*!< Interrupt error mask */
+        , _ITC = (1UL << 15)    /*!< Terminal count interrupt mask */
+        , _L   = (1UL << 16)    /*!< Lock */
+        , _A   = (1UL << 17)    /*!< Active */
+        , _H   = (1UL << 18)    /*!< Halt */
+    };
+    
+    /**
+     * The MODDMA constructor is used to initialise the DMA controller object.
+     */    
+    MODDMA() { init(true); }
+    
+    /**
+     * The MODDMA destructor.
+     */    
+    ~MODDMA() {}
+    
+    /**
+     * Used to setup the DMA controller to prepare for a data transfer.
+     *
+     * @param c A pointer to an instance of MODDMA_Config to setup.
+     */
+    Status Setup(MODDMA_Config *c);
+    
+    /**
+     * Enable and begin data transfer.
+     *
+     * @param ChannelNumber Type CHANNELS, the channel number to enable
+     */
+    void Enable(CHANNELS ChannelNumber);
+    
+    /**
+     * Enable and begin data transfer (overloaded function)
+     *
+     * @param ChannelNumber Type uin32_t, the channel number to enable
+     */
+    void Enable(uint32_t ChannelNumber) { Enable((CHANNELS)(ChannelNumber & 0x7)); }
+    
+    /**
+     * Disable a channel and end data transfer.
+     *
+     * @param ChannelNumber Type CHANNELS, the channel number to enable
+     */
+    void Disable(CHANNELS ChannelNumber);
+    
+    /**
+     * Disable a channel and end data transfer (overloaded function)
+     *
+     * @param ChannelNumber Type uin32_t, the channel number to disable
+     */
+    void Disable(uint32_t ChannelNumber) { Disable((CHANNELS)(ChannelNumber & 0x7)); }
+    
+    /**
+     * Is the specified channel enabled?
+     *
+     * @param ChannelNumber Type CHANNELS, the channel number to test
+     * @return bool true if enabled, false otherwise.
+     */
+    bool Enabled(CHANNELS ChannelNumber);
+    
+    /**
+     * Is the specified channel enabled? (overloaded function)
+     *
+     * @param ChannelNumber Type uin32_t, the channel number to test
+     * @return bool true if enabled, false otherwise.
+     */
+    bool Enabled(uint32_t ChannelNumber) { Enabled((CHANNELS)(ChannelNumber & 0x7)); }
+    
+    __INLINE uint32_t IntStat(uint32_t n)            { return (1UL << n) & 0xFF; }
+    __INLINE uint32_t IntTCStat_Ch(uint32_t n)       { return (1UL << n) & 0xFF; }
+    __INLINE uint32_t IntTCClear_Ch(uint32_t n)      { return (1UL << n) & 0xFF; }
+    __INLINE uint32_t IntErrStat_Ch(uint32_t n)      { return (1UL << n) & 0xFF; }
+    __INLINE uint32_t IntErrClr_Ch(uint32_t n)       { return (1UL << n) & 0xFF; }
+    __INLINE uint32_t RawIntErrStat_Ch(uint32_t n)   { return (1UL << n) & 0xFF; }
+    __INLINE uint32_t EnbldChns_Ch(uint32_t n)       { return (1UL << n) & 0xFF; }
+    __INLINE uint32_t SoftBReq_Src(uint32_t n)       { return (1UL << n) & 0xFFFF; }
+    __INLINE uint32_t SoftSReq_Src(uint32_t n)       { return (1UL << n) & 0xFFFF; }
+    __INLINE uint32_t SoftLBReq_Src(uint32_t n)      { return (1UL << n) & 0xFFFF; }
+    __INLINE uint32_t SoftLSReq_Src(uint32_t n)      { return (1UL << n) & 0xFFFF; }
+    __INLINE uint32_t Sync_Src(uint32_t n)           { return (1UL << n) & 0xFFFF; }
+    __INLINE uint32_t ReqSel_Input(uint32_t n)       { return (1UL << (n - 8)) & 0xFF; }
+    
+
+    __INLINE uint32_t CxControl_TransferSize(uint32_t n)     { return (n & 0xFFF) << 0; }
+    __INLINE uint32_t CxControl_SBSize(uint32_t n)           { return (n & 0x7) << 12; }
+    __INLINE uint32_t CxControl_DBSize(uint32_t n)           { return (n & 0x7) << 15; }
+    __INLINE uint32_t CxControl_SWidth(uint32_t n)           { return (n & 0x7) << 18; }
+    __INLINE uint32_t CxControl_DWidth(uint32_t n)           { return (n & 0x7) << 21; }
+    __INLINE uint32_t CxControl_SI()                         { return (1UL << 26); }
+    __INLINE uint32_t CxControl_DI()                         { return (1UL << 27); }
+    __INLINE uint32_t CxControl_Prot1()                      { return (1UL << 28); }
+    __INLINE uint32_t CxControl_Prot2()                      { return (1UL << 29); }
+    __INLINE uint32_t CxControl_Prot3()                      { return (1UL << 30); }
+    __INLINE uint32_t CxControl_I()                          { return (1UL << 31); }
+    __INLINE uint32_t CxControl_E()                          { return (1UL << 0); }
+    __INLINE uint32_t CxConfig_SrcPeripheral(uint32_t n)     { return (n & 0x1F) << 1; }
+    __INLINE uint32_t CxConfig_DestPeripheral(uint32_t n)    { return (n & 0x1F) << 6; }
+    __INLINE uint32_t CxConfig_TransferType(uint32_t n)      { return (n & 0x7) << 11; }
+    __INLINE uint32_t CxConfig_IE()                          { return (1UL << 14); }
+    __INLINE uint32_t CxConfig_ITC()                         { return (1UL << 15); }
+    __INLINE uint32_t CxConfig_L()                           { return (1UL << 16); }
+    __INLINE uint32_t CxConfig_A()                           { return (1UL << 17); }
+    __INLINE uint32_t CxConfig_H()                           { return (1UL << 18); }
+    
+    /**
+     * A store for up to 8 (8 channels) of configurations.
+     * @see MODDMA_Config
+     */
+    MODDMA_Config *setups[8];
+    
+    /**
+     * Get a pointer to the current configuration the ISR is servicing.
+     *
+     * @return MODDMA_Config * A pointer to the setup the ISR is currently servicing.
+     */
+    MODDMA_Config *getConfig(void) { return setups[IrqProcessingChannel]; }
+    
+    /**
+     * Set which channel the ISR is currently servicing.
+     *
+     * *** USED INTERNALLY. DO NOT CALL FROM USER PROGRAMS ***
+     *
+     * Must be public so the extern "C" ISR can use it.
+     */
+    void setIrqProcessingChannel(CHANNELS n) { IrqProcessingChannel = n; }
+    
+    /**
+     * Gets which channel the ISR is currently servicing.
+     *
+     * @return CHANNELS The current channel the ISR is servicing.
+     */
+    CHANNELS irqProcessingChannel(void) { return IrqProcessingChannel; }
+    
+    /**
+     * Gets which channel the ISR is currently servicing.
+     *
+     * @return uint32_t The current channel the ISR is servicing.
+     */
+    uint32_t irqProcessingChannel(void) { return (uint32_t)(IrqProcessingChannel & 0x7); }
+    
+    /**
+     * Sets which type of IRQ the ISR is making a callback for.
+     *
+     * *** USED INTERNALLY. DO NOT CALL FROM USER PROGRAMS ***
+     *
+     * Must be public so the extern "C" ISR can use it.
+     */ 
+    void setIrqType(IrqType_t n) { IrqType = n; }
+    
+    /**
+     * Get which type of IRQ the ISR is calling you about,
+     * terminal count or error.
+     */
+    IrqType_t irqType(void) { return IrqType; }
+    
+    /**
+     * Clear the interrupt after handling.
+     *
+     * @param CHANNELS The channel the IQR occured on.
+     */
+    void clearTcIrq(CHANNELS n) { LPC_GPDMA->DMACIntTCClear = (uint32_t)(1UL << n); } 
+    
+    /**
+     * Clear the interrupt the ISR is currently handing..
+     */
+    void clearTcIrq(void) { clearTcIrq( IrqProcessingChannel ); }
+    
+    /**
+     * Clear the error interrupt after handling.
+     *
+     * @param CHANNELS The channel the IQR occured on.
+     */
+    void clearErrIrq(CHANNELS n) { LPC_GPDMA->DMACIntTCClear = (uint32_t)(1UL << n); } 
+    
+    /**
+     * Clear the error interrupt the ISR is currently handing.
+     */
+    void clearErrIrq(void) { clearErrIrq( IrqProcessingChannel ); }
+   
+    /**
+     * Is the supplied channel currently active?
+     *
+     * @param CHANNELS The channel to inquire about.
+     * @return bool true if active, false otherwise.
+     */     
+    bool isActive(CHANNELS ChannelNumber);
+    
+    /**
+     * Halt the supplied channel. 
+     *
+     * @param CHANNELS The channel to halt.
+     */
+    void haltChannel(CHANNELS ChannelNumber);
+    
+    /**
+     * Wait for channel transfer to complete and then halt.
+     *
+     * @param CHANNELS The channel to wait for then halt.
+     */
+    void haltAndWaitChannelComplete(CHANNELS n) { haltChannel(n); while (isActive(n)); }
+    
+    /**
+     * The MODDMA controllers terminal count interrupt callback.
+     */
+    FunctionPointer isrIntTCStat;                        
+    
+    /**
+     * The MODDMA controllers error interrupt callback.
+     */
+    FunctionPointer isrIntErrStat;                        
+    
+protected:
+
+    void init(bool isConstructorCalling, int Channels = 0xFF, int Tc = 0xFF, int Err = 0xFF);
+    
+    // Data LUTs.
+    uint32_t LUTPerAddr(int n);
+    uint8_t  LUTPerBurst(int n);
+    uint8_t  LUTPerWid(int n);    
+    uint32_t Channel_p(int channel);
+    
+    CHANNELS IrqProcessingChannel;
+    
+    IrqType_t IrqType;
+};
+
+}; // namespace AjK ends.
+
+using namespace AjK;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SETUP.cpp	Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,156 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#include "MODDMA.h"
+
+namespace AjK {
+
+MODDMA::Status
+MODDMA::Setup(MODDMA_Config *config)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( config->channelNum() );
+    
+    if (LPC_GPDMA->DMACEnbldChns & EnbldChns_Ch( config->channelNum() )) {
+        return ErrChInUse;
+    }
+    
+    setups[config->channelNum() & 0x7] = config;
+    
+    // Reset the Interrupt status
+    LPC_GPDMA->DMACIntTCClear = IntTCClear_Ch( config->channelNum() );
+    LPC_GPDMA->DMACIntErrClr  = IntErrClr_Ch ( config->channelNum() );
+
+    // Clear DMA configure
+    pChannel->DMACCControl = 0x00;
+    pChannel->DMACCConfig  = 0x00;
+
+    // Assign Linker List Item value 
+    pChannel->DMACCLLI = config->dmaLLI();
+
+    // Set value to Channel Control Registers 
+    switch (config->transferType()) {
+    
+        // Memory to memory
+        case m2m:
+            // Assign physical source and destination address
+            pChannel->DMACCSrcAddr  = config->srcMemAddr();
+            pChannel->DMACCDestAddr = config->dstMemAddr();
+            pChannel->DMACCControl
+                = CxControl_TransferSize(config->transferSize()) 
+                | CxControl_SBSize(_32) 
+                | CxControl_DBSize(_32) 
+                | CxControl_SWidth(config->transferWidth()) 
+                | CxControl_DWidth(config->transferWidth()) 
+                | CxControl_SI() 
+                | CxControl_DI() 
+                | CxControl_I();
+            break;
+            
+        // Memory to peripheral
+        case m2p:
+            // Assign physical source
+            pChannel->DMACCSrcAddr = config->srcMemAddr();
+            // Assign peripheral destination address
+            pChannel->DMACCDestAddr = (uint32_t)LUTPerAddr(config->dstConn());
+            pChannel->DMACCControl
+                = CxControl_TransferSize((uint32_t)config->transferSize()) 
+                | CxControl_SBSize((uint32_t)LUTPerBurst(config->dstConn())) 
+                | CxControl_DBSize((uint32_t)LUTPerBurst(config->dstConn())) 
+                | CxControl_SWidth((uint32_t)LUTPerWid(config->dstConn())) 
+                | CxControl_DWidth((uint32_t)LUTPerWid(config->dstConn())) 
+                | CxControl_SI() 
+                | CxControl_I();
+            break;
+            
+        // Peripheral to memory
+        case p2m:
+            // Assign peripheral source address
+            pChannel->DMACCSrcAddr = (uint32_t)LUTPerAddr(config->srcConn());
+            // Assign memory destination address
+            pChannel->DMACCDestAddr = config->dstMemAddr();
+            pChannel->DMACCControl
+                = CxControl_TransferSize((uint32_t)config->transferSize()) 
+                | CxControl_SBSize((uint32_t)LUTPerBurst(config->srcConn())) 
+                | CxControl_DBSize((uint32_t)LUTPerBurst(config->srcConn())) 
+                | CxControl_SWidth((uint32_t)LUTPerWid(config->srcConn())) 
+                | CxControl_DWidth((uint32_t)LUTPerWid(config->srcConn())) 
+                | CxControl_DI() 
+                | CxControl_I();
+            break;
+            
+        // Peripheral to peripheral
+        case p2p:
+            // Assign peripheral source address
+            pChannel->DMACCSrcAddr = (uint32_t)LUTPerAddr(config->srcConn());
+            // Assign peripheral destination address
+            pChannel->DMACCDestAddr = (uint32_t)LUTPerAddr(config->dstConn());
+            pChannel->DMACCControl
+                = CxControl_TransferSize((uint32_t)config->transferSize()) 
+                | CxControl_SBSize((uint32_t)LUTPerBurst(config->srcConn())) 
+                | CxControl_DBSize((uint32_t)LUTPerBurst(config->dstConn())) 
+                | CxControl_SWidth((uint32_t)LUTPerWid(config->srcConn())) 
+                | CxControl_DWidth((uint32_t)LUTPerWid(config->dstConn())) 
+                | CxControl_I();
+            break;
+            
+        // Do not support any more transfer type, return ERROR
+        default:
+            return Error;
+    }
+
+     // Re-Configure DMA Request Select for source peripheral 
+    if (config->srcConn() > 15) {
+        LPC_SC->RESERVED9 |= (1 << (config->srcConn() - 16));
+    } 
+    else {
+        LPC_SC->RESERVED9 &= ~(1 << (config->srcConn() - 8));
+    }
+
+    // Re-Configure DMA Request Select for Destination peripheral
+    if (config->dstConn() > 15) {
+        LPC_SC->RESERVED9 |= (1 << (config->dstConn() - 16));
+    } 
+    else {
+        LPC_SC->RESERVED9 &= ~(1 << (config->dstConn() - 8));
+    }
+
+    // Enable DMA channels, little endian 
+    LPC_GPDMA->DMACConfig = _E;
+    while (!(LPC_GPDMA->DMACConfig & _E));
+
+    // Calculate absolute value for Connection number
+    uint32_t tmp1 = config->srcConn(); tmp1 = ((tmp1 > 15) ? (tmp1 - 8) : tmp1);
+    uint32_t tmp2 = config->dstConn(); tmp2 = ((tmp2 > 15) ? (tmp2 - 8) : tmp2);
+
+    // Configure DMA Channel, enable Error Counter and Terminate counter
+    pChannel->DMACCConfig 
+        = CxConfig_IE() 
+        | CxConfig_ITC() 
+        | CxConfig_TransferType((uint32_t)config->transferType()) 
+        | CxConfig_SrcPeripheral(tmp1) 
+        | CxConfig_DestPeripheral(tmp2);
+
+    return Ok;
+}
+
+}; // namespace AjK ends
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example1.cpp	Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,71 @@
+#ifdef COMPILE_EXAMPLE_CODE_MODDMA
+
+#include "mbed.h"
+#include "MODDMA.h"
+#include "MODSERIAL.h"
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+MODDMA dma;
+MODSERIAL pc(USBTX, USBRX);
+//Serial pc(USBTX, USBRX);
+
+void dmaCallback(void) {
+    led2 = 1;
+}
+
+void C0callback(void) {
+    MODDMA_Config *config = dma.getConfig();
+    dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum());
+    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
+    if (dma.irqType() == MODDMA::TcIrq)  {
+        led3 = 1;
+        dma.clearTcIrq();
+    }
+    if (dma.irqType() == MODDMA::ErrIrq) {
+        led4 = 1;
+        dma.clearErrIrq();
+    }
+}
+
+int main() {
+    char s[] = "**DMA** ABCDEFGHIJKLMNOPQRSTUVWXYZ **DMA**";
+    
+    pc.baud(115200);
+    
+    dma.isrIntTCStat.attach(&dmaCallback);
+    
+    MODDMA_Config *config = new MODDMA_Config;
+    config
+     ->channelNum    ( MODDMA::Channel_0 )
+     ->srcMemAddr    ( (uint32_t) &s )
+     //->dstMemAddr    ( 0 )
+     ->transferSize  ( sizeof(s) )
+     ->transferType  ( MODDMA::m2p )
+     //->transferWidth ( 0 )
+     //->srcConn       ( 0 )
+     ->dstConn       ( MODDMA::UART0_Tx )
+     //->dmaLLI        ( 0 )
+     ;//->isrIntTCStat->attach(&C0callback)
+    ; // config end
+   
+    dma.Setup(config);
+    
+    //dma.Enable( MODDMA::Channel_0 );
+    dma.Enable( config->channelNum() );
+    
+    pc.printf("123456789\r\n");
+    pc.printf("\r\nRESERVED9 = %p", &LPC_SC->RESERVED9);
+    pc.printf("\r\nOther = %p", &LPC_UART0->DMAREQSEL);
+    
+    while (1) {
+        led1 = !led1;
+        wait(0.2);
+        led1 = !led1;
+        wait(0.2);
+    }
+}
+
+#endif