CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Ring Buffer to implement simple lowpass filter
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kein



Joined: 23 Jul 2007
Posts: 103

View user's profile Send private message

Ring Buffer to implement simple lowpass filter
PostPosted: Thu Jun 19, 2008 5:07 am     Reply with quote

Hi Guys,
I would like some help on the implementation of a ring buffer. I've a data coming from adc and wouldlike to apply a simple FIR filter to the data. That's a a signed ring int16 buffer of size 50 would be a good enough.

What I want to do is read 40 samples from the ringbuffer into a processing array while the ringbuffer continuous to fill up in an interrupt subroutine. the interrupts occurs every 10ms and adc should be read into the ringbuffer.

I should then apply a filter to the processing buffer while the ringbuffer continous to fillup. My sampling frequency is 100Hz and my signal of interest is between 1-2HZ. My PIC processor is 18F4450.

Any help please is welcome...
Kind regards
Ttelmah
Guest







PostPosted: Thu Jun 19, 2008 7:43 am     Reply with quote

The FIFO buffer used in the EX_SISR example, is a basic ring buffer design.
I'd suggest you make the size 64 words (rather than 50), or alter the way the 'remainder' calculation is done, since the example, is 'inefficient', if not using a binary buffer size. This design will work just as well with 16bit data as the 8bit data it currently handles, by simply changing the size of the array elements.
Instead of driving this with the external serial interrupt, simply use a timer interrupt to trigger the acquisition. I'd suggest that you have your reading 'lagging' by one, so when you arrive in the interrupt, you read the last ADC value acquired, then trigger a new acquisition. This way the code won't have to wait for the ADC.
The real 'work' will be in calculating the FIR filter. Are you using a DSP PIC, or a basic design?.

Best Wishes
kein



Joined: 23 Jul 2007
Posts: 103

View user's profile Send private message

Digital filter and Circular buffer
PostPosted: Tue Jun 24, 2008 12:39 am     Reply with quote

Thanks Ttelmah for your response. No I'm not using DSP chip however I'm generating filter coefficient in MATLAB (fixed point math) and then store them into a buffer. The algorithm is as shown below however something is not working properly. I don't know if this has to do with circular buffer or not.
What im doing is to wait until the difference between the head and the tail is equal to 8 and then begins to take a reading from the circular buffer.
But this doesn't seem to go well any help?
Code:

#include <18F4550.h>
#device adc=10
#FUSES HSPLL, PLL5, CPUDIV1, NOWDT, PUT, BROWNOUT, NOLVP    // 20 MHz xtal
#use delay(clock=48000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define BUFF_SIZE   64

int1 filter_flag;
int1 new_data_flag;
int1 new_data_flag;
int16 new_data;
int16 ptimer;
int16 Ring[BUFF_SIZE];

const int order = 32;
const int16 filter[order] = {-17,-42,-80,-125,-159,-156,-80,104,421,883,1473,
                       2148,2838,3461,3934,4189,4189,3934,3461,2838,2148,
                       1473,883,421,104,-80,-156, 159,-125,-80,-42,-17
                       };

/*Timer2 interrupts every 3ms and keep on restarting adc every 10ms*/
#int_TIMER2
void  TIMER2_isr(void)
{
  static int8 ticker = 3;
  if(--ticker==0
  {
     ticker = 3;
     read_adc(ADC_START_ONLY);
  }
   
}

/*Read adc results into a buffer*/
#int_AD
void  AD_isr(void)
{
       Ring [head] = (read_adc(ADC_READ_ONLY) - 0X266);
       filter_flag = 1;
        if(++head==BUFF_SIZE) head = 0;
}

void DigitalFiler ()
{
   Int16 y = 0;
    Int16 data[order];
   int k;

   if(filter_flag==1)
   {
      filter_glag = 0;

      for (k = 0; k < order; k++) data[k] = 0;/*clear Buffer*/

         data[0] = Ring[tail];
         if (++tail == BUFF_SIZE) tail = 0;
            for (k = 0; k < FILTER_ORDER; k++)
             y += (Int16)(filter[k] * data[k]);
             new_data = y ;
             new_data_flag = 1 ;
            for (k = order-1; k > 0 ; k--)
             data[k]= data[k-1]; /* do convolution by reversing */               
            }
   }
}

 void FindPeak()
        {
            //throw new Exception("The method or operation is not implemented.");
            if (new_data_flag == 1)
            {
                new_data_flag = 0;
                if(++ptimer==1024) ptimer = 0 ;
            printf("%3d,\t%3Ld\n\r",ptimer, new_data);

                /*if (PAMP[pos] < new_data)
                {
                    PAMP[pos] = new_data;
                    PTIME[pos] = ptimer;
                   
                }   
            /*..........Todos.................
                    pos++;
                    */
            }
        }


void main()
{
   set_tris_b(0x17);                  // TRISB = 00010111; RB4,RB2,RB1 and RB0 
   setup_timer_2(T2_DIV_BY_16,249,10);                                                       
   setup_adc_ports(AN0_TO_AN2|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_64);
   set_adc_channel(0);                     // select the required channel //
   delay_us(10);
   enable_interrupts(INT_ADC);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);

for(;;)
   {
     
     DigitalFiler ();
    FindPeak();

   }
}
Ttelmah
Guest







PostPosted: Tue Jun 24, 2008 2:14 am     Reply with quote

Without looking very far, you are going to get a problem with subtracting 0x266, from the ADC value. If the value goes below 0x266, you are going to get a massive positive result. You either need to cast the ADC values to signed, and use a signed int16 to hold the readings, or check that the value is greater than 0x265, before performing the subtraction...
As a 'comment', read the ADC, in the timer loop, and gt rid of using the ADC interrupt. So:
Code:

/*Timer2 interrupts every 3ms and keep on restarting adc every 10ms*/
#int_TIMER2
void  TIMER2_isr(void)
{
  static int8 ticker = 3;
  if (ticker=3) {
       Ring [head] = (read_adc(ADC_READ_ONLY) - 0X266);
)       filter_flag = 1;
       if(++head==BUFF_SIZE) head = 0;
  }
  if(--ticker==0
  {
       ticker = 3;
       read_adc(ADC_START_ONLY);
  }
}

The reading will be taken 3mSec after the ADC was triggered, and this saves the cost of having a second interrupt.
The ADC interrupt, will 'cost' perhaps 70+ instructions, which you might as well not have. :-)
Your digital filter code, transfers the first entry in Ring, but I don't see it using the latter entries for the higher orders. You only every load data[0]. Since the data buffer is not static, and you clear it every time new data arrives, I can't see how this will work...
The bracket counts don't match in the routine as posted, and you are accessing 'filter_glag', which doesn't exist, so I suspect this part is a major 'typo'...

Best Wishes
kein



Joined: 23 Jul 2007
Posts: 103

View user's profile Send private message

What is wrong with my fir filter
PostPosted: Sun Jun 29, 2008 7:14 am     Reply with quote

Thanks Tlemah

Last edited by kein on Mon Jun 30, 2008 7:04 am; edited 1 time in total
kein



Joined: 23 Jul 2007
Posts: 103

View user's profile Send private message

What is wrong with my fir filter
PostPosted: Mon Jun 30, 2008 7:03 am     Reply with quote

Thanks Tlemah for ur help. I've incorporated the changes u made into my code and even made changes to my filter. The fact is the filter distort my signal. In my interrupt subroutine I've am reading a sinusoidal signal into a variable which is saved into a ring buffer in filter function. The sin(12.5*t) has a frequency of 2Hz. When i output/print out the unfiltered signal I get the correct sin wave and if i pass it through the filter, I get something similar to a noisy signal. What is the problem here? The filter coefficient from a lowpass filter whose cut-off frequency is 3Hz and coefficients are 16-bit integers.
Please help..

Code:
Code:


#include <18F4550.h>
#device adc=10
#FUSES HSPLL, PLL5, CPUDIV1, NOWDT, PUT, BROWNOUT, NOLVP    // 20 MHz xtal
#use delay(clock=48000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

#define BUFFER_SIZE     32
#define ORDER           32
#define BLEN             6

/*********************************************************************
*   STRUCTURE:      ADXL330ADC_SAMPLES { }                      *
*   DESCRIPTION:   This structure Contains three of all variables   *
*               flag, array of data[] and counter adxl330count   *
*                                                    *
*   PARAMTERS:      adxl330flag    -flag to signal event              *
*               adxl330Indx    -data counter                   *
*               adxl330Buf[] -Buffer for data storage          *
*                                                    *
**********************************************************************/
typedef struct ADXL330ADC_SAMPLES
{
   Int16 PAMP [BLEN];
   Int16 PTIME[BLEN];
   Int16 NAMP [BLEN];
   Int16 NTIME[BLEN];
   Int16 new_ADC;
   int16 adc;
   Int16 Ring[BUFFER_SIZE];

} SAMPLES;

/*    GLOBAL Variables*/
unsigned char tail;
unsigned char dir_change_flag;
unsigned char pIndx;
unsigned char nIndx;
unsigned Int16 ptimer;
int16 tick;
int1 new_data_flag;
int1 filter_data_flag;
int1 filterflag;
int1 direction_flag;

int16 h [order + 1] = { 0x0000, 0x0002, 0x000B, 0x0024, 0x0059, 0x00B9,
                        0x0155, 0x023C, 0x0375, 0x0501, 0x06D1, 0x08CC,
                        0x0ACA, 0x0C9C, 0x0E14, 0x0F08, 0x0F5C, 0x0F08,
                        0x0E14, 0x0C9C, 0x0ACA, 0x08CC, 0x06D1, 0x0501,
                        0x0375, 0x023C, 0x0155, 0x00B9, 0x0059, 0x0024,
                        0x000B, 0x0002, 0x0000};
                       
SAMPLES signal;

//void  Adxl330BuffFree(void);
void  TIMER2_isr(void);
void  FindPeak(void);
void  DigitalFilter(void);
//void  ADXL330VarsInitialize(void);



void main()
{
   //ADXL330VarsInitialize();
   //Adxl330BuffFree();
   
   setup_adc_ports(AN0_TO_AN2|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_64);
   set_adc_channel(0);                     /* select the required channel*/
   delay_us(10);
   //setup_timer_2 ( T2_DIV_BY_4, 0xc0, 2);
   setup_timer_2 ( T2_DIV_BY_16,249, 10);     /*interrupts occurs every 3ms*/
   set_timer2(0);                          /*this sets timer2 register to 0*/
 
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);
   
/*Setup_Oscillator parameter not selected from Intr Oscillator Config tab*/
   for(;;)
   {
      /* TODO: USER CODE!!*/
      DigitalFilter();
      FindPeak();
   }

}/*End Main()*/

/*Timer2 interrupts every 3ms and keep on restarting adc every 10ms*/
#int_TIMER2                 
void  TIMER2_isr(void)
{
   float t;
   static int8 ticker = 3;
   if(ticker == 3)
   {
      t = 0.01*tick;
      //signal.new_ADC= (int16)((int16)read_adc(ADC_READ_ONLY) - 0X266);
      signal.adc = (int16)((sin(50*t))*1000);
      filterflag = 1;
      if(++tick ==512) tick = 0;
   }
   
  if (--ticker == 0)
   {
      ticker = 3;
      read_adc(ADC_START_ONLY);     
   }

}

    //Int16 y = 0;
 void DigitalFilter(void)
 {
    int32  y = 0;

    if (filterflag == 1)
    {
      int i;
      filterflag = 0;
      signal.Ring[tail] =  signal.adc;
      for (i = 0; i < ORDER; i++)
      {
        y += (int32)(h[i] * signal.Ring[(i + tail) & (ORDER - 1)]);
      }
       
      signal.new_ADC = (int16)y;           
      filter_data_flag = 1;       
      tail = (tail + 1) & (ORDER - 1);           
    }   
 }
 
void FindPeak(void)
{
  //throw new Exception("The method or operation is not implemented.");
   if (filter_data_flag == 1)
   {
      filter_data_flag = 0;
      printf("%5Ld\n",signal.new_ADC);
   }
}
Ttelmah
Guest







PostPosted: Mon Jun 30, 2008 8:42 am     Reply with quote

You still have the _sign_ problem that I pointed out before.
This will completely distort the results.
You are now using a sin function in the interrupt to generate the psuedo value. This will return +1, to -1. So your value will be +1000 to -1000, which you are then putting into an int16, which is an _unsigned type_. The value will then be seen as +1000 to 0, and then jump to +65535, to 64536.
I pointed this out before....

Best Wishes
kein



Joined: 23 Jul 2007
Posts: 103

View user's profile Send private message

Thank you Tlemah
PostPosted: Tue Jul 01, 2008 4:40 am     Reply with quote

sorry I assumed int16 is signed by default . Yes indeed that solve some of my problem. The sin wave is perfect now however my filter output are really bad! Here are the changes made. Please help.
Kind regards,

Code:
#define order   32
signed Int16 Ring[BUFFER_SIZE];
signed Int16 new_ADC;
signed Int16 adc;

int16 h [order + 1] = { 0x0000, 0x0002, 0x000B, 0x0024, 0x0059, 0x00B9,
                        0x0155, 0x023C, 0x0375, 0x0501, 0x06D1, 0x08CC,
                        0x0ACA, 0x0C9C, 0x0E14, 0x0F08, 0x0F5C, 0x0F08,
                        0x0E14, 0x0C9C, 0x0ACA, 0x08CC, 0x06D1, 0x0501,
                        0x0375, 0x023C, 0x0155, 0x00B9, 0x0059, 0x0024,
                        0x000B, 0x0002, 0x0000};
                       
/*Timer2 interrupts every 3ms and keep on restarting adc every 10ms*/
#int_TIMER2                 
void  TIMER2_isr(void)
{
   float t;
   static int8 ticker = 3;
   if(ticker == 3)
   {
      t = 0.01*tick;
      //signal.new_ADC= (int16)((int16)read_adc(ADC_READ_ONLY) - 0X266);
      adc = (signed int16)(1000*sin(50*t)); /*signal: -1000 to +1000*/
      filterflag = 1;
      if(++tick ==512) tick = 0;
   }
   
  if (--ticker == 0)
   {
      ticker = 3;
      read_adc(ADC_START_ONLY);     
   }

}

void DigitalFilter(void)
 {
   signed int32  y = 0;

    if (filterflag == 1)
    {
      int i;
      filterflag = 0;
      signal.Ring[tail] =  signal.adc;
      for (i = 0; i < ORDER; i++)
      {
        y += (int32)(h[i] * signal.Ring[(i + tail) & (ORDER - 1)]);
      }
       
      snew_ADC = (signed int16)y;           
      filter_data_flag = 1;       
      tail = (tail + 1) & (ORDER - 1);           
    }   
 }
void FindPeak(void)
{
  //throw new Exception("The method or operation is not implemented.");
   if (filter_data_flag == 1)
   {
      filter_data_flag = 0;
      printf("%5Ld\n",new_ADC);
   }
}
Ttelmah
Guest







PostPosted: Tue Jul 01, 2008 3:15 pm     Reply with quote

I would suspect you are overflowing the arithmetic in several places. If you 'sum' your filter terms, you get 45604. If the routine was called with all the entries equal at (say) +1000, and the arithmetic applied to this, the result would be 45604000. Even if you assume the 'average' value coming in is +500, the arithmetic would give 22802000. Have performed the addition, you put the result straight into a signed int16 variable (can hold 32767 max....).
However this won't happen, since the multiplication of the buffer value and the term, is being done using signed int16, and will overflow on the way. Your biggest term, is 0xF5C (3932), and times 1000, will give 3932000, over 100* too large for the arithmetic being used...
Also, declare your variables at the start of the function, not the block. Though C++, allows this, and CCS, supposedly supports this, the older 'C style' declarations are safer...
Code:

void DigitalFilter(void) {
   signed int32  y = 0;
   int i;
   
   if (filterflag == 1) {
      filterflag = 0;
      signal.Ring[tail] =  signal.adc;
      for (i = 0; i < ORDER; i++)       {
        y += (signed int32)h[i] * signal.Ring[(i + tail) & (ORDER - 1)];
      }
       
      snew_ADC = (signed int16)(y/65536);           
      filter_data_flag = 1;       
      tail = (tail + 1) & (ORDER - 1);           
   }   
}


You will need to check the rest of the code for similar overflows, but these are the 'glaring' ones.

Best Wishes
kein



Joined: 23 Jul 2007
Posts: 103

View user's profile Send private message

Tlemah, mate you are a genius
PostPosted: Tue Jul 01, 2008 10:01 pm     Reply with quote

Dividing y by 65536 prevented the overflow indeed although the signal (sine wave) is still distorted making it look like a square wave. I've increased the number of division by factor of 8 and overflow is removed.

The filtered signal is sinusoidal just like the original sin wave but offsetted.
The offset doesn't seem normal to me! How can We prevents the offset
?
Code:
void DigitalFilter(void) {
   signed int32  y = 0;
   int i;
   
   if (filterflag == 1) {
      filterflag = 0;
      signal.Ring[tail] =  signal.adc;
      for (i = 0; i < ORDER; i++)       {
        y += (signed int32)h[i] * signal.Ring[(i + tail) & (ORDER - 1)];
      }
       
      snew_ADC = (signed int16)(y>>19); //=y/524288-----y/y/65536);           
      filter_data_flag = 1;       
      tail = (tail + 1) & (ORDER - 1);           
   }   
Ttelmah
Guest







PostPosted: Wed Jul 02, 2008 3:22 am     Reply with quote

Offset is normal.
The filter looks 'back in time' by 32 elements. The peak response is to the element 17 samples ago. Filters always introduce phase delays.

Now, If you are prepared to accept a slight loss of accuracy in your filter, and you want to do other things with the processor (currently the filter is using a _lot_ of the processor time), there are quite a few things you can change.
First, your 'simulation' (using the sin), is putting larger values into the buffer, than the real data. The ADC, only returns 0 to 1023. You subtract 0x266 (why this odd value? - if the input is symmetrical, you would normally expect the 'middle' value to be 0x200). With 0x266 subtracted, the 'real' values, can only be -614 to +409. If you can bring the signal to be symmetrical, and have -512 to +511, and then take your filter terms, and divide them by 64, you will 'lose' the some terms, and degrade the accuracy a little, but the multiplication, will then fit inside the signed int16 arithmetic. So the 'biggest' term, will be +511 * (0xF5C/64) = 511 * 62 = 31682. This will speed up the arithmetic a lot, and the loss of accuracy will be surprisingly small.
Now, your final result will need (presumably) to be scaled to some output range (DAC?.). If you can chose the terms, so that the final division, is a 'nice' value in binary terms (such as /256, /65536 etc.), this can be performed by taking the MSB's of the result, rather than an actual shift (or even worse a division...). However the saving from this is small (since this is only done once for each filter pass).
There is also a 'trick' you can do in the term array. If you make this _double the size_, with the whole array repeated a second time (so the elements go from 0 to 63), then you can avoid having to do any arithmetic on the index to the array. You do the maths like:
Code:

void DigitalFilter(void) {
   signed int32  y = 0;
   int i;
   signed int16 * filter;
   
   if (filterflag == 1) {
      filterflag = 0;
      signal.Ring[tail] =  signal.adc;
      filter=&h[order-tail];

      for (i = 0; i < ORDER; i++)       {
        y += *(filter++) * signal.Ring[i];
      }
       
      snew_ADC = y/4096;           
      filter_data_flag = 1;       
      tail = (tail + 1) & (ORDER - 1);           
   }   
}

(This done with the filter elements assumed to have been divided by 64).
What happens, is that you always go through the ring buffer from 0 to order-1, but offset the start location in the 'term' array, so that the right term is selected, according to the value in 'tail'.
Also make the term array signed int16 - this removes the need for the code to convert the value in the arithmetic.

So, the delay is normal, but there may be quite a bit you can do to improve the performance in terms of processor usage.

Best Wishes
kein



Joined: 23 Jul 2007
Posts: 103

View user's profile Send private message

Thanks again
PostPosted: Wed Jul 02, 2008 5:22 am     Reply with quote

Just a quick question with regards to the filter coeffecient. When you say I double the size of the term array, did you mean double the size of coeffeicent array (h[2*size] or the ring buffer (ring[])?
Because below it seems you have increased or double the size of the coefficient array (h[]).
Code:
signal.Ring[tail] =  signal.adc;
      filter=&h[order-tail];

Below are the changes I made, the results are worst. I should be doing something wrong!

v
Code:

#define order  64
#define ORDER 32

signed int16 h1[32]
void main()
{
   for( i=0 ; i < 32; i++)
    h1[i] = h[i]/64;
   .................................
 }

void DigitalFilter(void) {
   signed int32  y = 0;
   int i;
   signed int16 * filter;
   
   if (filterflag == 1) {
      filterflag = 0;
      signal.Ring[tail] =  signal.adc;
      filter=&h1[order-tail];

      for (i = 0; i < order; i++)       {
        y += *(filter++) * signal.Ring[i];
      }
       
      snew_ADC = y/4096;           
      filter_data_flag = 1;       
      tail = (tail + 1) & (ORDER - 1);           
   }   
}
Ttelmah
Guest







PostPosted: Wed Jul 02, 2008 7:47 am     Reply with quote

Coefficient array.
The entries in this are the 'terms' calculated for the filter being used.
The 'point' is that when you have the ring array 'full', your 32 ring elements will correspond exactly to the elements in the coefficient array. Then when you add one more element to the ring, if you worked from the start of the ring buffer, you would want to use 'coefficient -1' as the coefficient for the first entry in the ring buffer, then use coefficient 0, for the next element, and so on. By having the buffer double the size, with the contents duplicated, you can operate through the data array, without having to use any offsets, just shifting where you start in the coefficient array.
In what you show, You also need to have the table contents duplicated. So:
Code:

signed int16 h [(order*2) + 1] =
                        { 0x0000, 0x0002, 0x000B, 0x0024, 0x0059, 0x00B9,
                        0x0155, 0x023C, 0x0375, 0x0501, 0x06D1, 0x08CC,
                        0x0ACA, 0x0C9C, 0x0E14, 0x0F08, 0x0F5C, 0x0F08,
                        0x0E14, 0x0C9C, 0x0ACA, 0x08CC, 0x06D1, 0x0501,
                        0x0375, 0x023C, 0x0155, 0x00B9, 0x0059, 0x0024,
                        0x000B, 0x0002,
                        0x0000, 0x0002, 0x000B, 0x0024, 0x0059, 0x00B9,
                        0x0155, 0x023C, 0x0375, 0x0501, 0x06D1, 0x08CC,
                        0x0ACA, 0x0C9C, 0x0E14, 0x0F08, 0x0F5C, 0x0F08,
                        0x0E14, 0x0C9C, 0x0ACA, 0x08CC, 0x06D1, 0x0501,
                        0x0375, 0x023C, 0x0155, 0x00B9, 0x0059, 0x0024,
                        0x000B, 0x0002, 0x0000};

I think this is right, but you should step through it term by term, and check what is going on. Also, I'd make the division maths:
[/code]
for( i=0 ; i <=64; i++)
h1[i] = (h[i]+31)/64;
[/code]
which will effectively give 4/5 rounding on the division.

Best Wishes
kein



Joined: 23 Jul 2007
Posts: 103

View user's profile Send private message

Hi Tlemah
PostPosted: Thu Jul 03, 2008 4:39 am     Reply with quote

Sorry for bothering you much but it does not work. The signal is worst and severly distorted.
Below is the code:

Code:
signed int16 h [(order*2) + 1] =
                        { 0x0000, 0x0002, 0x000B, 0x0024, 0x0059, 0x00B9,
                        0x0155, 0x023C, 0x0375, 0x0501, 0x06D1, 0x08CC,
                        0x0ACA, 0x0C9C, 0x0E14, 0x0F08, 0x0F5C, 0x0F08,
                        0x0E14, 0x0C9C, 0x0ACA, 0x08CC, 0x06D1, 0x0501,
                        0x0375, 0x023C, 0x0155, 0x00B9, 0x0059, 0x0024,
                        0x000B, 0x0002,
                        0x0000, 0x0002, 0x000B, 0x0024, 0x0059, 0x00B9,
                        0x0155, 0x023C, 0x0375, 0x0501, 0x06D1, 0x08CC,
                        0x0ACA, 0x0C9C, 0x0E14, 0x0F08, 0x0F5C, 0x0F08,
                        0x0E14, 0x0C9C, 0x0ACA, 0x08CC, 0x06D1, 0x0501,
                        0x0375, 0x023C, 0x0155, 0x00B9, 0x0059, 0x0024,
                        0x000B, 0x0002, 0x0000};

signed int16 h1[(32*2)+1];
signed int16 Ring[2*32+1];

void DigitalFilter1(void)
{
   signed int32  y = 0;
   int i;
   signed int16 * filter;
   
   if (filterflag == 1)
   {
      filterflag = 0;
      signal.Ring[tail] =  signal.new_ADC;
      filter=&h1[64-tail];

      for (i = 0; i < 32-1; i++)       
      {
        y += *(filter++) * Ring[i];
      }

       snew_ADC = (signed int16) y/4096;             
      filter_data_flag = 1;       
      tail = (tail + 1) & (32 - 1);           
   }   
}

void main()
{
   for( i=0 ; i <= 64; i++)
    h1[i] = (h[i]+31)/64;
   .................................
 }
Guest








PostPosted: Thu Jul 03, 2008 4:53 am     Reply with quote

Have you scaled the incoming test numbers or real values as I said?. This will _only_ work, with a maximum +511 to -512 range. Otherwise back to overflowing the maths.
You really should be doing the testing I described earlier. Stick the data into a simulator, or ICD, and look for each pass, at what the numbers actually 'do'.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group