手習ひデジタル信号処理(87) Scilab、前回の続きでNCOした信号をLPF

Joseph Halfmoon

外乱も何もない「理想的な」BPSK変調信号をミキサにかけた後LPFという段で、前回はLPF生成関数に足をすくわれました。トホホのお約束か。まあなんとか乗り越えた(ホントか?)ように見えるので、今回は気を取り直してBPSK変調された信号にNCO(もどき)の信号を乗じたものをLPFしてみたいと思います。計算するだけなら只。

※「手習ひデジタル信号処理」投稿順 Indexはこちら

※動作確認に使用させていただいているのは、Scilab 6.1.1(Windows版)です。

当方で使用しておりますcomm_tbxは、以下のバージョンです。Scilab環境からATOMS(Scilabのライブラリ管理ツール?)でインストールをいたしたもの。

Scilab Communication Toolbox 0.3.1

補助用の関数定義2件

「計算するだけなら只(電気代が気になる昨今ですが)」ということで、各種ケースを複数計算するために以下の補助関数を追加定義いたしました。

genTESTSEQ.sci

// generate sampling signal of the test sequence
// Fs: sampling frequency [Hz]
// Fsym: symbol rate [baud]
// b: test sequence
function testseq=genTESTSEQ(Fs, Fsym, b)
    nSym=length(b);
    nLen=Fs/Fsym
    index = 1;
    for n=1:nSym
        for i=1:nLen
            testseq(index) = b(n);
            index = index +1;
        end
    end
endfunction

plotSIG4.sci

function plotSIG4(t, tseq, tWave, sT, cT, L1, L2, L3, L4)
    clf();
    figure(0);
    subplot(4, 1, 1);
    plot2d3(t, tseq);
    xlabel('TIME');
    title(L1);
    subplot(4, 1, 2);
    plot(t, tWave);
    xlabel('TIME');
    title(L2);
    subplot(4, 1, 3);
    plot(t, sT);
    xlabel('TIME');
    title(L3);
    subplot(4, 1, 4);
    plot(t, cT);
    xlabel('TIME');
    title(L4);
endfunction

上記の追加定義に加えて、過去回で作成済の以下の自前関数も使用しております。

    • genBPSK.sci
    • genNCO.sci
実験用のBPSK変調された入力信号発生

以前の回で生成したのとほぼほぼ同じ信号です。後で波形プロットしやすいように短い20ビットのテストシーケンスを発生したもの。

Fs = 10e5
Fc = 4e3
Fsym = 1e3
Fc2 = 2e3
nLEN = 20
nSYM = Fs/Fsym
t0SEQ = prbs(nLEN);
tWave = genBPSK(Fs, Fc, Fsym, t0SEQ);
t1SEQ = genTESTSEQ(Fs, Fsym, t0SEQ);

ここで、

    • Fs、サンプリング周波数
    • Fc、搬送波周波数
    • Fsym、シンボルレート
    • Fc2、後で使う中間周波数

です。生成された(変調された)信号波形は tWave に格納されています。

なんちゃってNCOでミキサ

上記のtWave信号に、なんちゃってNCO生成のSIN波、COS波を乗じてミキサしていくのですが、「計算するだけなら只(電気代が気になる昨今ですが)」ということで複数のケースを計算してます。

    • Fc2(搬送波周波数Fcより低い)を乗じて中間周波数に落とす想定のもの
    • Fcを乗じてマイナス方向は「Fc無?」まで一気に落とす想定のもの

また「なんちゃってNCO」生成の信号は、何も言わないとピッタンコで入力信号と位相があってしまっているので、以下のように位相をずらしたものも計算してみました。

    • 0度
    • 30度
    • 45度
    • 60度

2x4ケースで合計8種類とな。

中間周波数Fc2を使うものが以下に。

[t, swave0, cwave0]=genNCO(Fs, Fc2, nSYM*nLEN, 0);
[t, swave30, cwave30]=genNCO(Fs, Fc2, nSYM*nLEN, 30);
[t, swave45, cwave45]=genNCO(Fs, Fc2, nSYM*nLEN, 45);
[t, swave60, cwave60]=genNCO(Fs, Fc2, nSYM*nLEN, 60);
sT0 = swave0' .* tWave;
cT0 = cwave0' .* tWave;
sT30 = swave30' .* tWave;
cT30 = cwave30' .* tWave;
sT45 = swave45' .* tWave;
cT45 = cwave45' .* tWave;
sT60 = swave60' .* tWave;
cT60 = cwave60' .* tWave;

ダイレクトにFc使うものが以下に。

[t, swaveC0, cwaveC0]=genNCO(Fs, Fc, nSYM*nLEN, 0);
[t, swaveC30, cwaveC30]=genNCO(Fs, Fc, nSYM*nLEN, 30);
[t, swaveC45, cwaveC45]=genNCO(Fs, Fc, nSYM*nLEN, 45);
[t, swaveC60, cwaveC60]=genNCO(Fs, Fc, nSYM*nLEN, 60);
sTC0 = swaveC0' .* tWave;
cTC0 = cwaveC0' .* tWave;
sTC30 = swaveC30' .* tWave;
cTC30 = cwaveC30' .* tWave;
sTC45 = swaveC45' .* tWave;
cTC45 = cwaveC45' .* tWave;
sTC60 = swaveC60' .* tWave;
cTC00 = cwaveC60' .* tWave;

上記結果のうちFc2を使った場合の波形プロットが以下です。

plotSIG4(t, t1SEQ, tWave, sT0, cT0, 'TEST SEQ', 'BPSK', 'BPSK.*SIN0', 'BPSK.*COS0');

プロット結果が以下に。ST0

位相の違うやつらの波形を比べたものが以下に。

plotSIG4(t, sT0, sT30, sT45, sT60, 'BPSK.*SIN0', 'BPSK.*SIN30','BPSK.*SIN45','BPSK.*SIN60');

STs

そしてスペクトル密度が以下に。

clf();
plot_psd(sTC0, Fs, 0 , Fc*4);

ST0_PSD

ダイレクトFcの方の波形が以下に。

plotSIG4(t, t1SEQ, tWave, sTC0, cTC0, 'TEST SEQ', 'BPSK', 'BPSK.*SINC0', 'BPSK.*COSC0');

STC0

この時点でテストシーケンスが読めそうですな。

位相を比較したものが以下に。

plotSIG4(t, sTC0, sTC30, sTC45, sTC60, 'BPSK.*SINC0', 'BPSK.*SINC30','BPSK.*SINC45','BPSK.*SINC60');

STCs

スペクトル密度が以下に。

clf();
plot_psd(sTC0, Fs, 0 , Fc*4);

STC0_PSD

なんちゃってLPF(ローパスフィルタ)

まずはFc2側のI/Q波形にLPF。PSDプロットからカットオフ周波数は3kHzに設定っす。波形プロットまで一気に。

[wft, wfm, fr] = wfir('lp', 500, [0.003 0.0036], 'hm',[0 0]);
[sz0, szf] = filter(wft, 1, sT0);
[cz0, czf] = filter(wft, 1, cT0);
plotSIG4(t, t1SEQ, tWave, sz0, cz0, 'TEST SEQ', 'BPSK', 'SIN0 LPF', 'COS0 LPF');

LPF0

この状態でのパワースペクトル密度が以下に。

sigZ = complex(cz0, sz0);
clf();
plot_psd(sigZ, Fs, 0, Fc*4)

LPF0_PSD

一方、ダイレクトFc側のLPF通過後波形が以下に。LPFのカットオフ周波数は2kHzに設定。

[wft, wfm, fr] = wfir('lp', 500, [0.002 0.003], 'hm',[0 0]);
[szC0, szf] = filter(wft, 1, sTC0);
[czC0, czf] = filter(wft, 1, cTC0);
plotSIG4(t, t1SEQ, tWave, szC0, czC0, 'TEST SEQ', 'BPSK', 'SINC0 LPF', 'COSC0 LPF');

LPFC0

上記のSINC0_LPF波形みると、この時点で「復調」できている風、なんちゃって。

パワースペクトル密度が以下に。

sigCZ = complex(czC0, szC0);
clf();
plot_psd(sigCZ, Fs, 0, Fc*4)

LPFC0_PSD

「計算するだけなら只(電気代が気になる昨今ですが)」ということで、計算しまくった今回でした。

手習ひデジタル信号処理(87) Scilab、GUIつかってフィルタ作ろうとしてハマる へ戻る

手習ひデジタル信号処理(88) pyrtlsdr、PythonでRTL-SDRの信号を処理 へ進む