I have used the WinFilter Program to compute the FIR filter on C code but I got a issue:
The program only provide the 16 bits signed array and i need to that this vector be a unsigned int. So i am looking for a simple solution to relocated the array values to the next "values".
int16_t FIRCoef[Ntap] = {
-1029,
-1560,
-1188,
0,
1405,
2186,
1718,
0,
-2210,
-3647,
-3095,
0,
5160,
10947,
15482,
17197,
15482,
10947,
5160,
0,
-3095,
-3647,
-2210,
0,
1718,
2186,
1405,
0,
-1188,
-1560,
-1029,
0
};
uint16_t fir(uint16_t NewSample) {
static uint16_t x[Ntap]; //input samples
uint32_t y=0; //output sample
int n;
//shift the old samples
for(n=Ntap-1; n>0; n--)
x[n] = x[n-1];
//Calculate the new output
x[0] = NewSample;
for(n=0; n<Ntap; n++)
y += FIRCoef[n] * x[n]; // calculo da convolucao na amostra
// Calculation of the convolution in the sample
return y / DCgain;
}
I think that one solution should be like this:
uint16_t--------int16_t---------index
0 -32767 1
1 -32766 2
2 -32765 3
... ... ...
65535 32767 65535
any hint?
The value range for an int16_t
is -32768 to 32767. Your question is unclear on this point, but it seems like you want simply to shift these values into the range of a uint16_t
, 0 to 65535. That's reasonable, as the number of representable values for the two types is the same; it would be accomplished by adding the inverse of the minimum possible value of an int16_t
to the input.
Of course, the Devil is in the details. When signed addition overflows, undefined behavior results. When an out-of-range value is converted to a signed integer type, the result is implementation defined, and can be an (implementation-defined) exception. It is desirable to avoid implementation-defined behavior and essential to avoid undefined behavior; that can be done in this case with just a little care:
uint16_t convert(int16_t in) {
return (uint16_t) 32768 + (uint16_t) in;
}
That reliably does the right thing on any conforming system that provides the uint16_t
and int16_t
types in the first place, because the conversion and the addition operate modulo one plus the maximum value of a uint16_t
. The negative input values are converted to unsigned values in the upper half of the range of uint16_t
, and the addition then rotates all the values, bringing those from the upper half of the range around to the lower half.
As for doing it to a whole array, if you want to rely only on well-defined C behavior (i.e. if you want a solution that strictly conforms to the standard) then you'll need to make a copy of the data. You could use a function such as the above to populate the copy.