DSP program for the Surfboard hardware (PCB to be open sourced) http://www.avbotz.com/ourauv/electrical/signal-processing/

Dependencies:   MODDMA SimpleIOMacros mbed-dsp mbed

Revision:
0:2381a319fc35
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODDMA_cache.cpp	Fri Aug 02 02:23:36 2013 +0000
@@ -0,0 +1,606 @@
+#include "MODDMA_cache.h"
+
+// Exists so the IRQ handler can access MODDMA object.
+MODDMA_Cache* moddma_p;
+
+// Setup the DMA controller and then cache some values. they will be used in Reset().
+// does not work; these values do not change. we aren't caching the right ones.
+
+MODDMA_Cache::MODDMA_Cache()
+{
+    moddma_p = this;
+    init();
+}
+
+// A copy of Kirkham's setup function. This caches most values as they are set. 
+uint32_t MODDMA_Cache::Setup(MODDMA_Config* config)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( config->channelNum() );
+    
+    setups[config->channelNum() & 0x7] = config;
+    
+    // Reset the Interrupt status
+    LPC_GPDMA->DMACIntTCClear = DMACIntTCClear = IntTCClear_Ch( config->channelNum() );
+    LPC_GPDMA->DMACIntErrClr  = DMACIntErrClr  = IntErrClr_Ch ( config->channelNum() );
+
+    // Clear DMA configure
+    pChannel->DMACCControl = 0x00;
+    pChannel->DMACCConfig  = 0x00;
+
+    // Assign Linker List Item value 
+    pChannel->DMACCLLI = 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 = DMACCSrcAddr = config->srcMemAddr();
+            // Assign peripheral destination address
+            pChannel->DMACCDestAddr = DMACCDestAddr = (uint32_t)LUTPerAddr(config->dstConn());
+            pChannel->DMACCControl = 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 = DMACCSrcAddr = (uint32_t)LUTPerAddr(config->srcConn());
+            // Assign memory destination address
+            pChannel->DMACCDestAddr = DMACCDestAddr = config->dstMemAddr();
+            pChannel->DMACCControl = 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;
+            
+        // GPIO to memory
+        case g2m:
+            // Assign GPIO source address
+            pChannel->DMACCSrcAddr = config->srcMemAddr();
+            // 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;
+            
+        // Memory to GPIO
+        case m2g:
+            // Assign physical source
+            pChannel->DMACCSrcAddr = config->srcMemAddr();
+            // Assign peripheral destination address
+            pChannel->DMACCDestAddr = config->dstMemAddr();
+            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;
+            
+        // Do not support any more transfer type, return ERROR
+        default:
+            return 0;
+    }
+
+     // Re-Configure DMA Request Select for source peripheral 
+    if (config->srcConn() > 15) {
+        DMAREQSEL = LPC_SC->DMAREQSEL |= (1 << (config->srcConn() - 16));
+    } 
+    else {
+        DMAREQSEL = LPC_SC->DMAREQSEL &= ~(1 << (config->srcConn() - 8));
+    }
+
+    // Re-Configure DMA Request Select for destination peripheral
+    if (config->dstConn() > 15) {
+        DMAREQSEL = LPC_SC->DMAREQSEL |= (1 << (config->dstConn() - 16));
+    } 
+    else {
+        DMAREQSEL = LPC_SC->DMAREQSEL &= ~(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);
+
+    if (config->dmacSync()) {
+        uint32_t tmp3 = config->dmacSync(); tmp3 = ((tmp3 > 15) ? (tmp3 - 8) : tmp3);
+        LPC_GPDMA->DMACSync |= DMACSync = Sync_Src( tmp3 );
+    }
+    
+    uint32_t tfer_type = (uint32_t)config->transferType();
+    if (tfer_type == g2m || tfer_type == m2g) {
+        tfer_type -= 2; // Adjust psuedo transferType to a real transferType.
+    }
+    
+    // Configure DMA Channel, enable Error Counter and Terminate counter
+    pChannel->DMACCConfig = DMACCConfig
+        = CxConfig_IE() 
+        | CxConfig_ITC() 
+        | CxConfig_TransferType(tfer_type) 
+        | CxConfig_SrcPeripheral(tmp1) 
+        | CxConfig_DestPeripheral(tmp2);
+
+    return pChannel->DMACCControl;
+}
+/*
+uint32_t MODDMA_Cache::Setup(MODDMA_Config* config)
+{
+    moddma_p = this;
+    
+    //uint32_t ret = ((MODDMA*)this)->Setup(config);
+    uint32_t ret = MODDMA::Setup(config);
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef*)Channel_p(config->channelNum());
+    
+    DMACCSrcAddr = pChannel->DMACCSrcAddr;
+    DMACCDestAddr = pChannel->DMACCDestAddr;
+    DMACCLLI = pChannel->DMACCLLI;
+    //DMACCControl = pChannel->DMACCControl;
+    
+    switch (config->transferType())
+    {
+    case p2m:
+        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;
+        
+    case m2p:
+        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;
+        
+    default:
+        return 5000; // oh no, your mbed blew up!
+    }
+    
+    uint32_t tmp1 = config->srcConn(); tmp1 = ((tmp1 > 15) ? (tmp1 - 8) : tmp1);
+    uint32_t tmp2 = config->dstConn(); tmp2 = ((tmp2 > 15) ? (tmp2 - 8) : tmp2);
+
+    if (config->dmacSync()) {
+        uint32_t tmp3 = config->dmacSync(); tmp3 = ((tmp3 > 15) ? (tmp3 - 8) : tmp3);
+        LPC_GPDMA->DMACSync |= Sync_Src( tmp3 );
+    }
+    
+    uint32_t tfer_type = (uint32_t)config->transferType();
+    if (tfer_type == g2m || tfer_type == m2g) {
+        tfer_type -= 2; // Adjust psuedo transferType to a real transferType.
+    }
+    
+    // Configure DMA Channel, enable Error Counter and Terminate counter
+        DMACCConfig = CxConfig_IE() 
+        | CxConfig_ITC() 
+        | CxConfig_TransferType(tfer_type) 
+        | CxConfig_SrcPeripheral(tmp1) 
+        | CxConfig_DestPeripheral(tmp2);
+    
+    DMACSync = LPC_GPDMA->DMACSync;
+    
+    return ret;
+}*/
+
+// This is modified from MODDMA::Setup(). Values that don't change between DMA operations will be cached to make it faster.
+// Everything commented or deleted here wasn't necessary to restart DMA.
+/*void MODDMA_Cache::Reset(MODDMA_Config* config)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef*)Channel_p(config->channelNum());
+  
+    //LPC_GPDMA->DMACIntTCClear = IntTCClear_Ch( config->channelNum() );
+    //LPC_GPDMA->DMACIntErrClr  = IntErrClr_Ch ( config->channelNum() );
+    
+    //pChannel->DMACCLLI = DMACCLLI;
+    pChannel->DMACCConfig = DMACCConfig;//
+    
+    //LPC_GPDMA->DMACSync = DMACSync;
+    
+    
+    //setups[config->channelNum() & 0x7] = config;
+    
+    // Reset the Interrupt status
+    LPC_GPDMA->DMACIntTCClear = IntTCClear_Ch( config->channelNum() );//
+    LPC_GPDMA->DMACIntErrClr  = IntErrClr_Ch ( config->channelNum() );
+    
+    // BIGASS SWITCH WENT HERE
+    pChannel->DMACCControl = DMACCControl;
+    
+    if (config->transferType() == p2m)
+    {
+        pChannel->DMACCSrcAddr = DMACCSrcAddr;
+        pChannel->DMACCDestAddr = config->dstMemAddr();//
+    }
+
+    // Enable DMA channels, little endian 
+    pChannel->DMACCConfig |= _E;
+    return;
+}
+*/
+
+/*
+void MODDMA_Cache::Reset(MODDMA_Config* config)
+{
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef*)Channel_p(config->channelNum());
+  
+    LPC_GPDMA->DMACIntTCClear = IntTCClear_Ch( config->channelNum() );
+    LPC_GPDMA->DMACIntErrClr  = IntErrClr_Ch ( config->channelNum() );
+    
+    pChannel->DMACCLLI = DMACCLLI;
+    pChannel->DMACCConfig = DMACCConfig;//
+    
+    LPC_GPDMA->DMACSync = DMACSync;
+    
+    
+    setups[config->channelNum() & 0x7] = config;
+    
+    // Reset the Interrupt status
+    LPC_GPDMA->DMACIntTCClear = IntTCClear_Ch( config->channelNum() );//
+    LPC_GPDMA->DMACIntErrClr  = IntErrClr_Ch ( config->channelNum() );
+    
+    // BIGASS SWITCH WENT HERE
+    pChannel->DMACCControl = DMACCControl;
+    
+    if (config->transferType() == p2m)
+    {
+        pChannel->DMACCSrcAddr = DMACCSrcAddr;
+        pChannel->DMACCDestAddr = config->dstMemAddr();//
+    }
+
+    // Enable DMA channels, little endian 
+    //pChannel->DMACCConfig |= _E;
+    LPC_GPDMA->DMACConfig = _E;
+    return;
+}*/
+/*
+These notes based on the LPC17xx family datasheet:
+
+DMACIntTCClear
+Interrupt terminal count clear
+clear interrupt request
+from <http://dreamrunner.org/wiki/public_html/Embedded%20System/kernel/DMA.html>
+"When the value in the current count register goes from 0 to -1, a terminal count (TC) signal is generated, which signifies the completion of the DMA transfer sequence."
+"DMA controllers require reprogramming when a DMA channel reaches TC."
+
+DMACIntErrClr
+Write 1 to request that some error flags be cleared
+
+DMACCControl*
+contain tons of information: transfer size, burst size, transfer width, etc
+Updated by DMA controller when the linked list is followed. So may not change in our application?
+
+DMACCConfig
+Contains Enable, src type, dest type, transfer type, error mask (to find/mask out the error bit), terminal count irq mask, active (whether there is data), and halt (to stop transfer)
+
+DMACCLLI
+address of next linked list item. If zero, this is the last item in the list and the transfer is complete after this list item is done. 
+
+DMACCSrcAddr*
+User sets the starting address. DMA updates w/ current read address as it goes.
+
+DMACCDestAddr*
+same idea as SrcAddr, but for the data destination
+
+DMAREQSEL
+Datasheet calls it "DMAReqSel" for some reason. 
+I'm not too clear on what this is. 
+Lets you pick whether you want UART or Timer DMA for DMA inputs 8-15.
+
+*Changes very quickly while the transfer in progress, so don't bother reading at that time
+*/
+void MODDMA_Cache::Reset(MODDMA_Config *config)
+{
+    /*Setup(config);
+    return;*/
+    LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( config->channelNum() );
+    
+    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
+                = /*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
+                = /*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;
+            
+        // GPIO to memory
+        case g2m:
+            // Assign GPIO source address
+            pChannel->DMACCSrcAddr = config->srcMemAddr();
+            // 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;
+            
+        // Memory to GPIO
+        case m2g:
+            // Assign physical source
+            pChannel->DMACCSrcAddr = config->srcMemAddr();
+            // Assign peripheral destination address
+            pChannel->DMACCDestAddr = config->dstMemAddr();
+            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;
+            
+        // Do not support any more transfer type, return ERROR
+        default:
+            return;// 0;
+    }
+
+     // Re-Configure DMA Request Select for source peripheral 
+    if (config->srcConn() > 15) {
+        LPC_SC->DMAREQSEL |= (1 << (config->srcConn() - 16));
+    } 
+    else {
+        LPC_SC->DMAREQSEL &= ~(1 << (config->srcConn() - 8));
+    }
+
+    // Re-Configure DMA Request Select for destination peripheral
+    if (config->dstConn() > 15) {
+        LPC_SC->DMAREQSEL |= (1 << (config->dstConn() - 16));
+    }
+    else {
+        LPC_SC->DMAREQSEL &= ~(1 << (config->dstConn() - 8));
+    }
+
+    // Enable DMA channels, little endian 
+    LPC_GPDMA->DMACConfig = _E;
+    pChannel->DMACCConfig |= _E; // copied from MODDMA::Enable()
+    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);
+
+    if (config->dmacSync()) {
+        uint32_t tmp3 = config->dmacSync(); tmp3 = ((tmp3 > 15) ? (tmp3 - 8) : tmp3);
+        LPC_GPDMA->DMACSync |= Sync_Src( tmp3 );
+    }
+    
+    uint32_t tfer_type = (uint32_t)config->transferType();
+    if (tfer_type == g2m || tfer_type == m2g) {
+        tfer_type -= 2; // Adjust psuedo transferType to a real transferType.
+    }
+    
+    // Configure DMA Channel, enable Error Counter and Terminate counter
+    pChannel->DMACCConfig 
+        = /*DMACCConfig;*/CxConfig_IE() 
+        | CxConfig_ITC() 
+        | CxConfig_TransferType(tfer_type) 
+        | CxConfig_SrcPeripheral(tmp1) 
+        | CxConfig_DestPeripheral(tmp2);
+    
+    return;// pChannel->DMACCControl;
+}
+
+extern "C" void MODDMA_Cache_IRQHandler()
+{
+    p6_TOGGLE;
+    
+    /*if (moddma_p == (class MODDMA *)NULL) {
+        if (oldDMAHandler) {
+            ((MODDMA_FN)oldDMAHandler)();
+            return;
+        }
+        else {
+            error("Interrupt without instance");
+        }
+    }*/
+    
+    
+    // SEE UNROLLED VERSION BELOW. They are equivalent.
+    for (int channel_number = 0; channel_number < 2; channel_number++)
+    {
+        uint32_t channel_mask = (1UL << channel_number);
+        
+        // Since we only have one if statement inside anyway, I took this out
+        //if (LPC_GPDMA->DMACIntStat & channel_mask)
+        //{
+            if (LPC_GPDMA->DMACIntTCStat & channel_mask)
+            {
+                moddma_p->setups[channel_number]->isrIntTCStat->call();
+                LPC_GPDMA->DMACIntTCClear = channel_mask;
+            }
+            
+            //if (LPC_GPDMA->DMACIntErrStat & channel_mask)
+            //{
+                // removed for speed
+                //moddma_p->setups[channel_number]->isrIntErrStat->call();
+                LPC_GPDMA->DMACIntErrClr = channel_mask;
+            //}
+        //}
+    }
+    
+    
+    /*
+    // This is some nasty code
+    uint32_t channel_mask;
+    channel_mask = (1UL << 0);
+    
+    // Since we only have one if statement inside anyway, I took this out
+    //if (LPC_GPDMA->DMACIntStat & channel_mask)
+    //{
+        if (LPC_GPDMA->DMACIntTCStat & channel_mask)
+        {
+            moddma_p->setups[0]->isrIntTCStat->call();
+            LPC_GPDMA->DMACIntTCClear = channel_mask;
+        }
+        
+        //if (LPC_GPDMA->DMACIntErrStat & channel_mask)
+        //{
+            // removed for speed
+            //moddma_p->setups[channel_number]->isrIntErrStat->call();
+            LPC_GPDMA->DMACIntErrClr = channel_mask;
+        //}
+    //}
+    channel_mask = (1UL << 1);
+    // Since we only have one if statement inside anyway, I took this out
+    //if (LPC_GPDMA->DMACIntStat & channel_mask)
+    //{
+        if (LPC_GPDMA->DMACIntTCStat & channel_mask)
+        {
+            moddma_p->setups[1]->isrIntTCStat->call();
+            LPC_GPDMA->DMACIntTCClear = channel_mask;
+        }
+        
+        //if (LPC_GPDMA->DMACIntErrStat & channel_mask)
+        //{
+            // removed for speed
+            //moddma_p->setups[channel_number]->isrIntErrStat->call();
+            LPC_GPDMA->DMACIntErrClr = channel_mask;
+        //}
+    //}*/
+    
+    p6_TOGGLE;
+}
+
+void MODDMA_Cache::init()
+{
+    NVIC_SetVector(DMA_IRQn, (uint32_t)MODDMA_Cache_IRQHandler);
+    NVIC_EnableIRQ(DMA_IRQn);
+}