modified sstv test frames to match Pythn tx code bit<->byte ordering
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 20 Oct 2016 05:22:30 +0000 (05:22 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 20 Oct 2016 05:22:30 +0000 (05:22 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2894 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/ldpc_fsk_lib.m
codec2-dev/octave/test_ldpc_fsk_lib.m

index d45c19af9a90c6853441cbbf2631bd9503350636..db3e6353804cb9fb616968870453d5a17546d059 100644 (file)
@@ -270,21 +270,35 @@ function frame_rs232 = gen_sstv_frame
 \r
   % unpack bytes to bits and LPDC encode\r
 \r
-  mask = 2.^(0:7);          % LSB to MSB\r
+  mask = 2.^(7:-1:0);       % MSB to LSB unpacking to match python tx code.\r
   unpacked_data = [];\r
   for b=1:length(data)\r
     unpacked_data = [unpacked_data bitand(data(b), mask) > 0];\r
   end\r
-  codeword = ldpc_encode(code_param, unpacked_data);\r
+  codeword = [ldpc_encode(code_param, unpacked_data) 0 0 0 0];  % pad with 0s to get integer number of bytes\r
+\r
+  % pack back into bytes to match python code \r
+\r
+  lpacked_codeword = length(codeword)/8\r
+  packed_codeword = zeros(1,lpacked_codeword);\r
+  for b=1:lpacked_codeword\r
+    st = (b-1)*8 + 1;\r
+    packed_codeword(b) = sum(codeword(st:st+7) .* mask);\r
+  end\r
 \r
-  % generate unpacked header bits\r
+  % generate header bits\r
 \r
   header = [hex2dec('55')*ones(1,16) hex2dec('ab') hex2dec('cd') hex2dec('ef') hex2dec('01')];\r
-  unpacked_header = [];\r
-  for b=1:length(header)\r
-    unpacked_header = [unpacked_header bitand(header(b), mask) > 0];\r
+\r
+  % now construct entire unpacked frame\r
+\r
+  packed_frame = [header packed_codeword];\r
+  mask = 2.^(0:7);        % LSB to MSB packing for header\r
+  lpacked_frame = length(packed_frame);\r
+  frame = [];\r
+  for b=1:lpacked_frame\r
+    frame = [frame bitand(packed_frame(b), mask) > 0];\r
   end\r
-  frame = [unpacked_header codeword 0 0 0 0]; % integer number of bytes\r
 \r
   % insert rs232 framing bits\r
 \r
@@ -292,6 +306,8 @@ function frame_rs232 = gen_sstv_frame
   for b=1:8:length(frame)\r
     frame_rs232 = [frame_rs232 0 frame(b:b+7) 1];\r
   end\r
+\r
+  %printf("codeword: %d unpacked_header: %d frame: %d frame_rs232: %d \n", length(codeword), length(unpacked_header), length(frame), length(frame_rs232));\r
 endfunction\r
 \r
 \r
index 8f9ddb7e6004bc26e2dc27f8e3f84aed286ea399..e5109cdd1218f1563f374428b29894a2eb661e0d 100644 (file)
@@ -309,7 +309,7 @@ function [n_uncoded_errs n_uncoded_bits] = run_sstv_sim(sim_in, EbNodB)
   % note fixed frame of bits used for BER testing\r
 \r
   tx_codeword = gen_sstv_frame;\r
-\r
+  \r
   % init FSK modem\r
 \r
   fsk_horus_as_a_lib = 1;\r
@@ -318,6 +318,7 @@ function [n_uncoded_errs n_uncoded_bits] = run_sstv_sim(sim_in, EbNodB)
   states.df(1:states.M) = 0;\r
   states.dA(1:states.M) = 1;\r
   states.tx_real = 0;  % Octave fsk_mod generates complex valued output\r
+                       % so we can simulate rtl_sdr complex ouput\r
 \r
   % Set up simulated tx tones to sit in the middle of cdsr passband\r
 \r
@@ -337,9 +338,13 @@ function [n_uncoded_errs n_uncoded_bits] = run_sstv_sim(sim_in, EbNodB)
 \r
   tx_bit_stream = [];\r
   for i=1:frames\r
+    % uncomment for different data on each frame\r
+    %tx_codeword = gen_sstv_frame;\r
     tx_bit_stream = [tx_bit_stream tx_codeword];\r
   end\r
 \r
+  printf("%d bits at %d bit/s is a %3.1f second run\n", length(tx_bit_stream), 115200,length(tx_bit_stream)/115200);\r
\r
   % modulate and channel model\r
 \r
   tx = fsk_horus_mod(states, tx_bit_stream);\r
@@ -378,7 +383,9 @@ function [n_uncoded_errs n_uncoded_bits] = run_sstv_sim(sim_in, EbNodB)
 \r
         % demodulate to stream of bits\r
 \r
-        states.f = [f1 f2];\r
+        states.f = [f1 f2]; % note that for Octave demod we cheat and use known tone frequencies\r
+                            % allows us to determine if freq offset estimation in C demod is a problem\r
+\r
         [rx_bits states] = fsk_horus_demod(states, sf);\r
         rx_bit_stream = [rx_bit_stream rx_bits];\r
         rx_sd_stream = [rx_sd_stream states.rx_bits_sd];\r
@@ -520,6 +527,93 @@ function [n_uncoded_errs n_uncoded_bits] = run_sstv_sim(sim_in, EbNodB)
 \r
 endfunction\r
 \r
+\r
+% Function to test flight mode software.  Takes a rx stream of\r
+% demodulated bits, and locates frames using UW detection.  Extracts\r
+% data and parity bits.  Uses data bits to generate parity bits here\r
+% and compare.\r
+\r
+function compare_parity_bits(rx_bit_stream)\r
+    nframes = 2;\r
+\r
+    % init LDPC code\r
+\r
+    load('H2064_516_sparse.mat');\r
+    HRA = full(HRA);  \r
+    max_iterations = 100;\r
+    decoder_type = 0;\r
+    mod_order = 2;\r
+\r
+    code_param = ldpc_init(HRA, mod_order);\r
+\r
+    % generate frame, this will have random bits not related to\r
+    % rx_stream, however we just use it for the UW\r
+\r
+    tx_codeword = gen_sstv_frame;\r
+    l = length(tx_codeword);\r
+    printf("expected rs232 frames codeword length: %d\n", l);\r
+\r
+    % state machine. Look for SSTV UW.  When found count bit errors over one frame of bits\r
+\r
+    state = "wait for uw";\r
+    start_uw_ind = 16*10+1; end_uw_ind = start_uw_ind + 4*10 - 1;\r
+    uw_rs232 = tx_codeword(start_uw_ind:end_uw_ind); luw = length(uw_rs232);\r
+    start_frame_ind =  end_uw_ind + 1;\r
+    nbits = nframes*l;\r
+    uw_thresh = 5;\r
+    n_uncoded_errs = 0;\r
+    n_uncoded_bits = 0;\r
+    n_packets_rx = 0;\r
+    last_i = 0;\r
+\r
+    % might as well include RS232 framing bits in uncoded error count\r
+\r
+    uw_errs = luw*ones(1, nbits);\r
+    for i=luw:nbits\r
+      uw_errs(i) = sum(xor(rx_bit_stream(i-luw+1:i), uw_rs232));\r
+    end\r
+\r
+    frame_start = find(uw_errs < 6)+1;\r
+    nframes = length(frame_start);\r
+    for i=1:nframes\r
+\r
+      % double check UW OK\r
+\r
+      st_uw = frame_start(i) - luw; en_uw = frame_start(i) - 1;\r
+      uw_err_check = sum(xor(rx_bit_stream(st_uw:en_uw), uw_rs232));\r
+      printf("uw_err_check: %d\n", uw_err_check);\r
+\r
+      % strip off rs232 start/stop bits\r
+\r
+      nbits_rs232 = (256+2+65)*10;\r
+      nbits = (256+2+65)*8\r
+      nbits_byte = 10;\r
+      rx_codeword = zeros(1,nbits);\r
+      pdb = 1;\r
+\r
+      for k=1:nbits_byte:nbits_rs232\r
+        for l=1:8\r
+          rx_codeword(pdb) = rx_bit_stream(frame_start(i)-1+k+l);\r
+          pdb++;\r
+        end\r
+      end\r
+      assert(pdb == (nbits+1));\r
+      \r
+      data_bits = rx_codeword(1:256*8);\r
+      checksum_bits = rx_codeword(256*8+1:258*8);\r
+      parity_bits = rx_codeword(258*8+1:258*8+516);\r
+      padding_bits = rx_codeword(258*8+516+1:258*8+516+1);\r
+\r
+      % stopped here as we found bug lol!\r
+    end\r
+\r
+    figure(1); clf;\r
+    plot(uw_errs);\r
+    title('Unique Word Hamming Distance')\r
+\r
+endfunction\r
+\r
+\r
 % Start simulation --------------------------------------------------------\r
 \r
 more off;\r
@@ -704,7 +798,16 @@ end
 \r
 if demo == 11\r
   sim_in.frames = 100;\r
-  EbNodB = 13;\r
+  EbNodB = 7;\r
   sim_in.demod_type = 5;\r
   run_sstv_sim(sim_in, EbNodB);\r
 end\r
+\r
+\r
+% Compare parity bits from an off-air stream of demodulated bits\r
+\r
+if demo == 12\r
+  f = fopen("fsk_demod.bin","rb"); rx_bit_stream = fread(f, "uint8")'; fclose(f);\r
+\r
+  compare_parity_bits(rx_bit_stream);\r
+end\r