c - Is this filter implementation making correct output? -
i want make finite impulse response fixedpoint arithmetic. put program i'm not sure it's correct:
#include <stdio.h> #include "system.h" #define fbits 16 /* number of fraction bits */ const int c0 = (( 299<<fbits) + 5000) / 10000; /* (int)(0.0299*(1<<fbits) + 0.5) */ const int c1 = ((4701<<fbits) + 5000) / 10000; /* (int)(0.4701*(1<<fbits) + 0.5) */ /* ditto c3 , c2 */ const int c2 = (( 4701<<fbits) + 5000) / 10000; /* (int)(0.4701 *(1<<fbits) + 0.5) */ const int c3 = ((299<<fbits) + 5000) / 10000; /* (int)(0.299*(1<<fbits) + 0.5) */ #define half (1 << (fbits) >> 1) /* half adjust rounding = (int)(0.5 * (1<<fbits)) */ signed char input[4]; /* 4 recent input values */ char get_q7( void ); void put_q7( char ); void firfixed() { int sum = c0*input[0] + c1*input[1] + c2*input[2] + c3*input[3]; signed char output = (signed char)((sum + half) >> fbits); put_q7(output); } int main( void ) { int i=0; int a; while(1) { (a = 3 ; > 0 ; a--) { input[i] = input[i-1]; } input[0]=get_q7(); firfixed(); i++; } return 0; } #include <sys/alt_stdio.h> char get_q7( void ); char prompt[] = "enter q7 (in hex-code): "; char error1[] = "illegal hex-code - character "; char error2[] = " not allowed"; char error3[] = "number big"; char error4[] = "line long"; char error5[] = "line short"; char get_q7( void ) { int c; /* current character */ int i; /* loop counter */ int num; int ok = 0; /* flag: 1 means input accepted */ while( ok == 0 ) { num = 0; for( = 0; prompt[i]; += 1 ) alt_putchar( prompt[i] ); = 0; /* number of accepted characters */ while( ok == 0 ) { c = alt_getchar(); if( c == (char)26/*eof*/ ) return( -1 ); if( (c >= '0') && (c <= '9') ) { num = num << 4; num = num | (c & 0xf); = + 1; } else if( (c >= 'a') && (c <= 'f') ) { num = num << 4; num = num | (c + 10 - 'a'); = + 1; } else if( (c >= 'a') && (c <= 'f') ) { num = num << 4; num = num | (c + 10 - 'a'); = + 1; } else if( c == 10 ) /* lf finishes line */ { if( > 0 ) ok = 1; else { /* line short */ for( = 0; error5[i]; += 1 ) alt_putchar( error5[i] ); alt_putchar( '\n' ); break; /* ask new number */ } } else if( (c & 0x20) == 'x' || (c < 0x20) ) { /* ignored - nothing special */ } else { /* illegal hex-code */ for( = 0; error1[i]; += 1 ) alt_putchar( error1[i] ); alt_putchar( c ); for( = 0; error2[i]; += 1 ) alt_putchar( error2[i] ); alt_putchar( '\n' ); break; /* ask new number */ } if( ok ) { if( > 10 ) { alt_putchar( '\n' ); for( = 0; error4[i]; += 1 ) alt_putchar( error4[i] ); alt_putchar( '\n' ); ok = 0; break; /* ask new number */ } if( num >= 0 && num <= 255 ) return( num ); for( = 0; error3[i]; += 1 ) alt_putchar( error3[i] ); alt_putchar( '\n' ); ok = 0; break; /* ask new number */ } } } return( 0 ); /* dead code, or compiler complains */ } #include <sys/alt_stdio.h> void put_q7( char ); /* prototype */ char prom[] = "calculated fir-value in q7 (in hex-code): 0x"; char hexasc (char in) /* function */ { in = in & 0xf; if (in <=9 ) return (in + 0x30); if (in > 9 ) return (in - 0x0a + 0x41); return (-1); } void put_q7( char inval) { int i; /* loop counter */ for( = 0; prom[i]; += 1 ) alt_putchar( prom[i] ); alt_putchar (hexasc ((inval & 0xf0) >> 4)); alt_putchar (hexasc (inval & 0x0f)); alt_putchar ('\n'); }
when run i'm not sure whether currect results, can me verify or change program if has done?
the fir-filter receives , sends 8-bit fixed-point numbers in q7-format via standard input , output. remember output measured time (number of ticks) in hex format. following guidelines presented in previous section, program should call getchar() read q7-value. should call putchar() write q7-value.
the coefficients are
c0=0.0299 c1=0.4701 c2=0.4701 c3=0.299
i got here i'm not sure whether complete , still have questions answer: fixedpoint fir filter in c?
can tell me if program correct?
judging information on q (number format) @ wikipedia, constants not correct.
you mention q7 format, corresponds signed fractional number 7 fractional bits (for 8 bits in total). represent +0.0299 q7 value, you'd multiply 0.0299 128, yielding 3.8272, rounded 4. representation of +0.0299 q7 number 4. similarly, +0.4701, exact value 60.1728, represented 60.
the first part of firfixed()
function fine. division, though, needs 128, , 'half' 64. thus, think end with:
const int c0 = (0.0299 * 128 + 0.5); const int c1 = (0.4701 * 128 + 0.5); const int c2 = (0.4701 * 128 + 0.5); const int c3 = (0.0299 * 128 + 0.5); const int half = (0.5000 * 128 + 0.5); enum { q7_bits = 7 }; void firfixed(void) { int sum = c0*input[0] + c1*input[1] + c2*input[2] + c3*input[3]; signed char output = (signed char)((sum + half) >> q7_bits); put_q7(output); }
on other hand, define fbits 16. require 32-bit integer types store (because you'd have 16 fractional bits , sign bit, 17 bits in total).
working code
#include <stdio.h> const int c0 = (0.0299 * 128 + 0.5); const int c1 = (0.4701 * 128 + 0.5); const int c2 = (0.4701 * 128 + 0.5); const int c3 = (0.0299 * 128 + 0.5); const int half = (0.5000 * 128 + 0.5); enum { q7_bits = 7 }; void put_q7(signed char out); void firfixed(signed char input[4]); void firfixed(signed char input[4]) { int sum = c0*input[0] + c1*input[1] + c2*input[2] + c3*input[3]; signed char output = (signed char)((sum + half) >> q7_bits); put_q7(output); } void put_q7(signed char out) { printf("out = %d\n", out); } int main(void) { printf("c0 = c3 = %3d = 0x%.2x\n", c0, c0); printf("c1 = c2 = %3d = 0x%.2x\n", c1, c1); signed char data[] = { 27, 39, 69, 99, 82, 71, 42, 63 }; (size_t = 0; < sizeof(data) - 4; i++) firfixed(data + i); return 0; }
unvalidated output
i've not spent time calculating correct output. results shown plausible, that's as i'll claim.
c0 = c3 = 4 = 0x04 c1 = c2 = 60 = 0x3c out = 55 out = 83 out = 89 out = 76
Comments
Post a Comment