found some freq offsets that caused false syncs. Wrote ofdm_dev function to explore...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 8 May 2018 10:38:50 +0000 (10:38 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 8 May 2018 10:38:50 +0000 (10:38 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3584 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/ofdm_dev.m
codec2-dev/octave/ofdm_ldpc_rx.m
codec2-dev/octave/ofdm_ldpc_tx.m
codec2-dev/octave/ofdm_lib.m
codec2-dev/octave/ofdm_load_const.m
codec2-dev/octave/ofdm_rx.m
codec2-dev/octave/tofdm.m

index 1d47f882cfc0c7dd1893a73f4aa7f64fdff5e692..7c8be03bbaed3c5bbde6b71d9e9d033f0d9772b5 100644 (file)
@@ -112,14 +112,15 @@ function [sim_out rx states] = run_sim(sim_in)
     HRA = sim_in.ldpc_code;
     [aNr aNc] = size(HRA);
     rate = states.rate = (aNc-aNr)/aNc;
-    assert(aNc == Nbitsperframe, "Dude: Num cols of LDPC HRA must == Nbitsperframe");
+    Ndatabitsperframe = Nbitsperframe;
+    assert(aNc == Ndatabitsperframe, "Dude: Num cols of LDPC HRA must == Nbitsperframe");
     [H_rows, H_cols] = Mat2Hrows(HRA); 
     code_param.H_rows = H_rows; 
     code_param.H_cols = H_cols;
     code_param.P_matrix = [];
     code_param.data_bits_per_frame = length(code_param.H_cols) - length( code_param.P_matrix ); 
     code_param.code_bits_per_frame = aNc;
-    assert(aNr == Nbitsperframe*rate);
+    assert(aNr == Ndatabitsperframe*rate);
 
     modulation = states.ldpc_modulation = 'QPSK';
     mapping = states.ldpc_mapping = 'gray';
@@ -200,6 +201,9 @@ function [sim_out rx states] = run_sim(sim_in)
       else
         % uncoded mode
         codeword = tx_data_bits(st:en);
+        if isfield(sim_in, "uw_debug")
+          codeword(states.uw_ind) = states.tx_uw;
+        end
       end
       tx_bits = [tx_bits codeword];
       for b=1:2:Nbitsperframe
@@ -294,7 +298,8 @@ function [sim_out rx states] = run_sim(sim_in)
     Nerrs_log = []; Nerrs_coded_log = [];
     rx_bits = []; rx_np = []; rx_amp = [];
     sig_var_log = []; noise_var_log = [];
-
+    uw_errors_log = [];
+    
     % reset some states for each EbNo simulation point
 
     states.sample_point = states.timing_est = 1;
@@ -328,6 +333,17 @@ function [sim_out rx states] = run_sim(sim_in)
      
       rx_bits = [rx_bits arx_bits]; rx_np = [rx_np arx_np]; rx_amp = [rx_amp arx_amp];
 
+      % note: only supported in ldpc_en = 0 Nc=17 atm, see debug_false_sync()
+      
+      if isfield(sim_in, "uw_debug") 
+        rx_uw = arx_bits(states.uw_ind);
+        uw_errors = sum(xor(states.tx_uw,rx_uw));
+        if verbose
+          printf("f: %d uw_errors: %d\n", f, uw_errors);
+        end
+        uw_errors_log = [uw_errors_log uw_errors];
+      end
+      
       timing_est_log = [timing_est_log states.timing_est];
       delta_t_log = [delta_t_log states.delta_t];
       foff_est_hz_log = [foff_est_hz_log states.foff_est_hz];
@@ -463,6 +479,8 @@ function [sim_out rx states] = run_sim(sim_in)
         sim_out.per(nn) = Tpacketerrs/Tpackets; 
       end
     end
+
+    sim_out.uw_errors_log = uw_errors_log;
     
     % Optional plots, mostly used with run-single
 
@@ -573,7 +591,6 @@ function run_single(EbNodB = 100, error_pattern_filename);
   sim_in.ldpc_en = 1;
 
   sim_in.interleave_frames = 1;
-
   %sim_in.diversity_en = 1;
 
   sim_out = run_sim(sim_in);
@@ -1199,6 +1216,51 @@ function sync_metrics(x_axis = 'EbNo')
 endfunction
 
 
+% during development it was discovered demod could obtain a flase sync with no UW
+% errors at +/- 7Hz, approx the frame rate.  This function is used to explore that
+
+function debug_false_sync(EbNodB = 100)
+  Ts = 0.018; 
+  sim_in.Tcp = 0.002; 
+  sim_in.Rs = 1/Ts; sim_in.bps = 2; sim_in.Nc = 17; sim_in.Ns = 8;
+
+  sim_in.Nsec = (sim_in.Ns+1)/sim_in.Rs;  % one frame, make sure sim_in.interleave_frames = 1
+  sim_in.Nsec = 1;
+
+  sim_in.EbNodB = 40;
+  sim_in.verbose = 0;
+  sim_in.hf_en = 0;
+  sim_in.foff_hz = 0;
+  sim_in.dfoff_hz_per_sec = 0.00;
+  sim_in.sample_clock_offset_ppm = 0;
+  sim_in.gain = 1;
+  
+  sim_in.timing_en = 0;
+  sim_in.foff_est_en = 0;
+  sim_in.phase_est_en = 1;
+
+  load HRA_112_112.txt
+  sim_in.ldpc_code = HRA_112_112;
+  sim_in.ldpc_en = 0;
+
+  %sim_in.interleave_frames = 1;
+  %sim_in.diversity_en = 1;
+
+  sim_in.uw_debug = 1;
+
+  foff = -25:0.5:25;
+  for f=1:length(foff)
+    sim_in.foff_hz = foff(f);
+    sim_out = run_sim(sim_in);
+    min_uw_errors(f) = min(sim_out.uw_errors_log(2:end-1));
+    printf("f: %4.2f %2d\n", foff(f), min_uw_errors(f));
+  end
+  figure(1); clf;
+  plot(foff, min_uw_errors);
+  title('UW errors versus freq offset');
+  xlabel('Freq Offset (Hz)');
+end
+
 
 % ---------------------------------------------------------
 % choose simulation to run here 
@@ -1214,7 +1276,9 @@ init_cml('~/cml/');
 %run_curves_estimators
 %acquisition_histograms(fin_en=0, foff_hz=-15, EbNoAWGN=-1, EbNoHF=3)
 %acquisition_test(Ntests=100, EbNodB=-1, foff_hz=-10, hf_en=0)
-sync_metrics('freq')
+%sync_metrics('freq')
 %run_curves_snr
 %acquisition_dev(Ntests=10, EbNodB=100, foff_hz=0)
 %acquistion_curves
+
+debug_false_sync
index 4fedb11d509a9b1fc2dfa69ade80f00fc7e272f8..fe658ab6ff310c4ba95d5befdcb548f5ae88093b 100644 (file)
@@ -93,14 +93,16 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
   Nerrs_coded_log = Nerrs_log = [];
   error_positions = [];
   Nerrs_coded = Nerrs_raw = zeros(1, interleave_frames);
-  
-  % 'prime' rx buf to get correct coarse timing (for now)
 
+  #{
+  % 'prime' rx buf to get correct coarse timing (for now)
+  
   prx = 1;
   nin = Nsamperframe+2*(M+Ncp);
   states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx(prx:nin);
   prx += nin;
-
+  #}
+  
   % main loop ----------------------------------------------------------------
 
   for f=1:Nframes
@@ -125,11 +127,11 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
     if strcmp(states.sync_state,'search') 
       [timing_valid states] = ofdm_sync_search(states, rxbuf_in);
     end
-    
+
     if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial')
       [rx_bits states aphase_est_pilot_log arx_np arx_amp] = ofdm_demod(states, rxbuf_in);
-      rx_uw = rx_bits(1:states.Nuwbits);
-      
+      [rx_uw payload_syms payload_amps txt_bits] = disassemble_modem_frame(states, arx_np, arx_amp);
+           
       % we are in sync so log modem states
 
       rx_np_log = [rx_np_log arx_np];
@@ -144,9 +146,9 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
       % discarding UW and txt symbols at start of each modem frame
 
       rx_np(1:Nsymbolsperinterleavedframe-Nsymbolsperframe) = rx_np(Nsymbolsperframe+1:Nsymbolsperinterleavedframe);
-      rx_np(Nsymbolsperinterleavedframe-Nsymbolsperframe+1:Nsymbolsperinterleavedframe) = arx_np(Nuwtxtsymbolsperframe+1:end);
+      rx_np(Nsymbolsperinterleavedframe-Nsymbolsperframe+1:Nsymbolsperinterleavedframe) = payload_syms;
       rx_amp(1:Nsymbolsperinterleavedframe-Nsymbolsperframe) = rx_amp(Nsymbolsperframe+1:Nsymbolsperinterleavedframe);
-      rx_amp(Nsymbolsperinterleavedframe-Nsymbolsperframe+1:Nsymbolsperinterleavedframe) = arx_amp(Nuwtxtsymbolsperframe+1:end);
+      rx_amp(Nsymbolsperinterleavedframe-Nsymbolsperframe+1:Nsymbolsperinterleavedframe) = payload_amps;
            
       mean_amp = states.mean_amp;
       
index 071106a8c780c4dfea2ec0d55090d8775372e620..0f97502ca5066e46cabba9982c86599616366bfb 100644 (file)
@@ -83,18 +83,19 @@ function ofdm_ldpc_tx(filename, interleave_frames = 1, Nsec, EbNodB=100, channel
   
   % generate UW and txt symbols to prepend to every frame after LDPC encoding and interleaving
  
-  tx_uw_tx_bits = [tx_uw zeros(1,Ntxtbits)];
-  tx_uw_tx_symbols = [];
-  for b=1:2:length(tx_uw_tx_bits)
-    tx_uw_tx_symbols = [tx_uw_tx_symbols qpsk_mod(tx_uw_tx_bits(b:b+1))];
+  txt_bits = zeros(1,Ntxtbits);
+  txt_symbols = [];
+  for b=1:2:length(txt_bits)
+    txt_symbols = [txt_symbols qpsk_mod(txt_bits(b:b+1))];
   end
   
   atx = [];
   for f=1:interleave_frames
     st = (f-1)*code_param.code_bits_per_frame/bps+1; en = st + code_param.code_bits_per_frame/bps-1;
-    atx = [atx ofdm_txframe( states, [tx_uw_tx_symbols tx_symbols(st:en)] ) ];
+    modem_frame = assemble_modem_frame_symbols(states, tx_symbols(st:en), txt_symbols);
+    atx = [atx ofdm_txframe(states, modem_frame) ];
   end
+  
   tx = [];
   for f=1:Nframes/interleave_frames
     tx = [tx atx];
index cb1152124e5730585c326a44c33be519fed32383..b3de59ce24e9f87f9ba8aa2956e89219b6a3c3ed 100644 (file)
@@ -74,7 +74,7 @@ function [t_est timing_valid timing_mx] = est_timing(states, rx, rate_fs_pilot_s
     timing_valid = timing_mx > timing_mx_thresh;
     
     if verbose > 1
-      printf("   mx: %f timing_est: %d timing_valid: %d\n", timing_mx, t_est, timing_valid);
+      printf("  av_level: %f mx: %f timing_est: %d timing_valid: %d\n", av_level, timing_mx, t_est, timing_valid);
     end
 
 endfunction
@@ -108,7 +108,12 @@ function [foff_est states] = est_freq_offset(states, rx, rate_fs_pilot_samples,
     % averaging metric was found to be really important for reliable acquisition at low SNRs
 
     states.foff_metric = 0.9*states.foff_metric + 0.1*(conj(p1)*p2 + conj(p3)*p4);
-    foff_est = Fs1*angle(states.foff_metric)/(2*pi);    
+    foff_est = Fs1*angle(states.foff_metric)/(2*pi);
+
+    if states.verbose > 1
+        printf("  foff_metric: %f %f foff_est: %f\n", real(states.foff_metric), imag(states.foff_metric), foff_est);
+    end
 endfunction
 
 
@@ -137,17 +142,34 @@ function states = ofdm_init(bps, Rs, Tcp, Ns, Nc)
   states.Nbitsperframe = (Ns-1)*Nc*bps;
   states.Nrowsperframe = states.Nbitsperframe/(Nc*bps);
   states.Nsamperframe =  (states.Nrowsperframe+1)*(states.M+states.Ncp);
-  states.Ntxtbits = 4;   % reserve 4 bits/frame for auxillary text information
+  states.Ntxtbits = 4;   % reserved bits/frame for auxillary text information
   states.Nuwbits  = (Ns-1)*bps - states.Ntxtbits;
-  states.tx_uw = [1 0 0 1 0 1 0 0 1 0];
-  assert(length(states.tx_uw) == states.Nuwbits);
 
+  % UW symbol placement, designed to get no false syncs and any freq
+  % offset.  Use ofdm_dev.m, debug_false_sync() to test.  Note we need
+  % to pair the UW bits so the fit into symbols.  The LDPC decoder
+  % work on symbols so we can't break up any symbols into UW/LDPC
+  % bits.
+  
+  states.uw_ind = states.uw_ind_sym = [];
+  for i=1:states.Nuwbits/2
+    states.uw_ind = [states.uw_ind 1+i*(Nc+1) 2+i*(Nc+1)];
+    states.uw_ind_sym = [states.uw_ind_sym i*(Nc+1)/2+1];
+  end
+  states.tx_uw = [0 0 0 0 0 0 0 0 0 0];       
+  assert(length(states.tx_uw) == states.Nuwbits);
+  tx_uw_syms = [];
+  for b=1:2:states.Nuwbits
+    tx_uw_syms = [tx_uw_syms qpsk_mod(states.tx_uw(b:b+1))];
+  end
+  states.tx_uw_syms = tx_uw_syms;
+  
   % use this to scale tx output to 16 bit short.  Adjusted by experiment
   % to have same RMS power as FDMDV waveform
   
   states.amp_scale = 2E5*1.1491/1.06;
 
-  % this is used to scale input sto LDPC decoder to make it amplitude indep
+  % this is used to scale inputto LDPC decoder to make it amplitude indep
   
   states.mean_amp = 0;
 
@@ -392,10 +414,11 @@ function [rx_bits states aphase_est_pilot_log rx_np rx_amp] = ofdm_demod(states,
           
     [ft_est timing_valid timing_mx] = est_timing(states, rxbuf(st:en) .* exp(-j*woff_est*(st:en)), rate_fs_pilot_samples);
 
-    % keep the freq est statistic updated in case we lose sync, not we supply it with uncorrected rxbuf
+    % keep the freq est statistic updated in case we lose sync, note
+    % we supply it with uncorrected rxbuf
+    
+    [coarse_foff_est_hz states] = est_freq_offset(states, rxbuf(st:en), states.rate_fs_pilot_samples, ft_est);
     
-    [unused_foff_est states] = est_freq_offset(states, rxbuf(st:en), states.rate_fs_pilot_samples, ft_est);
-
     if timing_valid
       timing_est = timing_est + ft_est - ceil(ftwindow_width/2);
 
@@ -576,7 +599,102 @@ function [rx_bits states aphase_est_pilot_log rx_np rx_amp] = ofdm_demod(states,
   states.sample_point = sample_point;
   states.delta_t = delta_t;
   states.foff_est_hz = foff_est_hz;
-  states.coarse_foff_est_hz = coarse_foff_est_hz;
+  states.coarse_foff_est_hz = coarse_foff_est_hz; % just used for tofdm
+endfunction
+
+
+% assemble modem frame from UW, payload, and txt bits
+
+function modem_frame = assemble_modem_frame(states, payload_bits, txt_bits)
+  ofdm_load_const;
+
+  modem_frame = zeros(1,Nbitsperframe);
+  p = 1; u = 1;
+
+  for b=1:Nbitsperframe-Ntxtbits;
+    if (u <= Nuwbits) && (b == uw_ind(u))
+      modem_frame(b) = tx_uw(u++);
+    else
+      modem_frame(b) = payload_bits(p++);
+    end  
+  end
+  t = 1;
+  for b=Nbitsperframe-Ntxtbits+1:Nbitsperframe
+    modem_frame(b) = txt_bits(t++);
+  end
+  assert(u == (Nuwbits+1));
+  assert(p = (length(payload_bits)+1));
+endfunction
+
+
+% assemble modem frame from UW, payload, and txt symbols
+
+function modem_frame = assemble_modem_frame_symbols(states, payload_syms, txt_syms)
+  ofdm_load_const;
+
+  Nsymsperframe = Nbitsperframe/bps;
+  Nuwsyms = Nuwbits/bps;
+  Ntxtsyms = Ntxtbits/bps;
+  modem_frame = zeros(1,Nsymsperframe);
+  p = 1; u = 1;
+
+  for s=1:Nsymsperframe-Ntxtsyms;
+    if (u <= Nuwsyms) && (s == uw_ind_sym(u))
+      modem_frame(s) = states.tx_uw_syms(u++);
+    else
+      modem_frame(s) = payload_syms(p++);
+    end
+  end
+  t = 1;
+  for s=Nsymsperframe-Ntxtsyms+1:Nsymsperframe
+    modem_frame(s) = txt_syms(t++);
+  end
+  assert(u == (Nuwsyms+1));
+  assert(p = (length(payload_syms)+1));
+endfunction
+
+
+% extract UW and txt bits, and payload symbols from a frame of modem symbols
+
+function [rx_uw payload_syms payload_amps txt_bits] = disassemble_modem_frame(states, modem_frame_syms, modem_frame_amps)
+  ofdm_load_const;
+
+  Nsymsperframe = Nbitsperframe/bps;
+  Nuwsyms = Nuwbits/bps;
+  Ntxtsyms = Ntxtbits/bps;
+  payload_syms = zeros(1,Nsymsperframe-Nuwsyms-Ntxtsyms);
+  payload_amps = zeros(1,Nsymsperframe-Nuwsyms-Ntxtsyms);
+  rx_uw_syms = zeros(1,Nuwsyms);
+  txt_syms = zeros(1,Ntxtsyms);
+  p = 1; u = 1;
+
+  for s=1:Nsymsperframe-Ntxtsyms;
+    if (u <= Nuwsyms) && (s == uw_ind_sym(u))
+      rx_uw_syms(u++) = modem_frame_syms(s);
+    else
+      payload_syms(p) = modem_frame_syms(s);
+      payload_amps(p++) = modem_frame_amps(s);
+    end
+  end
+  t = 1;
+  for s=Nsymsperframe-Ntxtsyms+1:Nsymsperframe
+    txt_syms(t++) = modem_frame_syms(s);
+  end
+  assert(u == (Nuwsyms+1));
+  assert(p = (Nsymsperframe+1));
+
+  % now demodulate UW and txt bits
+  
+  rx_uw = zeros(1,Nuwbits);
+  txt_bits = zeros(1,Ntxtbits);
+  
+  for s=1:Nuwsyms
+    rx_uw(2*s-1:2*s) = qpsk_demod(rx_uw_syms(s));
+  end
+  for s=1:Ntxtsyms
+    txt_bits(2*s-1:2*s) = qpsk_demod(txt_syms(s));
+  end
+
 endfunction
 
 
@@ -622,7 +740,8 @@ function [tx_bits payload_data_bits codeword] = create_ldpc_test_frame
 
   % insert UW and txt bits
   
-  tx_bits = [tx_uw zeros(1,Ntxtbits) codeword_raw];
+  %tx_bits = [tx_uw zeros(1,Ntxtbits) codeword_raw];
+  tx_bits = assemble_modem_frame(states, codeword_raw, zeros(1,Ntxtbits));
   assert(Nbitsperframe == length(tx_bits));
 
 endfunction
index bfcb636eee2e60be4e613818c1c1f11c2ade2634..7499d50e2c277934e4abb857563f0dd0cfa400c0 100644 (file)
@@ -16,6 +16,8 @@ timing_mx_thresh = 0.25;
 Nuwbits = states.Nuwbits;
 Ntxtbits = states.Ntxtbits;
 tx_uw =  states.tx_uw;
+uw_ind = states.uw_ind;
+uw_ind_sym = states.uw_ind_sym;
 
 W = states.W;
 w = states.w;
index 9841255166d701f741f4184b46b5fdb1b6885726..0a450d538ce3be11ff05de6be34fedd5c4eb1566 100644 (file)
@@ -43,7 +43,7 @@ function ofdm_rx(filename, error_pattern_filename)
   %states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx(prx:nin);
   %prx += nin;
   
-  states.verbose = 0;
+  states.verbose = 1;
 
   Nerrs = 0; rx_uw = zeros(1,states.Nuwbits);
   
@@ -69,7 +69,7 @@ function ofdm_rx(filename, error_pattern_filename)
     
     if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial')
       [rx_bits states aphase_est_pilot_log arx_np arx_amp] = ofdm_demod(states, rxbuf_in);
-      rx_uw = rx_bits(1:states.Nuwbits);
+      [rx_uw payload_syms payload_amps txt_bits] = disassemble_modem_frame(states, arx_np, arx_amp);
       
       errors = xor(tx_bits, rx_bits);
       Nerrs = sum(errors);
index c570b6102bb90265da7c93ac0e5ccc409ad7f0c6..68c64a9f60e456a9b179af2ab123b1a063c7ffb9 100644 (file)
@@ -155,7 +155,7 @@ for f=1:Nframes
     
     % make sure LDPC decoding is working OK
     
-    assert(codeword == detected_data);
+    assert(codeword == detected_data);
     
     [m n] = size(symbol_likelihood);
     symbol_likelihood_log = [symbol_likelihood_log; reshape(symbol_likelihood,m*n,1)];