first pass at fuzzy quantiser, getting good perf from 5 bit quantiser compared to...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 17 Apr 2014 04:59:23 +0000 (04:59 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 17 Apr 2014 04:59:23 +0000 (04:59 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1496 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fuzzy_gray.m

index 3a4eb1d124b443f5964e763ac522a3fc2db59022..abb9e12e6f7314efb11cce596dcf1cc5f646d4cd 100644 (file)
@@ -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;