MODDMA GPDMA Controller fork EXPERIMENTAL -- do not use
Fork of MODDMA by
Revision 12:1dfee7208043, committed 2011-03-13
- Comitter:
- AjK
- Date:
- Sun Mar 13 23:28:21 2011 +0000
- Parent:
- 11:19009be5a0e7
- Child:
- 13:846c8b6ffb7f
- Commit message:
- 1.8 See ChangeLog.c
Changed in this revision
--- a/ChangeLog.c Sun Mar 13 12:46:55 2011 +0000 +++ b/ChangeLog.c Sun Mar 13 23:28:21 2011 +0000 @@ -1,5 +1,12 @@ /* $Id:$ +1.8 - 13 Mar 2011 + + * Renamed example files to .h + * Added pseudo g2m and m2g transferTypes to support GPIO + "memory moves" but triggered by peripheral timer. To + support this new operating mode added example3.h + 1.7 - 13 Mar 2011 * Remove the test at the beginning of the channel setup.
--- a/MODDMA.cpp Sun Mar 13 12:46:55 2011 +0000 +++ b/MODDMA.cpp Sun Mar 13 23:28:21 2011 +0000 @@ -37,7 +37,7 @@ bool MODDMA::Enabled(CHANNELS ChannelNumber) { - LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); return (bool)(pChannel->DMACCConfig & _E); }
--- a/MODDMA.h Sun Mar 13 12:46:55 2011 +0000 +++ b/MODDMA.h Sun Mar 13 23:28:21 2011 +0000 @@ -64,6 +64,7 @@ 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' + uint32_t DMACSync; //!< DMACSync if required. // Mbed specifics. @@ -81,6 +82,7 @@ SrcConn = 0; DstConn = 0; DMALLI = 0; + DMACSync = 0; } ~MODDMA_Config() { @@ -97,6 +99,7 @@ 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; } + class MODDMA_Config * dmacSync(uint32_t n) { DMACSync = n; return this; } uint32_t channelNum(void) { return ChannelNum; } uint32_t transferSize(void) { return TransferSize; } @@ -107,7 +110,8 @@ uint32_t srcConn(void) { return SrcConn; } uint32_t dstConn(void) { return DstConn; } uint32_t dmaLLI(void) { return DMALLI; } - + uint32_t dmacSync(void) { return DMACSync; } + /** * Attach a callback to the TC IRQ configuration. * @@ -306,7 +310,9 @@ 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 */ + , p2p = 3UL /*!< Src peripheral to dest peripheral - DMA control */ + , g2m = 4UL /*!< Psuedo special case for reading "peripheral GPIO" that's memory mapped. */ + , m2g = 5UL /*!< Psuedo Special case for writing "peripheral GPIO" that's memory mapped. */ }; //! Burst size in Source and Destination definitions */ @@ -651,13 +657,15 @@ */ FunctionPointer isrIntErrStat; + uint32_t Channel_p(int channel); + protected: // Data LUTs. uint32_t LUTPerAddr(int n); uint8_t LUTPerBurst(int n); uint8_t LUTPerWid(int n); - uint32_t Channel_p(int channel); + //uint32_t Channel_p(int channel); CHANNELS IrqProcessingChannel;
--- a/SETUP.cpp Sun Mar 13 12:46:55 2011 +0000 +++ b/SETUP.cpp Sun Mar 13 23:28:21 2011 +0000 @@ -108,6 +108,38 @@ | 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; @@ -121,7 +153,7 @@ LPC_SC->RESERVED9 &= ~(1 << (config->srcConn() - 8)); } - // Re-Configure DMA Request Select for Destination peripheral + // Re-Configure DMA Request Select for destination peripheral if (config->dstConn() > 15) { LPC_SC->RESERVED9 |= (1 << (config->dstConn() - 16)); } @@ -137,11 +169,21 @@ 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 = CxConfig_IE() | CxConfig_ITC() - | CxConfig_TransferType((uint32_t)config->transferType()) + | CxConfig_TransferType(tfer_type) | CxConfig_SrcPeripheral(tmp1) | CxConfig_DestPeripheral(tmp2);
--- a/example1.cpp Sun Mar 13 12:46:55 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -#ifdef COMPILE_EXAMPLE1_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); - -// Function prototypes for IRQ callbacks. -// See definitions following main() below. -void dmaTCCallback(void); -void dmaERRCallback(void); -void TC0_callback(void); -void ERR0_callback(void); - -int main() { - char s[] = "**DMA** ABCDEFGHIJKLMNOPQRSTUVWXYZ **DMA**"; - - pc.baud(PC_BAUD); - - dma.attach_tc( &dmaTCCallback ); - dma.attach_err( &dmaERRCallback ); - - 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 ) - ->attach_tc ( &TC0_callback ) - ->attach_err ( &ERR0_callback ) - ; // config end - - // Setup the configuration. - dma.Setup(config); - - //dma.Enable( MODDMA::Channel_0 ); - //dma.Enable( config->channelNum() ); - dma.Enable( config ); - - while (1) { - led1 = !led1; - wait(0.25); - } -} - -// Main controller TC IRQ callback -void dmaTCCallback(void) { - led2 = 1; -} - -// Main controller ERR IRQ callback -void dmaERRCallback(void) { - error("Oh no! My Mbed exploded! :( Only kidding, find the problem"); -} - -// Configuration callback on TC -void TC0_callback(void) { - MODDMA_Config *config = dma.getConfig(); - dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); - dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); - - // Configurations have two IRQ callbacks for TC and Err so you - // know which you are processing. However, if you want to use - // a single callback function you can tell what type of IRQ - // is being processed thus:- - if (dma.irqType() == MODDMA::TcIrq) { - led3 = 1; - dma.clearTcIrq(); - } - if (dma.irqType() == MODDMA::ErrIrq) { - led4 = 1; - dma.clearErrIrq(); - } -} - -// Configuration cakllback on Error -void ERR0_callback(void) { - error("Oh no! My Mbed exploded! :( Only kidding, find the problem"); -} - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example1.h Sun Mar 13 23:28:21 2011 +0000 @@ -0,0 +1,89 @@ +#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); + +// Function prototypes for IRQ callbacks. +// See definitions following main() below. +void dmaTCCallback(void); +void dmaERRCallback(void); +void TC0_callback(void); +void ERR0_callback(void); + +int main() { + char s[] = "**DMA** ABCDEFGHIJKLMNOPQRSTUVWXYZ **DMA**"; + + pc.baud(PC_BAUD); + + dma.attach_tc( &dmaTCCallback ); + dma.attach_err( &dmaERRCallback ); + + 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 ) + ->attach_tc ( &TC0_callback ) + ->attach_err ( &ERR0_callback ) + ; // config end + + // Setup the configuration. + dma.Setup(config); + + //dma.Enable( MODDMA::Channel_0 ); + //dma.Enable( config->channelNum() ); + dma.Enable( config ); + + while (1) { + led1 = !led1; + wait(0.25); + } +} + +// Main controller TC IRQ callback +void dmaTCCallback(void) { + led2 = 1; +} + +// Main controller ERR IRQ callback +void dmaERRCallback(void) { + error("Oh no! My Mbed exploded! :( Only kidding, find the problem"); +} + +// Configuration callback on TC +void TC0_callback(void) { + MODDMA_Config *config = dma.getConfig(); + dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); + dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); + + // Configurations have two IRQ callbacks for TC and Err so you + // know which you are processing. However, if you want to use + // a single callback function you can tell what type of IRQ + // is being processed thus:- + if (dma.irqType() == MODDMA::TcIrq) { + led3 = 1; + dma.clearTcIrq(); + } + if (dma.irqType() == MODDMA::ErrIrq) { + led4 = 1; + dma.clearErrIrq(); + } +} + +// Configuration cakllback on Error +void ERR0_callback(void) { + error("Oh no! My Mbed exploded! :( Only kidding, find the problem"); +} +
--- a/example2.cpp Sun Mar 13 12:46:55 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -#ifdef COMPILE_EXAMPLE2_CODE_MODDMA - -/* - * This example was provided to support Mbed forum thread:- - * http://mbed.org/forum/mbed/topic/1798 - */ - -#include "mbed.h" -#include "MODDMA.h" - -#define SAMPLE_BUFFER_LENGTH 32 - -DigitalOut led1(LED1); -DigitalOut led2(LED2); - -MODDMA dma; -Serial pc(USBTX, USBRX); - -// ISR set's this when transfer complete. -bool dmaTransferComplete = false; - -// Function prototypes for IRQ callbacks. -// See definitions following main() below. -void TC0_callback(void); -void ERR0_callback(void); - -int main() { - - // Create a buffer to hold the ADC samples and clear it. - // Note, we are going to sample two ADC inputs so they - // end up in this buffer "interleaved". So you will want - // a buffer twice this size to a real life given sample - // frequency. See the printf() output for details. - uint32_t adcInputBuffer[SAMPLE_BUFFER_LENGTH]; - memset(adcInputBuffer, 0, sizeof(adcInputBuffer)); - - // We use the ADC irq to trigger DMA and the manual says - // that in this case the NVIC for ADC must be disabled. - NVIC_DisableIRQ(ADC_IRQn); - - // Power up the ADC and set PCLK - LPC_SC->PCONP |= (1UL << 12); - LPC_SC->PCLKSEL0 &= ~(3UL << 24); // PCLK = CCLK/4 96M/4 = 24MHz - - // Enable the ADC, 12MHz, ADC0.0 & .1 - LPC_ADC->ADCR = (1UL << 21) | (1UL << 8) | (3UL << 0); - - // Set the pin functions to ADC - LPC_PINCON->PINSEL1 &= ~(3UL << 14); /* P0.23, Mbed p15. */ - LPC_PINCON->PINSEL1 |= (1UL << 14); - LPC_PINCON->PINSEL1 &= ~(3UL << 16); /* P0.24, Mbed p16. */ - LPC_PINCON->PINSEL1 |= (1UL << 16); - - // Setup the serial port to print out results. - pc.baud(115200); - pc.printf("ADC with DMA example\n"); - pc.printf("====================\n"); - - // Prepare an ADC configuration. - MODDMA_Config *conf = new MODDMA_Config; - conf - ->channelNum ( MODDMA::Channel_0 ) - ->srcMemAddr ( 0 ) - ->dstMemAddr ( (uint32_t)adcInputBuffer ) - ->transferSize ( SAMPLE_BUFFER_LENGTH ) - ->transferType ( MODDMA::p2m ) - ->transferWidth ( MODDMA::word ) - ->srcConn ( MODDMA::ADC ) - ->dstConn ( 0 ) - ->dmaLLI ( 0 ) - ->attach_tc ( &TC0_callback ) - ->attach_err ( &ERR0_callback ) - ; // end conf. - - // Prepare configuration. - dma.Setup( conf ); - - // Enable configuration. - dma.Enable( conf ); - - // Enable ADC irq flag (to DMA). - // Note, don't set the individual flags, - // just set the global flag. - LPC_ADC->ADINTEN = 0x100; - - // Enable burst mode on inputs 0 and 1. - LPC_ADC->ADCR |= (1UL << 16); - - while (1) { - // When transfer complete do this block. - if (dmaTransferComplete) { - delete conf; // No memory leaks, delete the configuration. - dmaTransferComplete = false; - for (int i = 0; i < SAMPLE_BUFFER_LENGTH; i++) { - int channel = (adcInputBuffer[i] >> 24) & 0x7; - int iVal = (adcInputBuffer[i] >> 4) & 0xFFF; - double fVal = 3.3 * (double)((double)iVal) / ((double)0x1000); // scale to 0v to 3.3v - pc.printf("Array index %02d : ADC input channel %d = 0x%03x %01.3f volts\n", i, channel, iVal, fVal); - } - } - - // Just flash LED1 for something to do. - led1 = !led1; - wait(0.25); - } -} - -// Configuration callback on TC -void TC0_callback(void) { - - MODDMA_Config *config = dma.getConfig(); - - // Disbale burst mode and switch off the IRQ flag. - LPC_ADC->ADCR &= ~(1UL << 16); - LPC_ADC->ADINTEN = 0; - - // Finish the DMA cycle by shutting down the channel. - dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); - dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); - - // Tell main() while(1) loop to print the results. - dmaTransferComplete = true; - - // Switch on LED2 to show transfer complete. - led2 = 1; - - // Clear DMA IRQ flags. - if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); - if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); -} - -// Configuration callback on Error -void ERR0_callback(void) { - // Switch off burst conversions. - LPC_ADC->ADCR |= ~(1UL << 16); - LPC_ADC->ADINTEN = 0; - error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); -} - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example2.h Sun Mar 13 23:28:21 2011 +0000 @@ -0,0 +1,137 @@ +/* + * This example was provided to support Mbed forum thread:- + * http://mbed.org/forum/mbed/topic/1798 + */ + +#include "mbed.h" +#include "MODDMA.h" + +#define SAMPLE_BUFFER_LENGTH 32 + +DigitalOut led1(LED1); +DigitalOut led2(LED2); + +MODDMA dma; +Serial pc(USBTX, USBRX); + +// ISR set's this when transfer complete. +bool dmaTransferComplete = false; + +// Function prototypes for IRQ callbacks. +// See definitions following main() below. +void TC0_callback(void); +void ERR0_callback(void); + +int main() { + + // Create a buffer to hold the ADC samples and clear it. + // Note, we are going to sample two ADC inputs so they + // end up in this buffer "interleaved". So you will want + // a buffer twice this size to a real life given sample + // frequency. See the printf() output for details. + uint32_t adcInputBuffer[SAMPLE_BUFFER_LENGTH]; + memset(adcInputBuffer, 0, sizeof(adcInputBuffer)); + + // We use the ADC irq to trigger DMA and the manual says + // that in this case the NVIC for ADC must be disabled. + NVIC_DisableIRQ(ADC_IRQn); + + // Power up the ADC and set PCLK + LPC_SC->PCONP |= (1UL << 12); + LPC_SC->PCLKSEL0 &= ~(3UL << 24); // PCLK = CCLK/4 96M/4 = 24MHz + + // Enable the ADC, 12MHz, ADC0.0 & .1 + LPC_ADC->ADCR = (1UL << 21) | (1UL << 8) | (3UL << 0); + + // Set the pin functions to ADC + LPC_PINCON->PINSEL1 &= ~(3UL << 14); /* P0.23, Mbed p15. */ + LPC_PINCON->PINSEL1 |= (1UL << 14); + LPC_PINCON->PINSEL1 &= ~(3UL << 16); /* P0.24, Mbed p16. */ + LPC_PINCON->PINSEL1 |= (1UL << 16); + + // Setup the serial port to print out results. + pc.baud(115200); + pc.printf("ADC with DMA example\n"); + pc.printf("====================\n"); + + // Prepare an ADC configuration. + MODDMA_Config *conf = new MODDMA_Config; + conf + ->channelNum ( MODDMA::Channel_0 ) + ->srcMemAddr ( 0 ) + ->dstMemAddr ( (uint32_t)adcInputBuffer ) + ->transferSize ( SAMPLE_BUFFER_LENGTH ) + ->transferType ( MODDMA::p2m ) + ->transferWidth ( MODDMA::word ) + ->srcConn ( MODDMA::ADC ) + ->dstConn ( 0 ) + ->dmaLLI ( 0 ) + ->attach_tc ( &TC0_callback ) + ->attach_err ( &ERR0_callback ) + ; // end conf. + + // Prepare configuration. + dma.Setup( conf ); + + // Enable configuration. + dma.Enable( conf ); + + // Enable ADC irq flag (to DMA). + // Note, don't set the individual flags, + // just set the global flag. + LPC_ADC->ADINTEN = 0x100; + + // Enable burst mode on inputs 0 and 1. + LPC_ADC->ADCR |= (1UL << 16); + + while (1) { + // When transfer complete do this block. + if (dmaTransferComplete) { + delete conf; // No memory leaks, delete the configuration. + dmaTransferComplete = false; + for (int i = 0; i < SAMPLE_BUFFER_LENGTH; i++) { + int channel = (adcInputBuffer[i] >> 24) & 0x7; + int iVal = (adcInputBuffer[i] >> 4) & 0xFFF; + double fVal = 3.3 * (double)((double)iVal) / ((double)0x1000); // scale to 0v to 3.3v + pc.printf("Array index %02d : ADC input channel %d = 0x%03x %01.3f volts\n", i, channel, iVal, fVal); + } + } + + // Just flash LED1 for something to do. + led1 = !led1; + wait(0.25); + } +} + +// Configuration callback on TC +void TC0_callback(void) { + + MODDMA_Config *config = dma.getConfig(); + + // Disbale burst mode and switch off the IRQ flag. + LPC_ADC->ADCR &= ~(1UL << 16); + LPC_ADC->ADINTEN = 0; + + // Finish the DMA cycle by shutting down the channel. + dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); + dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); + + // Tell main() while(1) loop to print the results. + dmaTransferComplete = true; + + // Switch on LED2 to show transfer complete. + led2 = 1; + + // Clear DMA IRQ flags. + if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); + if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); +} + +// Configuration callback on Error +void ERR0_callback(void) { + // Switch off burst conversions. + LPC_ADC->ADCR |= ~(1UL << 16); + LPC_ADC->ADINTEN = 0; + error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example3.h Sun Mar 13 23:28:21 2011 +0000 @@ -0,0 +1,125 @@ +/* + * Demonstrates capturing the GPIO P0.4 to P0.7 "nibble" to memory + * using GPDMA. The transfers from port pins to memory buffer are + * triggered using Timer1 MAT1.0 match compare. + * + * In this example all inputs have pullups. So with nothing connected + * the P0.4/7 reads as 0xF. Connecting a wire from one or more of the four + * inputs to ground will show up in the captured buffer sequence. + */ + +#include "mbed.h" +#include "MODDMA.h" +#include "iomacros.h" // within MODDMA library. + +// How long between grabbing GPIO FIO0PIN register. +// Value is in microseconds. (50000 is half a second). +#define SAMPLE_PERIOD 500000 + +#define NUM_OF_SAMPLES 5 + +Serial pc(USBTX, USBRX); + +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); + +uint32_t buffer[NUM_OF_SAMPLES]; + +bool dmaTransferComplete; + +MODDMA dma; +MODDMA_Config *conf; + +void TC0_callback(void); +void ERR0_callback(void); + +int main() { + + // Macros defined in iomacros.h, saves messing with DigitalIn + p30_AS_INPUT; p30_MODE( PIN_PULLUP ); // P0.4 + p29_AS_INPUT; p29_MODE( PIN_PULLUP ); // P0.5 + p8_AS_INPUT; p8_MODE( PIN_PULLUP ); // P0.6 + p7_AS_INPUT; p7_MODE( PIN_PULLUP ); // P0.7 + + // Clear the buffer. + memset(buffer, 0, sizeof(buffer)); + + // Setup the serial port to print out results. + pc.baud(115200); + pc.printf("Starting up...\n"); + + // Set-up timer1 as a periodic timer. + LPC_SC->PCONP |= (1UL << 2); // TIM1 On + LPC_SC->PCLKSEL0 |= (3UL << 4); // CCLK/8 = 12MHz + LPC_TIM1->PR = 11; // TC clocks at 1MHz. + LPC_TIM1->MCR = 2; // Reset TCR to zero on match. + LPC_TIM1->MR0 = SAMPLE_PERIOD; + + // Prepare the GPDMA system. + conf = new MODDMA_Config; + conf + ->channelNum ( MODDMA::Channel_0 ) + ->srcMemAddr ( (uint32_t)&LPC_GPIO0->FIOPIN ) + ->dstMemAddr ( (uint32_t)&buffer[0] ) + ->transferSize ( NUM_OF_SAMPLES ) + ->transferType ( MODDMA::g2m ) // pseudo transfer code MODDMA understands. + ->transferWidth ( MODDMA::word ) + ->srcConn ( MODDMA::MAT1_0 ) + ->dmacSync ( MODDMA::MAT1_0 ) + ->attach_tc ( TC0_callback ) + ->attach_err ( ERR0_callback ) + ; // end conf. + + // Prepare configuration. + if (!dma.Setup( conf )) { + error("Doh!"); + } + + // Enable GPDMA to be ready for the TIM1 "ticks". + dma.Enable( conf ); + + // Begin. + LPC_TIM1->TCR = 1; + + while (1) { + led1 = !led1; // Show some sort of life. + + if (dmaTransferComplete) { + dmaTransferComplete = false; + for (int i = 0; i < NUM_OF_SAMPLES; i++) { + int val = (buffer[i] >> 4) & 0xF; + pc.printf("Buffer index %d = 0x%x\n", i, val); + } + pc.printf("Done.\n"); + } + } +} + +// Configuration callback on TC +void TC0_callback(void) { + + // Just show sample sequence grab complete. + led3 = !led3; + + // Disable firing timer. + LPC_TIM1->TCR = 0; + + // Get configuration pointer. + MODDMA_Config *config = dma.getConfig(); + + // Finish the DMA cycle by shutting down the channel. + dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); + + // Tell main() while(1) loop to print the results. + dmaTransferComplete = true; + + // Clear DMA IRQ flags. + if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); + if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); +} + +// Configuration callback on Error +void ERR0_callback(void) { + error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); +}
--- a/iomacros.h Sun Mar 13 12:46:55 2011 +0000 +++ b/iomacros.h Sun Mar 13 23:28:21 2011 +0000 @@ -71,6 +71,7 @@ /* p8 is P0.6 */ #define p8_SEL_MASK ~(3UL << 12) #define p8_SET_MASK (1UL << 6) +#define p8_CLR_MASK ~(p8_SET_MASK) #define p8_AS_OUTPUT LPC_PINCON->PINSEL0&=p8_SEL_MASK;LPC_GPIO0->FIODIR|=p8_SET_MASK #define p8_AS_INPUT LPC_GPIO0->FIOMASK &= p8_CLR_MASK; #define p8_SET LPC_GPIO0->FIOSET = p8_SET_MASK