building up fuzzy codeword idea
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 17 Apr 2014 01:22:46 +0000 (01:22 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 17 Apr 2014 01:22:46 +0000 (01:22 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1495 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fuzzy_gray.m [new file with mode: 0644]

diff --git a/codec2-dev/octave/fuzzy_gray.m b/codec2-dev/octave/fuzzy_gray.m
new file mode 100644 (file)
index 0000000..3a4eb1d
--- /dev/null
@@ -0,0 +1,165 @@
+% fuzzy_gray.m
+% David Rowe
+% 10 April 2014
+%
+% Experiments in fuzzy gray codes.  Idea is that with one bit error
+% in the codeword only changes the encoded value by at most 1.
+
+1;
+
+function three_bit_code
+    m=4;
+    log2_m=2;
+    value_to_codeword = ["000"; "001"; "101"; "111"];
+    codeword_to_value = [0 1 1 2 1 2 2 3 3];
+
+    printf("tx_value tx_codeword rx_codeword rx_value distance\n");
+    for i=1:m
+        tx_codeword = bin2dec(value_to_codeword(i,:));
+        tx_codeword_bin = value_to_codeword(i,:);
+        rx_value = codeword_to_value(tx_codeword+1);
+        distance = abs((i-1) - rx_value);
+        printf("%8d %11s %11s %8d %8d\n", i-1, tx_codeword_bin, tx_codeword_bin, ...
+               rx_value, distance );
+    end
+    printf("\n");
+    for i=1:m
+        tx_codeword = bin2dec(value_to_codeword(i,:));
+        tx_codeword_bin = value_to_codeword(i,:);
+        for j=1:(log2_m+1)
+            rx_codeword = bitxor(tx_codeword, bitset(0,j));
+            rx_codeword_bin = dec2bin(rx_codeword, 3);
+            rx_value = codeword_to_value(rx_codeword+1);
+            distance = abs((i-1) - rx_value);
+            printf("%8d %11s %11s %8d %8d\n", i-1, tx_codeword_bin, rx_codeword_bin, ...
+                   rx_value, distance );
+       end
+    end
+endfunction
+
+function index = quantise_value(value, min_value, max_value, num_levels)
+    norm = (value - min_value)/(max_value - min_value);
+    index = floor(num_levels * norm + 0.5);
+    if (index < 0 ) 
+        index = 0;
+    end
+    if (index > (num_levels-1)) 
+        index = num_levels-1;
+    end
+endfunction
+
+function value = unquantise_value(index, min_value, max_value, num_levels)
+    step  = (max_value - min_value)/num_levels;
+    value = min_value + step*(index);
+endfunction
+
+function gray = binary_to_gray(natural)
+    gray = bitxor(bitshift(natural,-1),natural);
+endfunction
+
+function natural = gray_to_binary(gray)
+    for i=1:length(gray)
+        mask = bitshift(gray(i),-1);
+        num = gray(i);
+        while(mask)
+            num = bitxor(num, mask);
+            mask = bitshift(mask,-1);
+        end
+        natural(i) = num;
+    end
+endfunction
+
+function four_bit_code
+    Ebvec   = 0:7;
+    Ntrials = 10000;
+    Nbits   = 5; Nlevels = 2.^ Nbits; powersOfTwo = 2 .^ fliplr(0:(Nbits-1));
+    Nsymb   = Nbits;
+
+    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_bits = dec2bin(tx_index, Nbits) - '0';
+            tx_symbols = -1 + 2*tx_bits; 
+
+            % 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_bits = rx_symbols > 0;
+
+            error_positions = xor(rx_bits, tx_bits);
+            Nerrs = sum(error_positions);
+            Terrs += Nerrs;
+            Tbits += length(tx_bits);
+
+            rx_index = (powersOfTwo  * rx_bits');
+            rx_value = unquantise_value(rx_index, 0, 1, Nlevels);
+
+            qsignal += tx_value*tx_value;
+            qnoise  += (tx_value - rx_value) .^ 2;
+        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));
+    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)
+    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
+
+function tx_codeword = fuzzy_code_encode(codewords, value)
+endfunction
+
+function value = fuzzy_code_decode(codewords, rx_codeword)
+endfunction
+
+fuzzy_code_create(3,1)