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

MODDMA_cache.cpp

Committer:
avbotz
Date:
2013-08-02
Revision:
0:2381a319fc35

File content as of revision 0:2381a319fc35:

#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);
}