This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RE: RE: CCS/DK-TM4C129X: Sorting Six ADC conversions

Hello Bob,

I am extremely sorry as I didnt reply sooner. I was sick for a period of time... Yes that successive conversion is acceptable as its a very little time offset. I took some time to implement what you suggested and implemented successfully. I used ping pong mode to capture the 6 ADC samples from sequencer 0 FIFO, put a transfer size of 1024 in the DMA config and was able to sample 6 channels with a offset of around 7.8uS as I put a sample rate of 128KHz.....and I am sorting the 1024 sized ping/pong buffer into 6 separate buffers of 128 size each and performing fft on each one of them. The results are almost correct. But the buffers are not correctly sorted, the results keep on changing in buffer..like if give square wave to 3 inputs and sine wave to 3 inputs... I expect the respective buffers to have that wave...but It changes...at first it have square then sine ...like that...As I have not used scatter gather. Below is the way SS0 is configured and how data is taken from ping / pong buffer (unsorted):

    ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH3);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH14);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH15 | ADC_CTL_IE |
                             ADC_CTL_END);   

Extraction:

    for(m = 0; m < 128; m++)
      {
    		fftin1[m] =  g_ui8RxBufB[6*m];

    	  	fftin2[m] =  g_ui8RxBufB[6*m+1];

    		fftin3[m] =  g_ui8RxBufB[6*m+2];

    	  	fftin4[m] =  g_ui8RxBufB[6*m+3];

    		fftin5[m] =  g_ui8RxBufB[6*m+4];
fftin6[m] = g_ui8RxBufB[6*m+5]; }

But above , you said to use scatter gather mode to sort samples in 6 different buffers for proessing. Honestly , I dont know about this mode right now. I will study about this mode from the data sheet, and try to write some code for that....

Thank you for all your help, ...just have a small favor to ask...if you or anyone else who is reading this, can provide some example on implementing scatter gather.

Regards,

Harshul agarwal

  • I do have one more question. While I was implementing for 6 channels (without scatter gather) on a single sequencer 0, this was orking fine. But before this I thought of using3 sequencers SS0,1,2 and putting 2-2 channels each in the sequencers and then using ping pong mode to capture data, this was not working correctly. I dont know why this was not working. Prior to this, I tested SS0,1,2 individually with 2 channel input (commenting out all the other sequencer parts), and for 2 channels each sequencer was giving correct output. But when combined all together to take 6 inputs, the buffers were not filled correctly.

    I set the priority of SS0 to 0, SS1 to 1, and SS2 to 2. But in the result, only sequencer 2 was filling correctly. What might be the reason? I am attaching my code for this part: 

    void uDMAErrorHandler(void)
    
    {
    
        uint32_t ui32Status;
    
        //
    
        // Check for uDMA error bit
    
        //
    
        ui32Status = uDMAErrorStatusGet();
    
    
        //
    
        // If there is a uDMA error, then clear the error and increment
    
        // the error counter.
    
        //
    
        if(ui32Status)
    
        {
            uDMAErrorStatusClear();
            g_ui32uDMAErrCount++;
        }
    
    }
    
    void ADCseq0Handler()
    
    {
        //uint32_t ui32Status;
        uint32_t ui32Mode;
        uint32_t ui32Mode1;
        uint32_t ui32Mode2;
        uint32_t i;
        uint32_t j,k,l;
        uint32_t a,b,c;
        uint32_t d,m,n;
        uint32_t p,q,r;
        uint32_t s,x,y;
        ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS0);
        ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS1);
        ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS2);
    
        for(m = 0; m < 512; m++)
          {
        		fftin1[m] =  g_ui8RxBufB[2*m];
        	  //else
        	  	fftin2[m] =  g_ui8RxBufB[2*m+1];
    
        		fftin3[m] =  g_ui8RxBufB1[2*m];
        	  //else
        	  	fftin4[m] =  g_ui8RxBufB1[2*m+1];
    
        		fftin5[m] =  g_ui8RxBufB2[2*m];
        	  //else
        	  	fftin6[m] =  g_ui8RxBufB2[2*m+1];
          }
    
        for(i = 0; i < 512; i++)
          {
        		testInput_f32_10khz[2*i] =  (float32_t)fftin1[i];
        	  //else
        	  	testInput_f32_10khz[2*i + 1] =  0;
    
        		testInput_f32_10khz1[2*i] =  (float32_t)fftin2[i];
        	  //else
        	  	testInput_f32_10khz1[2*i + 1] =  0;
    
        		testInput_f32_10khz2[2*i] =  (float32_t)fftin3[i];
        	  //else
        	  	testInput_f32_10khz2[2*i + 1] =  0;
    
        		testInput_f32_10khz3[2*i] =  (float32_t)fftin4[i];
        	  //else
        	  	testInput_f32_10khz3[2*i + 1] =  0;
    
        		testInput_f32_10khz4[2*i] =  (float32_t)fftin5[i];
        	  //else
        	  	testInput_f32_10khz4[2*i + 1] =  0;
    
        		testInput_f32_10khz5[2*i] =  (float32_t)fftin6[i];
        	  //else
        	  	testInput_f32_10khz5[2*i + 1] =  0;
          }
    
        /* Process the data through the CFFT/CIFFT module */
        arm_cfft_f32(&arm_cfft_sR_f32_len512, testInput_f32_10khz, ifftFlag, doBitReverse);
        arm_cfft_f32(&arm_cfft_sR_f32_len512, testInput_f32_10khz1, ifftFlag, doBitReverse);
        arm_cfft_f32(&arm_cfft_sR_f32_len512, testInput_f32_10khz2, ifftFlag, doBitReverse);
        arm_cfft_f32(&arm_cfft_sR_f32_len512, testInput_f32_10khz3, ifftFlag, doBitReverse);
        arm_cfft_f32(&arm_cfft_sR_f32_len512, testInput_f32_10khz4, ifftFlag, doBitReverse);
        arm_cfft_f32(&arm_cfft_sR_f32_len512, testInput_f32_10khz5, ifftFlag, doBitReverse);
        /* Process the data through the Complex Magnitude Module for
        calculating the magnitude at each bin */
        arm_cmplx_mag_f32(testInput_f32_10khz, testOutput, fftSize);
        arm_cmplx_mag_f32(testInput_f32_10khz1, testOutput1, fftSize);
        arm_cmplx_mag_f32(testInput_f32_10khz2, testOutput2, fftSize);
        arm_cmplx_mag_f32(testInput_f32_10khz3, testOutput3, fftSize);
        arm_cmplx_mag_f32(testInput_f32_10khz4, testOutput4, fftSize);
        arm_cmplx_mag_f32(testInput_f32_10khz5, testOutput5, fftSize);
        testOutput[0] = 0;
        testOutput1[0] = 0;
        testOutput2[0] = 0;
        testOutput3[0] = 0;
        testOutput4[0] = 0;
        testOutput5[0] = 0;
        /* Calculates maxValue and returns corresponding BIN value */
        arm_max_f32(testOutput, fftSize, &maxValue, &testIndex);
        arm_max_f32(testOutput1, fftSize, &maxValue1, &testIndex1);
        arm_max_f32(testOutput2, fftSize, &maxValue2, &testIndex2);
        arm_max_f32(testOutput3, fftSize, &maxValue3, &testIndex3);
        arm_max_f32(testOutput4, fftSize, &maxValue4, &testIndex4);
        arm_max_f32(testOutput5, fftSize, &maxValue5, &testIndex5);
    
        maxValue = (maxValue*3.3/256.0)/4096.0;
        maxValue1 = (maxValue1*3.3/256.0)/4096.0;
        maxValue2 = (maxValue2*3.3/256.0)/4096.0;
        maxValue3 = (maxValue3*3.3/256.0)/4096.0;
        maxValue4 = (maxValue4*3.3/256.0)/4096.0;
        maxValue5 = (maxValue5*3.3/256.0)/4096.0;
    
    
        ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);
    
        if(ui32Mode == UDMA_MODE_STOP)
        {
    
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
    
                                       UDMA_MODE_PINGPONG,
    
                                       (void *)(ADC0_BASE + ADC_O_SSFIFO0),
    
                                       g_ui8RxBufA, MEM_BUFFER_SIZE);
    
            uDMAChannelEnable(UDMA_CHANNEL_ADC0);
    
        }
    
        ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);
    
        if(ui32Mode == UDMA_MODE_STOP)
    
        {
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
    
                                        UDMA_MODE_PINGPONG,
    
                                        (void *)(ADC0_BASE + ADC_O_SSFIFO0),
    
                                        g_ui8RxBufB, MEM_BUFFER_SIZE);
    
            uDMAChannelEnable(UDMA_CHANNEL_ADC0);
    
        }
    
        ui32Mode1 = uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT);
    
        if(ui32Mode1 == UDMA_MODE_STOP)
        {
    
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
    
                                       UDMA_MODE_PINGPONG,
    
                                       (void *)(ADC0_BASE + ADC_O_SSFIFO1),
    
                                       g_ui8RxBufA1, MEM_BUFFER_SIZE);
    
            uDMAChannelEnable(UDMA_CHANNEL_ADC1);
    
        }
    
        ui32Mode1 = uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT);
    
        if(ui32Mode1 == UDMA_MODE_STOP)
    
        {
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
    
                                        UDMA_MODE_PINGPONG,
    
                                        (void *)(ADC0_BASE + ADC_O_SSFIFO1),
    
                                        g_ui8RxBufB1, MEM_BUFFER_SIZE);
    
            uDMAChannelEnable(UDMA_CHANNEL_ADC1);
    
        }
    	    ui32Mode2 = uDMAChannelModeGet(UDMA_CHANNEL_ADC2 | UDMA_PRI_SELECT);
    
        if(ui32Mode2 == UDMA_MODE_STOP)
        {
    
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC2 | UDMA_PRI_SELECT,
    
                                       UDMA_MODE_PINGPONG,
    
                                       (void *)(ADC0_BASE + ADC_O_SSFIFO2),
    
                                       g_ui8RxBufA2, MEM_BUFFER_SIZE);
    
            uDMAChannelEnable(UDMA_CHANNEL_ADC2);
    
        }
    
        ui32Mode2 = uDMAChannelModeGet(UDMA_CHANNEL_ADC2 | UDMA_ALT_SELECT);
    
        if(ui32Mode2 == UDMA_MODE_STOP)
    
        {
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC2 | UDMA_ALT_SELECT,
    
                                        UDMA_MODE_PINGPONG,
    
                                        (void *)(ADC0_BASE + ADC_O_SSFIFO2),
    
                                        g_ui8RxBufB2, MEM_BUFFER_SIZE);
    
            uDMAChannelEnable(UDMA_CHANNEL_ADC2);
    
        }
    }
    
    void
    InitUART1Transfer(uint32_t sysclock)
    
    {
    	uint32_t ui32Period;
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    
        while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0)));
    
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_ADC0);
    
        ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 24);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    
        while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD)));
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
        while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE)));
    
        GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_0);
        GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_1);
    //    GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_2);
    //    GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
    
        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0);
        ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1);
        ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2);
    
        ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH14);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH15 | ADC_CTL_END);
    
        ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0);
        ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1 | ADC_CTL_END);
    //
        ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH2);
        ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH3 | ADC_CTL_IE |
                                 ADC_CTL_END);
    
        ADCSequenceEnable(ADC0_BASE, 0);
        ADCSequenceEnable(ADC0_BASE, 1);
        ADCSequenceEnable(ADC0_BASE, 2);
    //    ADCSequenceEnable(ADC1_BASE, 3);
        ADCIntClear(ADC0_BASE, 0);
        ADCIntClear(ADC0_BASE, 1);
        ADCIntClear(ADC0_BASE, 2);
    //    ADCIntClear(ADC1_BASE, 3);
    
        // Enable the Timer peripheral
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    
        // Timer should run periodically
        TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    
        // Set the value that is loaded into the timer everytime it finishes
        //   it's the number of clock cycles it takes till the timer triggers the ADC
        //#define F_SAMPLE    1000
        ui32Period = 120000000/512000;
        TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period-1);
    
        // Enable triggering
        TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
    
        ADCIntEnable(ADC0_BASE, 0);
        ADCIntEnable(ADC0_BASE, 1);
        ADCIntEnable(ADC0_BASE, 2);
    //	ADCIntEnable(ADC1_BASE, 3);
    
        // Enable the timer
        TimerEnable(TIMER0_BASE, TIMER_A);
    
        ADCSequenceDMAEnable(ADC0_BASE, 0);
        ADCSequenceDMAEnable(ADC0_BASE, 1);
        ADCSequenceDMAEnable(ADC0_BASE, 2);
    
        uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0,
    
                                        UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    
                                        UDMA_ATTR_HIGH_PRIORITY |
    
                                        UDMA_ATTR_REQMASK);
    
        uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC1,
    
                                        UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    
                                        UDMA_ATTR_HIGH_PRIORITY |
    
                                        UDMA_ATTR_REQMASK);
    
        uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC2,
    
                                        UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    
                                        UDMA_ATTR_HIGH_PRIORITY |
    
                                        UDMA_ATTR_REQMASK);
    
        uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
    
                                UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_NEXT_USEBURST |
    
                                  UDMA_ARB_2);
    
        uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
    
                                UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_NEXT_USEBURST |
    
                                UDMA_ARB_2);
    
        uDMAChannelControlSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
    
                                UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_NEXT_USEBURST |
    
                                  UDMA_ARB_2);
    
        uDMAChannelControlSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
    
                                UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_NEXT_USEBURST |
    
                                UDMA_ARB_2);
    
        uDMAChannelControlSet(UDMA_CHANNEL_ADC2 | UDMA_PRI_SELECT,
    
                                UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_NEXT_USEBURST |
    
                                  UDMA_ARB_2);
    
        uDMAChannelControlSet(UDMA_CHANNEL_ADC2 | UDMA_ALT_SELECT,
    
                                UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_NEXT_USEBURST |
    
                                UDMA_ARB_2);
    
    
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
    
                                   UDMA_MODE_PINGPONG,
    
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO0),
    
                                   g_ui8RxBufA, MEM_BUFFER_SIZE);
    
    
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
    
                                    UDMA_MODE_PINGPONG,
    
                                    (void *)(ADC0_BASE + ADC_O_SSFIFO0),
    
                                    g_ui8RxBufB, MEM_BUFFER_SIZE);
    
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
    
                                   UDMA_MODE_PINGPONG,
    
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO1),
    
                                   g_ui8RxBufA1, MEM_BUFFER_SIZE);
    
    
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
    
                                    UDMA_MODE_PINGPONG,
    
                                    (void *)(ADC0_BASE + ADC_O_SSFIFO1),
    
                                    g_ui8RxBufB1, MEM_BUFFER_SIZE);
    
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC2 | UDMA_PRI_SELECT,
    
                                   UDMA_MODE_PINGPONG,
    
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO2),
    
                                   g_ui8RxBufA2, MEM_BUFFER_SIZE);
    
    
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC2 | UDMA_ALT_SELECT,
    
                                    UDMA_MODE_PINGPONG,
    
                                    (void *)(ADC0_BASE + ADC_O_SSFIFO2),
    
                                    g_ui8RxBufB2, MEM_BUFFER_SIZE);
    
        uDMAChannelEnable(UDMA_CHANNEL_ADC0);
        uDMAChannelEnable(UDMA_CHANNEL_ADC1);
        uDMAChannelEnable(UDMA_CHANNEL_ADC2);
    
        ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0);
        ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS1);
        ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS2);
    
        IntEnable(INT_ADC0SS0);
        IntEnable(INT_ADC0SS1);
        IntEnable(INT_ADC0SS2);
    
    
    }
    
    int
    
    main(void)
    
    {
    //		uint32_t i;
    //		uint32_t j;
           // uint32_t sysclock;
    
            sysclock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
    
                                                  SYSCTL_OSC_MAIN |
    
                                                  SYSCTL_USE_PLL |
    
                                                  SYSCTL_CFG_VCO_480), 120000000);
    
         SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    
         while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)));
    
         SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
    
         IntMasterEnable();
    
          IntEnable(INT_UDMAERR);
    
          uDMAEnable();
    
          uDMAControlBaseSet(pui8ControlTable);
    
          InitUART1Transfer(sysclock);
    
    
        while(1)
        {
    
        }
    
    }
    

    So, I skipped this method, and moved on to use only 1 sequencer 0 and sample...Please if anyone can clarify why the above code is wrong and what can be done to make it work...just for clarification.

    Thank You,

    Harshul

  • Harshul,
    Your sorting is probably not working correctly because your buffer size (1024) is not an even multiple of 6. A buffer size of 768 would sort into 6 buffers of 128 samples each. Using a buffer size of 1024 means that when the DMA starts filling the second buffer, the first two value stored would be samples 5 and 6, not samples 1 and 2. (The first buffer would contain 170 times samples 1,2,3,4,5,6; and then samples 1,2,3,4. (170*6)+4=1024.
  • Yes, you are right. I tried with using all 8 inputs  for sequencer 0 such that last two channels are grounded. So, then extracting data out of the buffer by using this code:

        for(m = 0; m < 128; m++)
          {
        		fftin1[m] =  g_ui8RxBufB[8*m];
        	 
        	  	fftin2[m] =  g_ui8RxBufB[8*m+1];
    
        		fftin3[m] =  g_ui8RxBufB[8*m+2];
    
        	  	fftin4[m] =  g_ui8RxBufB[8*m+3];
    
        		fftin5[m] =  g_ui8RxBufB[8*m+4];
    
        	  	fftin6[m] =  g_ui8RxBufB[8*m+5];
          }

    Even this doesnt give right results. Still the sorting is not correct?

    ADC sequencer config:

        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0);
    
        ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH2);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH3);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH1);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH14);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH15);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_CH12);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_CH13 | ADC_CTL_IE |
                                 ADC_CTL_END);
    

    Regards,

    Harshul

  • "moved on to use only 1 sequencer 0 and sample"

    is it sufficiently understood now that what has been discussed here is not to solve your (original?) problem? ie, none of the approaches will deliver 6 simultaneous adc? in fact, the exact opposite is true: you are talking about taking 6 adc inputs sequentially (as in ***not*** simultaneously).

    just wanted to point that out in case the original goal is missed.
  • Yes, I understood that maximum 2 inputs can be sampled simultaneously. So, I talked about this with my senior and he said that sequentially is fine as there will be very less offsest. So, I moved on to use only 1 sequencer.

    As per now, I have a question. In the ADC interrupt handler, if I comment out the part that checks if buffer is full and then re enables it for nxt transfer, then, buffers get filled one time and correctly filled and sorted also. But, I need that kind of data continuously, so I can process that data regularly and display it. But by commenting out, the data in buffers keeps on changing. I am processing data here in the handler:

    void ADCseq0Handler()
    
    {
        uint32_t ui32Mode;
        uint32_t d,m;
    
        //Clears ADC sequence 0 interrupt caused by DMA
        ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS0);
    
    
        //checks udma primary control structure current mode
        ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);
    
        //if udma primary control structure is done transfering data, re-enable it
        if(ui32Mode == UDMA_MODE_STOP)
        {
        	//6 sampled inputs are extracted from the PING/PONG buffer
            for(m = 0; m < 128; m++)
              {
            		fftin1[m] =  g_ui8RxBufA[8*m];
    
            	  	fftin2[m] =  g_ui8RxBufA[8*m+1];
    
            		fftin3[m] =  g_ui8RxBufA[8*m+2];
    
            	  	fftin4[m] =  g_ui8RxBufA[8*m+3];
    
            		fftin5[m] =  g_ui8RxBufA[8*m+6];
    
            	  	fftin6[m] =  g_ui8RxBufA[8*m+7];
              }
             FFT();
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
    
                                       UDMA_MODE_PINGPONG,
    
                                       (void *)(ADC0_BASE + ADC_O_SSFIFO0),
    
                                       g_ui8RxBufA, MEM_BUFFER_SIZE);
    
            uDMAChannelEnable(UDMA_CHANNEL_ADC0);
    
        }
    
        //checks udma secondary control structure current mode
        ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);
    
        //if udma secondary control structure is done transfering data, re-enable it
        if(ui32Mode == UDMA_MODE_STOP)
    
        {
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
    
                                        UDMA_MODE_PINGPONG,
    
                                        (void *)(ADC0_BASE + ADC_O_SSFIFO0),
    
                                        g_ui8RxBufB, MEM_BUFFER_SIZE);
    
            uDMAChannelEnable(UDMA_CHANNEL_ADC0);
    
        }
    }
    
    void FFT()
    {
        uint32_t i;
        uint32_t j,k;
    
    	for(i = 0; i < 128; i++)
    	  {
    			testInput_f32_10khz[2*i] =  (float32_t)fftin1[i];
    		  //else
    			testInput_f32_10khz[2*i + 1] =  0;
    
    			testInput_f32_10khz1[2*i] =  (float32_t)fftin2[i];
    		  //else
    			testInput_f32_10khz1[2*i + 1] =  0;
    
    			testInput_f32_10khz2[2*i] =  (float32_t)fftin3[i];
    		  //else
    			testInput_f32_10khz2[2*i + 1] =  0;
    
    			testInput_f32_10khz3[2*i] =  (float32_t)fftin4[i];
    		  //else
    			testInput_f32_10khz3[2*i + 1] =  0;
    //
    			testInput_f32_10khz4[2*i] =  (float32_t)fftin5[i];
    		  //else
    			testInput_f32_10khz4[2*i + 1] =  0;
    
    			testInput_f32_10khz5[2*i] =  (float32_t)fftin6[i];
    		  //else
    			testInput_f32_10khz5[2*i + 1] =  0;
    	  }
    	/* Process the data through the CFFT/CIFFT module */
    	arm_cfft_f32(&arm_cfft_sR_f32_len128, testInput_f32_10khz, ifftFlag, doBitReverse);
    	arm_cfft_f32(&arm_cfft_sR_f32_len128, testInput_f32_10khz1, ifftFlag, doBitReverse);
    	arm_cfft_f32(&arm_cfft_sR_f32_len128, testInput_f32_10khz2, ifftFlag, doBitReverse);
    	arm_cfft_f32(&arm_cfft_sR_f32_len128, testInput_f32_10khz3, ifftFlag, doBitReverse);
    	arm_cfft_f32(&arm_cfft_sR_f32_len128, testInput_f32_10khz4, ifftFlag, doBitReverse);
    	arm_cfft_f32(&arm_cfft_sR_f32_len128, testInput_f32_10khz5, ifftFlag, doBitReverse);
    	/* Process the data through the Complex Magnitude Module for
    	calculating the magnitude at each bin */
    	arm_cmplx_mag_f32(testInput_f32_10khz, testOutput, fftSize);
    	arm_cmplx_mag_f32(testInput_f32_10khz1, testOutput1, fftSize);
    	arm_cmplx_mag_f32(testInput_f32_10khz2, testOutput2, fftSize);
    	arm_cmplx_mag_f32(testInput_f32_10khz3, testOutput3, fftSize);
    	arm_cmplx_mag_f32(testInput_f32_10khz4, testOutput4, fftSize);
    	arm_cmplx_mag_f32(testInput_f32_10khz5, testOutput5, fftSize);
    	testOutput[0] = 0;
    	testOutput1[0] = 0;
    	testOutput2[0] = 0;
    	testOutput3[0] = 0;
    	testOutput4[0] = 0;
    	testOutput5[0] = 0;
    	/* Calculates maxValue and returns corresponding BIN value */
    	arm_max_f32(testOutput, fftSize, &maxValue, &testIndex);
    	arm_max_f32(testOutput1, fftSize, &maxValue1, &testIndex1);
    	arm_max_f32(testOutput2, fftSize, &maxValue2, &testIndex2);
    	arm_max_f32(testOutput3, fftSize, &maxValue3, &testIndex3);
    	arm_max_f32(testOutput4, fftSize, &maxValue4, &testIndex4);
    	arm_max_f32(testOutput5, fftSize, &maxValue5, &testIndex5);
    
    	maxValue = (maxValue*3.3/64.0)/4096.0;
    	maxValue1 = (maxValue1*3.3/64.0)/4096.0;
    	maxValue2 = (maxValue2*3.3/64.0)/4096.0;
    	maxValue3 = (maxValue3*3.3/64.0)/4096.0;
    	maxValue4 = (maxValue4*3.3/64.0)/4096.0;
    	maxValue5 = (maxValue5*3.3/64.0)/4096.0;
    }

  • "So, I moved on to use only 1 sequencer."

    In that case it may be helpful to your cause if you start a new thread with the right subject line: it wouldn't surprise if some people skipped this discussion because they thought the subject is helpless.

    By putting the right subject line you have a better chance of getting more people involved in helping you find a solution to your problem.

  • Danny F said:
    is it sufficiently understood now that what has been discussed here is not to solve your (original?) problem? ie, none of the approaches will deliver 6 simultaneous adc?

    While that's (almost) true - did not (first I) and then (you) note the fact that six independent (external) ADC ICs (or even, 6 MCUs) - provided they could be properly 'sync'ed' - could meet poster's objectives?

    The issue of the (strict) requirement for, 'Six (only) simultaneous ADC conversions was immediately challenged' - and generated 'NO poster response!'   

    The thread has further devolved into a data-sorting effort - and as you note - the, "NEED for SIX" - has, "LONG - Left the Building!"

  • Is it possible that the time taken to do the FFT calculation is longer than the time for the ADC/uDAM to fill the buffer? You might want to move your FFT calculation out of the interrupt routine. If you are still in the interrupt routine when the ADC/uDMA fills the second buffer, you will miss samples because you will not restart the uDMA in time. the use of static volatile flags to show the buffer state allow you to move the FFT calculation into an infinite loop of the main function. (See attached project for an example of using static volatile flags.) You may want to toggle some I/O pins to measure how long your FFT calculation takes and compare that to the time between uDMA interrupts.

    /cfs-file/__key/communityserver-discussions-components-files/908/0564.ADCwDMA.zip

  • I went ahead and split this thread and re-titled it as suggested by Danny and CB1. The first part is here:
    e2e.ti.com/.../703428
  • Greetings Bob,

    Hats OFF to you - multiple 'coding keys/aids/methods' present - your (inspired) posting!      Bravo!      We especially note: (and would 'LIKE' - should that (still) be possible...)

    Bob's neat guidelines for, 'Managing a reasonably intense calculation while employing the µDMA to 'fill' multiple (two here) buffers.

    • Place your FFT (or other) calculations out of the interrupt routine. 
    • Prolonged 'stay' w/in an 'ISR' (likely) will cause 'missed samples' - as the uDMA may not restart 'in time.'
    • The use of 'static volatile flags' - to show the buffer state - allows  the FFT calculation (or others) to be better placed w/in an  infinite loop - w/in 'main.'
    • 'Toggling I/O pins' enables the ready  measure of calculation's execution (FFT duration, here) - and facilitates comparing that time - to that  between µDMA interrupts.

    I've taken the liberty of (very slight) re-phrasing - and placing your guides in youth favored, 'bullets.'       (Staff & I appreciate your thoughtful & effective effort...)      (this guide will 'invade' our 'modus operandi.')

    Should this 'consolidation' breach some (little known) rule/regulation - PM me - and I will 'round file.'      (the well practiced destination - for (much) cb1 work...)

  • I am sorry everybody to make a mess in this thread.

    Thank you very much Bob for clarifying what might have been the problem. I will surely go through the example project you attached and try to implement the use of static volatile flags and move my fft routine to the while loop. If I get any progress, I will surely update in this thread. 

    Thank You

    Harshul

  • You must insure that your 'FFT routine' (while loop) is, 'Outside of any ISR.'
    You've made 'no mess' - instead 'KISS' dictates that (only) ONE SUBJECT THRUST per Thread - proves 'easiest & most efficient to understand - and to locate when (later) 'searching.' Bon chance mon ami...
  • it is generally unwise to run long routines from within the ISR - it simply makes no sense to do that.

    as to your FFT routines, you should debug it using simulated values. For example, generate a set of data within known frequency / amplitude parameters so you know for sure if  your FFT routines are returning the right values.

    right now, you simply have too many things convoluted together to know what is wrong.

  • Hey cb1, I have now ensured that my FFT routine is not in the interrupt handler. I modified my code and used the static volatile flags that Bob suggested (thank you for that Bob :D), now I am able to generate the required output. Thanks everybody for coming forward and helping me.

    And yeah, BUENA SUERTE MI AMIGO!!

    Regards,
    Harshul

  • Yeah Danny, that was a wrong approach. Now, I have implemented it correctly. I already tested all the things before arriving at this 6 channel processing. I tested my FFT routine, 1 channel ADC with DMA, 2 channels and its FFT (was working correctly in ISR, as small process). So, for 6 channels I didnot think about it and thoughtlessly put the FFT routine in the ISR.

    Regards,
    Harshul