手習ひデジタル信号処理(85) Scilab、自前版NCO、単なるSIN/COSの計算だけど

Joseph Halfmoon

前回、自前のBPSK変調とtbx版のBPSK変調で差がありました。この差はI,Q分離してグラフにしたら一目瞭然なやつでないかと思いました。自前でI/Q信号にするためには直交信号を生成しないとね。実時間処理とかハード化とか何も考えない数字上の「自前処理」なのでSIN/COS計算すれば良いか?でも意外と小ネタに躓きます。

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

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

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

Scilab Communication Toolbox 0.3.1

前回のBPSK変調信号に単純SIN/COS乗じてみる

まずは、前回生成したBPSK変調信号と同等のものを生成しておきます。サンプリング周波数10e5Hz、搬送波周波数 4e3Hz、ボーレート1e3に、疑似乱数ビット列20ビットを載せたものです。

test = genBPSK(10e5, 4e3, 1e3, prbs(20));

上記の信号(実数)に直交する正弦波、余弦波信号を掛け合わせてやればI/Q分離の第1段階となる筈。まあこの後、2つの信号毎にLPFかけて、ダウンサンプラをとおしてI/Q信号ということになります。自前の先は長いな。ハードウエアに実装するならば、NCO(Numericall-Controlled Oscillator)とMixerに相当する部分ということでいいのかな?しかし、今回はScilab上での数値実験用なので、まずは一撃、以下のような形で正弦波(余弦波も)作ってみました。こんな感じ。

swave = sin(2*%pi*Fc*t)

しかしあろうことかエラーです。以下のごとし。

dimMIsmatchError

ええ、swaveとtest、ちょうど同じ長さになるようにちゃんと計算したよ。しかし変数ブラウザを見れば一目瞭然。dimMismatch

何も考えずに”:”演算子で生成した時間ベクトルtが行ベクトルであったために、sin/cos波形(swave, cwave)は成り行きで行ベクトル。一方、前回生成のBPSK信号は列ベクトルでした。

後に述べる理由でswaveの方を転置して計算することにいたしました。なお転置演算子は ‘ なのですが、前につけると文字列と間違われるので後置です。

sT = swave' .* test;

これで、BPSK変調波に正弦波(サンプリング周波数も搬送波周波数も同じとしてあります)を乗じることができました。

なお、plotの場合は行ベクトルのままでも文句は言われますがプロット可能です。plotWarning

気を利かせてくれるときもあるのね。。。まあ上記の警告を回避するためにも、基本は列ベクトル、としておくのが宜しいかと思いました(個人の感想デス。)

しかし、変調波にSIN波、COS波を乗じた信号をプロットしてみて「足らないもの」に気づきましたです。あれれこの波形はなぜ?

上記は、サンプリング周波数、搬送波周波数がともに完璧に一致しており、かつフェーズも一致という現実にはあり得ない(でも何も考えなければ計算上はそうなる)組み合わせのために見える現象だと思います。

波形を拡大するとこんな感じ。mixResults2

いくら「数値実験」といってもこれではマズイんでないの?

ということでチョイ変

以下が直交信号生成用の自前関数です。ベクトルの転置は外でもできるのでそのままにしてます(一文字つけるだけだし。)一方、送受両側で完璧に位相があっているようなことはあり得ないので、位相だけはずらせるようにしてみました。

// generate NCO waveform
// Fs: sampling frequency [Hz]
// Fc: carrier frequency [Hz]
// nSample: number of samples
// phdeg: phase [deg]
function [t, swave, cwave]=genNCO(Fs, Fc, nSample, phdeg)
    t = ((1:nSample) - 1) / Fs;
    swave = sin(2*%pi*(Fc*t+(phdeg/360)))
    cwave = cos(2*%pi*(Fc*t+(phdeg/360)))
endfunction

上記を使って、テスト用のBPSK変調信号を作って、SIN波、COS波を乗じてみる操作が以下に。

tstSEQ = prbs(20);
tWave = genBPSK(10e5, 4e3, 1e3, tstSEQ);
[t, swave2, cwave2]=genNCO(10e5, 4e3, 10e2*20, 45);
sT = swave2' .* tWave;
cT = cwave2' .* tWave;

上で生成したtWave、sT、cTをプロットする操作が以下に。

clf();
figure(1);
subplot(3, 1, 1);
plot(t, tWave);
xlabel('TIME');
title('BPSK Signal');
subplot(3, 1, 2);
plot(t, sT);
xlabel('TIME');
title('BPSK .* SIN');
subplot(3, 1, 3);
plot(t, cT);
xlabel('TIME');
title('BPSK .* COS');

プロット結果っす。

mix45Results2

LPFかけなくても復調が見えているような気がしないでも無いですが。まあ順次実験していくのが自前シリーズと。ホントか?

手習ひデジタル信号処理(85) Scilab、BPSK、自前版とtbx版、微妙な違い? へ戻る

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