added AWGN and HF channel simulation, usual confusion with real signals, SNR est...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 3 May 2017 00:40:36 +0000 (00:40 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 3 May 2017 00:40:36 +0000 (00:40 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3118 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/ofdm_tx.m

index 57b32de15c066ba40e3d5b175dc25115653a24e5..903c7c8dee2c39a613e920682a17142bb6fad90a 100644 (file)
@@ -5,7 +5,7 @@
 % optional channel simulation.
 
 
-function ofdm_tx(filename, Nsec)
+function ofdm_tx(filename, Nsec, EbNodB=100, channel='awgn', freq_offset_Hz=0)
   ofdm_lib;
   Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 16; Ns = 8;
   states = ofdm_init(bps, Rs, Tcp, Ns, Nc);
@@ -24,7 +24,63 @@ function ofdm_tx(filename, Nsec)
   for f=1:Nframes
     tx = [tx ofdm_mod(states, tx_bits)];
   end
+  Nsam = length(tx);
+
+  % channel simulation
+
+  EbNo = bps * (10 .^ (EbNodB/10));
+  variance = 1/(M*EbNo/2);
+  woffset = 2*pi*freq_offset_Hz/Fs;
+
+  % SNR calculation is probably a bit off or confused, need to compare
+  % to cohpsk_frame_design.ods and make sure I've got it right.  PLus
+  % 3 is used as we are dealing with real channels because mumble
+  % mumble not understood very well mumble magic number.
+
+  SNRdB = EbNodB + 10*log10(bps*Rs*Nc/Fs) + 3;
+  printf("EbNo: %3.1f SNR(3k): %3.1f foff: %3.1f\n", EbNodB, SNRdB, freq_offset_Hz);
+
+  % set up HF model ---------------------------------------------------------------
+
+  if strcmp(channel, 'hf')
+
+    % some typical values, or replace with user supplied
+
+    dopplerSpreadHz = 1.0; path_delay_ms = 1;
+
+    path_delay_samples = path_delay_ms*Fs/1000;
+    printf("Doppler Spread: %3.2f Hz Path Delay: %3.2f ms %d samples\n", dopplerSpreadHz, path_delay_ms, path_delay_samples);
+
+    % generate same fading pattern for every run
+
+    randn('seed',1);
+
+    spread1 = doppler_spread(dopplerSpreadHz, Fs, (Nsec*(M+Ncp)/M+0.2)*Fs);
+    spread2 = doppler_spread(dopplerSpreadHz, Fs, (Nsec*(M+Ncp)/M+0.2)*Fs);
+
+    % sometimes doppler_spread() doesn't return exactly the number of samples we need
+    assert(length(spread1) >= Nsam, "not enough doppler spreading samples");
+    assert(length(spread2) >= Nsam, "not enough doppler spreading samples");
+
+    hf_gain = 1.0/sqrt(var(spread1)+var(spread2));
+  end
+
+  rx = tx;
+
+  if strcmp(channel, 'hf')
+    rx  = hf_gain * tx(1:Nsam) .* spread1(1:Nsam);
+    rx += hf_gain * [zeros(1,path_delay_samples) tx(1:Nsam-path_delay_samples)] .* spread2(1:Nsam);
+  end
+
+  rx = rx .* exp(j*woffset*(1:Nsam));
+
+  % note variance/2 as we are using real() operator
+
+  noise = sqrt(variance/2)*(0.5*randn(1,Nsam) + j*0.5*randn(1,Nsam));
+  rx += noise;
+  10*log10(var(tx)/var(noise))
 
   Ascale = 4E5;
-  ftx=fopen(filename,"wb"); fwrite(ftx, Ascale*real(tx), "short"); fclose(ftx);
+  frx=fopen(filename,"wb"); fwrite(frx, Ascale*real(rx), "short"); fclose(frx);
 endfunction