From cee5bce1eee052a77c187a8fbb1d3da8ac953b4b Mon Sep 17 00:00:00 2001 From: drowe67 Date: Wed, 18 Mar 2015 21:32:56 +0000 Subject: [PATCH] rate Fs tx and rx filtering working, a preliminary frame sync (coarse timing) and BER measurment working in Octave. next step, set up C side to match that git-svn-id: https://svn.code.sf.net/p/freetel/code@2082 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/fdmdv.m | 109 ++++++++++++++++-------------------- codec2-dev/octave/gmsk.m | 5 +- codec2-dev/octave/tcohpsk.m | 102 ++++++++++++++++++++++++++++++--- 3 files changed, 146 insertions(+), 70 deletions(-) diff --git a/codec2-dev/octave/fdmdv.m b/codec2-dev/octave/fdmdv.m index c0ad4540..4fcdc153 100644 --- a/codec2-dev/octave/fdmdv.m +++ b/codec2-dev/octave/fdmdv.m @@ -247,54 +247,35 @@ endfunction % Frequency shift each modem carrier down to Nc+1 baseband signals -function rx_baseband = fdm_downconvert(rx_fdm, nin) - global Fs; - global M; - global Nc; - global Fsep; - global phase_rx; - global freq; - - rx_baseband = zeros(1,nin); +function [rx_baseband fdmdv] = fdm_downconvert(fdmdv, rx_fdm, nin) + Fs = fdmdv.Fs; + M = fdmdv.M; + Nc = fdmdv.Nc; + phase_rx = fdmdv.phase_rx; + freq = fdmdv.freq; - % Nc/2 tones below centre freq + rx_baseband = zeros(Nc+1,nin); - for c=1:Nc/2 - for i=1:nin - phase_rx(c) = phase_rx(c) * freq(c); - rx_baseband(c,i) = rx_fdm(i)*phase_rx(c)'; - end - end - - % Nc/2 tones above centre freq - - for c=Nc/2+1:Nc + for c=1:Nc+1 for i=1:nin phase_rx(c) = phase_rx(c) * freq(c); rx_baseband(c,i) = rx_fdm(i)*phase_rx(c)'; end end - % Pilot - - c = Nc+1; - for i=1:nin - phase_rx(c) = phase_rx(c) * freq(c); - rx_baseband(c,i) = rx_fdm(i)*phase_rx(c)'; - end - + fdmdv.phase_rx = phase_rx; endfunction % Receive filter each baseband signal at oversample rate P -function rx_filt = rx_filter(rx_baseband, nin) - global Nc; - global M; - global P; - global rx_filter_memory; - global Nfilter; - global gt_alpha5_root; +function [rx_filt fdmdv] = rx_filter(fdmdv, rx_baseband, nin) + Nc = fdmdv.Nc; + M = fdmdv.M; + P = fdmdv.P; + rx_filter_memory = fdmdv.rx_filter_memory; + Nfilter = fdmdv.Nfilter; + gt_alpha5_root = fdmdv.gt_alpha5_root; rx_filt = zeros(Nc+1,nin*P/M); @@ -309,16 +290,18 @@ function rx_filt = rx_filter(rx_baseband, nin) rx_filter_memory(:,1:Nfilter-N) = rx_filter_memory(:,1+N:Nfilter); j+=1; end + + fdmdv.rx_filter_memory = rx_filter_memory; endfunction % LP filter +/- 1000 Hz, allows us to perfrom rx filtering at a lower rate saving CPU -function rx_fdm_filter = rxdec_filter(rx_fdm, nin) - global M; - global Nrxdec; - global rxdec_coeff; - global rxdec_lpf_mem; +function [rx_fdm_filter fdmdv] = rxdec_filter(fdmdv, rx_fdm, nin) + M = fdmdv.M; + Nrxdec = fdmdv.Nrxdec; + rxdec_coeff = fdmdv.rxdec_coeff; + rxdec_lpf_mem = fdmdv.rxdec_lpf_mem; rxdec_lpf_mem(1:Nrxdec-1+M-nin) = rxdec_lpf_mem(nin+1:Nrxdec-1+M); rxdec_lpf_mem(Nrxdec-1+M-nin+1:Nrxdec-1+M) = rx_fdm(1:nin); @@ -327,6 +310,8 @@ function rx_fdm_filter = rxdec_filter(rx_fdm, nin) for i=1:nin rx_fdm_filter(i) = rxdec_lpf_mem(i:Nrxdec-1+i) * rxdec_coeff; end + + fdmdv.rxdec_lpf_mem = rxdec_lpf_mem; end @@ -334,17 +319,17 @@ end % TODO: Decimate mem update and downconversion, this will save some more CPU and memory % note phase would have to advance 4 times as fast -function rx_filt = down_convert_and_rx_filter(rx_fdm, nin, dec_rate) - global Nc; - global M; - global P; - global rx_fdm_mem; - global phase_rx; - global freq; - global freq_pol; - global Nfilter; - global gt_alpha5_root; - global Q; +function [rx_filt fdmdv] = down_convert_and_rx_filter(fdmdv, rx_fdm, nin, dec_rate) + Nc = fdmdv.Nc; + M = fdmdv.M; + P = fdmdv.P; + rx_fdm_mem = fdmdv.rx_fdm_mem; + phase_rx = fdmdv.phase_rx; + freq = fdmdv.freq; + freq_pol = fdmdv.freq_pol; + Nfilter = fdmdv.Nfilter; + gt_alpha5_root = fdmdv.gt_alpha5_root; + Q = fdmdv.Q; % update memory of rx_fdm @@ -389,6 +374,9 @@ function rx_filt = down_convert_and_rx_filter(rx_fdm, nin, dec_rate) k+=1; end end + + fdmdv.phase_rx = phase_rx; + fdmdv.rx_fdm_mem = rx_fdm_mem; endfunction @@ -479,15 +467,14 @@ endfunction % Estimate optimum timing offset, re-filter receive symbols -function [rx_symbols rx_timing_M env] = rx_est_timing(rx_filt, nin) - global M; - global Nt; - global Nc; - global rx_filter_mem_timing; - global P; - global Nfilter; - global Nfiltertiming; - global gt_alpha5_root; +function [rx_symbols rx_timing_M env fdmdv] = rx_est_timing(fdmdv, rx_filt, nin) + M = fdmdv.M; + Nt = fdmdv.Nt; + Nc = fdmdv.Nc; + rx_filter_mem_timing = fdmdv.rx_filter_mem_timing; + P = fdmdv.P; + Nfilter = fdmdv.Nfilter; + Nfiltertiming = fdmdv.Nfiltertiming; % nin adjust % -------------------------------- @@ -537,6 +524,8 @@ function [rx_symbols rx_timing_M env] = rx_est_timing(rx_filt, nin) % rx_symbols = rx_filter_mem_timing(:,high_sample+1); rx_timing_M = norm_rx_timing*M; + + fdmdv.rx_filter_mem_timing = rx_filter_mem_timing; endfunction diff --git a/codec2-dev/octave/gmsk.m b/codec2-dev/octave/gmsk.m index 2092a593..0549c338 100644 --- a/codec2-dev/octave/gmsk.m +++ b/codec2-dev/octave/gmsk.m @@ -837,7 +837,7 @@ function gmsk_rx(rx_file_name, err_file_name) Rs = 1200; framesize = 480; npreamble = 480; - fc = 1900; + fc = 1500; gmsk_states.npreamble = npreamble; gmsk_states.verbose = 1; @@ -1013,5 +1013,6 @@ endfunction %gmsk_rx("ssb-ber5.wav") %gmsk_rx("ssb25db.wav") %gmsk_rx("~/Desktop/ssb_fm_gmsk_high.wav") -gmsk_rx("~/Desktop/test_gmsk_28BER.raw") +%gmsk_rx("~/Desktop/test_gmsk_28BER.raw") +gmsk_rx("~/Desktop/gmsk_rec1.wav") diff --git a/codec2-dev/octave/tcohpsk.m b/codec2-dev/octave/tcohpsk.m index b5e6e060..57906e4f 100644 --- a/codec2-dev/octave/tcohpsk.m +++ b/codec2-dev/octave/tcohpsk.m @@ -71,18 +71,54 @@ Nerrs = Tbits = 0; fdmdv.Fs = 8000; fdmdv.Nc = Nc-1; -fdmdv.M = Fs/Rs; +M = fdmdv.M = Fs/Rs; fdmdv.tx_filter_memory = zeros(fdmdv.Nc+1, Nfilter); fdmdv.Nfilter = Nfilter; fdmdv.gt_alpha5_root = gt_alpha5_root; fdmdv.Fsep = 75; -fdmdv.phase_tx = exp(j*2*pi*(0:Nc)/(Nc+1)); +fdmdv.phase_tx = ones(fdmdv.Nc+1,1); freq_hz = Fsep*( -Nc/2 - 0.5 + (1:Nc) ); -fdmdv.freq = exp(j*2*pi*freq_hz/Fs); +fdmdv.freq_pol = 2*pi*freq_hz/Fs; +fdmdv.freq = exp(j*fdmdv.freq_pol); Fcentre = 1500; fdmdv.fbb_rect = exp(j*2*pi*Fcentre/Fs); fdmdv.fbb_phase_tx = 1; +fdmdv.Nrxdec = 31; +fdmdv.rxdec_coeff = fir1(fdmdv.Nrxdec-1, 0.25)'; +fdmdv.rxdec_lpf_mem = zeros(1,fdmdv.Nrxdec-1+M); + +P = fdmdv.P = 4; +fdmdv.phase_rx = ones(fdmdv.Nc+1,1); +fdmdv.Nsym = 6; +fdmdv.Nfilter = fdmdv.Nsym*fdmdv.M; +fdmdv.rx_fdm_mem = zeros(1,fdmdv.Nfilter + fdmdv.M); +Q = fdmdv.Q = fdmdv.M/4; + +fdmdv.Nt = 5; +fdmdv.rx_filter_mem_timing = zeros(fdmdv.Nc+1, fdmdv.Nt*fdmdv.P); +fdmdv.Nfiltertiming = fdmdv.M + fdmdv.Nfilter + fdmdv.M; + +fdmdv.rx_filter_memory = zeros(fdmdv.Nc+1, fdmdv.Nfilter); + +rx_filt_log = []; +rx_fdm_filter_log = []; +rx_baseband_log = []; + +fbb_phase_rx = 1; + +% frame of just pilots ofr coarse sync + +tx_bits = zeros(1,framesize); +[tx_symb_pilot tx_bits prev_tx_sym] = bits_to_qpsk_symbols(sim_in, tx_bits, [], []); +for r=1:(sim_in.Ns+1):sim_in.Nsymbrowpilot + tx_symb_pilot(r+1:r+sim_in.Ns,:) = zeros(sim_in.Ns, sim_in.Nc); +end + +ct_symb_buf = zeros(2*sim_in.Nsymbrowpilot, sim_in.Nc); + +% main loop -------------------------------------------------------------------- + for i=1:frames tx_bits = tx_bits_coh(ptx_bits_coh:ptx_bits_coh+framesize-1); ptx_bits_coh += framesize; @@ -93,15 +129,48 @@ for i=1:frames tx_bits_log = [tx_bits_log tx_bits]; [tx_symb tx_bits prev_tx_sym] = bits_to_qpsk_symbols(sim_in, tx_bits, [], []); + %tx_symb = tx_symb_pilot; tx_symb_log = [tx_symb_log; tx_symb]; + tx_fdm_frame = []; for r=1:sim_in.Nsymbrowpilot - [tx_baseband fdmdv] = tx_filter(fdmdv, rot90(tx_symb(r,:),1)); + tx_onesymb = tx_symb(r,:); + [tx_baseband fdmdv] = tx_filter(fdmdv, tx_onesymb); tx_baseband_log = [tx_baseband_log tx_baseband]; [tx_fdm fdmdv] = fdm_upconvert(fdmdv, tx_baseband); - tx_fdm_log = [tx_fdm_log tx_fdm]; + tx_fdm_frame = [tx_fdm_frame tx_fdm]; end + tx_fdm_log = [tx_fdm_log tx_fdm_frame]; + nin = M; + + % shift frame down to complex baseband + + rx_fdm_frame_bb = zeros(1, sim_in.Nsymbrowpilot*M); + for r=1:sim_in.Nsymbrowpilot*M + fbb_phase_rx = fbb_phase_rx*fdmdv.fbb_rect'; + rx_fdm_frame_bb(r) = tx_fdm_frame(r)*fbb_phase_rx; + end + mag = abs(fbb_phase_rx); + fbb_phase_rx /= mag; + + ch_symb = zeros(sim_in.Nsymbrowpilot, Nc); + for r=1:sim_in.Nsymbrowpilot + %[rx_fdm_filter fdmdv] = rxdec_filter(fdmdv, rx_fdm_frame_bb(1+(r-1)*M:r*M), nin); + %rx_fdm_filter_log = [rx_fdm_filter_log rx_fdm_filter]; + %[rx_filt fdmdv] = down_convert_and_rx_filter(fdmdv, rx_fdm_filter, nin, M/Q); + + [rx_baseband fdmdv] = fdm_downconvert(fdmdv, rx_fdm_frame_bb(1+(r-1)*M:r*M), nin); + rx_baseband_log = [rx_baseband_log rx_baseband]; + [rx_filt fdmdv] = rx_filter(fdmdv, rx_baseband, nin); + + rx_filt_log = [rx_filt_log rx_filt]; + + [rx_onesym rx_timing env fdmdv] = rx_est_timing(fdmdv, rx_filt, nin); + ch_symb(r,:) = rx_onesym; + end + +if 0 noise = sqrt(variance*0.5)*(randn(sim_in.Nsymbrowpilot,sim_in.Nc) + j*randn(sim_in.Nsymbrowpilot,sim_in.Nc)); noise_log = [noise_log; noise]; @@ -110,9 +179,25 @@ for i=1:frames ch_symb(r,:) = tx_symb(r,:)*phase + noise(r,:); end phase = phase/abs(phase); +end ch_symb_log = [ch_symb_log; ch_symb]; - [rx_symb rx_bits rx_symb_linear amp_linear amp_ phi_ EsNo_ prev_sym_rx sim_in] = qpsk_symbols_to_bits(sim_in, ch_symb, []); + % coarse timing + + ct_symb_buf(1:sim_in.Nsymbrowpilot,:) = ct_symb_buf(sim_in.Nsymbrowpilot+1:2*sim_in.Nsymbrowpilot,:); + ct_symb_buf(sim_in.Nsymbrowpilot+1:2*sim_in.Nsymbrowpilot,:) = ch_symb; + + max_corr = 0; + for t=0:sim_in.Nsymbrowpilot-1 + corr = sum(sum(rot90(ct_symb_buf(t+1:t+sim_in.Nsymbrowpilot,:),1) * tx_symb_pilot)); + if corr > max_corr + max_corr = corr; + ct = t; + end + end + %printf("max_corr: %f ct: %d\n", max_corr, ct); + + [rx_symb rx_bits rx_symb_linear amp_linear amp_ phi_ EsNo_ prev_sym_rx sim_in] = qpsk_symbols_to_bits(sim_in, ct_symb_buf(ct+1:ct+sim_in.Nsymbrowpilot,:), []); rx_symb_log = [rx_symb_log; rx_symb]; rx_amp_log = [rx_amp_log; amp_]; rx_phi_log = [rx_phi_log; phi_]; @@ -120,12 +205,13 @@ for i=1:frames % BER stats - if i > 2 - error_positions = xor(prev_tx_bits, rx_bits); + if i > 3 + error_positions = xor(prev_tx_bits2, rx_bits); Nerrs += sum(error_positions); nerr_log = [nerr_log sum(error_positions)]; Tbits += length(error_positions); end + prev_tx_bits2 = prev_tx_bits; prev_tx_bits = tx_bits; end -- 2.25.1