global pilot_baseband2;
global pilot_lpf1;
global pilot_lpf2;
- global Nbpf;
- global Nbpfcoeff;
- global bpf_coeff;
- global bpf;
-
-if 0
- % Band Pass filter input so we have (mainly) just the pilots
-
- bpf(1:Nbpf-nin) = bpf(nin+1:Nbpf);
- bpf(Nbpf-nin+1:Nbpf) = rx_fdm(1:nin);
- k = 1;
- for i = Nbpf-nin+1:Nbpf
- rx_fdm_bpf(k) = bpf(i-(Nbpfcoeff-1):i) * bpf_coeff';
- k++;
- end
-end
% down convert latest nin samples of pilot by multiplying by ideal
% BPSK pilot signal we have generated locally. The peak of the DFT
% Estimate optimum timing offset, re-filter receive symbols
-function [rx_symbols rx_timing env] = rx_est_timing(rx_filt, rx_baseband, nin)
+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 rx_baseband_mem_timing;
global P;
global Nfilter;
global Nfiltertiming;
x = env * exp(-j*2*pi*(0:m-1)/P)';
-linear_interp = 1;
-
-if linear_interp
-
- rx_timing = angle(x)*P/(2*pi) + P/4;
+ norm_rx_timing = angle(x)/(2*pi);
+ rx_timing = norm_rx_timing*P + P/4;
if (rx_timing > P)
rx_timing -= P;
end
low_sample = floor(rx_timing);
fract = rx_timing - low_sample;
high_sample = ceil(rx_timing);
- % printf("rx_timing: %f low_sample: %f high_sample: %f fract: %f\n", rx_timing, low_sample, high_sample, fract);
-
+ %printf("rx_timing: %f low_sample: %f high_sample: %f fract: %f\n", rx_timing, low_sample, high_sample, fract);
+
rx_symbols = rx_filter_mem_timing(:,low_sample)*(1-fract) + rx_filter_mem_timing(:,high_sample)*fract;
+ % rx_symbols = rx_filter_mem_timing(:,high_sample+1);
-else
-
- % map phase to estimated optimum timing instant at rate M
- % the M/4 part was adjusted by experiment, I know not why....
-
- rx_timing = angle(x)*M/(2*pi) + M/4;
- if (rx_timing > M)
- rx_timing -= M;
- end
- if (rx_timing < -M)
- rx_timing += M;
- end
-
- % rx_baseband_mem_timing contains M + Nfilter + M samples of the
- % baseband signal at rate M this enables us to resample the filtered
- % rx symbol with M sample precision once we have rx_timing
-
- rx_baseband_mem_timing(:,1:Nfiltertiming-nin) = rx_baseband_mem_timing(:,nin+1:Nfiltertiming);
- rx_baseband_mem_timing(:,Nfiltertiming-nin+1:Nfiltertiming) = rx_baseband;
-
- % sample right in the middle of the timing estimator window, by filtering
- % at rate M
-
- s = round(rx_timing) + M;
- rx_symbols = rx_baseband_mem_timing(:,s+1:s+Nfilter) * gt_alpha5_root';
-end
-
+ rx_timing_M = norm_rx_timing*M;
endfunction
% Freq offset estimator constants
-if 0
-global Nbpfcoeff; % number of input BPF coeffs
- Nbpfcoeff = 100;
-global bpf_coeff;
- bpf_coeff = fir1(Nbpfcoeff-1, [Fcentre-100 Fcentre+100]/(Fs/2),'pass')';
-global Nbpf;
- Nbpf = Nbpfcoeff + M + M/P; % number of pilot baseband samples reqd for pilot LPF
-end
-
global Mpilotfft = 256;
global Npilotcoeff; % number of pilot LPF coeffs
% Freq offset estimator states
-if 0
-global bpf;
- bpf = zeros(1, Nbpf); % BPF pilot input samples
-end
global pilot_baseband1;
global pilot_baseband2;
pilot_baseband1 = zeros(1, Npilotbaseband); % pilot baseband samples
% adjust this if the screen is getting a bit cluttered
global no_plot_list;
-no_plot_list = [1 2 3 4 5 6 7 8 11 12 16];
+no_plot_list = [1 2 3 4 5 6 7 8 16];
for f=1:frames
% channel
- %nin = next_nin;
- nin = M;
+ nin = next_nin;
+
+ % nin = M; % when debugging good idea to uncomment this to "open loop"
+
channel = [channel real(tx_fdm)];
channel_count += M;
rx_fdm = channel(1:nin);
[pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, nin);
[foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, nin);
+
+ %sync = 0; % when debugging good idea to uncomment this to "open loop"
+
if sync == 0
foff = foff_coarse;
end
rx_filt = rx_filter(rx_baseband, nin);
rx_filt_log = [rx_filt_log rx_filt];
- [rx_symbols rx_timing env] = rx_est_timing(rx_filt, rx_baseband, nin);
+ [rx_symbols rx_timing env] = rx_est_timing(rx_filt, nin);
env_log = [env_log env];
-
rx_timing_log = [rx_timing_log rx_timing];
rx_symbols_log = [rx_symbols_log rx_symbols];
plot_sig_and_error(10, 211, foff_log, foff_log - foff_log_c, 'Freq Offset' )
plot_sig_and_error(10, 212, sync_log, sync_log - sync_log_c, 'Sync & Freq Est Coarse(0) Fine(1)', [1 frames -1.5 1.5] )
-c=15;
+c=1;
plot_sig_and_error(11, 211, real(rx_baseband_log(c,:)), real(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband real' )
plot_sig_and_error(11, 212, imag(rx_baseband_log(c,:)), imag(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband imag' )
f->rx_filter_mem_timing[c][k].real = 0.0;
f->rx_filter_mem_timing[c][k].imag = 0.0;
}
- for(k=0; k<NFILTERTIMING; k++) {
- f->rx_baseband_mem_timing[c][k].real = 0.0;
- f->rx_baseband_mem_timing[c][k].imag = 0.0;
- }
}
fdmdv_set_fsep(f, FSEP);
float rx_est_timing(COMP rx_symbols[],
int Nc,
COMP rx_filt[NC+1][P+1],
- COMP rx_baseband[NC+1][M+M/P],
COMP rx_filter_mem_timing[NC+1][NT*P],
float env[],
- COMP rx_baseband_mem_timing[NC+1][NFILTERTIMING],
int nin)
{
- int c,i,j,k;
- int adjust, s;
+ int c,i,j;
+ int adjust;
COMP x, phase, freq;
- float rx_timing;
+ float rx_timing, fract, norm_rx_timing;
+ int low_sample, high_sample;
/*
nin adjust
phase = cmult(phase, freq);
}
- /* Map phase to estimated optimum timing instant at rate M. The
- M/4 part was adjusted by experiment, I know not why.... */
+ /* Map phase to estimated optimum timing instant at rate P. The
+ P/4 part was adjusted by experiment, I know not why.... */
- rx_timing = atan2(x.imag, x.real)*M/(2*PI) + M/4;
+ norm_rx_timing = atan2(x.imag, x.real)/(2*PI);
+ rx_timing = norm_rx_timing*P + P/4;
- if (rx_timing > M)
- rx_timing -= M;
- if (rx_timing < -M)
- rx_timing += M;
-
- /* rx_filt_mem_timing contains M + Nfilter + M samples of the
- baseband signal at rate M this enables us to resample the
- filtered rx symbol with M sample precision once we have
- rx_timing */
+ if (rx_timing > P)
+ rx_timing -= P;
+ if (rx_timing < -P)
+ rx_timing += P;
- for(c=0; c<Nc+1; c++)
- for(i=0,j=nin; i<NFILTERTIMING-nin; i++,j++)
- rx_baseband_mem_timing[c][i] = rx_baseband_mem_timing[c][j];
- for(c=0; c<Nc+1; c++)
- for(i=NFILTERTIMING-nin,j=0; i<NFILTERTIMING; i++,j++)
- rx_baseband_mem_timing[c][i] = rx_baseband[c][j];
-
- /* rx filter to get symbol for each carrier at estimated optimum
- timing instant. We use rate M filter memory to get fine timing
- resolution. */
+ /* rx_filter_mem_timing contains Nt*P samples (Nt symbols at rate
+ P), where Nt is odd. Lets use linear interpolation to resample
+ in the centre of the timing estimation window .*/
+
+ rx_timing += floorf(NT/2.0)*P;
+ low_sample = floorf(rx_timing);
+ fract = rx_timing - low_sample;
+ high_sample = ceilf(rx_timing);
- s = round(rx_timing) + M;
+ //printf("rx_timing: %f low_sample: %d high_sample: %d fract: %f\n", rx_timing, low_sample, high_sample, fract);
+
for(c=0; c<Nc+1; c++) {
- rx_symbols[c].real = 0.0;
- rx_symbols[c].imag = 0.0;
- for(k=s,j=0; k<s+NFILTER; k++,j++)
- rx_symbols[c] = cadd(rx_symbols[c], fcmult(gt_alpha5_root[j], rx_baseband_mem_timing[c][k]));
+ rx_symbols[c] = cadd(fcmult(1.0-fract, rx_filter_mem_timing[c][low_sample-1]), fcmult(fract, rx_filter_mem_timing[c][high_sample-1]));
+ //rx_symbols[c] = rx_filter_mem_timing[c][high_sample];
}
-
- return rx_timing;
+
+ return norm_rx_timing*M;
}
/*---------------------------------------------------------------------------*\
fdm_downconvert(rx_baseband, fdmdv->Nc, rx_fdm_fcorr, fdmdv->phase_rx, fdmdv->freq, *nin);
rx_filter(rx_filt, fdmdv->Nc, rx_baseband, fdmdv->rx_filter_memory, *nin);
- fdmdv->rx_timing = rx_est_timing(rx_symbols, fdmdv->Nc, rx_filt, rx_baseband, fdmdv->rx_filter_mem_timing, env, fdmdv->rx_baseband_mem_timing, *nin);
+ fdmdv->rx_timing = rx_est_timing(rx_symbols, fdmdv->Nc, rx_filt, fdmdv->rx_filter_mem_timing, env, *nin);
/* Adjust number of input samples to keep timing within bounds */
\*---------------------------------------------------------*/
nin = next_nin;
- /*
- if (f == 2)
- nin = 120;
- if (f == 3)
- nin = 200;
- if ((f !=2) && (f != 3))
- nin = M;
- */
- nin = M;
+
+ //nin = M; // when debugging good idea to uncomment this to "open loop"
+
/* add M tx samples to end of buffer */
assert((channel_count + M) < CHANNEL_BUF_SIZE);
/* freq offset estimation and correction */
foff_coarse = rx_est_freq_offset(fdmdv, rx_fdm, nin);
+
+ //fdmdv->sync = 0; // when debugging good idea to uncomment this to "open loop"
+
if (fdmdv->sync == 0)
fdmdv->foff = foff_coarse;
fdmdv_freq_shift(rx_fdm_fcorr, rx_fdm, -fdmdv->foff, &fdmdv->foff_phase_rect, nin);
fdm_downconvert(rx_baseband, FDMDV_NC, rx_fdm_fcorr, fdmdv->phase_rx, fdmdv->freq, nin);
rx_filter(rx_filt, FDMDV_NC, rx_baseband, fdmdv->rx_filter_memory, nin);
- rx_timing = rx_est_timing(rx_symbols, FDMDV_NC, rx_filt, rx_baseband, fdmdv->rx_filter_mem_timing, env, fdmdv->rx_baseband_mem_timing, nin);
+ rx_timing = rx_est_timing(rx_symbols, FDMDV_NC, rx_filt, fdmdv->rx_filter_mem_timing, env, nin);
foff_fine = qpsk_to_bits(rx_bits, &sync_bit, FDMDV_NC, fdmdv->phase_difference, fdmdv->prev_rx_symbols, rx_symbols, 0);
//for(i=0; i<FDMDV_NC;i++)
// printf("rx_symbols: %f %f prev_rx_symbols: %f %f phase_difference: %f %f\n", rx_symbols[i].real, rx_symbols[i].imag,