Question

I am programming on an embedded microcontroller (TMS320F28069) a 32-bit floating point MCU. I was going over some of the example projects, and one of them implements a simple FIR filter on ADC sampled data.

Block diagram here

Let's say the ADC buffer has 10 elements. And let's say the filter has length 3 (FILTER_LEN=3). The filter implementation is pretty straightforward, it starts at the end of the delay chain and moves its way to the beginning.

float32 ssfir(float32 *x, float32 *a, Uint16 n)
{

Uint16 i;                                   // general purpose
float32 y;                                  // result
float32 *xold;                              // delay line pointer

/*** Setup the pointers ***/
    a = a + (n-1);                      // a points to last coefficient
    x = x + (n-1);                      // x points to last buffer element
    xold = x;                           // xold points to last buffer element

/*** Last tap has no delay line update ***/
    y = (*a--)*(*x--);

/*** Do the other taps from end to beginning ***/
    for(i=0; i<n-1; i++)
    {
        y = y + (*a--)*(*x);            // filter tap
        *xold-- = *x--;                 // delay line update
    }

/*** Finish up ***/
    return(y);

}

Now, here is how the ADC circular buffer is implemented.

//---------------------------------------------------------------------
interrupt void ADCINT1_ISR(void)                // PIE1.1 @ 0x000D40  ADCINT1
{
static float32 *AdcBufPtr = AdcBuf;                 // Pointer to ADC data buffer
static float32 *AdcBufFilteredPtr = AdcBufFiltered; // Pointer to ADC filtered data buffer

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;     // Must acknowledge the PIE group

//--- Manage the ADC registers     
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;       // Clear ADCINT1 flag

//--- Read the ADC result:
    *AdcBufPtr = ADC_FS_VOLTAGE*(float32)AdcResult.ADCRESULT0;

//--- Call the filter function
    xDelay[0] = *AdcBufPtr++;                   // Add the new entry to the delay chain
    *AdcBufFilteredPtr++ = ssfir(xDelay, coeffs, FILTER_LEN);

//--- Brute-force the circular buffer
    if( AdcBufPtr == (AdcBuf + ADC_BUF_LEN) )
    {
        AdcBufPtr = AdcBuf;                     // Rewind the pointer to the beginning
        AdcBufFilteredPtr = AdcBufFiltered;     // Rewind the pointer to the beginning
    }

}

xDelay is a float32 array of length FILTER_LEN initialized with 0s and coeffs is a float32 array of length FILTER_LEN initialized with the filter coefficients.

My question is, what is going on here:

//--- Call the filter function
    xDelay[0] = *AdcBufPtr++;                   // Add the new entry to the delay chain
    *AdcBufFilteredPtr++ = ssfir(xDelay, coeffs, FILTER_LEN);

How do values ever get stored in xDelay[1] or xDelay[2]? Their implementation seems to work fine, but I'm not following how old data gets pushed back in the xDelay array.

Was it helpful?

Solution

in the ssfir() function the following line shuffles the elements in the xDelay array

    *xold-- = *x--;                 // delay line update

the line is in the for loop so the [1] element is copied to the [2] then the [0] element is copied to the [1] since the x and xold pointers decrement in spite of the for loop counting up

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top