1% channel.m 2% 3% Commonly used channel simulation functions 4 51; 6 7function [spread1 spread2 path_delay_samples] = channel_multipath(channel, Fs, Nsam) 8 % Winlink multipath definitions 9 if strcmp(channel, 'mpg') dopplerSpreadHz = 0.1; path_delay_ms = 0.5; 10 elseif strcmp(channel, 'mpm') dopplerSpreadHz = 0.5; path_delay_ms = 1.0; 11 elseif strcmp(channel, 'mpp') dopplerSpreadHz = 1.0; path_delay_ms = 2.0; 12 elseif strcmp(channel, 'mpd') dopplerSpreadHz = 2.0; path_delay_ms = 4.0; 13 elseif strcmp(channel, 'mpf') dopplerSpreadHz = 4.0; path_delay_ms = 4.0; 14 elseif strcmp(channel, 'notch') dopplerSpreadHz = 0.0; path_delay_ms = 2.0; 15 elseif printf("Unknown multipath channel\n"); assert(0); end 16 17 path_delay_samples = path_delay_ms*Fs/1000; 18 %printf(" Doppler Spread: %3.2f Hz Path Delay: %3.2f ms %d samples\n", dopplerSpreadHz, path_delay_ms, path_delay_samples); 19 20 if strcmp(channel, "notch") 21 % simple notch filter (not time varying), hand tweaked to be 10dB down at about 1300 Hz (Fc-200Hz) 22 spread1 = 0.5*ones(1,Nsam); 23 spread2 = j*0.2*ones(1,Nsam); 24 else 25 % generate same fading pattern for every run 26 spread1 = doppler_spread(dopplerSpreadHz, Fs, Nsam); 27 spread2 = doppler_spread(dopplerSpreadHz, Fs, Nsam); 28 end 29 30 % sometimes doppler_spread() doesn't return exactly the number of samples we need 31 if length(spread1) < Nsam 32 printf("not enough doppler spreading samples %d %d\n", length(spread1), Nsam); 33 assert(0); 34 end 35 if length(spread2) < Nsam 36 printf("not enough doppler spreading samples %d %d\n", length(spread2), Nsam); 37 assert(0); 38 end 39endfunction 40 41% returns real rx signal with noise added, input is complex tx signal 42function [rx_real rx sigma] = channel_simulate(Fs, SNR3kdB, freq_offset_Hz, channel, tx, verbose=0) 43 Nsam = length(tx); 44 rx = tx; 45 46 if strcmp(channel, 'awgn') == 0 47 [spread1 spread2 path_delay_samples] = channel_multipath(channel, Fs, Nsam); 48 rx = tx(1:Nsam) .* spread1(1:Nsam); 49 rx += [zeros(1,path_delay_samples) tx(1:Nsam-path_delay_samples)] .* spread2(1:Nsam); 50 end 51 52 woffset = 2*pi*freq_offset_Hz/Fs; 53 rx = rx .* exp(j*woffset*(1:Nsam)); 54 55 rx_real = real(rx); S = rx_real*rx_real'; 56 rpapr = 10*log10(max(abs(rx_real).^2)/mean(abs(rx_real).^2)); 57 58 % SNR in a 4k bandwidth will be lower than 3k as total noise power N is higher 59 SNR4kdB = SNR3kdB - 10*log10(Fs/2) + 10*log10(3000); SNR = 10^(SNR4kdB/10); 60 N = S/SNR; sigma = sqrt(N/Nsam); 61 n = sigma*randn(1,Nsam); 62 % printf("SNR3kdB: %f SNR4kdB: %f N: %f %f\n", SNR3kdB, SNR4kdB, N, n*n'); 63 rx_real += n; 64 % check our sums are OK to within 0.25 dB 65 SNR4kdB_measured = 10*log10(S/(n*n')); 66 assert (abs(SNR4kdB - SNR4kdB_measured) < 0.5); 67 if verbose 68 printf("foff: %3.1f Hz SNR(3k): %3.1f dB ", freq_offset_Hz, SNR3kdB); 69 printf("measSNR3k: %3.2f dB N: %3.2f dB\n", 70 10*log10(S/(n*n')) + 10*log10(4000) - 10*log10(3000), 10*log10(n*n')); 71 end 72endfunction 73