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.

CCS/TMS320F28379D: CCS

Part Number: TMS320F28379D

Tool/software: Code Composer Studio

Hello All,

             This is Sainath. I'm presently working on implementing a correlation algorithm using the TI DSP. I'm trying to normalize the adc output and then implement my correlation using a function. I attached my code below. The problem I am facing is that when I include the cross-correlation function the sampling rate is getting reduced automatically. Actually, I have configured my adc at a sampling rate of 44.1kHz. When I include the correlation function, the sampling rate is turning out to be 5kHz. Can someone help me rectify this problem.  Please find the code attached below. Please note that the name of the correlation function in my code is Corr()

//###########################################################################
//
// FILE: adc_soc_epwm_cpu01.c
//
// TITLE: ADC triggering via epwm for F2837xD.
//
//! \addtogroup cpu01_example_list
//! <h1> ADC ePWM Triggering (adc_soc_epwm)</h1>
//!
//! This example sets up the ePWM to periodically trigger the ADC.
//!
//! After the program runs, the memory will contain:\n
//! - \b AdcaResults \b: A sequence of analog-to-digital conversion samples from
//! pin A0. The time between samples is determined based on the period
//! of the ePWM timer.
//
//###########################################################################
// $TI Release: F2837xD Support Library v210 $
// $Release Date: Tue Nov 1 14:46:15 CDT 2016 $
// $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

//
// Included Files
//

#include "F28x_Project.h"

//
// Function Prototypes
//
void ConfigureADC(void);

void ConfigureEPWM(void);

void SetupADCEpwm(Uint16 channel);

interrupt void adca1_isr(void);

float Corr();

//
// Defines
//

#define RESULTS_BUFFER_SIZE 256

//
// Globals
//

Uint16 AdcaResults[RESULTS_BUFFER_SIZE];

Uint16 resultsIndex;

volatile Uint16 bufferFull;

int bufferIndex = 0;

float normalized_array[RESULTS_BUFFER_SIZE] = {0};

float filter[400] = {0.0163,-0.0069,0.0103,0.0088,0.0109,0.0165 ,0.0224,-0.0091,0.0094,-0.0081,0.0114,0.0060,0.0154,-0.0018,0.0339,0.1016,0.2103,0.2792,0.3139,0.2842,0.2850,0.2735,0.2478,0.2496,0.3135,0.3284,0.2305,0.1926,0.2342,0.3531,0.3701,0.3910,0.5126,0.6676,0.7166,0.7414,0.7653,0.7996,0.7991,0.8057,0.8329,0.8295,0.8479,0.8338,0.8140,0.8210,0.8301,0.8034,0.7677,0.7048,0.6983,0.6957,0.6248,0.5485,0.5858,0.6613,0.6770,0.5989,0.4721,0.3811,0.3567,0.3584,0.3613,0.3429,0.2659,0.2617,0.3239,0.3308,0.2589,0.1722,0.0947,0.0532,0.0821,0.0996,0.0790,0.0924,0.0873,0.0809,0.0878,0.0670,0.0727,0.0754,0.0137,0.0640,0.1973,0.3587,0.5031,0.6667,0.8310,0.7853,0.6194,0.4845,0.3999,0.2866,0.2158,0.2012,0.1592,0.0672,0.0787,0.1873,0.3205,0.3636,0.3666,0.4194,0.4000,0.3457,0.3121,0.3875,0.5380,0.6427,0.7295,0.7635,0.7545,0.7926,0.7347,0.6392,0.5417,0.4738,0.4846,0.5247,0.5699,0.5867,0.5555,0.4857,0.4225,0.4341,0.4204,0.2339,0.0294, -0.0797,-0.0217,0.0377,0.0392,0.0595,0.0751,0.1192,0.1348,0.1468,0.1402,0.0759,0.0367,0.0429,0.0627,0.0968,0.0975,0.0655,-0.0545,-0.2212,-0.2579,-0.2611,-0.3271,-0.4310,-0.4971,-0.5212,-0.5847,-0.6036,-0.5984,-0.5684,-0.4879,-0.5073,-0.5847,-0.5482,-0.4201,-0.3531,-0.3856,-0.4550,-0.5055,-0.5451,-0.5791,-0.5962,-0.6388,-0.7350,-0.7776,-0.7120,-0.6828,-0.6749,-0.7125,-0.7711,-0.7303,-0.6565,-0.5803,-0.5426,-0.5471,-0.5299,-0.4884,-0.4623,-0.4409,-0.4146,-0.3436,-0.2169,-0.1125,-0.0901,-0.1890,-0.3435,-0.5004,-0.6040,-0.5998,-0.5177,-0.3957,-0.2677,-0.1347,-0.0363,0.0253,0.0351,0.0029,-0.0009,-0.0112,-0.0297,-0.0432,-0.0944,-0.1792,-0.2360,-0.2734,-0.2474,-0.1670,-0.1473,-0.2091,-0.3363,-0.4371,-0.4424,-0.3652,-0.2777,-0.2153,-0.2218,-0.3008,-0.2942,-0.2166,-0.2272,-0.3096,-0.3245,-0.2888,-0.3171,-0.4544,-0.5883,-0.5809,-0.4863,-0.4118,-0.4249,-0.4342,-0.3705,-0.3185,-0.3143,-0.3424,-0.3746,-0.3404,-0.2070,-0.1125,-0.1510,-0.3132,-0.4736,-0.4586,-0.3453,-0.3190,-0.3912,-0.4579,-0.4528,-0.3677,-0.3440,-0.4265,-0.5006,-0.5111,-0.4322,-0.3290,-0.2860,-0.3341,-0.4168,-0.4527,-0.4149,-0.3436,-0.3391,-0.4395,-0.5568,-0.5878,-0.5730,-0.5641,-0.5750,-0.5971,-0.6265,-0.6824,-0.7018,-0.6522,-0.6117,-0.6177,-0.5788,-0.5188,-0.4928,-0.4069,-0.2427,-0.1039,-0.0690,-0.1012,-0.1470,-0.1452,-0.0515,0.0414,0.0296,-0.0438,-0.1505,-0.2681,-0.2580,-0.1727,-0.1557,-0.1847,-0.2377,-0.2570,-0.1141,0.0841,0.1054,-0.0175,-0.1747,-0.2758,-0.2191,-0.0910,-0.0671,-0.1691,-0.3220,-0.4546,-0.5044,-0.4895,-0.4320,-0.3358,-0.2927,-0.3598,-0.3938,-0.2742,-0.0990,0.0405,0.1248,0.1158,0.0291,-0.0394,-0.0489,-0.0165,0.0964,0.2615,0.2798,0.0444,-0.2340,-0.3210,-0.2323,-0.0917,-0.0210,-0.1063,-0.2705,-0.3724,-0.4099,-0.4142,-0.3882,-0.3484,-0.2798,-0.2075,-0.1987,-0.2353,-0.2875,-0.3217,-0.1885,0.0804,0.2025,0.1574,0.1402,0.1379,0.1548,0.3040,0.4565,0.4843,0.4967,0.4863,0.3980,0.3622,0.3875,0.3585,0.3168,0.2960,0.2637,0.2711,0.3394,0.4037,0.4219,0.4118,0.4016,0.3438,0.1996,0.0535,-0.0305,-0.0494,-0.0120,-0.0168,-0.1003,-0.1482,-0.1557,-0.1784,-0.1451,-0.0636,-0.0514,-0.1244,-0.2374,-0.3208,-0.3103,-0.2920,-0.3172};

float result[256] = {0};

float Corr()

{

float out = 0;

int i = 0;

int index = 0;

for (i = 0; i < 256; i++)

{
index = ((i + resultsIndex + 1) % 256);

out = out + (normalized_array[index-1] * filter[i]);

}

return out;

}

void main(void)

{
//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//

InitSysCtrl();

//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//

InitGpio(); // Skipped for this example

//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//

DINT;

//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
//

InitPieCtrl();

//
// Disable CPU interrupts and clear all CPU interrupt flags:
//

IER = 0x0000;

IFR = 0x0000;

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//

InitPieVectTable();

//
// Map ISR functions
//

EALLOW;

PieVectTable.ADCA1_INT = &adca1_isr; //function for ADCA interrupt 1

EDIS;

//
// Configure the ADC and power it up
//
ConfigureADC();

//
// Configure the ePWM
//

ConfigureEPWM();

//
// Setup the ADC for ePWM triggered conversions on channel 0
//

SetupADCEpwm(0);

//
// Enable global Interrupts and higher priority real-time debug events:
//
IER |= M_INT1; //Enable group 1 interrupts

EINT; // Enable Global interrupt INTM

ERTM; // Enable Global realtime interrupt DBGM

//
// Initialize results buffer
//
for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)

{

AdcaResults[resultsIndex] = 0;

}

resultsIndex = 0;

bufferIndex = 0;

bufferFull = 0;

//
// enable PIE interrupt
//
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;

//
// sync ePWM
//

EALLOW;

CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;

//
//take conversions indefinitely in loop
//
do

{
//
//start ePWM
//

EPwm1Regs.ETSEL.bit.SOCAEN = 1; //enable SOCA

EPwm1Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode

//
//wait while ePWM causes ADC conversions, which then cause interrupts,
//which fill the results buffer, eventually setting the bufferFull
//flag
//

while(!bufferFull);

bufferFull = 0; //clear the buffer full flag

//
//stop ePWM

//

EPwm1Regs.ETSEL.bit.SOCAEN = 0; //disable SOCA

EPwm1Regs.TBCTL.bit.CTRMODE = 3; //freeze counter

//
//at this point, AdcaResults[] contains a sequence of conversions
//from the selected channel
//

//
//software breakpoint, hit run again to get updated conversions
//
asm(" ESTOP0");

}while(1);

}

//
// ConfigureADC - Write ADC configurations and power up the ADC for both
// ADC A and ADC B
//

void ConfigureADC(void)

{

EALLOW;

//
//write configurations
//

AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4

AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);

//
//Set pulse positions to late
//

AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;

//
//power up the ADC
//

AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;

//
//delay for 1ms to allow ADC time to power up
//

DELAY_US(1000);

EDIS;
}

//
// ConfigureEPWM - Configure EPWM SOC and compare values
//

void ConfigureEPWM(void)

{
EALLOW;

// Assumes ePWM clock is already enabled

EPwm1Regs.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group

EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Select SOC on up-count

EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event

EPwm1Regs.CMPA.bit.CMPA = 142; // Set compare A value to 2048 counts

EPwm1Regs.TBPRD = 248; // Set period to 4096 counts

EPwm1Regs.TBCTL.bit.CTRMODE = 3; // freeze counter

EDIS;

}

//
// SetupADCEpwm - Setup ADC EPWM acquisition window
//

void SetupADCEpwm(Uint16 channel)

{
Uint16 acqps;

//
//determine minimum acquisition window (in SYSCLKS) based on resolution
//

if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION)

{

acqps = 14; //75ns

}

else //resolution is 16-bit

{

acqps = 63; //320ns

}

//
//Select the channels to convert and end of conversion flag
//

EALLOW;

AdcaRegs.ADCSOC0CTL.bit.CHSEL = channel; //SOC0 will convert pin A0

AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 100 SYSCLK cycles

AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //trigger on ePWM1 SOCA/C

AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; //end of SOC0 will set INT1 flag

AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; //enable INT1 flag

AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared

EDIS;

}

//
// adca1_isr - Read ADC Buffer in ISR
//

interrupt void adca1_isr(void)

{
AdcaResults[resultsIndex] = AdcaResultRegs.ADCRESULT0;

normalized_array[resultsIndex] = ((2.0*AdcaResults[resultsIndex])/4095.0) - 1.0;

result[resultsIndex] = Corr();

resultsIndex++;

bufferIndex++;

if(RESULTS_BUFFER_SIZE <= resultsIndex && bufferIndex <= RESULTS_BUFFER_SIZE)

{
resultsIndex = 0;

bufferFull = 1;

bufferIndex = 0;

}

AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag

PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

}


//
// End of file
//

Thank you.

Sincerely,

Sainath Reddy.

  • Hi Sainath,

    If you are samplingn at 44.1kHz and running the device at 200MHz then you have about 200/0.0441 = 4535 cycles per sample to process the data. You might want to benchmark how many cycles the corr() function actually takes since it is in the main ISR (and also ensure that the MCU is running at the maximum possible speed).
  • Hello Devin,

                        Thank you so much for your reply. The only problem I'm facing here is because of an assignment statement in the main ISR i.e., 

    result[resultsIndex] = Corr();

    Everything is working fine if I just execute the function and don't assign the return value to an array.

    But, if assign the value to an array, then the sampling rate is getting reduced automatically.

    Can you please help me in solving the problem of what difference the assigning statement is bringing to the code.

    Thank you.

    Sincerely,

    Sainath Reddy.

  • Hi Sainath,

    I think in both cases it may be worth determining how long the instruction takes to execute.

    Some ways you can do this:
    *Toggle a GPIO before and after and use a scope to measure the time (very crude, but simple and gives a good ballpark)
    *Set a breakpoint before and after the code in question. Enable the clock in Run->Clock menu of CCS. Observe the time between breakpoints.
    *Or see processors.wiki.ti.com/.../Profiling_on_C28x_Targets

    You might also look at the disassembly to see if the function is even called when no assignment is made; it may be that the compiler sees that you don't use the result and is smart enough to skip the call entirely in that case.