global rx_filter_memory;
global Nfilter;
global gt_alpha5_root;
- global Fsep;
rx_filt = zeros(Nc+1,nin*P/M);
endfunction
+% Combined down convert and rx filter, more memort efficentut less intuitive design
+
+function rx_filt = down_convert_and_rx_filter(rx_fdm, nin)
+ global Nc;
+ global M;
+ global P;
+ global rx_fdm_mem;
+ global phase_rx;
+ global freq;
+ global freq_pol;
+ global Nfilter;
+ global gt_alpha5_root;
+
+ % update memory of rx_fdm
+
+ rx_fdm_mem(1:Nfilter+M-nin) = rx_fdm_mem(nin+1:Nfilter+M);
+ rx_fdm_mem(Nfilter+M-nin+1:Nfilter+M) = rx_fdm(1:nin);
+
+ for c=1:Nc+1
+
+ % now downconvert using current freq offset to get Nfilter+nin
+ % baseband samples.
+ %
+ % Nfilter nin
+ % |--------------------------|---------|
+ % |
+ % phase_rx(c)
+ %
+ % This means winding phase(c) back from this point
+ % to ensure phase continuity
+
+ wind_back_phase = -freq_pol(c)*Nfilter;
+ phase_rx(c) = phase_rx(c)*exp(j*wind_back_phase);
+
+ % down convert all samples in buffer
+
+ rx_baseband = zeros(1,Nfilter+M);
+ st = Nfilter+M; % end of buffer
+ st -= nin-1; % first new sample
+ st -= Nfilter; % first sample used in filtering
+
+ for i=st:Nfilter+M
+ phase_rx(c) = phase_rx(c) * freq(c);
+ rx_baseband(i) = rx_fdm_mem(i)*phase_rx(c)';
+ end
+
+ % now we can filter this carrier's P symbols
+
+ N=M/P;
+ k=1;
+ for i=1:N:nin
+ rx_filt(c,k) = rx_baseband(st+i-1:st+i-1+Nfilter-1) * gt_alpha5_root';
+ k+=1;
+ end
+ end
+endfunction
+
+
% LPF and peak pick part of freq est, put in a function as we call it twice
function [foff imax pilot_lpf_out S] = lpf_peak_pick(pilot_baseband, pilot_lpf, nin)
global rx_filter_memory;
rx_filter_memory = zeros(Nc+1, Nfilter);
+global rx_fdm_mem;
+ rx_fdm_mem = zeros(1,Nfilter+M);
+
% phasors used for up and down converters
global freq;
-freq = zeros(Nc+1,1);
+ freq = zeros(Nc+1,1);
+global freq_pol;
+ freq_pol = zeros(Nc+1,1);
for c=1:Nc/2
carrier_freq = (-Nc/2 - 1 + c)*Fsep + Fcentre;
- freq(c) = exp(j*2*pi*carrier_freq/Fs);
+ freq_pol(c) = 2*pi*carrier_freq/Fs;
+ freq(c) = exp(j*freq_pol(c));
end
for c=Nc/2+1:Nc
carrier_freq = (-Nc/2 + c)*Fsep + Fcentre;
- freq(c) = exp(j*2*pi*carrier_freq/Fs);
+ freq_pol(c) = 2*pi*carrier_freq/Fs;
+ freq(c) = exp(j*freq_pol(c));
end
-freq(Nc+1) = exp(j*2*pi*Fcentre/Fs);
+freq_pol(c) = 2*pi*Fcentre/Fs;
+freq(Nc+1) = exp(j*freq_pol(c));
% Spread initial FDM carrier phase out as far as possible. This
% helped PAPR for a few dB. We don't need to adjust rx phase as DQPSK
frames = 100;
EbNo_dB = 7.3;
-Foff_hz = 0;
+Foff_hz = 10;
modulation = 'dqpsk';
hpa_clip = 150;
rx_timing_log = 0;
tx_pwr = 0;
noise_pwr = 0;
-rx_fdm_mem = zeros(1,Nfilter+M);
rx_fdm_log = [];
rx_baseband_log = [];
rx_bits_offset = zeros(Nc*Nb*2);
S=fft(spec_mem.*hanning(Nspec)',Nspec);
SdB = 0.9*SdB + 0.1*20*log10(abs(S));
- % Delay
-
- %rx_fdm_delay(1:Ndelay-M) = rx_fdm_delay(M+1:Ndelay);
- %rx_fdm_delay(Ndelay-M+1:Ndelay) = rx_fdm;
- rx_fdm_delay = rx_fdm;
-
+
% -------------------
% Demodulator
% -------------------
% frequency offset estimation and correction, need to call rx_est_freq_offset even in sync
% mode to keep states updated
+ [pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, M);
+ [foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, M);
+
if sync == 0
- foff = foff_course;
+ foff = foff_coarse;
end
+
foff_log = [ foff_log foff ];
foff_rect = exp(j*2*pi*foff/Fs);
for i=1:M
foff_phase *= foff_rect';
- rx_fdm_delay(i) = rx_fdm_delay(i)*foff_phase;
+ rx_fdm(i) = rx_fdm(i)*foff_phase;
end
if 1
-
- nin = M;
-
- % update memory of rx_fdm
-
- rx_fdm_mem(1:Nfilter+M-nin) = rx_fdm_mem(nin+1:Nfilter+M);
- rx_fdm_mem(Nfilter+M-nin+1:Nfilter+M) = rx_fdm_delay(1:nin);
-
- for c=1:Nc+1
-
- % now downconvert using current freq offset to get Nfilter+nin
- % baseband samples.
- %
- % Nfilter nin
- % |--------------------------|---------|
- % |
- % phase_rx(c)
- %
- % This means winding phase(c) back and fwd from this point
- % to ensure phase continuity
-
- freq_pol = atan2(imag(freq(c)), real(freq(c)));
- wind_back_phase = -freq_pol*Nfilter;
- phase_rx(c) = phase_rx(c)*exp(j*wind_back_phase);
-
- % down convert all samples in buffer
-
- rx_baseband = zeros(1,Nfilter+M);
- st = Nfilter+M; % end of buffer
- st -= nin-1; % first new sample
- st -= Nfilter; % first sample involved in filtering
-
- for i=st:Nfilter+M
- phase_rx(c) = phase_rx(c) * freq(c);
- rx_baseband(i) = rx_fdm_mem(i)*phase_rx(c)';
- end
-
- % now we can filter this carrier's P symbols
-
- N=M/P;
- k=1;
- for i=1:N:nin
- rx_filt(c,k) = rx_baseband(st+i-1:st+i-1+Nfilter-1) * gt_alpha5_root';
- k+=1;
- end
- end
-
+ % more memory efficient but more complex
+ rx_filt = down_convert_and_rx_filter(rx_fdm, M);
else
-
- % baseband processing
-
- rx_baseband = fdm_downconvert(rx_fdm_delay(1:M), M);
+ rx_baseband = fdm_downconvert(rx_fdm, M);
rx_baseband_log = [rx_baseband_log rx_baseband];
rx_filt = rx_filter(rx_baseband, M);
end
else
rx_symbols_log = [rx_symbols_log rx_symbols];
endif
- foff -= 0.5*ferr;
+ foff -= 0.5*foff_fine;
+
prev_rx_symbols = rx_symbols;
sync_bit_log = [sync_bit_log sync_bit];