added DQPSK mode, which works and can demod with small frequency offsets, modiied...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 2 Mar 2012 07:09:18 +0000 (07:09 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 2 Mar 2012 07:09:18 +0000 (07:09 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@338 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fdmdv.m
codec2-dev/octave/fdmdv_demod.m
codec2-dev/octave/fdmdv_mod.m
codec2-dev/octave/fdmdv_ut.m

index 030b8ba43f37e493d5018512418c2018bcfa319b..ea06e3ff9517f353b4bb96e35a1cb6759f711571 100644 (file)
@@ -63,7 +63,7 @@ global gt_alpha5_root = real((ifft_GF_alpha5_root(1:Nfilter)));
 
 % generate Nc QPSK symbols from vector of (1,Nc*Nb) input bits
 
-function tx_symbols = bits_to_qpsk(tx_bits)
+function tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits, modulation)
   global Nc;
   global Nb;
 
@@ -73,9 +73,29 @@ function tx_symbols = bits_to_qpsk(tx_bits)
   tx_bits_matrix(1:Nc,1) = tx_bits(1:Nb:Nb*Nc);
   tx_bits_matrix(1:Nc,2) = tx_bits(2:Nb:Nb*Nc);
 
-  % map to (Nc,1) QPSK symbols
-
-  tx_symbols = -1 + 2*tx_bits_matrix(:,1) - j + 2j*tx_bits_matrix(:,2); 
+  if (strcmp(modulation,'dqpsk')) 
+    % map to (Nc,1) DQPSK symbols
+
+    for c=1:Nc
+      msb = tx_bits_matrix(c,1); lsb = tx_bits_matrix(c,2);
+
+      if ((msb == 0) && (lsb == 0))
+         tx_symbols(c) = prev_tx_symbols(c);
+      endif  
+      if ((msb == 0) && (lsb == 1))
+         tx_symbols(c) = j*prev_tx_symbols(c);
+      endif  
+      if ((msb == 1) && (lsb == 0))
+         tx_symbols(c) = -prev_tx_symbols(c);
+      endif  
+      if ((msb == 1) && (lsb == 1))
+         tx_symbols(c) = -j*prev_tx_symbols(c);
+      endif 
+  end
+  else
+    % QPSK mapping
+    tx_symbols = -1 + 2*tx_bits_matrix(:,1) - j + 2j*tx_bits_matrix(:,2); 
+  endif
 
 endfunction
 
@@ -261,7 +281,7 @@ endfunction
 % sure but it's worth 3dB so worth experimenting or using coherent as
 % an option.
 
-function rx_phase = rx_est_phase(rx_symbols)
+function rx_phase = rx_est_phase(prev_rx_symbols, rx_symbols)
 
   % modulation strip
 
@@ -272,15 +292,42 @@ endfunction
 
 % convert symbols back to an array of bits
 
-function rx_bits = qpsk_to_bits(rx_symbols)
+function rx_bits = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation)
   global Nc;
   global Nb;
+  global Nb;
 
-  % map (Nc,1) QPSK symbols back into an (1,Nc*Nb) array of bits
+  if (strcmp(modulation,'dqpsk')) 
+    % extra 45 degree clockwise lets us use real and imag axis as
+    % decision boundaries
 
-  rx_bits = zeros(1,Nc*Nb);
-  rx_bits(1:Nb:Nc*Nb) = real(rx_symbols) > 0;
-  rx_bits(2:Nb:Nc*Nb) = imag(rx_symbols) > 0;
+    phase_difference = rx_symbols .* conj(prev_rx_symbols) * exp(j*pi/4);
+  
+    % map (Nc,1) DQPSK symbols back into an (1,Nc*Nb) array of bits
+
+    for c=1:Nc
+      d = phase_difference(c);
+      if ((real(d) >= 0) && (imag(d) >= 0))
+         msb = 0; lsb = 0;
+      endif  
+      if ((real(d) < 0) && (imag(d) >= 0))
+         msb = 0; lsb = 1;
+      endif  
+      if ((real(d) < 0) && (imag(d) < 0))
+         msb = 1; lsb = 0;
+      endif
+      if ((real(d) >= 0) && (imag(d) < 0))
+         msb = 1; lsb = 1;
+      endif
+      rx_bits(2*(c-1)+1) = msb;
+      rx_bits(2*(c-1)+2) = lsb;
+    end
+  else
+    % map (Nc,1) QPSK symbols back into an (1,Nc*Nb) array of bits
+
+    rx_bits(1:Nb:Nc*Nb) = real(rx_symbols) > 0;
+    rx_bits(2:Nb:Nc*Nb) = imag(rx_symbols) > 0;
+  endif
 
 endfunction
 
@@ -358,7 +405,7 @@ global rx_baseband_mem_timing = zeros(Nc, Nfiltertiming);
 
 % Test bit stream state variables
 
-global Ntest_bits = 100;     % length of test sequence
+global Ntest_bits = Nc*Nb*4;     % length of test sequence
 global current_test_bit = 1; 
 global test_bits = rand(1,Ntest_bits) > 0.5;
 global rx_test_bits_mem = zeros(1,Ntest_bits);
index f19d9941312ef1ba09d8bfe6dd5409a08692eb34..9cc707e6486645afefb2d69d5258e84b35e92d4c 100644 (file)
@@ -7,7 +7,7 @@
 % Version 2
 %
 
-function fdmdv_demod(rawfilename)
+function fdmdv_demod(rawfilename, nbits)
 
 fdmdv; % include modem code
 
@@ -15,13 +15,20 @@ fin = fopen(rawfilename, "rb");
 rx_fdm = fread(fin, Inf, "short");
 gain = 1000;
 rx_fdm /= gain;
-frames = floor(length(rx_fdm)/M);
+if (nargin == 1)
+  frames = floor(length(rx_fdm)/M);
+else
+  frames = nbits/(Nc*Nb);
+endif
 
 total_bit_errors = 0;
 total_bits = 0;
 
 rx_timing_log = [];
 rx_symbols_log = [];
+rx_phase_log = [];
+prev_rx_symbols = ones(Nc,1)*exp(j*pi/4);
+modulation = 'dqpsk';
 
 % Main loop ----------------------------------------------------
 
@@ -32,8 +39,17 @@ for i=1:frames
   [rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband);
   rx_timing_log = [rx_timing_log rx_timing];
 
-  rx_symbols_log = [rx_symbols_log rx_symbols];
-  rx_bits = qpsk_to_bits(rx_symbols);
+  %rx_phase = rx_est_phase(rx_symbols);
+  %rx_phase_log = [rx_phase_log rx_phase];
+  %rx_symbols = rx_symbols*exp(j*rx_phase);
+
+  if strcmp(modulation,'dqpsk')
+    rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)];
+  else
+    rx_symbols_log = [rx_symbols_log rx_symbols];
+  endif
+  rx_bits = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
+  prev_rx_symbols = rx_symbols;
 
   [sync bit_errors] = put_test_bits(rx_bits);
 
@@ -55,10 +71,12 @@ clf;
 plot(real(rx_symbols_log(:,20:m)),imag(rx_symbols_log(:,20:m)),'+')
 figure(2)
 clf;
-subplot(211)
+subplot(311)
 plot(rx_timing_log)
-subplot(212)
+subplot(312)
 Nfft=Fs;
 S=fft(rx_fdm,Nfft);
 SdB=20*log10(abs(S));
 plot(SdB(1:Fs/4))
+subplot(313)
+%plot(rx_phase_log)
index 7148619c7c9db357746cf3437eba8789bd86bfe7..69a310c10b0a81b6b66438da7ff7618b52281dd0 100644 (file)
@@ -13,11 +13,13 @@ fdmdv; % include modem code
 
 frames = floor(nbits/(Nc*Nb));
 tx_fdm = [];
-gain = 1000; % Sccle up to 16 bit shorts
+gain = 1000; % Scale up to 16 bit shorts
+prev_tx_symbols = ones(Nc,1)*exp(j*pi/4);
 
 for i=1:frames
   tx_bits = get_test_bits(Nc*Nb);
-  tx_symbols = bits_to_qpsk(tx_bits);
+  tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits,'dqpsk');
+  prev_tx_symbols = tx_symbols;
   tx_baseband = tx_filter(tx_symbols);
   tx_fdm = [tx_fdm fdm_upconvert(tx_baseband)];
 end
@@ -25,3 +27,4 @@ end
 tx_fdm *= gain;
 fout = fopen(rawfilename,"wb");
 fwrite(fout, tx_fdm, "short");
+fclose(fout);
index 8071f49b1f3e71578288987e22ad6243b856cb54..562da5c4d7bdedd55ac35ee97cfe25f755eb0f60 100644 (file)
@@ -13,7 +13,15 @@ fdmdv;               % load modem code
 rand('state',1); 
 randn('state',1);
  
+% Simulation Parameters --------------------------------------
+
 frames = 50;
+EbNo_dB = 40;
+Foff_hz = 1;
+modulation = 'dqpsk';
+
+% ------------------------------------------------------------
+
 tx_filt = zeros(Nc,M);
 rx_symbols_log = zeros(Nc,1);
 rx_phase_log = 0;
@@ -23,6 +31,9 @@ noise_pwr = 0;
 total_bit_errors = 0;
 total_bits = 0;
 rx_fdm_log = [];
+rx_bits_offset = zeros(Nc*Nb*2);
+prev_tx_symbols = ones(Nc,1)*exp(j*pi/4);
+prev_rx_symbols = ones(Nc,1)*exp(j*pi/4);
 
 % Eb/No calculations.  We need to work out Eb/No for each FDM carrier.
 % Total power is sum of power in all FDM carriers
@@ -31,8 +42,6 @@ C = 1;  % power of each FDM carrier (energy/sample)
 N = 1;  % total noise power (energy/sample) of noise source before scaling 
         % by Ngain
 
-EbNo_dB = 40;
-
 % Eb  = Carrier power * symbol time / (bits/symbol)
 %     = C *(Rs/Fs) / 2
 Eb_dB = 10*log10(C) + 10*log10(Rs) - 10*log10(Fs) - 10*log10(2);
@@ -53,19 +62,30 @@ CNo_dB = 10*log10(C)  + 10*log10(Nc) - No_dBHz;
 B = 2400;
 SNR = CNo_dB - 10*log10(B);
 
+phase_offset = 1;
+freq_offset = exp(j*2*pi*Foff_hz/Fs);
 
 % Main loop ----------------------------------------------------
 
 for i=1:frames
   tx_bits = get_test_bits(Nc*Nb);
-  tx_symbols = bits_to_qpsk(tx_bits);
+  %tx_bits = zeros(1,Nc*Nb);
+  %tx_bits = ones(1,Nc*Nb);
+  %tx_bits = [0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1];
+  %tx_bits = [1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0];
+  tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits, modulation);
+  prev_tx_symbols = tx_symbols;
   tx_baseband = tx_filter(tx_symbols);
   tx_fdm = fdm_upconvert(tx_baseband);
   tx_pwr = 0.9*tx_pwr + 0.1*tx_fdm*tx_fdm'/(M);
 
   noise = Ngain/sqrt(2)*[randn(1,M) + j*randn(1,M)];
   noise_pwr = 0.9*noise_pwr + 0.1*noise*noise'/M;
-  rx_fdm = tx_fdm + noise;
+  for i=1:M
+    phase_offset *= freq_offset;
+    rx_fdm(i) = phase_offset*tx_fdm(i);
+  end
+  rx_fdm += noise;
   rx_fdm_log = [rx_fdm_log rx_fdm];
 
   rx_baseband = fdm_downconvert(rx_fdm);
@@ -78,8 +98,13 @@ for i=1:frames
   %rx_phase_log = [rx_phase_log rx_phase];
   %rx_symbols = rx_symbols*exp(j*rx_phase);
 
-  rx_symbols_log = [rx_symbols_log rx_symbols];
-  rx_bits = qpsk_to_bits(rx_symbols);
+  if strcmp(modulation,'dqpsk')
+    rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)];
+  else
+    rx_symbols_log = [rx_symbols_log rx_symbols];
+  endif
+  rx_bits = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
+  prev_rx_symbols = rx_symbols;
 
   [sync bit_errors] = put_test_bits(rx_bits);
   if (sync == 1)
@@ -123,6 +148,10 @@ plot(SdB(1:Fs/4))
 % dump file type plotting & instrumentation
 % determine if error pattern is bursty
 % HF channel simulation
+%
+% phase estimator not working too well and would need a UW
+% to resolve ambiguity.  But this is probably worth it for
+% 3dB.  Test with small freq offset
 
 % Implementation loss BER issues:
 %   QPSK mapping