0

固定小数点演算で有限インパルス応答を作成したいと考えています。私はこのプログラムをまとめましたが、それが正しいかどうかはわかりません:

    #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 for C3 and 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 for rounding = (int)(0.5 * (1<<FBITS)) */
    signed char input[4]; /* The 4 most 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)
        {    
         for (a = 3 ; a > 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[] = " is not allowed";
char error3[] = "Number too big";
char error4[] = "Line too long";
char error5[] = "Line too short";

char get_q7( void )
{
    int c; /* Current character */
    int i; /* Loop counter */
    int num;
    int ok = 0; /* Flag: 1 means input is accepted */

    while( ok == 0 )
    {
        num = 0;
        for( i = 0; prompt[i]; i += 1 )
            alt_putchar( prompt[i] );

        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);
                i = i + 1;
            }
            else if( (c >= 'A') && (c <= 'F') )
            {
                num = num << 4;
                num = num | (c + 10 - 'A');
                i = i + 1;
            }
            else if( (c >= 'a') && (c <= 'f') )
            {
                num = num << 4;
                num = num | (c + 10 - 'a');
                i = i + 1;
            }
            else if( c == 10 ) /* LF finishes line */
            {
                if( i > 0 ) ok = 1;
                else
                {    /* Line too short */
                    for( i = 0; error5[i]; i += 1 )
                        alt_putchar( error5[i] );
                    alt_putchar( '\n' );
                    break; /* Ask for a new number */
                }
            }
            else if( (c & 0x20) == 'X' || (c < 0x20) )
            {
                /* Ignored - do nothing special */
            }
            else
            {   /* Illegal hex-code */
                for( i = 0; error1[i]; i += 1 )
                    alt_putchar( error1[i] );
                alt_putchar( c );
                for( i = 0; error2[i]; i += 1 )
                    alt_putchar( error2[i] );
                alt_putchar( '\n' );
                break; /* Ask for a new number */
            }
            if( ok )
            {
                if( i > 10 )
                {
                    alt_putchar( '\n' );
                    for( i = 0; error4[i]; i += 1 )
                        alt_putchar( error4[i] );
                    alt_putchar( '\n' );
                    ok = 0;
                    break; /* Ask for a new number */
                }
                if( num >= 0 && num <= 255 )
                    return( num );
                for( i = 0; error3[i]; i += 1 )
                    alt_putchar( error3[i] );
                alt_putchar( '\n' );
                ok = 0;
                break; /* Ask for a new number */
            }
        }
    }
    return( 0 ); /* Dead code, or the 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)   /* help 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( i = 0; prom[i]; i += 1 )
            alt_putchar( prom[i] );
    alt_putchar (hexasc ((inval & 0xF0) >> 4));
    alt_putchar (hexasc (inval & 0x0F));
    alt_putchar ('\n');     
}

実行したときに正しい結果が得られるかどうかわかりません。実行する必要がある場合は、プログラムの検証または変更を手伝ってもらえますか?

FIR フィルターは、標準入出力を介して Q7 形式で 8 ビットの固定小数点数を送受信します。測定された時間 (ティック数) も 16 進形式で出力することを忘れないでください。前のセクションで示したガイドラインに従って、プログラムは getchar() を呼び出して Q7 値を読み取る必要があります。Q7 値を書き込むために putchar() を呼び出す必要があります。

係数は

c0=0.0299 c1=0.4701 c2=0.4701 c3=0.299

私は以前ここで助けを得ましたが、今は完全かどうかわかりません。この答えについてまだ質問があります: Fixedpoint FIR filter in C?

私のプログラムが正しいかどうか教えてもらえますか?

4

1 に答える 1

2

ウィキペディアのQ (数値形式)に関する情報から判断すると、あなたの定数は正しくありません。

あなたは、7つの小数ビット(合計8ビット)の符号付き小数に対応するQ7形式について言及しています。+0.0299 を Q7 の値として表すには、0.0299 に 128 を掛けて 3.8272 を求め、これを 4 に丸めます。したがって、Q7 の数値として +0.0299 を表すと 4 になります。同様に、+0.4701 の場合、正確な値は次のようになります。 60.1728、これは 60 で表されます。

関数の最初の部分firFixed()は問題ありません。ただし、除算は 128 である必要があり、「半分」は 64 になります。したがって、次のようになると思います。

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);
}

一方、FBITS も 16 として定義します。これを格納するには、32 ビットの整数型が必要になります (小数ビットが 16 ビットと符号ビットが 1 つあり、合計で 17 ビットになるため)。

作業コード

#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 };
    for (size_t i = 0; i < sizeof(data) - 4; i++)
        firFixed(data + i);
    return 0;
}

検証されていない出力

正しい出力を計算するのに時間を費やしていません。示されている結果はもっともらしいように見えますが、それは私が主張する限りです.

c0 = c3 =   4 = 0x04
c1 = c2 =  60 = 0x3C
out = 55
out = 83
out = 89
out = 76
于 2013-10-07T06:30:07.560 に答える