diff --git a/ofdm/calcWiener.m b/ofdm/calcWiener.m new file mode 100644 index 0000000..a20c9ed --- /dev/null +++ b/ofdm/calcWiener.m @@ -0,0 +1,53 @@ +function W_syms = calcWiener(drm_mode, drm_bw) +% calcWiener('B', '10k'); +fs = 12000; +fd_max = 0.1; +tau_max = 0.0001; + +[params, spec_occ] = drm_params(drm_mode, drm_bw); +N = params.nu +Ts = params.nu/fs +dF = 1/Ts + +frames_per_window = 2*params.y +window_delay = params.y +num_symbols_per_frame = params.nspf +num_carrier_per_symbol = spec_occ.kmax - spec_occ.kmin - 1 +num_symbols_per_frame = num_symbols_per_frame * num_carrier_per_symbol + +% PHI = auto-covariance-matrix +f_cut_t = 0.0675*1/window_delay; % two-sided maximum doppler frequency (normalized w.r.t symbol duration Ts) +f_cut_k = 1.75*params.ng/params.nu; % two-sided maximum echo delay (normalized w.r.t useful symbol duration Tu) + +W_syms = cell( params.y, 1 ); + +for d=0:window_delay-1 + k2_pos = []; + t2_pos = []; + for s=0:frames_per_window-1 + [c, p, a] = getRefGain(params, spec_occ, s+d); + k2_pos = [k2_pos c]; % length = window_delay*frames_per_window + t2_pos = [t2_pos ones(1, length(c))*(s)]; % length = window_delay*frames_per_window + end + + PHI = zeros(length(k2_pos)); + % PHI + for k1=1:length(k2_pos) + k2 = [1:length(k2_pos)]; + k1_pos = k2_pos(k1); + t1_pos = t2_pos(k1); + PHI(k1,k2) = sinc(f_cut_k*(k1_pos-k2_pos)) .* sinc(f_cut_t*(t1_pos-t2_pos)); + end + PHI_inv = inv(PHI + eye(length(PHI))*0.0001); + + THETA = zeros(1, length(k2_pos)); + % THETA + carriers = spec_occ.kmin:spec_occ.kmax; + for k1=1:length(carriers) + k2 = [1:length(k2_pos)]; + k1_pos = carriers(k1); + t1_pos = window_delay; + THETA(k2) = sinc( (k1_pos-k2_pos)*f_cut_k ).*sinc( (t1_pos-t2_pos)*f_cut_t ); + W_syms{d+1}(:, k1) = transpose( THETA*PHI_inv ); + end +end diff --git a/ofdm/jcorr.m b/ofdm/jcorr.m new file mode 100644 index 0000000..7570cf3 --- /dev/null +++ b/ofdm/jcorr.m @@ -0,0 +1,7 @@ +function Rxy = jcorr(X, Y) + N = min(length(X), length(Y)); +% X = X - mean(X); +% Y = Y - mean(Y); + for m=0:N-1 + Rxy(m+1,:) = sum(X(1+m:N) .* conj(Y(1:N-m))); + end diff --git a/ofdm/wiener_eval.m b/ofdm/wiener_eval.m new file mode 100644 index 0000000..8429626 --- /dev/null +++ b/ofdm/wiener_eval.m @@ -0,0 +1,58 @@ +function wiener_eval(N, SNR, sigm) + +close all; + +USE_TD = 0; + +s = exp(j*4*pi.*(0:N-1)'/N); +h = -exp(j*4*pi.*(0:N-1)'/N) .* (1+(0.5 - 0.5*cos(2*pi.*(0:N-1)'/N))); +r = awgn(h.*s, SNR); + +hr = r./s; + +if USE_TD +[ss, gs, rxy, ryy] = wiener_td(s, r, sigm); +ss = ss./abs(ss); + +[hs, gh, rxyh, ryyh] = wiener_td(h, hr, sigm); + +figure +plot(rxy); grid; legend('rxy'); +figure +plot(ryy); grid; legend('ryy'); + +else +[ss, gs] = wiener_fd(s, r, sigm); +ss = ss./abs(ss); + +[hs, gh] = wiener_fd(h, hr, sigm); +end + +figure; +subplot(2, 1, 1) +plot(0:N-1, abs(h), 'b-', 0:N-1, abs(hr), 'g-', 0:N-1, abs(hs), 'r-'); grid; legend('|h|', '|h_{r}|', '|h_{s}|'); +subplot(2, 1, 2) +plot(0:N-1, angle(h), 'b-', 0:N-1, angle(hr), 'g-', 0:N-1, angle(hs), 'r-'); grid; legend('phi(h)', 'phi(h_{r})', 'phi(h_{s})'); + +figure; +plot(real(s), imag(s), 'bO', real(r), imag(r), 'rx', real(ss), imag(ss), 'm+'); grid; legend('s', 'r', 'W*r'); + +figure; +plot(real(gs), imag(gs), 'b+'); grid; legend('gh'); + +figure; +plot(abs(gh)); grid; legend('|gs|'); + +function h = channel(N, L, phi_max, omega_d_max, delay_max) +k = 1; % time +for l=1:L % frequency + hsum = 0; + for n=1:N + delay_n = delay_max*(1+fix(rand)); + omega_n = omega_d_max*(1 - 2*rand()); + phi_n = phi_max*pi*(1 - 2*rand()); + hsum = hsum + exp(j*0*(phi_n+2*pi*omega_n*k + 2*pi*delay_n/L*l)) + end + h(l,:) = 1/sqrt(N) * hsum; +end + diff --git a/ofdm/wiener_fd.m b/ofdm/wiener_fd.m new file mode 100644 index 0000000..28128e0 --- /dev/null +++ b/ofdm/wiener_fd.m @@ -0,0 +1,14 @@ +function [xs, g, PSDx, PSDy] = wiener_fd(x, y, sigma_noise) + N = length(x); + Y = fft(y); + X = fft(x); + PSDx = 1/N*abs(X).^2; % spectral power + PSDy = 1/N*abs(Y).^2; % spectral power + + k = sqrt(sum(PSDx)./sum(PSDy)) + % fourier transform of the wiener filter + G = PSDx./(PSDx + sigma_noise.^2); + % perform the filtering over the fourier + G = 1/k*G.*PSDx./PSDy; + xs = ifft(G.*Y); + g = ifft(G); diff --git a/ofdm/wiener_td.m b/ofdm/wiener_td.m new file mode 100644 index 0000000..8cb0aa4 --- /dev/null +++ b/ofdm/wiener_td.m @@ -0,0 +1,20 @@ +function [xs, g, rxy, ryy] = wiener_td(x, y, sigma_noise) +%rxy = ifft(fft(x).*conj(fft(y))); +x = x - mean(x); +y = y - mean(y); +rxy = circulant(y, 'step', -1).'*conj(x); +%ryy = ifft(fft(y).*conj(fft(y))); +ryy = circulant(y, 'step', -1).'*conj(y); + +sum_rxy = sum(abs(rxy)) +sum_ryy = sum(abs(ryy)) + +R = toeplitz(ryy + sigma_noise.^2*(1-j)); +g = inv(R)*(rxy)./sum_ryy; + +sum_g = mean(abs(g)) +g = g./sum_g; + +xs = (circulant((g)))*(y); + +