もっかい、一からやり直し。 複素化による周波数変換

1.ありがたい、お言葉をいただきました。

 

ある方から、大変ありがたいメールをいただきました。

私は、尊敬を込めて、「応援団長様」と、呼んでいます。

 

「これまでのレポートを見ると、以下の何れかのことが発生しているのではと感じてい

ます。

現在の対処療法は、本質を見失う可能性があるような気がします。現在の取り組みは、

SSBへの道のりを遠くするかもしれません。ディジタル信号処理ですから、理論どおりに

動くはずなのです。

1) 複素化の直交性が崩れている

実数部の方の、遅延タップの位置を確認したほうがいいかも知れません

ヒルベルトフィルタを通す前に、BPFに通したほうが良いと思います。

特に信号の低域はヒルベルトフィルタの働きをしません。

局発のヒルベルトフィルタは41タップはもったいない気がします。

単一周波数なので、それが通るぎりぎりの帯域があれば充分だと思い

ます。

2) 実数部と虚数部の振幅がおなじで無い

固定小数点の桁取りを確認したほうが良いかも?

のような気がします。

...

直交性の確認は虚数部と実数部を1周期分掛け算したものを積分してゼロになるかどうか

で分かります。

...」

 

前節で、私が、行き当たりばったりの対症療法を、行っていたからです。

私自身も、前節で書いた通りに、疲れを感じておりました。

「こんな筈ではない...」と。

 

応援団長様の、お言葉は、私を充分、勇気づけて下さいました。

 

「ディジタル信号処理ですから、理論どおりに

動くはずなのです。」

 

そうか、やっぱり、自分が間違ってたんやんか...

 

「現在の対処療法は、本質を見失う可能性があるような気がします。」

ありがたいお言葉に、勇気付けられました、御礼申し上げます。

 

2.先を急ぎすぎた...

 

そんなんで、一つ一つ、解決して、

それから、信号の複素化による周波数変換に進みたいと思っております。

 

3.hilbert変換で求めた虚部と、遅延させた実部の振幅が違う件について

hilbert変換単独を、もっかい、調べます。

 

結論を、先に申しますと、

虚部と、実部で振幅が違うのは、計算の誤差によると、結論いたしました。

 

理由は

「hilbert変換フィルタを、以下のように、設計し、通過域が平坦になるようにいたしました所、

周波数を変えてみましても、

hilbert変換フィルタ通過後の、信号の虚部の振幅は、常に一定でありました。」故。

MATH

   (三上直樹先生ご製作のフィルタ作成プログラムより [C言語によるディジタル信号処理 CQ出版社])

 

3−2.プログラムにミスは、ないのか?

 

積和の計算をする,自前のint macw(short* a,short* b)を、まず、疑いました。

この部分です。

 

inline int macw( short *a,short *b )

{

int c;

asm("clrmac");

asm("mov.l %0,r2\n"

"mov.l %1,r3"::"m" (a),"m" (b) );

asm(".rept 81 \n" //ここのNだけは、手動で変える事

"mac.w @r2+,@r3+\n"

".endr");

asm("sts MACL,r4\n" //積和MACの下位だけr4に移す。MACHに溢れたら、どうするんや?

"mov.l r4,%1":"=m" (c) );

return c; //int Cを返す

}

 

これに付きまして、MACHが溢れる訳では、ありませんが、

 

計算の結果がマイナスの時

 

mac.wは

「MAC.W @Rm+, @Rn+ 0 1 0 0 n n n n m m m m 1 1 1 1 符号付きで (Rn) ラ (Rm) + MAC

→ MAC

16ラ16+64→64 ビット

」(SH7047シリーズハードウェアマニュアルから抜粋)

 

なので、MACHが 0xffffffffになるのです。

ですので、

MACLだけ、int cに移すのは、間違いであると、判断致しました。

 

そこで、long型の整数を導入し、(GCCでは、long long intと宣言いたします。)

 

inline int macw( short *a,short *b )

{

long long int longc;

int intd;

asm("clrmac");

asm("mov.l %0,r2\n"

"mov.l %1,r3"::"m" (a),"m" (b) );

asm(".rept 81 \n" //ここのNだけは、手動で変える事

"mac.w @r2+,@r3+\n"

".endr");

asm("sts MACL,r4\n"

"sts MACH,r5");

asm("mov.l r4,%0\n"

"mov.l r5,%1":"=m" (intd),"=m" (longc) );

longc =longc<<32;

longc \=intd;

intd=(int)longc;

return intd; //int intdを返す

}

と、改めました。

 

GDBにて、リモートデバッグいたしました所

(r4にMACL,r5にMACHを表示するようにいたしました。)

MATH

MATH

これを見ますと、r5(MACH)が0xffffffffの時、r4(MACL)の値と、returnするintdは、一致しておりました。

次に、r5(MACH)が0の時

MATH

64ビット長の変数 longc は、不思議な値になっていますが、これも、やはり下位は

 

r4(MACL)=longc下位=intd(リターンするint値)

 

なのです。

結局、結論として

「long long int longc;

int intd;

...

longc =longc<<32;

longc \=intd;

intd=(int)longc;」

の部分は、不要でありました...勉強不足なり。

 

虚部のみ、出力してみました所、スプリアスが約25dB位下に見られますので

応援団長様、ご指摘のように、バンドパスをいれたほうが、よいようです。

MATH

 

3−3.実部と虚部は、正しく直交しているのか?

 

これが、大問題です。

 

「直交性の確認は虚数部と実数部を1周期分掛け算したものを積分してゼロになるかどうか

で分かります。」(応援団長様)

 

なーるほどです。

 

フーリエ級数の係数を求める時、この直交性を使うんでしたね。

 

サンプリング周波数を、きっちり求めて、入力信号の周波数から、

1周期分が、何ポイントか、又は、1周期分の整数倍のポイント数を算出して

ポイント間の距離を1として

虚部*実部を、1周期分積和計算すれば、よいのですね。(中点も要るやんか、そうせんと積分が、ゼロにならん...)

 

サンプリング周波数が、36.84KHzの時

入力信号が1.5KHzとすると、

[36.84/1.5]が、できるだけ整数に近くなるように、数周期分を出せば、よいのだと思いますが...

これは、入力信号をシリアルで、PCに送り、その値で、シミュレートしてみないことには、

私には、これしか、思いつきません...(実測が、ええ加減なもので...)

他の方法は、全然解りません。

 

オシロで、フォスファなるもので、積分できるものが、オプションであるそうですが...

でも、SH側から2チャンネルで出力しないと、駄目なんでしょうね..

 

 

ひとつひとつ調べて行きたいと思います。

また、宜しくお願い申しあげます。

 

 

H.16.3.13 [ A happy birthdayでした。]

.

This document created by Scientific Notebook 4.1. この文書は次の製品で作成しました Scientific Notebook 4.1.