Конкатенированные сверточные коды обеспечивают высокую надежность и получили известность и использование в качестве турбокодов. The comm.TurboEncoder
и comm.TurboDecoder
Системные объекты поддерживают только сверточные коды скорости 1/n. Этот пример показывает параллельную конкатенацию двух сверточных кодов скорости 2/3 для достижения эффективной скорости 1/3 турбокода при помощи comm.ConvolutionalEncoder
и comm.APPDecoder
Системные объекты.
blkLength = 1024; % Block length EbNo = 0:5; % Eb/No values to loop over numIter = 3; % Number of decoding iterations maxNumBlks = 1e2; % maximum number of blocks per Eb/No value
trellis = poly2trellis([5 4],[23 35 0; 0 5 13]); k = log2(trellis.numInputSymbols); % number of input bits n = log2(trellis.numOutputSymbols); % number of output bits intrIndices = randperm(blkLength/k)'; % Random interleaving decAlg = 'True App'; % Decoding algorithm modOrder = 2; % PSK-modulation order
Инициализируйте объект Systems для сверточного кодирования, декодирования APP, модуляции и демодуляции BPSK, канала AGWN и расчета частоты ошибок. Демодуляция выводит мягкие биты с использованием метода логарифмического отношения логарифмической правдоподобности.
cEnc1 = comm.ConvolutionalEncoder('TrellisStructure',... trellis,'TerminationMethod','Truncated'); cEnc2 = comm.ConvolutionalEncoder('TrellisStructure',... trellis,'TerminationMethod','Truncated'); cAPPDec1 = comm.APPDecoder('TrellisStructure',trellis,... 'TerminationMethod','Truncated','Algorithm',decAlg); cAPPDec2 = comm.APPDecoder('TrellisStructure',trellis,... 'TerminationMethod','Truncated','Algorithm',decAlg); bpskMod = comm.BPSKModulator; bpskDemod = comm.BPSKDemodulator('DecisionMethod','Log-likelihood ratio', ... 'VarianceSource','Input port'); awgnChan = comm.AWGNChannel('NoiseMethod','Variance', ... 'VarianceSource','Input port'); bitError = comm.ErrorRate; % BER measurement
Цикл через область значений значения для генерации результатов для эффективности BER. The helperTurboEnc
и helperTurboDec
вспомогательные функции выполняют турбокодирование и декодирование.
ber = zeros(length(EbNo),1); bitsPerSymbol = log2(modOrder); turboEncRate = k/(2*n); for ebNoIdx = 1:length(EbNo) % Calculate the noise variance from EbNo EsNo = EbNo(ebNoIdx) + 10*log10(bitsPerSymbol); SNRdB = EsNo + 10*log10(turboEncRate); % Account for code rate noiseVar = 10^(-SNRdB/10); for numBlks = 1:maxNumBlks % Generate binary data data = randi([0 1],blkLength,1); % Turbo encode the data [encodedData,outIndices] = helperTurboEnc(data,cEnc1,cEnc2, ... trellis,blkLength,intrIndices); % Modulate the encoded data modSignal = bpskMod(encodedData); % Pass the modulated signal through an AWGN channel receivedSignal = awgnChan(modSignal,noiseVar); % Demodulate the noisy signal using LLR to output soft bits demodSignal = bpskDemod(receivedSignal,noiseVar); % Turbo decode the demodulated data receivedBits = helperTurboDec(-demodSignal,cAPPDec1,cAPPDec2, ... trellis,blkLength,intrIndices,outIndices,numIter); % Calculate the error statistics errorStats = bitError(data,receivedBits); end ber(ebNoIdx) = errorStats(1); reset(bitError); end
Хотя практичные беспроводные системы, такие как LTE и CCSDS, задают сверточные коды базовой скорости-1/n для турбокодов, результаты показывают, что использование сверточных кодов более высокой скорости в качестве турбокодов жизнеспособно.
figure; semilogy(EbNo, ber, '*-'); grid on; xlabel('E_b/N_0 (dB)'); ylabel('BER'); title('High Rate Convolutional Codes for Turbo Coding'); legend(['N = ' num2str(blkLength) ', ' num2str(numIter) ' iterations']);
function [yEnc,outIndices] = helperTurboEnc(data,hCEnc1,hCEnc2,trellis,blkLength,intrIndices) % Turbo encoding using two parallel convolutional encoders. % No tail bits handling and assumes no output stream puncturing. % Trellis parameters k = log2(trellis.numInputSymbols); n = log2(trellis.numOutputSymbols); cLen = blkLength*n/k; punctrVec = [0;0;0;0;0;0]; % assumes all streams are output N = length(find(punctrVec==0)); % Encode random data bits y1 = step(hCEnc1, data); y2 = step(hCEnc2, reshape(intrlv(reshape(data, k, [])',intrIndices)', [], 1)); y1D = reshape(y1(1:cLen), n, []); y2D = reshape(y2(1:cLen), n, []); yDTemp = [y1D; y2D]; y = yDTemp(:); % Generate output indices vector using puncturing vector idx = 0 : 2*n : (blkLength - 1)*2*(n/k); punctrVecIdx = find(punctrVec==0); dIdx = repmat(idx, N, 1) + punctrVecIdx; outIndices = dIdx(:); yEnc = y(outIndices); end function yDec = helperTurboDec(yEnc,cAPPDec1,cAPPDec2,trellis,blkLength,intrIndices,inIndices,numIter) % Turbo decoding using two a-posteriori probability (APP) decoders % Trellis parameters k = log2(trellis.numInputSymbols); n = log2(trellis.numOutputSymbols); rCodLen = 2*(n/k)*blkLength; typeyEnc = class(yEnc); % Re-order encoded bits according to outIndices x = zeros(rCodLen, 1); x(inIndices) = yEnc; % Generate output of first encoder yD = reshape(x(1:rCodLen), 2*n, []); lc1D = yD(1:n, :); Lc1_in = lc1D(:); % Generate output of second encoder lc2D = yD(n+1:2*n, :); Lc2_in = lc2D(:); % Initialize unencoded data input Lu1_in = zeros(blkLength, 1, typeyEnc); % Turbo Decode out1 = zeros(blkLength/k, k, typeyEnc); for iterIdx = 1 : numIter [Lu1_out, ~] = step(cAPPDec1, Lu1_in, Lc1_in); tmp = Lu1_out(1:blkLength); Lu2_in = reshape(tmp, k, [])'; [Lu2_out, ~] = step(cAPPDec2, ... reshape(Lu2_in(intrIndices, :)', [], 1), Lc2_in); out1(intrIndices, :) = reshape(Lu2_out(1:blkLength), k, [])'; Lu1_in = reshape(out1', [], 1); end % Calculate llr and decoded bits for the final iteration llr = reshape(out1', [], 1) + Lu1_out(1:blkLength); yDec = cast((llr>=0), typeyEnc); end