From: drowe67 Date: Thu, 17 Apr 2014 04:59:23 +0000 (+0000) Subject: first pass at fuzzy quantiser, getting good perf from 5 bit quantiser compared to... X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=5b24318db630fced45a0e268e1ef0acc5933ca7e;p=freetel-svn-tracking.git first pass at fuzzy quantiser, getting good perf from 5 bit quantiser compared to original git-svn-id: https://svn.code.sf.net/p/freetel/code@1496 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/fuzzy_gray.m b/codec2-dev/octave/fuzzy_gray.m index 3a4eb1d1..abb9e12e 100644 --- a/codec2-dev/octave/fuzzy_gray.m +++ b/codec2-dev/octave/fuzzy_gray.m @@ -69,12 +69,12 @@ function natural = gray_to_binary(gray) end endfunction -function four_bit_code - Ebvec = 0:7; - Ntrials = 10000; - Nbits = 5; Nlevels = 2.^ Nbits; powersOfTwo = 2 .^ fliplr(0:(Nbits-1)); +function sim_out = test_baseline_uncoded(Ebvec, Nbits, Ntrials) + Nlevels = 2.^ Nbits; powersOfTwo = 2 .^ fliplr(0:(Nbits-1)); Nsymb = Nbits; + sim_out.qnoise_log = zeros(length(Ebvec),Ntrials); + for ne = 1:length(Ebvec) EbNodB = Ebvec(ne); EbNo = 10^(EbNodB/10); @@ -83,7 +83,7 @@ function four_bit_code Terrs = 0; Tbits = 0; qsignal = qnoise = 0; - + for nn = 1:Ntrials tx_value = rand(1,1); @@ -109,27 +109,16 @@ function four_bit_code qsignal += tx_value*tx_value; qnoise += (tx_value - rx_value) .^ 2; + sim_out.qnoise_log(ne,nn) = tx_value - rx_value; end - TERvec(ne) = Terrs; - BERvec(ne) = Terrs/Tbits; - QSNRvec(ne) = 10*log10(qsignal/qnoise); - printf("EbNo (dB): %3.2f Terrs: %6d BER %1.4f QSNR (dB): %3.2f\n", EbNodB, Terrs, Terrs/Tbits, QSNRvec(ne)); + sim_out.TERvec(ne) = Terrs; + sim_out.BERvec(ne) = Terrs/Tbits; + sim_out.QSNRvec(ne) = 10*log10(qsignal/qnoise); + printf("EbNo (dB): %3.2f Terrs: %6d BER %1.4f QSNR (dB): %3.2f\n", + EbNodB, Terrs, Terrs/Tbits, 10*log10(qsignal/qnoise)); end - figure(1); - clf; - semilogy(Ebvec, BERvec) - xlabel('Eb/N0') - ylabel('BER') - grid("minor") - - figure(2); - clf; - plot(Ebvec, QSNRvec) - xlabel('Eb/N0') - ylabel('SNR') - grid("minor") endfunction function valid_codewords = fuzzy_code_create(ndata,nparity) @@ -157,9 +146,124 @@ function valid_codewords = fuzzy_code_create(ndata,nparity) endfunction function tx_codeword = fuzzy_code_encode(codewords, value) + tx_codeword = codewords(value+1,:); +endfunction + +function value = fuzzy_code_decode(codewords, rx_symbols) + max_corr = 0; + value = 0; + [rows,cols] = size(codewords); + for i=1:rows + corr = (-1 + 2*codewords(i,:)) * transpose(rx_symbols); + if (corr > max_corr) + max_corr = corr; + value = i-1; + end + end endfunction -function value = fuzzy_code_decode(codewords, rx_codeword) +function valid_codewords = fuzzy_code_create(ndata, nparity) + Nbits = ndata + nparity; + Nvalid = 2 .^ ndata; + codewords = binary_to_gray(0:(2 .^ Nbits)-1); + valid_codewords = dec2bin(codewords(1:2:(2 .^ Nbits)), Nbits) - '0'; + + % check all valid codewords have a hamming distance of at least 2^nparity + + bad_distance = 0; + for i=1:Nvalid + for k=i+1:Nvalid + distance = sum(bitxor(valid_codewords(i,:), valid_codewords(k,:))); + if distance < 2 + bad_distance++; + end + end + end + if bad_distance != 0 + printf("Error: Nvalid: %d bad_distance: %d\n", Nvalid, bad_distance); + return; + end + endfunction -fuzzy_code_create(3,1) + +function sim_out = test_fuzzy_code(Ebvec, Ndata, Ntrials) + Nparity = 1; + Nbits = Ndata + Nparity; + Nlevels = 2 .^ Ndata; + Nsymb = Nbits; + powersOfTwo = 2 .^ fliplr(0:(Nbits-1)); + + codewords = fuzzy_code_create(Ndata,Nparity); + sim_out.qnoise_log = zeros(length(Ebvec), Ntrials); + + for ne = 1:length(Ebvec) + EbNodB = Ebvec(ne); + EbNo = 10^(EbNodB/10); + + variance = 1/EbNo; + + Terrs = 0; Tbits = 0; + qsignal = qnoise = 0; + + for nn = 1:Ntrials + + tx_value = rand(1,1); + tx_index = quantise_value(tx_value, 0, 1, Nlevels); + tx_codeword = fuzzy_code_encode(codewords, tx_index); + tx_symbols = -1 + 2*tx_codeword; + + % AWGN noise and phase/freq offset channel simulation + % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im + + noise = sqrt(variance*0.5)*(randn(1,Nsymb) + j*randn(1,Nsymb)); + rx_symbols = tx_symbols + noise; + + rx_index = fuzzy_code_decode(codewords, rx_symbols); + rx_value = unquantise_value(rx_index, 0, 1, Nlevels); + + qsignal += tx_value*tx_value; + qnoise += (tx_value - rx_value) .^ 2; + sim_out.qnoise_log(ne,nn) = tx_value - rx_value; + end + + sim_out.QSNRvec(ne) = 10*log10(qsignal/qnoise); + printf("EbNo (dB): %3.2f QSNR (dB): %3.2f\n", EbNodB, sim_out.QSNRvec(ne)); + end +endfunction + +Ebvec = 0:7; +Ntrials = 1000; +Nbits = 5; + +baseline = test_baseline_uncoded(Ebvec, Nbits, Ntrials); +fuzzy = test_fuzzy_code(Ebvec, Nbits, Ntrials); + +figure(1); +clf; +semilogy(Ebvec, baseline.BERvec) +xlabel('Eb/N0') +ylabel('BER') +grid("minor") + +figure(2); +clf; +plot(Ebvec, baseline.QSNRvec,'b;baseline;') +hold on; +plot(Ebvec, fuzzy.QSNRvec,'r;fuzzy;') +hold off; +xlabel('Eb/N0') +ylabel('SNR') +grid("minor") + +figure(3); +subplot(211) +hist(baseline.qnoise_log(4,:),50); +subplot(212) +hist(fuzzy.qnoise_log(4,:),50); + +figure(4) +plot(baseline.qnoise_log(4,1:250),'b;baseline;') +hold on; +plot(fuzzy.qnoise_log(4,1:250),'r;fuzzy;') +hold off;