Hi,
I'm trying to get the following to work (sample 2 channels on 1Khz triggered by Timer1 Capture with DMA driven transfer ie based on Andy's code).
#include "mbed.h"
#include "MODDMA.h"
// How long between grabbing samples on all channels.
// Value is in microseconds (1000 fails probably on modserial output)
#define SAMPLE_PERIOD 1000
#define NUM_OF_SAMPLES 10
Serial pc(USBTX, USBRX);
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
//TODO Add three timing arrays,
// 1) timer0 int start,
// 2) after the dma config (skew)
// 3) inside the dma_callback.
uint32_t adBuffer[NUM_OF_SAMPLES * 2];
int t1[NUM_OF_SAMPLES];
int t2[NUM_OF_SAMPLES];
int t3[NUM_OF_SAMPLES];
bool dmaTransferComplete;
int sample_index = 0;
MODDMA dma;
MODDMA_Config *conf;
Timer cap_timing;
void TC0_callback(void);
void ERR0_callback(void);
extern "C" void TIMER1_handler(void)
__irq {
if (sample_index<NUM_OF_SAMPLES) {
t1[sample_index]=cap_timing.read_us();
// Pre-prep a transfer
dma.Setup(conf);
dma.Enable(conf);
LPC_ADC->ADCR |= (1UL << 16); // ADC burst mode
LPC_ADC->ADINTEN = 0x100; // Do all channels.
t2[sample_index]=cap_timing.read_us();
}
LPC_TIM1->IR = 1; // Clr timer1 irq.
}
int main() {
memset(adBuffer, 0, sizeof(adBuffer));
memset(t1, 0, sizeof(t1));
memset(t2, 0, sizeof(t2));
memset(t3, 0, sizeof(t3));
sample_index=0;
// Setup the serial port to print out results.
pc.baud(115200);
pc.printf("Starting up...\n");
// Power up the ADC and set PCLK
LPC_SC->PCONP |= (1UL << 12);
LPC_SC->PCLKSEL0 |= (3UL << 24); // PCLK = CCLK/8 96M/8 = 12MHz
NVIC_DisableIRQ(ADC_IRQn);
// Set the pin functions to ADC
LPC_PINCON->PINSEL1 &= ~(3UL << 14); /* P0.23, Mbed p15 AD0.0 */
LPC_PINCON->PINSEL1 |= (1UL << 14);
LPC_PINCON->PINSEL1 &= ~(3UL << 16); /* P0.24, Mbed p16 AD0.1 */
LPC_PINCON->PINSEL1 |= (1UL << 16);
LPC_ADC->ADINTEN = 0x100;
// Enable the ADC,
// 1MHz,
// ADC0.0, ADC0.1
LPC_ADC->ADCR = (1UL << 21) | (11UL << 8) | (3UL << 0); ///VEG: @ 4Mhz the slip starts. Now 1Mhz
LPC_SC->PCONP |= (1UL << 2); // TIM1 On
LPC_SC->PCLKSEL0 |= (3UL << 4); // Timer0 CCLK/8 = 12MHz
LPC_TIM1->PR = 11; // TC clocks at 1MHz.
LPC_TIM1->MR0 = SAMPLE_PERIOD-1; //VEG: To be exact!
LPC_TIM1->MCR = 3; // Reset TCR to zero on match and irq.
NVIC_SetVector(TIMER1_IRQn, (uint32_t)TIMER1_handler);
NVIC_EnableIRQ(TIMER1_IRQn);
// Prepare the GPDMA system.
conf = new MODDMA_Config;
conf
->channelNum ( MODDMA::Channel_0 )
->dstMemAddr ( (uint32_t)adBuffer )
->transferSize ( 2 )
->transferType ( MODDMA::p2m )
->transferWidth ( MODDMA::word )
->srcConn ( MODDMA::ADC )
->attach_tc ( &TC0_callback )
->attach_err ( &ERR0_callback )
; // end conf.
// Prepare configuration.
if (!dma.Setup( conf )) {
error("Doh!");
}
pc.printf("Before %ld\r\n", conf->dstMemAddr());
cap_timing.reset();
cap_timing.start();
// Begin.
LPC_TIM1->TCR = 1;
bool dumped = false;
while (1) {
if (!dumped && sample_index==NUM_OF_SAMPLES) {
for (int j=0;j<NUM_OF_SAMPLES;j++) {
pc.printf("ADC 0x%08lx 0x%08lx\r\n", adBuffer[j*2+0], adBuffer[j*2+1]);
pc.printf("TIMING %d %d %d\r\n", t1[j], t2[j], t3[j]);
}
dumped=true;
cap_timing.stop();
}
}
}
// Configuration callback on TC
void TC0_callback(void) {
t3[sample_index]=cap_timing.read_us();
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() );
//Does not clear any flags
//uint32_t dummy = LPC_ADC->ADDR0;
//TODO Store TimeStamp or better Increment Destination Address.
config->dstMemAddr(config->dstMemAddr()+2*sizeof(uint32_t));
// Clear DMA IRQ flags.
if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();
sample_index++;
}
// 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");
}
The output is look like:
ADC 0x8000bef0 0x81000000
TIMING 1000 1010 1139
ADC 0xc000b4b0 0x81000000
TIMING 2000 2010 2139
ADC 0xc000b4d0 0x81000000
TIMING 3000 3010 3139
ADC 0xc000b720 0x81000000
TIMING 4000 4010 4139
ADC 0xc000b810 0x81000000
TIMING 5000 5010 5139
ADC 0xc000b8b0 0x81000000
TIMING 6000 6010 6139
ADC 0xc000b8d0 0x81000000
TIMING 7000 7010 7139
ADC 0xc000b950 0x81000000
TIMING 8000 8010 8139
ADC 0xc0000a00 0x81000000
TIMING 9000 9010 9139
ADC 0xc000b650 0x81000000
TIMING 10000 10010 10139
Strangely enough did I not see overrun flags in the original 3 channel code. Channel slipping starts at 3-4Mhz.
Is this overrrun flag caused by DMA to finished a started ADC conversion?
Hi,
I'm trying to get the following to work (sample 2 channels on 1Khz triggered by Timer1 Capture with DMA driven transfer ie based on Andy's code).
The output is look like:
Strangely enough did I not see overrun flags in the original 3 channel code. Channel slipping starts at 3-4Mhz.
Is this overrrun flag caused by DMA to finished a started ADC conversion?