Vorwärtsfehlerkorrektur bei einem 16-QAM-Signal verwenden
Dieses Beispiel erweitert das Beispiel Impulsformung bei einem 16-QAM-Signal verwenden so, dass die Leistungsverbesserung der BER (Bit Error Rate, Bitfehlerrate) bei Verwendung der Vorwärtsfehlerkorrektur-Codierung (Forward Error Correction, FEC) angezeigt wird.
Dieses Beispiel veranschaulicht, wie mithilfe einer Kommunikationsverbindung, die aus einem Basisband-Modulator, einem Kanal, einem Demodulator, Impulsformung, Raised-Cosine-Filterung und Fehlerkorrektur besteht, ein Binärdatenstrom verarbeitet wird.
Simulationsumgebung einrichten
In diesem Beispiel wird, um eine genauere BER-Schätzung zu erreichen, die Anzahl der zu verarbeitenden Bits gegenüber dem im Beispiel Impulsformung bei einem 16-QAM-Signal verwenden verwendeten Wert erhöht. Die anderen Simulationsvariablen stimmen mit den Einstellungen in jenem Beispiel überein.
Definieren Sie die Simulationsparameter für ein 16-QAM-Modulationsschema mit Raised-Cosine-Filterung und einem AWGN-Kanal.
M = 16; % Modulation order k = log2(M); % Bits per symbol numBits = k*2.5e5; % Total bits to process sps = 4; % Samples per symbol (oversampling factor) filtlen = 10; % Filter length in symbols rolloff = 0.25; % Filter rolloff factor
Zufallsdaten generieren
Verwenden Sie die Funktion rng
mit ihren Standardeinstellungen oder legen Sie einen statischen Startwert fest, damit das Beispiel wiederholbare Ergebnisse generiert. Verwenden Sie anschließend die Funktion randi
, um zufällige binäre Daten zu generieren.
rng default; % Use default random number generator dataIn = randi([0 1],numBits,1); % Generate vector of binary data
Faltungscodierung anwenden
Um Fehler, die durch den mit Rauschen behafteten Kanal entstehen, zu korrigieren, wenden Sie vor Übertragung und Viterbi-Decodierung der empfangenen Daten eine Faltungscodierung auf die Daten an. Der Decoder verwendet einen Algorithmus mit fester Entscheidung, was bedeutet, dass jedes empfangene Datenbit als 0
oder 1
interpretiert wird.
Definieren Sie mit der Funktion poly2trellis
ein Faltungscodierungsgitter (Trellis) für eine Coderate von 2/3. Dieses definierte Gitter stellt den Faltungscode dar, der durch die Funktion convenc
für die Codierung des binären Vektors dataIn
verwendet wird.
constrlen = [5 4]; % Code constraint length genpoly = [23 35 0; 0 5 13] % Generator polynomials
genpoly = 2×3
23 35 0
0 5 13
tPoly = poly2trellis(constrlen,genpoly); codeRate = 2/3;
Codieren Sie mit dem tPoly
-Gitter die Eingabedaten.
dataEnc = convenc(dataIn,tPoly);
Daten modulieren
Verwenden Sie die Funktion bit2int
, um die als k
-Tupel codierten binären Daten in einen ganzzahligen Wert zu konvertieren.
dataSymbolsIn = bit2int(dataEnc,k);
Verwenden Sie die Funktion qammod
, um eine 16-QAM-Modulation anzuwenden.
dataMod = qammod(dataSymbolsIn,M);
Raised-Cosine-Filterung anwenden
Verwenden Sie die Funktion rcosdesign
, um einen RRC-Filter zu erstellen.
rrcFilter = rcosdesign(rolloff,filtlen,sps);
Verwenden Sie die Funktion upfirdn
, um ein Upsampling des Signals um den Oversampling-Faktor durchzuführen und den RRC-Filter anzuwenden. Die Funktion upfirdn
füllt nach dem Upsampling das Signal am Ende mit Nullen auf, um den Filter zu füllen. Danach wendet die Funktion den Filter an.
txSignal = upfirdn(dataMod,rrcFilter,sps,1);
AWGN-Kanal anwenden
Konvertieren Sie mit der Anzahl der Bits pro Symbol (k
) und der Anzahl der Abtastungen pro Symbol (sps
) das Verhältnis der Energie pro Bit zur Spektraldichte der Rauschleistung (EbNo
) in einen SNR-Wert für die Verwendung durch die Funktion awgn
. Beim Konvertieren von in SNR müssen Sie die Anzahl der Informationsbits pro Symbol berücksichtigen. Ohne angewendete FEC entsprach jedes Symbol genau k
Bits. Mit angewendeter FEC entspricht jedes Symbol genau (k
codeRate
) Informationsbits. Bei der Coderate von 2/3 und den 16-QAM-Übertragungen, die in diesem Beispiel verwendet werden, entsprechen drei Symbole genau 12 codierten Bits und 8 nicht codierten (Informations-)Bits.
EbNo = 10; snr = EbNo+10*log10(k*codeRate)-10*log10(sps);
Leiten Sie das gefilterte Signal durch einen AWGN-Kanal.
rxSignal = awgn(txSignal,snr,'measured');
Signal empfangen und demodulieren
Filtern Sie mit dem RRC-Filter das empfangene Signal. Entfernen Sie einen Teil des Signals, um die Filterverzögerung zu berücksichtigen.
rxFiltSignal = ... upfirdn(rxSignal,rrcFilter,1,sps); % Downsample and filter rxFiltSignal = ... rxFiltSignal(filtlen + 1:end - filtlen); % Account for delay
Verwenden Sie die Funktion qamdemod
, um das empfangene gefilterte Signal zu demodulieren.
dataSymbolsOut = qamdemod(rxFiltSignal,M);
Viterbi-Decodierung anwenden
Verwenden Sie die Funktion int2bit
, um die wiederhergestellten ganzzahligen Symbole in binäre Daten zu konvertieren.
codedDataOut = int2bit(dataSymbolsOut,k); % Return data in column vector
Verwenden Sie die Funktion vitdec
, die für feste Entscheidungen und kontinuierlichen Betrieb konfiguriert wurde, um die faltungscodierten Daten zu decodieren. Im kontinuierlichen Betrieb bleibt der interne Zustand erhalten, wenn der Decoder wiederholt aufgerufen wird, wie zum Beispiel beim Empfang von Datenframes beim Durchlaufen einer Schleife. Im kontinuierlichen Betrieb kommt es auch zu einer zusätzlichen Verzögerung im System. Obwohl in diesem Beispiel keine Schleife verwendet wird, wird der Modus 'cont
' verwendet, um zu veranschaulichen, wie die Verzögerung in dieser Decodierungsoperation kompensiert wird.
traceBack = 16; % Decoding traceback length numCodeWords = ... floor(length(codedDataOut)*2/3); % Number of complete codewords dataOut = ... vitdec(codedDataOut(1:numCodeWords*3/2), ... tPoly,traceBack,'cont','hard'); % Decode data
BER des Systems berechnen
Die durch die zwei RRC-Sende- und -Empfangsfilter verursachte Verzögerung wird in den wiederhergestellten Daten bereits berücksichtigt, die Decoder-Verzögerung allerdings noch nicht. Im kontinuierlichen Betrieb des Viterbi-Decoders entsteht eine Verzögerung mit einer Bitdauer, die der Traceback-Länge, traceBack
, multipliziert mit der Anzahl der Eingabedatenströme am Codierer entspricht. Da bei der Coderate von 2/3, die in diesem Beispiel verwendet wird, der Codierer zwei Eingabedatenströme hat, beträgt die Verzögerung 2 × traceBack
Bits. Deshalb sind die ersten 2 × traceBack
Bits im decodierten Vektor dataOut
Nullen. Beim Berechnen der BER müssen Sie die ersten 2 × traceBack
Bits in dataOut
und die letzten 2 × traceBack
Bits im ursprünglichen Vektor dataIn
löschen.
Verwenden Sie die Funktion biterr
, um die Anzahl der Fehler und die BER durch den Vergleich von dataIn
und dataOut
zu berechnen. Bei demselben von 10 dB treten weniger Fehler auf, wenn FEC in der Verarbeitungskette enthalten ist.
decDelay = 2*traceBack; % Decoder delay, in bits [numErrors,ber] = ... biterr(dataIn(1:end - decDelay),dataOut(decDelay + 1:end)); fprintf('\nThe bit error rate is %5.2e, based on %d errors.\n', ... ber,numErrors)
The bit error rate is 4.30e-05, based on 43 errors.
Weitere Informationen zu Verzögerungen
Die Decodierungsoperation in diesem Beispiel verursacht eine Verzögerung, die dazu führt, dass die Ausgabe des Decoders hinter der Eingabe zurückliegt. In diesem Beispiel gibt es keine expliziten Informationen zum zeitlichen Ablauf. Außerdem hängt die Dauer der Verzögerung von den ausgeführten Operationen ab. Verzögerungen treten in verschiedenen Operationen eines Kommunikationssystems auf, wie zum Beispiel Faltungsdecodierung, Faltungsverflechtung und -entflechtung, Ausgleich und Filterung. Die Dauer der Verzögerung, die durch bestimmte Funktionen oder Operationen verursacht wird, finden Sie in der Dokumentation für die betreffenden Funktionen bzw. Operationen. Weitere Informationen zu Verzögerungen finden Sie unter Delays of Convolutional Interleavers und Fading Channels.