void setupDMAInput( void ) { cbADC.cbFunc = adcCb; cbADC.userPtr = NULL; DMA_CfgChannel_TypeDef chnlCfg; chnlCfg.highPri = true; chnlCfg.enableInt = true; chnlCfg.select = DMAREQ_ADC0_SCAN; chnlCfg.cb = &cbADC; DMA_CfgChannel(DMA_CHANNEL_ADC, &chnlCfg); DMA_CfgDescr_TypeDef descrCfg; descrCfg.dstInc = dmaDataInc2; descrCfg.srcInc = dmaDataIncNone; descrCfg.size = dmaDataSize2; descrCfg.hprot = 0; DMA_CfgDescr(DMA_CHANNEL_ADC, true, &descrCfg); DMA_CfgDescr(DMA_CHANNEL_ADC, false, &descrCfg); DMA_ActivatePingPong(DMA_CHANNEL_ADC, false, sourceP, (void*)((uint32_t) &(ADC0->SCANDATA)), N - 1, sourceS, (void*)((uint32_t) &(ADC0->SCANDATA)), N - 1); bufferPrimary = true; }
/***************************************************************************//** * @brief * Configure ADC and DMA for this application. *******************************************************************************/ static void guitarADCConfig(void) { DMA_CfgDescr_TypeDef descrCfg; DMA_CfgChannel_TypeDef chnlCfg; ADC_Init_TypeDef init = ADC_INIT_DEFAULT; ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT; /* Configure DMA usage by ADC */ cbInData.cbFunc = guitarDMAInCb; cbInData.userPtr = NULL; /* Set up high pri channel with callback with request from ADC scan complete. */ chnlCfg.highPri = true; chnlCfg.enableInt = true; chnlCfg.select = DMAREQ_ADC0_SCAN; chnlCfg.cb = &cbInData; DMA_CfgChannel(GUITAR_DMA_AUDIO_IN, &chnlCfg); /* Configure datasize, increment and primary, alternate structure for pingpong. */ descrCfg.dstInc = dmaDataInc2; descrCfg.srcInc = dmaDataIncNone; descrCfg.size = dmaDataSize2; descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; DMA_CfgDescr(GUITAR_DMA_AUDIO_IN, true, &descrCfg); DMA_CfgDescr(GUITAR_DMA_AUDIO_IN, false, &descrCfg); DMA_ActivatePingPong(GUITAR_DMA_AUDIO_IN, false, guitarAudioInBuffer1, (void *)((uint32_t) &(ADC0->SCANDATA)), (GUITAR_AUDIO_BUFFER_SAMPLES * 2) - 1, guitarAudioInBuffer2, (void *)((uint32_t) &(ADC0->SCANDATA)), (GUITAR_AUDIO_BUFFER_SAMPLES * 2) - 1); /* Configure ADC */ /* Keep warm due to "high" frequency sampling */ init.warmUpMode = adcWarmupKeepADCWarm; /* Init common issues for both single conversion and scan mode */ /* 0 means, figure out the base frequency based on current cmu config. */ init.timebase = ADC_TimebaseCalc(0); /* Calculate necessary prescaler to get 4MHz adc clock with current cmu configuration. */ init.prescale = ADC_PrescaleCalc(4000000, 0); /* Sample potentiometer by tailgating in order to not disturb fixed rate */ /* audio sampling. */ init.tailgate = true; ADC_Init(ADC0, &init); /* Init for scan sequence use (audio in right/left channels). */ scanInit.prsSel = adcPRSSELCh0; scanInit.prsEnable = true; scanInit.reference = adcRefVDD; scanInit.input = ADC_SCANCTRL_INPUTMASK_CH6 | ADC_SCANCTRL_INPUTMASK_CH7; ADC_InitScan(ADC0, &scanInit); }
static void ADCConfig(void) { DMA_CfgDescr_TypeDef descrCfg; DMA_CfgChannel_TypeDef chnlCfg; ADC_Init_TypeDef init = ADC_INIT_DEFAULT; ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT; /* Configure DMA usage by ADC */ cbInData.cbFunc = adcCb; cbInData.userPtr = NULL; chnlCfg.highPri = true; chnlCfg.enableInt = true; chnlCfg.select = DMAREQ_ADC0_SCAN; chnlCfg.cb = &cbInData; DMA_CfgChannel(DMA_CHANNEL_ADC, &chnlCfg); descrCfg.dstInc = dmaDataInc2; descrCfg.srcInc = dmaDataIncNone; descrCfg.size = dmaDataSize2; descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; DMA_CfgDescr(DMA_CHANNEL_ADC, true, &descrCfg); DMA_CfgDescr(DMA_CHANNEL_ADC, false, &descrCfg); DMA_ActivatePingPong(DMA_CHANNEL_ADC, false, sourceP, (void *)((uint32_t) &(ADC0->SCANDATA)), N - 1, sourceS, (void *)((uint32_t) &(ADC0->SCANDATA)), N - 1); /* Indicate starting with primary in-buffer (according to above DMA setup) */ bufferPrimary = true; /* Configure ADC */ /* Keep warm due to "high" frequency sampling */ init.warmUpMode = adcWarmupKeepADCWarm; /* Init common issues for both single conversion and scan mode */ init.timebase = ADC_TimebaseCalc(0); init.prescale = ADC_PrescaleCalc(4000000, 0); /* Sample potentiometer by tailgating in order to not disturb fixed rate */ /* audio sampling. */ init.tailgate = true; ADC_Init(ADC0, &init); /* Init for scan sequence use (audio in right/left channels). */ scanInit.prsSel = adcPRSSELCh0; scanInit.prsEnable = true; scanInit.reference = adcRefVDD; scanInit.input = ADC_SCANCTRL_INPUTMASK_CH6 | ADC_SCANCTRL_INPUTMASK_CH7; ADC_InitScan(ADC0, &scanInit); }
static void DACConfig(void) { DMA_CfgDescr_TypeDef descrCfg; DMA_CfgChannel_TypeDef chnlCfg; DAC_Init_TypeDef dacInit = DAC_INIT_DEFAULT; DAC_InitChannel_TypeDef dacChInit = DAC_INITCHANNEL_DEFAULT; /* Notice: Audio out buffers are by default filled with 0, since */ /* uninitialized data; no need to clear explicitly. */ /* Configure DAC */ /* Init common DAC issues */ dacInit.reference = dacRefVDD; DAC_Init(DAC0, &dacInit); /* Start with "no" signal out */ DAC0->COMBDATA = 0x0; /* Init channels, equal config for both channels. */ dacChInit.enable = true; dacChInit.prsSel = dacPRSSELCh0; dacChInit.prsEnable = true; DAC_InitChannel(DAC0, &dacChInit, 0); /* Right channel */ DAC_InitChannel(DAC0, &dacChInit, 1); /* Left channel */ /* Configure DMA usage by DAC */ cbOutData.cbFunc = dacCb; cbOutData.userPtr = NULL; chnlCfg.highPri = true; chnlCfg.enableInt = true; chnlCfg.select = DMAREQ_DAC0_CH0; chnlCfg.cb = &cbOutData; DMA_CfgChannel(DMA_CHANNEL_DAC, &chnlCfg); descrCfg.dstInc = dmaDataIncNone; descrCfg.srcInc = dmaDataInc4; descrCfg.size = dmaDataSize4; descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; DMA_CfgDescr(DMA_CHANNEL_DAC, true, &descrCfg); DMA_CfgDescr(DMA_CHANNEL_DAC, false, &descrCfg); DMA_ActivatePingPong(DMA_CHANNEL_DAC, false, (void *)((uint32_t) &(DAC0->COMBDATA)), sourceP, N - 1, (void *)((uint32_t) &(DAC0->COMBDATA)), sourceS, N - 1); }
void setupDMAOutput( void ) { cbDAC.cbFunc = dacCb; cbDAC.userPtr = NULL; DMA_CfgChannel_TypeDef chnlCfg = { .highPri = true, .enableInt = true, .select = DMAREQ_DAC0_CH0, .cb = &cbDAC }; DMA_CfgChannel(DMA_CHANNEL_DAC, &chnlCfg); DMA_CfgDescr_TypeDef descrCfg = { .dstInc = dmaDataIncNone, .srcInc = dmaDataInc4, .size = dmaDataSize4, .hprot = 0 }; DMA_CfgDescr(DMA_CHANNEL_DAC, true, &descrCfg); DMA_CfgDescr(DMA_CHANNEL_DAC, false, &descrCfg); DMA_ActivatePingPong(DMA_CHANNEL_DAC, false, (void*)((uint32_t) &DAC0->COMBDATA), sourceP, N - 1, (void*)((uint32_t) &DAC0->COMBDATA), sourceS, N - 1); } /* * Sets up the DMA to copy from src to dst0 and dst1 with the pattern: * * src: | 1, 2, 3, 4, ... | * dst0: | 1, 3, ... | * dst1: | 2, 4, ... | */ void setupDMASplit(void) { DMA_Init_TypeDef dmaInit; dmaInit.hprot = 0; dmaInit.controlBlock = dmaControlBlock; DMA_Init(&dmaInit); DMA_CfgChannel_TypeDef chnlCfgLeft; chnlCfgLeft.highPri = false; chnlCfgLeft.enableInt = true; chnlCfgLeft.select = 0; chnlCfgLeft.cb = NULL; //&cbInLeft; DMA_CfgChannel(DMA_CHANNEL_IN_LEFT, &chnlCfgLeft); DMA_CfgChannel_TypeDef chnlCfgRight; chnlCfgRight.highPri = false; chnlCfgRight.enableInt = true; chnlCfgRight.select = 0; chnlCfgRight.cb = NULL; //&cbInRight; DMA_CfgChannel(DMA_CHANNEL_IN_RIGHT, &chnlCfgRight); DMA_CfgDescr_TypeDef descrCfg; descrCfg.dstInc = dmaDataInc2; descrCfg.srcInc = dmaDataInc4; descrCfg.size = dmaDataSize2; descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; DMA_CfgDescr(DMA_CHANNEL_IN_LEFT, true, &descrCfg); DMA_CfgDescr(DMA_CHANNEL_IN_RIGHT, false, &descrCfg); DMA_ActivateAuto(DMA_CHANNEL_IN_LEFT, true, left, source, N - 1); DMA_ActivateAuto(DMA_CHANNEL_IN_RIGHT, false, right, (char*)source+sizeof(uint16_t), N - 1); } /* * Sets up the DMA to copy from src0 and src1 to dst with the pattern: * * src0: | 1, 3, ... | * src1: | 2, 4, ... | * dst: | 1, 2, 3, 4, ... | */ void setupDMAMerge(void) { DMA_CfgChannel_TypeDef chnlCfgLeft; chnlCfgLeft.highPri = false; chnlCfgLeft.enableInt = true; chnlCfgLeft.select = 0; chnlCfgLeft.cb = NULL; //&cbOutLeft; DMA_CfgChannel(DMA_CHANNEL_OUT_LEFT, &chnlCfgLeft); DMA_CfgChannel_TypeDef chnlCfgRight; chnlCfgRight.highPri = false; chnlCfgRight.enableInt = true; chnlCfgRight.select = 0; chnlCfgRight.cb = NULL; //&cbOutRight; DMA_CfgChannel(DMA_CHANNEL_OUT_RIGHT, &chnlCfgRight); DMA_CfgDescr_TypeDef descrCfg; descrCfg.dstInc = dmaDataInc4; descrCfg.srcInc = dmaDataInc2; descrCfg.size = dmaDataSize2; descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; DMA_CfgDescr(DMA_CHANNEL_OUT_LEFT, true, &descrCfg); DMA_CfgDescr(DMA_CHANNEL_OUT_RIGHT, false, &descrCfg); DMA_ActivateAuto(DMA_CHANNEL_OUT_LEFT, true, destination, left, N - 1); DMA_ActivateAuto(DMA_CHANNEL_OUT_RIGHT, false, (char*)destination+sizeof(uint16_t), right, N - 1); }
/**************************************************************************//** * @brief * Setup DMA in ping pong mode * @details * The DMA is set up to transfer data from memory to the DAC, triggered by * PRS (which in turn is triggered by the TIMER). When the DMA finishes, * it will trigger the callback (PingPongTransferComplete). *****************************************************************************/ void DMA_setup(void) { /* DMA configuration structs */ DMA_Init_TypeDef dmaInit; DMA_CfgChannel_TypeDef chnlCfg; DMA_CfgDescr_TypeDef descrCfg; ramBufferTX0Zeros[0] = 0; /* Initializing the DMA */ dmaInit.hprot = 0; dmaInit.controlBlock = dmaControlBlock; DMA_Init(&dmaInit); /* Set the interrupt callback routine */ DMAcallBackTX.cbFunc = PingPongTransferCompleteTX; /* Callback doesn't need userpointer */ DMAcallBackTX.userPtr = NULL; /* Setting up channel */ chnlCfg.highPri = false; /* Can't use with peripherals */ chnlCfg.enableInt = true; /* Interrupt needed when buffers are used */ chnlCfg.select = DMAREQ_USART2_TXBL; chnlCfg.cb = &DMAcallBackTX; DMA_CfgChannel(0, &chnlCfg); // Enable TX DMA Channel /* Set the interrupt callback routine */ DMAcallBackRX.cbFunc = PingPongTransferCompleteRX; /* Callback doesn't need userpointer */ DMAcallBackRX.userPtr = NULL; /* Setting up channel */ chnlCfg.highPri = false; /* Can't use with peripherals */ chnlCfg.enableInt = true; /* Interrupt needed when buffers are used */ /* channel 0 and 1 will need data at the same time, * can use channel 0 as trigger */ chnlCfg.select = DMAREQ_USART2_RXDATAV; chnlCfg.cb = &DMAcallBackRX; DMA_CfgChannel(1, &chnlCfg); /* Setting up channel descriptor */ /* Destination is DAC/USART register and doesn't move */ descrCfg.dstInc = dmaDataIncNone; descrCfg.srcInc = dmaDataIncNone; descrCfg.size = dmaDataSize1; /* We have time to arbitrate again for each sample */ descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; /* Configure both primary and secondary descriptor alike */ DMA_CfgDescr(0, true, &descrCfg); DMA_CfgDescr(0, false, &descrCfg); /* Setting up channel descriptor */ /* Destination is DAC/USART register and doesn't move */ descrCfg.dstInc = dmaDataInc1; descrCfg.srcInc = dmaDataIncNone; descrCfg.size = dmaDataSize1; /* We have time to arbitrate again for each sample */ descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; /* Configure both primary and secondary descriptor alike */ DMA_CfgDescr(1, true, &descrCfg); DMA_CfgDescr(1, false, &descrCfg); /* Enabling PingPong Transfer*/ DMA_ActivatePingPong(0, false, (void *) & (USART2->TXDATA), (void *) &ramBufferTX0Zeros, (2 * BUFFERSIZE) - 1, (void *) &(USART2->TXDATA), (void *) &ramBufferTX1Zeros, (2 * BUFFERSIZE) - 1); /* Enabling PingPong Transfer*/ DMA_ActivatePingPong(1, false, (void *) &ramBufferDacData0Stereo, (void *) & (USART2->RXDATA), (2 * BUFFERSIZE) - 1, (void *) &ramBufferDacData1Stereo, (void *) &(USART2->RXDATA), (2 * BUFFERSIZE) - 1); }
/***************************************************************************//** * @brief * Start a UDMA transfer. ******************************************************************************/ static Ecode_t StartTransfer( DmaMode_t mode, DmaDirection_t direction, unsigned int channelId, DMADRV_PeripheralSignal_t peripheralSignal, void *buf0, void *buf1, void *buf2, bool bufInc, int len, DMADRV_DataSize_t size, DMADRV_Callback_t callback, void *cbUserParam ) { ChTable_t *ch; DMA_CfgChannel_TypeDef chCfg; DMA_CfgDescr_TypeDef descrCfg; if ( !initialized ) { return ECODE_EMDRV_DMADRV_NOT_INITIALIZED; } if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT ) || ( buf0 == NULL ) || ( buf1 == NULL ) || ( len > DMADRV_MAX_XFER_COUNT ) || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) ) { return ECODE_EMDRV_DMADRV_PARAM_ERROR; } ch = &chTable[ channelId ]; if ( ch->allocated == false ) { return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED; } /* Setup the interrupt callback routine. */ if ( mode == dmaModeBasic ) { dmaCallBack[ channelId ].cbFunc = DmaBasicCallback; } else { dmaCallBack[ channelId ].cbFunc = DmaPingPongCallback; } dmaCallBack[ channelId ].userPtr = NULL; /* Setup the channel */ chCfg.highPri = false; /* Can't use hi pri with peripherals. */ /* Interrupt needed ? */ if ( ( callback != NULL ) || ( mode == dmaModePingPong ) ) { chCfg.enableInt = true; } else { chCfg.enableInt = false; } chCfg.select = peripheralSignal; chCfg.cb = &dmaCallBack[ channelId ]; DMA_CfgChannel( channelId, &chCfg ); /* Setup channel descriptor. */ if ( direction == dmaDirectionMemToPeripheral ) { if ( bufInc ) { if ( size == dmadrvDataSize1 ) { descrCfg.srcInc = dmaDataInc1; } else if ( size == dmadrvDataSize2 ) { descrCfg.srcInc = dmaDataInc2; } else /* dmadrvDataSize4 */ { descrCfg.srcInc = dmaDataInc4; } } else { descrCfg.srcInc = dmaDataIncNone; } descrCfg.dstInc = dmaDataIncNone; } else { if ( bufInc ) { if ( size == dmadrvDataSize1 ) { descrCfg.dstInc = dmaDataInc1; } else if ( size == dmadrvDataSize2 ) { descrCfg.dstInc = dmaDataInc2; } else /* dmadrvDataSize4 */ { descrCfg.dstInc = dmaDataInc4; } } else { descrCfg.dstInc = dmaDataIncNone; } descrCfg.srcInc = dmaDataIncNone; } descrCfg.size = (DMA_DataSize_TypeDef)size; descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; DMA_CfgDescr( channelId, true, &descrCfg ); if ( mode == dmaModePingPong ) { DMA_CfgDescr( channelId, false, &descrCfg ); } ch->callback = callback; ch->userParam = cbUserParam; ch->callbackCount = 0; ch->length = len; DMA->IFC = 1 << channelId; /* Start DMA cycle. */ if ( mode == dmaModeBasic ) { DMA_ActivateBasic( channelId, true, false, buf0, buf1, len - 1 ); } else { if ( direction == dmaDirectionMemToPeripheral ) { DMA_ActivatePingPong( channelId, false, buf0, /* dest */ buf1, /* src */ len - 1, buf0, /* dest */ buf2, /* src */ len - 1); } else { DMA_ActivatePingPong( channelId, false, buf0, /* dest */ buf2, /* src */ len - 1, buf1, /* dest */ buf2, /* src */ len - 1); } } return ECODE_EMDRV_DMADRV_OK; }
/***************************************************************************//** * @brief * Configure ADC usage for this application. *******************************************************************************/ static void preampADCConfig(void) { DMA_CfgDescr_TypeDef descrCfg; DMA_CfgChannel_TypeDef chnlCfg; ADC_Init_TypeDef init = ADC_INIT_DEFAULT; ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT; /* Configure DMA usage by ADC */ cbInData.cbFunc = preampDMAInCb; cbInData.userPtr = NULL; chnlCfg.highPri = true; chnlCfg.enableInt = true; chnlCfg.select = DMAREQ_ADC0_SCAN; chnlCfg.cb = &cbInData; DMA_CfgChannel(PREAMP_DMA_AUDIO_IN, &chnlCfg); descrCfg.dstInc = dmaDataInc2; descrCfg.srcInc = dmaDataIncNone; descrCfg.size = dmaDataSize2; descrCfg.arbRate = dmaArbitrate1; descrCfg.hprot = 0; DMA_CfgDescr(PREAMP_DMA_AUDIO_IN, true, &descrCfg); DMA_CfgDescr(PREAMP_DMA_AUDIO_IN, false, &descrCfg); DMA_ActivatePingPong(PREAMP_DMA_AUDIO_IN, false, preampAudioInBuffer1, (void *)((uint32_t)&(ADC0->SCANDATA)), (PREAMP_AUDIO_BUFFER_SIZE * 2) - 1, preampAudioInBuffer2, (void *)((uint32_t)&(ADC0->SCANDATA)), (PREAMP_AUDIO_BUFFER_SIZE * 2) - 1); /* Indicate starting with primary in-buffer (according to above DMA setup) */ preampProcessPrimary = true; /* Configure ADC */ /* Keep warm due to "high" frequency sampling */ init.warmUpMode = adcWarmupKeepADCWarm; /* Init common issues for both single conversion and scan mode */ init.timebase = ADC_TimebaseCalc(0); init.prescale = ADC_PrescaleCalc(4000000, 0); /* Sample potentiometer by tailgating in order to not disturb fixed rate */ /* audio sampling. */ init.tailgate = true; ADC_Init(ADC0, &init); /* Init for single conversion use (potentiometer). */ singleInit.reference = adcRefVDD; singleInit.input = adcSingleInpCh5; /* According to DVK HW design */ singleInit.resolution = adcRes8Bit; /* Use at least 8 bit since unlinear voltage */ ADC_InitSingle(ADC0, &singleInit); /* Init for scan sequence use (audio in right/left channels). */ scanInit.prsSel = adcPRSSELCh0; scanInit.prsEnable = true; scanInit.reference = adcRefVDD; scanInit.input = ADC_SCANCTRL_INPUTMASK_CH0 | ADC_SCANCTRL_INPUTMASK_CH1; ADC_InitScan(ADC0, &scanInit); }