figure(1); clf;
plot(rx_np,'+');
- axis([-2 2 -2 2]);
+ %axis([-2 2 -2 2]);
title('Scatter');
figure(2); clf;
figure(5); clf;
plot(Nerrs_log);
-#{
- figure(2)
+
+ figure(6)
Tx = abs(fft(tx(1:Nsam).*hanning(Nsam)'));
Tx_dB = 20*log10(Tx);
dF = Fs/Nsam;
plot((1:Nsam)*dF, Tx_dB);
mx = max(Tx_dB);
axis([0 Fs/2 mx-60 mx])
-#}
+
#{
if hf_en
sim_in.Tcp = 0.002;
sim_in.Rs = 1/Ts; sim_in.bps = 2; sim_in.Nc = 16; sim_in.Ns = 8;
- %sim_in.Nsec = 5*(sim_in.Ns+1)/sim_in.Rs; % one frame
- sim_in.Nsec = 30;
+ sim_in.Nsec = 5*(sim_in.Ns+1)/sim_in.Rs; % one frame
+ %sim_in.Nsec = 30;
- sim_in.EbNodB = 3;
+ sim_in.EbNodB = 10;
sim_in.verbose = 1;
- sim_in.hf_en = 1;
+ sim_in.hf_en = 0;
sim_in.foff_hz = 0;
- sim_in.timing_en = 1;
sim_in.sample_clock_offset_ppm = 0;
+
+ sim_in.timing_en = 1;
sim_in.foff_est_en = 1;
sim_in.phase_est_en = 1;
% carrier tables for up and down conversion
- w = (0:Nc+1)*2*pi*Rs/states.Fs;
+ fcentre = 1500;
+ Nlower = floor((fcentre - Rs*Nc/2)/Rs);
+ w = (Nlower:Nlower+Nc+1)*2*pi*Rs/states.Fs;
W = zeros(Nc+2,states.M);
for c=1:Nc+2
W(c,:) = exp(j*w(c)*(0:states.M-1));
% fine timing search +/- window_width/2 from current timing instant
- states.window_width = 11;
+ states.ftwindow_width = 11;
% Receive buffer: D P DDD P DDD P DDD P D
% ^
function [rx_bits states aphase_est_pilot_log rx_np] = ofdm_demod(states, rxbuf_in)
ofdm_load_const;
- % extra states that are st up at run time rather than init time
-
- timing_est = states.timing_est;
- timing_en = states.timing_en;
- foff_est_hz = states.foff_est_hz;
- foff_est_gain = states.foff_est_gain;
- foff_est_en = states.foff_est_en;
- sample_point = states.sample_point;
- rate_fs_pilot_samples = states.rate_fs_pilot_samples;
- verbose = states.verbose;
- phase_est_en = states.phase_est_en;
-
% insert latest input samples into rxbuf
rxbuf(1:Nrxbuf-states.nin) = rxbuf(states.nin+1:Nrxbuf);
% update timing estimate --------------------------------------------------
- delta_t = sample_point = 0;
+ delta_t = 0;
if timing_en
% update timing at start of every frame
- st = M+Ncp + Nsamperframe + 1 - floor(window_width/2) + (timing_est-1);
- en = st + Nsamperframe-1 + M+Ncp + window_width-1;
+ st = M+Ncp + Nsamperframe + 1 - floor(ftwindow_width/2) + (timing_est-1);
+ en = st + Nsamperframe-1 + M+Ncp + ftwindow_width-1;
ft_est = coarse_sync(states, rxbuf(st:en) .* exp(-j*woff_est*(st:en)), rate_fs_pilot_samples);
- timing_est += ft_est - ceil(window_width/2);
+ timing_est = timing_est + ft_est - ceil(ftwindow_width/2);
if verbose > 1
printf(" ft_est: %2d timing_est: %2d sample_point: %2d\n", ft_est, timing_est, sample_point);
% Black magic to keep sample_point inside cyclic prefix. Or something like that.
- delta_t = ft_est - ceil(window_width/2);
+ delta_t = ft_est - ceil(ftwindow_width/2);
sample_point = max(timing_est+Ncp/4, sample_point);
sample_point = min(timing_est+Ncp, sample_point);
end
rx_sym = zeros(1+Ns+1+1, Nc+2);
% previous pilot
-
+
st = M+Ncp + Nsamperframe + (-Ns)*(M+Ncp) + 1 + sample_point; en = st + M - 1;
for c=1:Nc+2
if foff_est_en
freq_err_rect = sum(rx_sym(2,:))' * sum(rx_sym(2+Ns,:));
freq_err_hz = angle(freq_err_rect)*Rs/(2*pi*Ns);
- foff_est_hz += foff_est_gain*freq_err_hz;
+ foff_est_hz = foff_est_hz + foff_est_gain*freq_err_hz;
end
% OK - now estimate and correct phase ----------------------------------
Nc = states.Nc;
M = states.M;
Ncp = states.Ncp;
-bps = sim_in.bps;
+bps = states.bps;
Nbitsperframe = states.Nbitsperframe;
Nrowsperframe = states.Nrowsperframe;
Nsamperframe = states.Nsamperframe;
+
+W = states.W;
+w = states.w;
+
+timing_est = states.timing_est;
+sample_point = states.sample_point;
+ftwindow_width = states.ftwindow_width;
+
+Nrxbuf = states.Nrxbuf;
+rxbuf = states.rxbuf;
+
pilots = states.pilots;
+rate_fs_pilot_samples = states.rate_fs_pilot_samples;
+
+foff_est_gain = states.foff_est_gain;
+foff_est_hz = states.foff_est_hz;
+
+timing_en = states.timing_en;
+foff_est_en = states.foff_est_en;
+phase_est_en = states.phase_est_en;
+
+verbose = states.verbose;
+
rand('seed', 100);
tx_bits = rand(1,Nbitsperframe) > 0.5;
- % load real samples from file
+ % init logs and BER stats
- frx=fopen(filename,"rb"); rx = fread(frx, Inf, "short"); fclose(frx);
+ rx_bits = []; rx_np = []; timing_est_log = []; delta_t_log = []; foff_est_hz_log = [];
+ phase_est_pilot_log = [];
+ Nerrs = Nbits = 0;
+
+ % load real samples from file
+ Ascale= 4E5;
+ frx=fopen(filename,"rb"); rx = 2*fread(frx, Inf, "short")/4E5; fclose(frx);
Nsam = length(rx); Nframes = floor(Nsam/Nsamperframe);
prx = 1;
- rx_bits = []; rx_np = []; timing_est_log = []; delta_t_log = []; foff_est_hz_log = [];
- phase_est_pilot_log = [];
+
+ % 'prime' rx buf to get correct coarse timing (for now)
+
+ prx = 1;
+ states.rxbuf(M+Ncp+2*Nsamperframe+1:Nrxbuf) = rx(prx:Nsamperframe+2*(M+Ncp));
+ prx += Nsamperframe+2*(M+Ncp);
+
+ % main loop ----------------------------------------------------------------
for f=1:Nframes
end
prx += states.nin;
- [arx_bits states aphase_est_pilot_log arx_np] = ofdm_demod(states, rxbuf_in);
+ [rx_bits states aphase_est_pilot_log arx_np] = ofdm_demod(states, rxbuf_in);
- rx_bits = [rx_bits arx_bits]; rx_np = [rx_np arx_np];
+ rx_np = [rx_np arx_np];
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];
phase_est_pilot_log = [phase_est_pilot_log; aphase_est_pilot_log];
+
+ % measure bit errors
+
+ errors = xor(tx_bits, rx_bits);
+ Nerrs += sum(errors);
+ Nerrs_log(f) = sum(errors);
+ Nbits += Nbitsperframe;
end
+ printf("BER: %5.4f Nbits: %d Nerrs: %d\n", Nerrs/Nbits, Nbits, Nerrs);
+
figure(1); clf;
plot(rx_np,'+');
- %axis([-2 2 -2 2]);
+ axis([-2 2 -2 2]);
title('Scatter');
+ figure(2); clf;
+ plot(phase_est_pilot_log(:,2:Nc+1),'g+', 'markersize', 5);
+ title('Phase est');
+ axis([1 length(phase_est_pilot_log) -pi pi]);
+
+ figure(3); clf;
+ subplot(211)
+ stem(delta_t_log)
+ title('delta t');
+ subplot(212)
+ plot(timing_est_log);
+ title('timing est');
+
+ figure(4); clf;
+ plot(foff_est_hz_log)
+ axis([1 max(Nframes,2) -3 3]);
+ title('Fine Freq');
+
+ figure(5); clf;
+ %plot(Nerrs_log);
+
endfunction
ofdm_load_const;
% generate fixed test frame of tx bits and run OFDM modulator
+ % todo: maybe extend this to 4 or 8 frames, one is a bit short
Nrows = Nsec*Rs;
Nframes = floor((Nrows-1)/Ns);
tx = [tx ofdm_mod(states, tx_bits)];
end
- Ascale = 32000/max(real(tx));
+ Ascale = 4E5;
ftx=fopen(filename,"wb"); fwrite(ftx, Ascale*real(tx), "short"); fclose(ftx);
endfunction