Main Content

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

comm.LinearEqualizer

線形フィルターを使用した変調信号のイコライズ

説明

comm.LinearEqualizer System object™ は、重み付き和をもつ線形フィルター タップ付き遅延線を使用して、分散チャネルを介して送信される変調信号をイコライズします。イコライザー オブジェクトは、選択されたアルゴリズムに基づいてタップ重みを適応的に調整します。詳細については、アルゴリズムを参照してください。

線形フィルターを使用して変調信号をイコライズするには:

  1. comm.LinearEqualizer オブジェクトを作成し、そのプロパティを設定します。

  2. 関数と同様に、引数を指定してオブジェクトを呼び出します。

System object の機能の詳細については、System object とはを参照してください。

作成

説明

lineq = comm.LinearEqualizer は、線形イコライザー System object を作成して信号を適応的にイコライズします。

lineq = comm.LinearEqualizer(Name,Value) は、1 つ以上の名前と値のペアを使用してプロパティを設定します。たとえば、comm.LinearEqualizer('Algorithm','RLS') は、再帰的最小二乗 (RLS) アルゴリズムを使用してタップ重みを更新するようにイコライザー オブジェクトを構成します。各プロパティ名を引用符で囲みます。

プロパティ

すべて展開する

特に指定がない限り、プロパティは "調整不可能" です。つまり、オブジェクトの呼び出し後に値を変更することはできません。オブジェクトは呼び出すとロックされ、ロックを解除するには関数 release を使用します。

プロパティが "調整可能" の場合、その値をいつでも変更できます。

プロパティ値の変更の詳細については、System object を使用した MATLAB でのシステム設計を参照してください。

イコライズに使用される適応アルゴリズム。以下のいずれかの値として指定します。

データ型: char | string

イコライザーのタップ数。正の整数として指定します。

データ型: double

適応アルゴリズムで使用されるステップ サイズ。正のスカラーとして指定します。ステップ サイズを大きくすると、イコライザーの収束時間が短縮されますが、イコライザーの出力推定の安定性が低下します。

ヒント

許容される最大ステップ サイズを決定するには、オブジェクト関数 maxstep を使用します。

調整可能: Yes

依存関係

このプロパティを有効にするには、Algorithm'LMS' または 'CMA' に設定します。

データ型: double

適応アルゴリズムで使用される忘却係数。範囲 (0, 1] のスカラーとして指定します。忘却係数を小さくすると、イコライザーの収束時間が短縮されますが、イコライザーの出力推定の安定性が低下します。

調整可能: Yes

依存関係

このプロパティを有効にするには、Algorithm'RLS' に設定します。

データ型: double

初期逆相関行列。スカラーまたは NTaps 行 NTaps 列の行列として指定します。NTapsNumTaps プロパティ値と等しくなります。InitialInverseCorrelationMatrix をスカラー a として指定した場合、イコライザーは初期逆相関行列を、単位行列を a 倍した a(eye(NTaps)) に設定します。

調整可能: Yes

依存関係

このプロパティを有効にするには、Algorithm'RLS' に設定します。

データ型: double

コンスタレーション。ベクトルとして指定します。既定値は、次のコードを使用して生成された QPSK コンスタレーションです: pskmod(0:3,4,pi/4)

調整可能: Yes

データ型: double

リファレンス タップ。NumTaps プロパティ値以下の正の整数として指定します。イコライザーは、リファレンス タップ位置を使用してチャネルのメイン エネルギーを追跡します。

データ型: double

イコライザーのリセット時間に関連するサンプル単位の入力信号遅延。非負の整数として指定します。入力信号が 1 よりも大きい長さのベクトルの場合、入力遅延は入力ベクトルの始点に相対します。入力信号がスカラーの場合、入力遅延は System object の最初の呼び出しと、オブジェクト関数 release または reset を呼び出した後の System object の最初の呼び出しに関連します。

データ型: double

シンボルごとの入力サンプル数。正の整数として指定します。このプロパティを 1 より大きい数値に設定すると、分数間隔イコライザーが効率的に作成されます。詳細については、シンボル タップ間隔を参照してください。

データ型: double

学習制御入力を有効にします。false または true として指定します。このプロパティを true に設定すると、イコライザーの学習フラグ入力 tf が有効になります。

調整可能: Yes

データ型: logical

学習中でないときにタップ重みを更新します。true または false として指定します。このプロパティが true に設定されている場合、System object は判定指向モードを使用してイコライザーのタップ重みを更新します。このプロパティが false に設定されている場合、System object は学習後にイコライザーのタップ重みを変更せずに維持します。

調整可能: Yes

データ型: logical

タップ重みの適応要求のソース。以下のいずれかの値として指定します。

  • 'Property' — System object がタップ重みをいつ適応させるかを制御するために AdaptWeights プロパティを使用するには、この値を指定します。

  • 'Input port' — System object がタップ重みをいつ適応させるかを制御するために aw 入力を使用するには、この値を指定します。

依存関係

このプロパティを有効にするには、Algorithm'CMA' に設定します。

データ型: char | string

タップ重みの適応。true または false として指定します。このプロパティが true に設定されている場合、System object はイコライザーのタップ重みを更新します。このプロパティが false に設定されている場合、System object はイコライザーのタップ重みを変更せずに維持します。

調整可能: Yes

依存関係

このプロパティを有効にするには、AdaptWeightsSource'Property' に設定し、AdaptAfterTrainingtrue に設定します。

データ型: logical

初期タップ重みのソース。以下で指定します。

  • 'Auto'InitialWeights プロパティで説明されているように、タップ重みをアルゴリズム固有の既定値に初期化します。

  • 'Property'InitialWeights プロパティ値を使用してタップ重みを初期化します。

データ型: char | string

適応アルゴリズムで使用される初期タップ重み。スカラーまたはベクトルとして指定します。Algorithm プロパティが 'LMS' または 'RLS' に設定されている場合、既定は 0 です。Algorithm プロパティが 'CMA' に設定されている場合、既定は [0;0;1;0;0] です。

InitialWeights をベクトルとして指定した場合、ベクトルの長さは NumTaps プロパティ値と等しくなければなりません。InitialWeights をスカラーとして指定した場合、イコライザーはスカラー拡張を使用して、長さが NumTaps ですべての値が InitialWeights に設定されたベクトルを作成します。

調整可能: Yes

依存関係

このプロパティを有効にするには、InitialWeightsSource'Property' に設定します。

データ型: double

シンボル単位のタップ重みの更新周期。正の整数として指定します。イコライザーは、この数のシンボルを処理した後にタップ重みを更新します。

データ型: double

使用法

説明

y = lineq(x,tsym) は、トレーニング シンボル tsym を使用して入力信号 x をイコライズします。出力はイコライズされたシンボルです。この構文を有効にするには、Algorithm プロパティを 'LMS' または 'RLS' に設定します。

y = lineq(x,tsym,tf) は、学習フラグ tf も指定します。(立ち上がりエッジで) tffalse から true に変化すると、System object が学習を開始します。System object は、tsym のすべてのシンボルが処理されるまで学習を続けます。tffalse の場合、入力 tsym は無視されます。この構文を有効にするには、Algorithm プロパティを 'LMS' または 'RLS' に設定し、TrainingFlagInputPort プロパティを true に設定します。

y = lineq(x) は入力信号 x をイコライズします。この構文を有効にするには、Algorithm プロパティを 'CMA' に設定します。

y = lineq(x,aw) は、重みの適応フラグ aw も指定します。System object は、awtrue の場合にイコライザーのタップ重みを適応させます。awfalse の場合、System object は重みを変更せずに維持します。この構文を有効にするには、Algorithm プロパティを 'CMA' に設定し、AdaptWeightsSource プロパティを 'Input port' に設定します。

[y,err] = lineq(___) は、前述の構文のいずれかの入力引数を使用して、誤差信号 err も返します。

[y,err,weights] = lineq(___) は、前述の構文のいずれかの入力引数を使用して、最新のタップ重みの更新からのタップ重み weights も返します。

入力引数

すべて展開する

入力信号。列ベクトルで指定します。入力信号のベクトルの長さは、InputSamplesPerSymbol プロパティ値の整数倍に等しくなければなりません。詳細については、シンボル タップ間隔を参照してください。

データ型: double
複素数のサポート: あり

トレーニング シンボル。入力 x の長さ以下の長さの列ベクトルとして指定します。tffalse の場合、入力 tsym は無視されます。

依存関係

この引数を有効にするには、Algorithm プロパティを 'LMS' または 'RLS' に設定します。

データ型: double
複素数のサポート: あり

学習フラグ。true または false として指定します。(立ち上がりエッジで) tffalse から true に変化すると、System object が学習を開始します。System object は、tsym のすべてのシンボルが処理されるまで学習を続けます。tffalse の場合、入力 tsym は無視されます。

依存関係

この引数を有効にするには、Algorithm プロパティを 'LMS' または 'RLS' に設定し、TrainingFlagInputPort プロパティを true に設定します。

データ型: logical

重みの適応フラグ。true または false として指定します。awtrue の場合、System object は重みを適応させます。awfalse の場合、System object は重みを変更せずに維持します。

依存関係

この引数を有効にするには、Algorithm プロパティを 'CMA' に設定し、AdaptWeightsSource プロパティを 'Input port' に設定します。

データ型: logical

出力引数

すべて展開する

イコライズされたシンボル。入力信号 x と同じ長さの列ベクトルとして返されます。

誤差信号。入力信号 x と同じ長さの列ベクトルとして返されます。

タップ重み。NumTaps 個の要素をもつ列ベクトルとして返されます。weights には最新のタップ重みの更新のタップ重みが含まれます。

オブジェクト関数

オブジェクト関数を使用するには、System object を最初の入力引数として指定します。たとえば、obj という名前の System object のシステム リソースを解放するには、次の構文を使用します。

release(obj)

すべて展開する

isLockedSystem object が使用中かどうかの判定
cloneSystem object の複製
infoイコライザー オブジェクトの特性情報
maxstepLMS イコライザーの収束のための最大ステップ サイズ
mmseweights線形イコライザーの MMSE タップ重み
stepSystem object のアルゴリズムの実行
releaseリソースを解放し、System object のプロパティ値と入力特性の変更を可能にします。
resetSystem object の内部状態のリセット

すべて折りたたむ

8 つのタップをもちステップ サイズが 0.03 の線形 LMS イコライザーを指定して、BPSK 変調器とイコライザー System object™ を作成します。

bpsk = comm.BPSKModulator;
eqlms = comm.LinearEqualizer('Algorithm','LMS','NumTaps',8,'StepSize',0.03);

イコライザーのリファレンス タップ インデックスを変更します。

eqlms.ReferenceTap = 4;

テスト データのセットを作成します。信号の畳み込みを行ってデータを受信します。

x = bpsk(randi([0 1],1000,1));
rxsig = conv(x,[1 0.8 0.3]);

maxstep を使用して最大許容ステップ サイズを求めます。

mxStep = maxstep(eqlms,rxsig)
mxStep = 0.1384

受信信号をイコライズします。最初の 200 個のシンボルをトレーニング シーケンスとして使用します。

y = eqlms(rxsig,x(1:200));

最小平均二乗 (LMS) アルゴリズムを使用した線形イコライズを適用して、マルチパス AWGN チャネル経由で渡した QPSK シンボルを復元します。

シミュレーション変数を初期化します。

M = 4; % QPSK
numSymbols = 10000;
numTrainingSymbols = 1000;
chtaps = [1 0.5*exp(1i*pi/6) 0.1*exp(-1i*pi/8)];

QPSK 変調されたシンボルを生成します。シンボルにマルチパス チャネルのフィルター処理と AWGN 障害を適用します。

data = randi([0 M-1],numSymbols,1);
tx = pskmod(data,M,pi/4);
rx = awgn(filter(chtaps,1,tx),25,'measured');

線形イコライザー System object を作成し、既定の構成を表示します。リファレンス タップを 1 に調整します。最大許容ステップ サイズをチェックします。劣化したシンボルをイコライズします。

eq = comm.LinearEqualizer
eq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'LMS'
                  NumTaps: 5
                 StepSize: 0.0100
            Constellation: [1x4 double]
             ReferenceTap: 3
               InputDelay: 0
    InputSamplesPerSymbol: 1
    TrainingFlagInputPort: false
       AdaptAfterTraining: true
     InitialWeightsSource: 'Auto'
       WeightUpdatePeriod: 1

eq.ReferenceTap = 1;

mxStep = maxstep(eq,rx)
mxStep = 0.3154
[y,err,weights] = eq(rx,tx(1:numTrainingSymbols));

劣化したシンボルとイコライズされたシンボルのコンスタレーションをプロットします。

constell = comm.ConstellationDiagram('NumInputPorts',2);
constell(rx,y)

イコライザーの誤差信号をプロットし、イコライズされたシンボルのエラー ベクトル振幅 (EVM) を計算します。

plot(abs(err))
grid on; xlabel('Symbols'); ylabel('|e|');title('Equalizer Error Signal')

errevm = comm.EVM;
evm = errevm(tx,y)
evm = 11.7710

イコライザーのタップ重みをプロットします。

subplot(3,1,1); 
stem(real(weights)); ylabel('real(weights)'); xlabel('Tap'); grid on; axis([0 6 -0.5 1])
title('Equalizer Tap Weights')
subplot(3,1,2); 
stem(imag(weights)); ylabel('imag(weights)'); xlabel('Tap'); grid on; axis([0 6 -0.5 1])
subplot(3,1,3); 
stem(abs(weights)); ylabel('abs(weights)'); xlabel('Tap'); grid on; axis([0 6 -0.5 1])

最小平均二乗 (LMS) アルゴリズムを使用した線形イコライズを示して、AWGN チャネル経由で渡した QPSK シンボルを復元します。異なるイコライザーの学習スキームを適用して、シンボルの誤差の大きさを示します。

システム設定

AWGN の影響を受ける QPSK 変調システムをシミュレートします。200 個のトレーニング シンボルと 1800 個のランダム データ シンボルで構成されるパケットを送信します。パケット データを復元するように線形 LMS イコライザーを構成します。

M = 4;
numTrainSymbols = 200;
numDataSymbols = 1800;
SNR = 20;
trainingSymbols = pskmod(randi([0 M-1],numTrainSymbols,1),M,pi/4);
numPkts = 10;
lineq = comm.LinearEqualizer('Algorithm','LMS', ...
    'NumTaps',5,'ReferenceTap',3,'StepSize',0.01);

リセットを使用する各パケットの先頭でのイコライザーの学習

各パケットを処理するときに、先頭に追加されたトレーニング シンボルを使用します。各パケットの処理後にイコライザーをリセットします。このリセットにより、イコライザーは事前知識なしにタップを学習するようになります。最初、2 番目、および最後のパケットのイコライザー誤差信号プロットは、各パケットの先頭でシンボル誤りが多くなっていることを示しています。

jj = 1;
figure
for ii = 1:numPkts
    b = randi([0 M-1],numDataSymbols,1);
    dataSym = pskmod(b,M,pi/4);
    packet = [trainingSymbols;dataSym];
    rx = awgn(packet,SNR);
    [~,err] = lineq(rx,trainingSymbols);
    reset(lineq)
    if (ii ==1 || ii == 2 ||ii == numPkts)
        subplot(3,1,jj)
        plot(abs(err))
        title(['Packet # ',num2str(ii)])
        xlabel('Symbols')
        ylabel('Error Magnitude')
        axis([0,length(packet),0,1])
        grid on;
        jj = jj+1;
    end
end

リセットを使用しない各パケットの先頭でのイコライザーの学習

先頭に追加されたトレーニング シンボルを使用して各パケットを処理します。各パケットの処理後にイコライザーをリセットしません。各パケットの後にリセットしないことで、イコライザーは前のパケットの学習によるタップ重みを保持します。最初、2 番目、および最後のパケットのイコライザー誤差信号プロットは、最初のパケットに対する初期学習の後に、後続のパケットが各パケットの先頭でシンボル誤りが少なくなることを示しています。

release(lineq)
jj = 1;
figure
for ii = 1:numPkts
    b = randi([0 M-1],numDataSymbols,1);
    dataSym = pskmod(b,M,pi/4);
    packet = [trainingSymbols;dataSym];
    channel = 1;
    rx = awgn(packet*channel,SNR);
    [~,err] = lineq(rx,trainingSymbols);
    if (ii ==1 || ii == 2 ||ii == numPkts)
        subplot(3,1,jj)
        plot(abs(err))
        title(['Packet # ',num2str(ii)])
        xlabel('Symbols')
        ylabel('Error Magnitude')
        axis([0,length(packet),0,1])
        grid on;
        jj = jj+1;
    end
end

周期的なイコライザーの学習

時変チャネルの影響を受ける信号があるシステムには、チャネル変動に対してロックを維持するために周期的なイコライザーの学習が必要です。1800 個のデータ シンボルごとに 200 個のシンボルの学習を行うシステムを指定します。学習の合間では、イコライザーはタップ重みを更新しません。イコライザーはパケットあたり 200 個のシンボルを処理します。

Rs = 1e6;
fd = 20;
spp = 200; % Symbols per packet
b = randi([0 M-1],numDataSymbols,1);
dataSym = pskmod(b,M,pi/4);
packet = [trainingSymbols; dataSym];
stream = repmat(packet,10,1);
tx = (0:length(stream)-1)'/Rs;
channel = exp(1i*2*pi*fd*tx);
rx = awgn(stream.*channel,SNR);

AdaptAfterTraining プロパティを false に設定して、学習フェーズの後にイコライザーのタップ重みの更新を停止します。

release(lineq)
lineq.AdaptAfterTraining = false
lineq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'LMS'
                  NumTaps: 5
                 StepSize: 0.0100
            Constellation: [1x4 double]
             ReferenceTap: 3
               InputDelay: 0
    InputSamplesPerSymbol: 1
    TrainingFlagInputPort: false
       AdaptAfterTraining: false
     InitialWeightsSource: 'Auto'
       WeightUpdatePeriod: 1

劣化したデータをイコライズします。チャネルからの角度誤差、イコライザーの誤差信号、およびコンスタレーションをプロットします。チャネルが変動しても、イコライザー出力からチャネルの影響は除去されません。出力コンスタレーションが同期せずに回転し、ビット誤りが発生します。

[y,err] = lineq(rx,trainingSymbols);

figure
subplot(2,1,1)
plot(tx, unwrap(angle(channel)))
xlabel('Time (sec)')
ylabel('Channel Angle (rad)')
title('Angular Error Over Time')
subplot(2,1,2)
plot(abs(err))
xlabel('Symbols')
ylabel('Error Magnitude')
grid on
title('Time-Varying Channel Without Retraining')

scatterplot(y)

TrainingInputPort プロパティを true に設定し、trainFlag 入力により信号が送られたときにタップを再学習するようにイコライザーを構成します。イコライザーは、trainFlagtrue の場合にのみ学習を行います。イコライザーは 2000 個のシンボルごとにタップを再学習し、チャネルの変動に対してロックを維持します。チャネルからの角度誤差、イコライザーの誤差信号、およびコンスタレーションをプロットします。チャネルが変動すると、イコライザー出力からチャネルの影響が除去されます。出力コンスタレーションが同期せずに回転することがなくなり、ビット誤りが減少します。

release(lineq)
lineq.TrainingFlagInputPort = true;
symbolCnt = 0;
numPackets = length(rx)/spp;
trainFlag = true;
trainingPeriod = 2000;
eVec = zeros(size(rx));
yVec = zeros(size(rx));
for p=1:numPackets
    [yVec((p-1)*spp+1:p*spp,1),eVec((p-1)*spp+1:p*spp,1)] = ...
        lineq(rx((p-1)*spp+1:p*spp,1),trainingSymbols,trainFlag);
    symbolCnt = symbolCnt + spp;
    if symbolCnt >= trainingPeriod
        trainFlag = true;
        symbolCnt = 0;
    else
        trainFlag = false;
    end
end
figure
subplot(2,1,1)
plot(tx, unwrap(angle(channel)))
xlabel('t (sec)')
ylabel('Channel Angle (rad)')
title('Angular Error Over Time')
subplot(2,1,2)
plot(abs(eVec))
xlabel('Symbols')
ylabel('Error Magnitude')
grid on
title('Time-Varying Channel With Retraining')

scatterplot(yVec)

送信シンボルと受信サンプルの間に遅延があるシステムをシミュレートします。一般的なシステムには送信側と受信側のフィルターがあり、これにより遅延が発生します。システムを同期させるには、この遅延を考慮しなければなりません。この例では、送信フィルターと受信フィルターを使用せずにシステム遅延が発生しています。線形イコライズは、最小平均二乗 (LMS) アルゴリズムを使用して、QPSK シンボルを復元します。

シミュレーション変数を初期化します。

M = 4; % QPSK
numSymbols = 10000;
numTrainingSymbols = 1000;
mpChan = [1 0.5*exp(1i*pi/6) 0.1*exp(-1i*pi/8)];
systemDelay = dsp.Delay(20);
snr = 24;

QPSK 変調されたシンボルを生成します。送信シンボルにマルチパス チャネルのフィルター処理、システム遅延、および AWGN を適用します。

data = randi([0 M-1],numSymbols,1);
tx = pskmod(data,M,pi/4); % OQPSK
delayedSym = systemDelay(filter(mpChan,1,tx));
rx = awgn(delayedSym,snr,'measured');

イコライザーおよび EVM の System object を作成します。イコライザー System object は、LMS アルゴリズムを使用する線形イコライザーを指定します。

lineq = comm.LinearEqualizer('Algorithm','LMS', ...
    'NumTaps',9,'ReferenceTap',5);
evm = comm.EVM('ReferenceSignalSource', ...
    'Estimated from reference constellation');

入力遅延を調整しないイコライズ

受信シンボルをイコライズします。

[y1,err1,wts1] = lineq(rx,tx(1:numTrainingSymbols,1));

関数 finddelay を使用して、受信シンボルと送信シンボルの間の遅延を検出します。

rxDelay = finddelay(tx,rx)
rxDelay = 20

イコライザー情報を表示します。レイテンシ値は、イコライザーによって発生した遅延を示します。合計遅延を、rxDelay とイコライザーのレイテンシの合計として計算します。

eqInfo = info(lineq)
eqInfo = struct with fields:
    Latency: 4

totalDelay = rxDelay + eqInfo.Latency;

イコライザー出力が収束するまで、シンボル誤り率は高くなります。誤り出力 err1 をプロットして、イコライズされた出力がいつ収束するかを判断します。

plot(abs(err1))
xlabel('Symbols')
ylabel('Error Magnitude')
title('Equalizer Error Signal')

このプロットでは、1000 個のシンボルの学習期間を超えて過度な誤りが示されています。シンボルを復調してシンボル誤りを計算するときは、収束していない出力と、イコライザー出力と送信シンボルの間のシステム遅延を考慮して、最初の 2000 個のシンボルをスキップします。

dataRec1 = pskdemod(y1(2000+totalDelay:end),M,pi/4);
symErrWithDelay = symerr(data(2000:end-totalDelay),dataRec1)
symErrWithDelay = 5999
evmWithDelay = evm(y1)
evmWithDelay = 29.5795

イコライザー System object で受信遅延が考慮されていないため、誤り率と EVM が高くなります。

イコライザーでの入力遅延の調整

遅延値を使用して InputDelay プロパティを設定し、受信データをイコライズします。InputDelay は調整できないプロパティであるため、InputDelay プロパティを再構成するには lineq System object を解放しなければなりません。受信シンボルをイコライズします。

release(lineq)
lineq.InputDelay = rxDelay
lineq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'LMS'
                  NumTaps: 9
                 StepSize: 0.0100
            Constellation: [1x4 double]
             ReferenceTap: 5
               InputDelay: 20
    InputSamplesPerSymbol: 1
    TrainingFlagInputPort: false
       AdaptAfterTraining: true
     InitialWeightsSource: 'Auto'
       WeightUpdatePeriod: 1

[y2,err2,wts2] = lineq(rx,tx(1:numTrainingSymbols,1));

タップ重みとイコライズされた誤差の大きさをプロットします。ステム プロットは、システム遅延が除去される前後のイコライザーのタップ重みを示します。2 次元ライン プロットは、遅延が除去された信号と比較して、遅延信号のイコライザー収束が遅いことを示しています。

subplot(2,1,1)
stem([real(wts1),real(wts2)])
xlabel('Taps')
ylabel('Tap Weight Real')
legend('rxDelayed','rxDelayRemoved')
grid on
subplot(2,1,2)
stem([imag(wts1),imag(wts2)])
xlabel('Taps')
ylabel('Tap Weight Imaginary')
legend('rxDelayed','rxDelayRemoved')
grid on

figure
plot([abs(err1),abs(err2)])
xlabel('Symbols')
ylabel('Error Magnitude')
legend('rxDelayed','rxDelayRemoved')
grid on

イコライズされた信号 rxDelayed および rxDelayRemoved の誤り出力をプロットします。遅延が除去された信号では、イコライザーは 1000 個のシンボルの学習期間中に収束します。シンボルを復調してシンボル誤りを計算するときは、収束していない出力と、イコライザー出力と送信シンボルの間のシステム遅延を考慮して、最初の 500 個のシンボルをスキップします。システム遅延を考慮するためにイコライザーを再構成すると、信号のイコライズが改善され、シンボル誤りと EVM が減少します。

eqInfo = info(lineq)
eqInfo = struct with fields:
    Latency: 4

totalDelay = rxDelay + eqInfo.Latency;
dataRec2 = pskdemod(y2(500+totalDelay:end),M,pi/4);
symErrDelayRemoved = symerr(data(500:end-totalDelay),dataRec2)
symErrDelayRemoved = 0
evmDelayRemoved = evm(y2(500+totalDelay:end))
evmDelayRemoved = 9.4435

定包絡線基準アルゴリズム (CMA) と EVM ベースのタップの学習を使用して、線形イコライザーで QPSK シンボルを復元します。CMA などのブラインド イコライザー アルゴリズムを使用する場合は、AdaptWeights プロパティを使用して学習を開始および停止することによって、イコライザーのタップを学習させます。補助関数を使用してプロットを生成し、位相補正を適用します。

システム変数を初期化します。

rng(123456);
M = 4; % QPSK
numSymbols = 100;
numPackets = 5000;
raylChan = comm.RayleighChannel('PathDelays',[0 1], ...
    'AveragePathGains',[0 -12],'MaximumDopplerShift',1e-5);
SNR = 50;
adaptWeights = true;

イコライザーおよび EVM の System object を作成します。イコライザー System object は、CMA 適応アルゴリズムを使用して線形イコライザーを指定します。補助関数を呼び出して Figure のプロットを初期化します。

lineq = comm.LinearEqualizer('Algorithm','CMA', ...
    'NumTaps',5,'ReferenceTap',3, ...
    'StepSize',0.03,'AdaptWeightsSource','Input port')
lineq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'CMA'
                  NumTaps: 5
                 StepSize: 0.0300
            Constellation: [1x4 double]
             ReferenceTap: 3
    InputSamplesPerSymbol: 1
       AdaptWeightsSource: 'Input port'
     InitialWeightsSource: 'Auto'
       WeightUpdatePeriod: 1

info(lineq)
ans = struct with fields:
    Latency: 2

evm = comm.EVM('ReferenceSignalSource', ...
    'Estimated from reference constellation');
[errPlot,evmPlot,scatSym,adaptState] = initFigures(numPackets,lineq);

イコライズ ループ

イコライズ ループを実装するには、以下の手順に従います。

  1. PSK データ パケットを生成します。

  2. レイリー フェージングと AWGN を送信データに適用します。

  3. 受信データにイコライズを、イコライザー出力に位相補正を適用します。

  4. EVM を推定し、EVM レベルに基づいて adaptWeights フラグを true または false に切り替えます。

  5. Figure のプロットを更新します。

for p=1:numPackets
    data = randi([0 M-1],numSymbols,1);
    tx = pskmod(data,M,pi/4);
    rx = awgn(raylChan(tx),SNR);
    rxDelay = finddelay(rx,tx);
    [y,err,wts] = lineq(rx,adaptWeights);
    y = phaseCorrection(y);
    evmEst = evm(y);
    adaptWeights = (evmEst > 20);
    
    updateFigures(errPlot,evmPlot,scatSym,adaptState, ...
        wts,y(end),evmEst,adaptWeights,p,numPackets)
end

rxDelay
rxDelay = 0

Figure のプロットは、EVM が変化するにつれて、イコライザーが判定指向の重み適応モードのオンとオフを切り替えていることを示しています。

補助関数

この補助関数は、シミュレーション結果の 4 つのプロットを示す Figure を初期化します。

function [errPlot,evmPlot,scatter,adaptState] = initFigures(numPkts,lineq)
yVec = nan(numPkts,1);
evmVec = nan(numPkts,1);
wVec = zeros(lineq.NumTaps,1);
adaptVec = nan(numPkts,1);

figure
subplot(2,2,1)
evmPlot = stem(wVec);
grid on; axis([1 lineq.NumTaps 0 1.8])
xlabel('Taps'); ylabel('|Weights|'); title('Tap Weight Magnitude')

subplot(2,2,2)
scatter = plot(yVec, '.');
axis square; axis([-1.2 1.2 -1.2 1.2]); grid on
xlabel('In-phase'); ylabel('Quadrature'); title('Scatter Plot');
subplot(2,2,3)
adaptState = plot(adaptVec);
grid on; axis([0 numPkts -0.2 1.2])
ylabel('Training'); xlabel('Symbols'); title('Adapt Weights Signal')
subplot(2,2,4)
errPlot = plot(evmVec);
grid on; axis([1 numPkts 0 100])
xlabel('Symbols'); ylabel('EVM (%)'); title('EVM')
end

この補助関数は Figure を更新します。

function updateFigures(errPlot,evmPlot,scatSym, ...
    adaptState,w,y,evmEst,adaptWts,p,numFrames)
persistent yVec evmVec adaptVec

if p == 1
    yVec = nan(numFrames,1);
    evmVec = nan(numFrames,1);
    adaptVec = nan(numFrames,1);
end

yVec(p) = y;
evmVec(p) = evmEst;
adaptVec(p) = adaptWts;

errPlot.YData = abs(evmVec);
evmPlot.YData = abs(w);
scatSym.XData = real(yVec);
scatSym.YData = imag(yVec);
adaptState.YData = adaptVec;
drawnow limitrate
end

この補助関数は位相補正を適用します。

function y = phaseCorrection(y)
a = angle(y((real(y) > 0) & (imag(y) > 0)));
a(a < 0.1) = a(a < 0.1) + pi/2;
theta = mean(a) - pi/4;
y = y * exp(-1i*theta);
end

最小平均二乗 (LMS) アルゴリズムを使用して、線形イコライザーでフェージング環境の QPSK シンボルを復元します。オブジェクト関数 reset を使用して、独立したパケットをイコライズします。補助関数を使用してプロットを生成します。この例では、シンボルベースの処理とフレームベースの処理も示します。

設定

システム変数を初期化し、イコライザー System object を作成して、プロット図を初期化します。

M = 4; % QPSK
numSym = 1000;
numTrainingSym = 100;
numPackets = 5;
numTaps = 9;
ttlNumSym = numSym + numTrainingSym;
raylChan = comm.RayleighChannel('PathDelays',[0 1], ...
    'AveragePathGains',[0 -9], ...
    'MaximumDopplerShift',0, ...
    'PathGainsOutputPort',true);
SNR = 35;
rxVec = zeros(ttlNumSym,numPackets);
txVec = zeros(ttlNumSym,numPackets);
yVec = zeros(ttlNumSym,1);
eVec = zeros(ttlNumSym,1);

lineq1 = comm.LinearEqualizer('Algorithm','LMS', ...
    'NumTaps',numTaps,'ReferenceTap',5, ...
    'StepSize',0.01,'TrainingFlagInputPort',true);

[errPlot,wStem,hStem,scatPlot] = initFigures(ttlNumSym,lineq1, ...
    raylChan.AveragePathGains);

シンボルベースの処理

シンボルベースの処理では、イコライザーの入力で 1 つのシンボルを指定します。各パケットの処理後にイコライザーの状態とチャネルをリセットします。

for p = 1:numPackets
    trainingFlag = true;
    for q=1:ttlNumSym
        data = randi([0 M-1],1,1);
        tx = pskmod(data,M,pi/4);
        [xc,pg] = raylChan(tx);
        rx = awgn(xc,25);
        [y,err,wts] = lineq1(rx,tx,trainingFlag);       

numTrainingSym 個のトレーニング シンボルを処理した後に学習を無効にします。

        if q == numTrainingSym
            trainingFlag = false;
        end        
        updateFigures(errPlot,wStem,hStem,scatPlot,err,wts,y,pg,q,ttlNumSym);
        txVec(q,p) = tx;
        rxVec(q,p) = rx;
    end 

各パケットの処理後に、チャネル System object をリセットしてチャネル タップの新しい実現を取得し、イコライザー System object をリセットして既定のタップ重み集合に戻します。

    reset(raylChan)
    reset(lineq1)
end

パケットベースの処理

パケットベースの処理では、イコライザーの入力で 1 つのパケットを指定します。各パケットには ttlNumSym 個のシンボルが含まれています。学習期間がパケット長よりも短いため、学習の開始の入力を指定する必要はありません。

yVecPkt = zeros(ttlNumSym,numPackets);
errVecPkt = zeros(ttlNumSym,numPackets);
wgtVecPkt = zeros(numTaps,numPackets);
lineq2 = comm.LinearEqualizer('Algorithm','LMS', ...
    'NumTaps',9,'ReferenceTap',6,'StepSize',0.01);
for p = 1:numPackets
    [yVecPkt(:,p),errVecPkt(:,p),wgtVecPkt(:,p)] = ...
        lineq2(rxVec(:,p),txVec(1:numTrainingSym,p));
    for q=1:ttlNumSym
        updateFigures(errPlot,wStem,hStem,scatPlot, ...
            errVecPkt(q,p),wgtVecPkt(:,p),yVecPkt(q,p),pg,q,ttlNumSym);
    end

各パケットの処理後に、チャネル System object をリセットしてチャネル タップの新しい実現を取得し、イコライザー System object をリセットして既定のタップ重み集合に戻します。

    reset(raylChan)
    reset(lineq2)
end

補助関数

この補助関数は Figure を初期化します。

function [errPlot,wStem,hStem,scatPlot] = initFigures(ttlNumSym,lineq,pg)
yVec = nan(ttlNumSym,1);
eVec = nan(ttlNumSym,1);
wVec = zeros(lineq.NumTaps,1);
figure;
subplot(2,2,1);
wStem = stem(wVec);
axis([1 lineq.NumTaps 0 1.8]); grid on
xlabel('Taps'); ylabel('|Weights|'); title('Tap Weight Magnitude')
subplot(2,2,2);
hStem = stem([0 abs(pg) 0]);
grid on;
xlabel('Taps'); ylabel('|Path Gain|'); title('Channel Path Gain Magnitude')
subplot(2,2,3);
errPlot = plot(eVec);
axis([1 ttlNumSym 0 1.2]); grid on
xlabel('Symbols'); ylabel('|Error Magnitude|'); title('Error Magnitude')
subplot(2,2,4);
scatPlot = plot(yVec,'.');
axis square; axis([-1.2 1.2 -1.2 1.2]); grid on;
xlabel('In-phase'); ylabel('Quadrature'); title(sprintf('Scatter Plot'));
end

この補助関数は Figure を更新します。

function updateFigures(errPlot,wStem,hStem,scatPlot, ...
    err,wts,y,pg,p,ttlNumSym)
persistent yVec eVec
if p == 1
    yVec = nan(ttlNumSym,1);
    eVec = nan(ttlNumSym,1);
end
yVec(p) = y;
eVec(p) = abs(err);
errPlot.YData = abs(eVec);
wStem.YData = abs(wts);
hStem.YData = [0 abs(pg) 0];
scatPlot.XData = real(yVec);
scatPlot.YData = imag(yVec);
drawnow limitrate
end

非適応モードで線形イコライザーを使用します。オブジェクト関数 mmseweights を使用して最小平均二乗誤差 (MMSE) の解を計算し、線形イコライザーのタップ重み集合にその重みを使用します。

シミュレーション変数を初期化します。

M = 4; % QPSK
numSymbols = 10000;
numTrainingSymbols = 1000;
chtaps = [1 0.5*exp(1i*pi/6) 0.1*exp(-1i*pi/8)];
EbN0 = 20;

QPSK 変調されたシンボルを生成します。シンボルに遅延したマルチパス チャネルのフィルター処理と AWGN 障害を適用します。

data = randi([0 M-1], numSymbols, 1);
tx = pskmod(data, M, pi/4);
rx = awgn(filter(chtaps,1,tx),25,'measured');

CMA アルゴリズムを使用するように構成された線形イコライザー System object を作成し、AdaptWeights プロパティを falseInitialWeightsSource プロパティを Property に設定します。MMSE 重みを計算します。初期タップ重みを計算された MMSE 重みに設定します。劣化したシンボルをイコライズします。

eq = comm.LinearEqualizer('Algorithm','CMA','AdaptWeights',false,'InitialWeightsSource','Property')
eq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'CMA'
                  NumTaps: 5
                 StepSize: 0.0100
            Constellation: [1x4 double]
    InputSamplesPerSymbol: 1
       AdaptWeightsSource: 'Property'
             AdaptWeights: false
     InitialWeightsSource: 'Property'
           InitialWeights: [5x1 double]
       WeightUpdatePeriod: 1

wgts = mmseweights(eq,chtaps,EbN0)
wgts = 5×1 complex

   0.0005 - 0.0068i
   0.0103 + 0.0117i
   0.9694 - 0.0019i
  -0.3987 + 0.2186i
   0.0389 - 0.1756i

eq.InitialWeights = wgts;

[y,err,weights] = eq(rx);

劣化したシンボルとイコライズされたシンボルのコンスタレーションをプロットします。

constell = comm.ConstellationDiagram('NumInputPorts',2);
constell(rx,y)

イコライザーの誤差信号をプロットし、イコライズされたシンボルのエラー ベクトル振幅を計算します。

plot(abs(err))
grid on; xlabel('Symbols'); ylabel('|e|')

errevm = comm.EVM;
evm = errevm(tx,y)
evm = 140.6177

イコライザーのタップ重みをプロットします。

subplot(3,1,1); stem(real(weights)); ylabel('real(weights)'); xlabel('Tap'); grid on; axis([1 8 -0.5 1])
line([eq.NumTaps+0.5 eq.NumTaps+0.5], [-0.5 1], 'Color', 'r', 'LineWidth', 1)
title('Equalizer Tap Weights')
subplot(3,1,2); stem(imag(weights)); ylabel('imag(weights)'); xlabel('Tap'); grid on; axis([1 8 -0.5 1])
line([eq.NumTaps+0.5 eq.NumTaps+0.5], [-0.5 1], 'Color', 'r', 'LineWidth', 1)
subplot(3,1,3); stem(abs(weights)); ylabel('abs(weights)'); xlabel('Tap'); grid on; axis([1 8 -0.5 1])
line([eq.NumTaps+0.5 eq.NumTaps+0.5], [-0.5 1], 'Color', 'r', 'LineWidth', 1)

詳細

すべて展開する

アルゴリズム

すべて展開する

拡張機能

C/C++ コード生成
MATLAB® Coder™ を使用して C および C++ コードを生成します。

R2019a で導入