Convert MS-DOS text files to Unix
authorsjlongland <sjlongland@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 24 Sep 2015 08:11:15 +0000 (08:11 +0000)
committersjlongland <sjlongland@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 24 Sep 2015 08:11:15 +0000 (08:11 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2352 01035d8c-6547-0410-b346-abe4f91aad63

36 files changed:
codec2-dev/octave/cml.patch
codec2-dev/octave/ldpc.m
codec2-dev/octave/ldpcdec.m
codec2-dev/octave/ldpcenc.m
codec2-dev/octave/ldpcut.m
codec2-dev/octave/lpcauto.m
codec2-dev/octave/test_dqpsk.m
codec2-dev/octave/test_dqpsk2.m
codec2-dev/octave/test_foff.m
codec2-dev/octave/test_qpsk.m
codec2-dev/octave/test_qpsk2.m
codec2-dev/octave/test_qpsk3.m
codec2-dev/stm32/inc/stm32f4xx_conf.h
codec2-dev/stm32/src/adc_rec.c
codec2-dev/stm32/src/adc_sd.c
codec2-dev/stm32/src/adc_sfdr_ut.c
codec2-dev/stm32/src/adcdac_ut.c
codec2-dev/stm32/src/codec2_profile.c
codec2-dev/stm32/src/dac_it.c
codec2-dev/stm32/src/dac_play.c
codec2-dev/stm32/src/dac_ut.c
codec2-dev/stm32/src/debugblinky.c
codec2-dev/stm32/src/fast_dac_ut.c
codec2-dev/stm32/src/fdmdv_dump_rt.c
codec2-dev/stm32/src/fdmdv_profile.c
codec2-dev/stm32/src/fft_test.c
codec2-dev/stm32/src/freedv_rx_profile.c
codec2-dev/stm32/src/freedv_tx_profile.c
codec2-dev/stm32/src/power_ut.c
codec2-dev/stm32/src/sm1000_leds_switches_ut.c
codec2-dev/stm32/src/startup_stm32f4xx.s
codec2-dev/stm32/src/stm32f4_dac.c
codec2-dev/stm32/src/stm32f4_dacduc.c
codec2-dev/stm32/src/system_stm32f4xx.c
codec2-dev/stm32/src/tuner_ut.c
codec2-dev/stm32/stlink/stlink.patch

index c7cadd0c745f97faf075579b124d3a57c166dde8..d5ba3205768bbe8d853c7788d52bcc334e956db8 100644 (file)
@@ -2,21 +2,21 @@ diff -ruN -x '*.o' -x '*.dll' -x '*.mex' -x '*.mat' cml-orig/CmlStartup.m cml/Cm
 --- cml-orig/CmlStartup.m      2007-09-08 23:12:26.000000000 +0930
 +++ cml/CmlStartup.m   2015-09-04 07:21:14.218455223 +0930
 @@ -41,7 +41,7 @@
-     addpath( strcat( cml_home, '/mex'), ...\r
-         strcat( cml_home, '/mat'), ...\r
-         strcat( cml_home, '/matalt' ), ...\r
--        strcat( cml_home, '/mexhelp'), ...\r
-+        %strcat( cml_home, '/mexhelp'), ...\r
-         strcat( cml_home, '/demos' ), ...\r
-         strcat( cml_home, '/scenarios'), ...\r
-         strcat( cml_home, '/localscenarios'),...\r
+     addpath( strcat( cml_home, '/mex'), ...
+         strcat( cml_home, '/mat'), ...
+         strcat( cml_home, '/matalt' ), ...
+-        strcat( cml_home, '/mexhelp'), ...
++        %strcat( cml_home, '/mexhelp'), ...
+         strcat( cml_home, '/demos' ), ...
+         strcat( cml_home, '/scenarios'), ...
+         strcat( cml_home, '/localscenarios'),...
 @@ -59,4 +59,4 @@
-     save_directory = strcat( cml_home, '/scenarios/CmlHome.mat' );\r
- end\r
\r
+     save_directory = strcat( cml_home, '/scenarios/CmlHome.mat' );
+ end
 -save( save_directory, save_flag, 'cml_home' );
 \ No newline at end of file
-+save( save_directory, save_flag, 'cml_home' );\r
++save( save_directory, save_flag, 'cml_home' );
 diff -ruN -x '*.o' -x '*.dll' -x '*.mex' -x '*.mat' cml-orig/source/matrix.h cml/source/matrix.h
 --- cml-orig/source/matrix.h   1970-01-01 09:30:00.000000000 +0930
 +++ cml/source/matrix.h        2015-09-04 07:06:46.907248420 +0930
index 004996254e76691984552763cfd72ac027a53977..38713031a0c6385909024b9548b725672cd51204 100644 (file)
-% ldpc.m\r
-%\r
-% David Rowe 2013\r
-% Octave functions to help us use the CML LDPC code.\r
-%\r
-% Installing CML library\r
-% ----------------------\r
-%\r
-% $ sudo apt-get install liboctave-dev\r
-% $ wget http://www.iterativesolutions.com/user/image/cml.1.10.zip\r
-% $ unzip cml.1.10.zip\r
-% $ patch < ~/codec2-dev/octave/cml.patch\r
-% $ cd source\r
-% $ octave\r
-% octave:> make\r
-\r
-1;\r
-\r
-\r
-function code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping)\r
-    [code_param.H_rows, code_param.H_cols, code_param.P_matrix] = InitializeWiMaxLDPC( rate, framesize,  0 );\r
-    code_param.data_bits_per_frame = length(code_param.H_cols) - length( code_param.P_matrix );\r
-    code_param.S_matrix = CreateConstellation( modulation, mod_order, mapping );\r
-    code_param.bits_per_symbol = log2(mod_order);\r
-    code_param.code_bits_per_frame = framesize;\r
-    code_param.symbols_per_frame = framesize/2;\r
-endfunction\r
-\r
-\r
-\r
-function [codeword s] = ldpc_enc(data, code_param)\r
-        codeword = LdpcEncode( data, code_param.H_rows, code_param.P_matrix );\r
-        s = Modulate( codeword, code_param.S_matrix );\r
-endfunction\r
-\r
-\r
-function detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, r, EsNo, fading)\r
-    if nargin == 6\r
-      fading = ones(1, length(r));\r
-    end\r
-\r
-    symbol_likelihood = Demod2D( r, code_param.S_matrix, EsNo, fading);\r
-         \r
-    % initialize the extrinsic decoder input\r
-\r
-    input_somap_c = zeros(1, code_param.code_bits_per_frame );\r
-    bit_likelihood = Somap( symbol_likelihood, demod_type, input_somap_c );\r
-        \r
-    input_decoder_c = bit_likelihood(1:code_param.code_bits_per_frame);\r
-        \r
-    x_hat= MpDecode( -input_decoder_c, code_param.H_rows, code_param.H_cols, ...\r
-                     max_iterations, decoder_type, 1, 1);\r
-    detected_data = x_hat(max_iterations,:);\r
-endfunction\r
-\r
-\r
-% Packs a binary array into an array of 8 bit bytes, MSB first\r
-\r
-function packed = packmsb(unpacked)\r
-    packed = zeros(1,floor(length(unpacked)+7)/8);\r
-    bit = 7; byte = 1;\r
-    for i=1:length(unpacked)\r
-        packed(byte) = bitor(packed(byte), bitshift(unpacked(i),bit));\r
-        bit--;\r
-        if (bit < 0)\r
-            bit = 7;\r
-            byte++;\r
-        end \r
-    end\r
-endfunction\r
-\r
-\r
-% unpacks an array of 8 bit bytes into a binary array of unpacked bits, MSB first\r
-\r
-function unpacked = unpackmsb(packed)\r
-    bit = 7; byte = 1;\r
-    for i=1:length(packed)*8\r
-        unpacked(i) = bitand(bitshift(packed(byte), -bit), 1);\r
-        bit--;\r
-        if (bit < 0)\r
-            bit = 7;\r
-            byte++;\r
-        end \r
-    end\r
-endfunction\r
-\r
-\r
-% symbol interleaver that acts on bits 2 at a time\r
-\r
-function y = interleave_bits(interleaver, x)\r
-    y =  zeros(1,length(x));\r
-    for i = 1:length(interleaver)\r
-        dst = interleaver(i);\r
-        y(2*(dst-1)+1:2*dst) = x(2*(i-1)+1:2*(i));\r
-    end\r
-endfunction\r
-\r
-% symbol de-interleaver\r
-\r
-function x = deinterleave_symbols(interleaver, y)\r
-    for i = 1:length(interleaver)\r
-        x(i) = y(interleaver(i));\r
-    end\r
-endfunction\r
+% ldpc.m
+%
+% David Rowe 2013
+% Octave functions to help us use the CML LDPC code.
+%
+% Installing CML library
+% ----------------------
+%
+% $ sudo apt-get install liboctave-dev
+% $ wget http://www.iterativesolutions.com/user/image/cml.1.10.zip
+% $ unzip cml.1.10.zip
+% $ patch < ~/codec2-dev/octave/cml.patch
+% $ cd source
+% $ octave
+% octave:> make
+
+1;
+
+
+function code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping)
+    [code_param.H_rows, code_param.H_cols, code_param.P_matrix] = InitializeWiMaxLDPC( rate, framesize,  0 );
+    code_param.data_bits_per_frame = length(code_param.H_cols) - length( code_param.P_matrix );
+    code_param.S_matrix = CreateConstellation( modulation, mod_order, mapping );
+    code_param.bits_per_symbol = log2(mod_order);
+    code_param.code_bits_per_frame = framesize;
+    code_param.symbols_per_frame = framesize/2;
+endfunction
+
+
+
+function [codeword s] = ldpc_enc(data, code_param)
+        codeword = LdpcEncode( data, code_param.H_rows, code_param.P_matrix );
+        s = Modulate( codeword, code_param.S_matrix );
+endfunction
+
+
+function detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, r, EsNo, fading)
+    if nargin == 6
+      fading = ones(1, length(r));
+    end
+
+    symbol_likelihood = Demod2D( r, code_param.S_matrix, EsNo, fading);
+         
+    % initialize the extrinsic decoder input
+
+    input_somap_c = zeros(1, code_param.code_bits_per_frame );
+    bit_likelihood = Somap( symbol_likelihood, demod_type, input_somap_c );
+        
+    input_decoder_c = bit_likelihood(1:code_param.code_bits_per_frame);
+        
+    x_hat= MpDecode( -input_decoder_c, code_param.H_rows, code_param.H_cols, ...
+                     max_iterations, decoder_type, 1, 1);
+    detected_data = x_hat(max_iterations,:);
+endfunction
+
+
+% Packs a binary array into an array of 8 bit bytes, MSB first
+
+function packed = packmsb(unpacked)
+    packed = zeros(1,floor(length(unpacked)+7)/8);
+    bit = 7; byte = 1;
+    for i=1:length(unpacked)
+        packed(byte) = bitor(packed(byte), bitshift(unpacked(i),bit));
+        bit--;
+        if (bit < 0)
+            bit = 7;
+            byte++;
+        end 
+    end
+endfunction
+
+
+% unpacks an array of 8 bit bytes into a binary array of unpacked bits, MSB first
+
+function unpacked = unpackmsb(packed)
+    bit = 7; byte = 1;
+    for i=1:length(packed)*8
+        unpacked(i) = bitand(bitshift(packed(byte), -bit), 1);
+        bit--;
+        if (bit < 0)
+            bit = 7;
+            byte++;
+        end 
+    end
+endfunction
+
+
+% symbol interleaver that acts on bits 2 at a time
+
+function y = interleave_bits(interleaver, x)
+    y =  zeros(1,length(x));
+    for i = 1:length(interleaver)
+        dst = interleaver(i);
+        y(2*(dst-1)+1:2*dst) = x(2*(i-1)+1:2*(i));
+    end
+endfunction
+
+% symbol de-interleaver
+
+function x = deinterleave_symbols(interleaver, y)
+    for i = 1:length(interleaver)
+        x(i) = y(interleaver(i));
+    end
+endfunction
index 6f71f832bc63e735fd7dca0e3ee2a58511b057c2..2607766dd3cd8285f043c03757d46fc8993d21df 100644 (file)
-% ldpcdec.m\r
-% David Rowe 31 Dec 2013\r
-% \r
-% LDPC decoder test program, given a file of QPSK symbols (IQIQ floats), \r
-% performs frame sync, decodes, and measures BER.\r
-\r
-function ldpcdec(filename, Eprob)\r
-\r
-  % Start CML library\r
-\r
-  currentdir = pwd;\r
-  addpath '/home/david/tmp/cml/mat'    % assume the source files stored here\r
-  cd /home/david/tmp/cml\r
-  CmlStartup                           % note that this is not in the cml path!\r
-  cd(currentdir)\r
-\r
-  % Our LDPC library\r
-\r
-  ldpc;\r
-\r
-  % Start simulation\r
-\r
-  rand('state',1);\r
-\r
-  rate = 3/4; \r
-  framesize = 576;  \r
-\r
-  mod_order = 4; \r
-  modulation = 'QPSK';\r
-  mapping = 'gray';\r
-\r
-  demod_type = 0;\r
-  decoder_type = 0;\r
-  max_iterations = 100;\r
-  EsNo = 4;\r
-  if (nargin == 1)\r
-    Eprob = 0.0;\r
-  end\r
-\r
-  nbitspervocoderframe = 52;\r
-  nvocoderframes = 8;\r
-  nbitspermodemframe = 72;\r
-\r
-  code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);\r
-  code_param.code_bits_per_frame = 576;\r
-\r
-  data = [];\r
-  r = []; \r
-  load interleaver.txt\r
-  interleaver = interleaver + 1;\r
-\r
-  Nframes = 100;\r
-  uw = [1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0];\r
-\r
-  Nc = 18;\r
-\r
-  % repeat same simulated vocoder data to ease testing\r
-\r
-  vd = round( rand( 1, nbitspervocoderframe*nvocoderframes) );\r
-\r
-  % Decoder: Sync with LDPC frames, de-interleave, LDPC decode, strip off UW, measure BER -------\r
-\r
-  mcwfilename = strcat(filename,"_modcodeword.bin");\r
-  fm=fopen(mcwfilename,"rb");\r
-  etfilename = strcat(filename,"_modcodeword_et.bin");\r
-  fet=fopen(etfilename ,"rb");\r
-  epfilename = strcat(filename,".err");\r
-  fep=fopen(epfilename ,"wb");\r
-  printf("Input QPSK symbols: %s\n", mcwfilename);\r
-  if (fet == -1)\r
-    printf("Input entered track file: none\n");\r
-  else\r
-    printf("Input entered track file: %s\n", etfilename);\r
-  end\r
-  printf("Output error pattern file: %s\n", epfilename);\r
-\r
-  mod_uw = build_mod_uw(uw, 2*length(vd)/length(uw));\r
-\r
-  mod_codeword = zeros(1, code_param.code_bits_per_frame/2);\r
-  lmod_codeword = code_param.code_bits_per_frame/2;\r
-\r
-  Terrs = 0; Trawerrs = 0; Ferrs = 0; Tbits = 0; Tframes = 0; nerr = []; nrawerr = [];\r
-  corr = []; n = 0;\r
-  sync_state = 0; sync_count = 0;\r
-  mod_unpackedmodem_log = [];\r
-  sync_state_log = [];\r
-  entered_track_log = [];\r
-  sig_pwr_log = [];\r
-\r
-  symbols = erasures = 0;\r
-\r
-  [mod_unpackedmodem_float32, count] = fread(fm,nbitspermodemframe, "float32");\r
-  if (fet == -1)\r
-      entered_track = 0;\r
-  else\r
-     entered_track = fread(fet, 1, "int");\r
-  end\r
-\r
-  while (count == nbitspermodemframe)\r
-      n++;\r
-\r
-      mod_unpackedmodem = mod_unpackedmodem_float32(1:2:nbitspermodemframe) + j*mod_unpackedmodem_float32(2:2:nbitspermodemframe);\r
-      mod_unpackedmodem_log = [mod_unpackedmodem_log mod_unpackedmodem];\r
-      %erasures = rand(1,length(mod_unpackedmodem)) < Eprob; \r
-      %mod_unpackedmodem(erasures) = 0;\r
-\r
-      % keep buffer of one entire codeword\r
-\r
-      mod_codeword(1:lmod_codeword-length(mod_unpackedmodem)) = mod_codeword(length(mod_unpackedmodem)+1:lmod_codeword);\r
-      mod_codeword(lmod_codeword-length(mod_unpackedmodem)+1:lmod_codeword) = mod_unpackedmodem;\r
-\r
-      [uw_sync corr(n)] = look_for_uw(mod_codeword(1:length(mod_uw)), mod_uw);\r
-\r
-      next_sync_state = sync_state;\r
-      if ((sync_state == 0) && (uw_sync == 1))\r
-        next_sync_state = 1;\r
-        sync_count = 0;\r
-      end\r
-      if ((sync_state == 1) && (entered_track != 0))\r
-        next_sync_state = 0;\r
-      end\r
-      sync_state = next_sync_state;\r
-      sync_state_log = [sync_state_log sync_state];\r
-      entered_track_log = [entered_track_log entered_track];\r
-\r
-      if (sync_state && (sync_count == 0))\r
-          Tframes++;\r
-\r
-          % remove UW symbols\r
-\r
-          mod_codeword_no_uw = remove_uw_symbols(mod_codeword, code_param.data_bits_per_frame/2 - length(uw)/2, length(uw)/2);\r
-          mod_codeword_no_uw = [mod_codeword_no_uw mod_codeword((code_param.data_bits_per_frame/2+1):code_param.code_bits_per_frame/2)];\r
-\r
-          % de-interleave\r
-\r
-          tmp = deinterleave_symbols(interleaver, mod_codeword_no_uw);\r
-        \r
-          % insert known symbols at end of data\r
-\r
-          mod_codeword_deinter = [ tmp(1:(code_param.data_bits_per_frame/2 - length(uw)/2)) ...\r
-                                 ones(1,length(uw)/2) * qpsk_mod([0 0]) ...\r
-                                 tmp((code_param.data_bits_per_frame/2 - length(uw)/2+1):length(tmp)) ];\r
\r
-          % determine BER stats of raw data before decoding\r
-\r
-          raw_bits = zeros(1, code_param.data_bits_per_frame - length(uw));\r
-          for i=1:(code_param.data_bits_per_frame - length(uw))/2\r
-              raw_bits(2*(i-1)+1:2*i) = qpsk_demod(mod_codeword_deinter(i));\r
-          end\r
-          error_positions = xor(vd, raw_bits);\r
-          Nerrs = sum(error_positions);\r
-          Trawerrs += Nerrs;\r
-          nrawerr(Tframes) = Nerrs;\r
-\r
-          % Determine Es/N for each carrier. For this codeword we assume\r
-          % across codeword (currently 320ms) signal is stationary.\r
-          % So for each carrier signal level is constant, so we can\r
-          % average across all symols of that carrier to get a better\r
-          % estimate of the carrier power.  The spectral noise density\r
-          % No will be the same for the bandwidth of each carrier.  So\r
-          % we can use noise samples from all symbols together to get\r
-          % a better estimate of the noise power.\r
-          \r
-          sig_pwr(Tframes,:) = zeros(1,Nc);\r
-          noise_samples = [];\r
-          for n=1:Nc\r
-\r
-            % extract a vector of one carrier's symbols for this codeword\r
-            % rotate so that decision boundaries are now real and imag axis\r
-\r
-            r = mod_codeword(n:Nc:length(mod_codeword)) .* exp(j*pi/4);\r
-\r
-            sig_est = mean(abs(r));\r
-\r
-            % The noise is the variance of symbols (samples) about the actual symbol position\r
-            % we reflect all symbols into the first quadrant to simplify things, as the actual\r
-            % received symbol isn't matter, just the noise around it.  We model the received\r
-            % symbol based on the estimated signal level.\r
-\r
-            refl_symbols = abs(real(r)) + j*abs(imag(r));    \r
-            est_symbols = exp(j*pi/4)*sig_est*ones(1,length(r));\r
-            noise_samples = [ noise_samples (est_symbols - refl_symbols)];\r
-                       \r
-            sig_pwr(Tframes,n) = sig_est .^ 2;\r
-          end\r
-          noise_pwr(Tframes) = var(noise_samples);\r
-          %plot(real(refl_symbols), imag(refl_symbols), '+');\r
-          %hold on;\r
-          %plot(real(exp(j*pi/4)*sig_est*ones(1,length(r))), imag(exp(j*pi/4)*sig_est*ones(1,length(r))), 'r+');\r
-          %hold off;\r
-          %printf("SNR: %f\n", 10*log10(sig_est*sig_est/noise_pwr(Tframes)));\r
\r
-          % Set erasures for carrier beneath a certain Es/N\r
-          \r
-          for n=1:Nc\r
-              symbols++;\r
-              EsN(n) = 10*log10(sig_pwr(Tframes,n)/noise_pwr(Tframes));\r
-              if (EsN(n) < 1)\r
-                 %mod_codeword(n:Nc:length(mod_codeword)) = 0;    \r
-                 %printf("Tframes: %d n: %d EsN = %3.2fdB\n", Tframes, n, EsN(n)); \r
-                 erasures++;                                     \r
-              end\r
-          end\r
-\r
-          % De-interleave again with erasures set ----------------------\r
-\r
-          % remove UW symbols\r
-\r
-          mod_codeword_no_uw = remove_uw_symbols(mod_codeword, code_param.data_bits_per_frame/2 - length(uw)/2, length(uw)/2);\r
-          mod_codeword_no_uw = [mod_codeword_no_uw mod_codeword((code_param.data_bits_per_frame/2+1):code_param.code_bits_per_frame/2)];\r
-\r
-          tmp = deinterleave_symbols(interleaver, mod_codeword_no_uw);\r
-        \r
-          % insert known symbols at end of data\r
-\r
-          mod_codeword_deinter = [ tmp(1:(code_param.data_bits_per_frame/2 - length(uw)/2)) ...\r
-                                 ones(1,length(uw)/2) * qpsk_mod([0 0]) ...\r
-                                 tmp((code_param.data_bits_per_frame/2 - length(uw)/2+1):length(tmp)) ];\r
-\r
-          % LDPC decode ------------------------------------------------\r
-\r
-          detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, mod_codeword_deinter, EsNo);\r
-\r
-          % unpack payload data, removing UW\r
-\r
-          vd_rx = detected_data(1:(code_param.data_bits_per_frame - length(uw)));\r
-\r
-          % measure coded BER\r
-\r
-          error_positions = xor(vd, vd_rx);\r
-          Nerrs = sum(error_positions);\r
-          if Nerrs>0, fprintf(1,'x'); Ferrs++; ,  else fprintf(1,'.'),  end\r
-          Tbits += length(vd);\r
-          Terrs += Nerrs;\r
-          nerr(Tframes) = Nerrs;\r
-\r
-          % save error patterns is simulated vocoder data to disk\r
-\r
-          fwrite(fep, error_positions, "short");\r
-          \r
-      end\r
-\r
-      if (sync_state)\r
-          sync_count++;\r
-          if (sync_count == 8)\r
-              sync_count = 0;\r
-          end\r
-      end\r
-\r
-      % read in one modulated modem frame at a time\r
-\r
-      [mod_unpackedmodem_float32, count] = fread(fm, nbitspermodemframe, "float32");\r
-      if (fet == -1)\r
-          entered_track = 0;\r
-      else\r
-          entered_track = fread(fet, 1, "int");\r
-      end\r
-  end\r
-\r
-  fclose(fep);\r
-\r
-  printf("\nFrames: %d bits: %d errors: %d Raw BER = %f Coded BER = %f FER = %f\n", Tframes, Tbits, Terrs, Trawerrs/Tbits, Terrs/Tbits, Ferrs/Tframes);\r
-  printf("Symbols: %d Erasures: %d  %f\n", symbols, erasures, erasures/symbols);\r
-  figure(8)\r
-  clf;\r
-  [n m] = size(mod_unpackedmodem_log);\r
-  plot( real(mod_unpackedmodem_log), imag(mod_unpackedmodem_log), '+')\r
-  axis([-2 2 -2 2]);\r
-  title('Scatter Diagram');\r
-\r
-  figure(9)\r
-  subplot(311)\r
-  plot(sync_state_log);\r
-  subplot(312)\r
-  plot(nrawerr);\r
-  subplot(313)\r
-  plot(nerr);\r
-\r
-  figure(10);\r
-  plot(10*log10(sig_pwr(:,3)./noise_pwr(:)),'b');\r
-  hold on;\r
-  plot(10+10*log10(noise_pwr(:)));\r
-  plot(10+10*log10(sig_pwr(:,3)),'r');\r
-%  for n=2:Nc\r
-%    plot(n*10+10*log10(sig_pwr(:,n)./noise_pwr(:,n)));\r
-%    plot(n*10+10*log10(sig_pwr(:,n)),'r');\r
-%  end\r
-  hold off;\r
-\r
-  y = 1:Tframes;\r
-  x = 1:Nc;\r
-  z = 10*log10(sig_pwr(:,:)./((noise_pwr(:)*ones(1, Nc))));\r
-  %printf("mean SNR = %3.2fdB\n", mean(z));\r
-  figure(11);\r
-  imagesc(x,y,z);\r
-  figure(12);\r
-  mesh(x,y,z);\r
-  axis([1 Nc 1 Tframes 5 15]);\r
-\r
-endfunction\r
+% ldpcdec.m
+% David Rowe 31 Dec 2013
+% 
+% LDPC decoder test program, given a file of QPSK symbols (IQIQ floats), 
+% performs frame sync, decodes, and measures BER.
+
+function ldpcdec(filename, Eprob)
+
+  % Start CML library
+
+  currentdir = pwd;
+  addpath '/home/david/tmp/cml/mat'    % assume the source files stored here
+  cd /home/david/tmp/cml
+  CmlStartup                           % note that this is not in the cml path!
+  cd(currentdir)
+
+  % Our LDPC library
+
+  ldpc;
+
+  % Start simulation
+
+  rand('state',1);
+
+  rate = 3/4; 
+  framesize = 576;  
+
+  mod_order = 4; 
+  modulation = 'QPSK';
+  mapping = 'gray';
+
+  demod_type = 0;
+  decoder_type = 0;
+  max_iterations = 100;
+  EsNo = 4;
+  if (nargin == 1)
+    Eprob = 0.0;
+  end
+
+  nbitspervocoderframe = 52;
+  nvocoderframes = 8;
+  nbitspermodemframe = 72;
+
+  code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);
+  code_param.code_bits_per_frame = 576;
+
+  data = [];
+  r = []; 
+  load interleaver.txt
+  interleaver = interleaver + 1;
+
+  Nframes = 100;
+  uw = [1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0];
+
+  Nc = 18;
+
+  % repeat same simulated vocoder data to ease testing
+
+  vd = round( rand( 1, nbitspervocoderframe*nvocoderframes) );
+
+  % Decoder: Sync with LDPC frames, de-interleave, LDPC decode, strip off UW, measure BER -------
+
+  mcwfilename = strcat(filename,"_modcodeword.bin");
+  fm=fopen(mcwfilename,"rb");
+  etfilename = strcat(filename,"_modcodeword_et.bin");
+  fet=fopen(etfilename ,"rb");
+  epfilename = strcat(filename,".err");
+  fep=fopen(epfilename ,"wb");
+  printf("Input QPSK symbols: %s\n", mcwfilename);
+  if (fet == -1)
+    printf("Input entered track file: none\n");
+  else
+    printf("Input entered track file: %s\n", etfilename);
+  end
+  printf("Output error pattern file: %s\n", epfilename);
+
+  mod_uw = build_mod_uw(uw, 2*length(vd)/length(uw));
+
+  mod_codeword = zeros(1, code_param.code_bits_per_frame/2);
+  lmod_codeword = code_param.code_bits_per_frame/2;
+
+  Terrs = 0; Trawerrs = 0; Ferrs = 0; Tbits = 0; Tframes = 0; nerr = []; nrawerr = [];
+  corr = []; n = 0;
+  sync_state = 0; sync_count = 0;
+  mod_unpackedmodem_log = [];
+  sync_state_log = [];
+  entered_track_log = [];
+  sig_pwr_log = [];
+
+  symbols = erasures = 0;
+
+  [mod_unpackedmodem_float32, count] = fread(fm,nbitspermodemframe, "float32");
+  if (fet == -1)
+      entered_track = 0;
+  else
+     entered_track = fread(fet, 1, "int");
+  end
+
+  while (count == nbitspermodemframe)
+      n++;
+
+      mod_unpackedmodem = mod_unpackedmodem_float32(1:2:nbitspermodemframe) + j*mod_unpackedmodem_float32(2:2:nbitspermodemframe);
+      mod_unpackedmodem_log = [mod_unpackedmodem_log mod_unpackedmodem];
+      %erasures = rand(1,length(mod_unpackedmodem)) < Eprob; 
+      %mod_unpackedmodem(erasures) = 0;
+
+      % keep buffer of one entire codeword
+
+      mod_codeword(1:lmod_codeword-length(mod_unpackedmodem)) = mod_codeword(length(mod_unpackedmodem)+1:lmod_codeword);
+      mod_codeword(lmod_codeword-length(mod_unpackedmodem)+1:lmod_codeword) = mod_unpackedmodem;
+
+      [uw_sync corr(n)] = look_for_uw(mod_codeword(1:length(mod_uw)), mod_uw);
+
+      next_sync_state = sync_state;
+      if ((sync_state == 0) && (uw_sync == 1))
+        next_sync_state = 1;
+        sync_count = 0;
+      end
+      if ((sync_state == 1) && (entered_track != 0))
+        next_sync_state = 0;
+      end
+      sync_state = next_sync_state;
+      sync_state_log = [sync_state_log sync_state];
+      entered_track_log = [entered_track_log entered_track];
+
+      if (sync_state && (sync_count == 0))
+          Tframes++;
+
+          % remove UW symbols
+
+          mod_codeword_no_uw = remove_uw_symbols(mod_codeword, code_param.data_bits_per_frame/2 - length(uw)/2, length(uw)/2);
+          mod_codeword_no_uw = [mod_codeword_no_uw mod_codeword((code_param.data_bits_per_frame/2+1):code_param.code_bits_per_frame/2)];
+
+          % de-interleave
+
+          tmp = deinterleave_symbols(interleaver, mod_codeword_no_uw);
+        
+          % insert known symbols at end of data
+
+          mod_codeword_deinter = [ tmp(1:(code_param.data_bits_per_frame/2 - length(uw)/2)) ...
+                                 ones(1,length(uw)/2) * qpsk_mod([0 0]) ...
+                                 tmp((code_param.data_bits_per_frame/2 - length(uw)/2+1):length(tmp)) ];
+          % determine BER stats of raw data before decoding
+
+          raw_bits = zeros(1, code_param.data_bits_per_frame - length(uw));
+          for i=1:(code_param.data_bits_per_frame - length(uw))/2
+              raw_bits(2*(i-1)+1:2*i) = qpsk_demod(mod_codeword_deinter(i));
+          end
+          error_positions = xor(vd, raw_bits);
+          Nerrs = sum(error_positions);
+          Trawerrs += Nerrs;
+          nrawerr(Tframes) = Nerrs;
+
+          % Determine Es/N for each carrier. For this codeword we assume
+          % across codeword (currently 320ms) signal is stationary.
+          % So for each carrier signal level is constant, so we can
+          % average across all symols of that carrier to get a better
+          % estimate of the carrier power.  The spectral noise density
+          % No will be the same for the bandwidth of each carrier.  So
+          % we can use noise samples from all symbols together to get
+          % a better estimate of the noise power.
+          
+          sig_pwr(Tframes,:) = zeros(1,Nc);
+          noise_samples = [];
+          for n=1:Nc
+
+            % extract a vector of one carrier's symbols for this codeword
+            % rotate so that decision boundaries are now real and imag axis
+
+            r = mod_codeword(n:Nc:length(mod_codeword)) .* exp(j*pi/4);
+
+            sig_est = mean(abs(r));
+
+            % The noise is the variance of symbols (samples) about the actual symbol position
+            % we reflect all symbols into the first quadrant to simplify things, as the actual
+            % received symbol isn't matter, just the noise around it.  We model the received
+            % symbol based on the estimated signal level.
+
+            refl_symbols = abs(real(r)) + j*abs(imag(r));    
+            est_symbols = exp(j*pi/4)*sig_est*ones(1,length(r));
+            noise_samples = [ noise_samples (est_symbols - refl_symbols)];
+                       
+            sig_pwr(Tframes,n) = sig_est .^ 2;
+          end
+          noise_pwr(Tframes) = var(noise_samples);
+          %plot(real(refl_symbols), imag(refl_symbols), '+');
+          %hold on;
+          %plot(real(exp(j*pi/4)*sig_est*ones(1,length(r))), imag(exp(j*pi/4)*sig_est*ones(1,length(r))), 'r+');
+          %hold off;
+          %printf("SNR: %f\n", 10*log10(sig_est*sig_est/noise_pwr(Tframes)));
+          % Set erasures for carrier beneath a certain Es/N
+          
+          for n=1:Nc
+              symbols++;
+              EsN(n) = 10*log10(sig_pwr(Tframes,n)/noise_pwr(Tframes));
+              if (EsN(n) < 1)
+                 %mod_codeword(n:Nc:length(mod_codeword)) = 0;    
+                 %printf("Tframes: %d n: %d EsN = %3.2fdB\n", Tframes, n, EsN(n)); 
+                 erasures++;                                     
+              end
+          end
+
+          % De-interleave again with erasures set ----------------------
+
+          % remove UW symbols
+
+          mod_codeword_no_uw = remove_uw_symbols(mod_codeword, code_param.data_bits_per_frame/2 - length(uw)/2, length(uw)/2);
+          mod_codeword_no_uw = [mod_codeword_no_uw mod_codeword((code_param.data_bits_per_frame/2+1):code_param.code_bits_per_frame/2)];
+
+          tmp = deinterleave_symbols(interleaver, mod_codeword_no_uw);
+        
+          % insert known symbols at end of data
+
+          mod_codeword_deinter = [ tmp(1:(code_param.data_bits_per_frame/2 - length(uw)/2)) ...
+                                 ones(1,length(uw)/2) * qpsk_mod([0 0]) ...
+                                 tmp((code_param.data_bits_per_frame/2 - length(uw)/2+1):length(tmp)) ];
+
+          % LDPC decode ------------------------------------------------
+
+          detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, mod_codeword_deinter, EsNo);
+
+          % unpack payload data, removing UW
+
+          vd_rx = detected_data(1:(code_param.data_bits_per_frame - length(uw)));
+
+          % measure coded BER
+
+          error_positions = xor(vd, vd_rx);
+          Nerrs = sum(error_positions);
+          if Nerrs>0, fprintf(1,'x'); Ferrs++; ,  else fprintf(1,'.'),  end
+          Tbits += length(vd);
+          Terrs += Nerrs;
+          nerr(Tframes) = Nerrs;
+
+          % save error patterns is simulated vocoder data to disk
+
+          fwrite(fep, error_positions, "short");
+          
+      end
+
+      if (sync_state)
+          sync_count++;
+          if (sync_count == 8)
+              sync_count = 0;
+          end
+      end
+
+      % read in one modulated modem frame at a time
+
+      [mod_unpackedmodem_float32, count] = fread(fm, nbitspermodemframe, "float32");
+      if (fet == -1)
+          entered_track = 0;
+      else
+          entered_track = fread(fet, 1, "int");
+      end
+  end
+
+  fclose(fep);
+
+  printf("\nFrames: %d bits: %d errors: %d Raw BER = %f Coded BER = %f FER = %f\n", Tframes, Tbits, Terrs, Trawerrs/Tbits, Terrs/Tbits, Ferrs/Tframes);
+  printf("Symbols: %d Erasures: %d  %f\n", symbols, erasures, erasures/symbols);
+  figure(8)
+  clf;
+  [n m] = size(mod_unpackedmodem_log);
+  plot( real(mod_unpackedmodem_log), imag(mod_unpackedmodem_log), '+')
+  axis([-2 2 -2 2]);
+  title('Scatter Diagram');
+
+  figure(9)
+  subplot(311)
+  plot(sync_state_log);
+  subplot(312)
+  plot(nrawerr);
+  subplot(313)
+  plot(nerr);
+
+  figure(10);
+  plot(10*log10(sig_pwr(:,3)./noise_pwr(:)),'b');
+  hold on;
+  plot(10+10*log10(noise_pwr(:)));
+  plot(10+10*log10(sig_pwr(:,3)),'r');
+%  for n=2:Nc
+%    plot(n*10+10*log10(sig_pwr(:,n)./noise_pwr(:,n)));
+%    plot(n*10+10*log10(sig_pwr(:,n)),'r');
+%  end
+  hold off;
+
+  y = 1:Tframes;
+  x = 1:Nc;
+  z = 10*log10(sig_pwr(:,:)./((noise_pwr(:)*ones(1, Nc))));
+  %printf("mean SNR = %3.2fdB\n", mean(z));
+  figure(11);
+  imagesc(x,y,z);
+  figure(12);
+  mesh(x,y,z);
+  axis([1 Nc 1 Tframes 5 15]);
+
+endfunction
index 023c5172094156e4ed748eb4354e0dff61fc32a1..87df284af78be9e38603bf8973889453540dbd3f 100644 (file)
-% ldpcenc.m\r
-% David Rowe 20 Dec 2013\r
-% \r
-% LDPC encoder function. Takes a random data pattern, LDPC Encodes and\r
-% inserts Unique Word (UW) sync bits and ouputs this as a packed\r
-% binary file suitable for the Nc=18 carrier FDMDV modulator,\r
-% fdmdv_mod.  Also produces a "modulated" output file of QPSK\r
-% symbols, suitable for feeding into ldpcdec for testing.\r
-\r
-function ldpcenc(filename)\r
-\r
-  % Start CML library\r
-\r
-  currentdir = pwd;\r
-  addpath '/home/david/tmp/cml/mat'    % assume the source files stored here\r
-  cd /home/david/tmp/cml\r
-  CmlStartup                           % note that this is not in the cml path!\r
-  cd(currentdir)\r
-  \r
-  % Our LDPC library\r
-\r
-  ldpc;\r
-\r
-  % Start simulation\r
-\r
-  rand('state',1);\r
-\r
-  rate = 3/4; \r
-  framesize = 576;  \r
-\r
-  mod_order = 4; \r
-  modulation = 'QPSK';\r
-  mapping = 'gray';\r
-\r
-  demod_type = 0;\r
-  decoder_type = 0;\r
-  max_iterations = 100;\r
-\r
-  nbitspervocoderframe = 52;\r
-  nvocoderframes = 8;\r
-  nbitspermodemframe = 72;\r
-\r
-  code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);\r
-\r
-  data = [];\r
-  r = []; \r
-  load interleaver.txt\r
-  interleaver = interleaver + 1;\r
-\r
-  % Encoder: Generate simulated vocoder data\r
-  %          LPDC encode\r
-  %          interleave           \r
-  %          insert UW bits\r
-\r
-  Nframes = 100;\r
-  uw = [1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0];\r
-\r
-  % repeat same simulated vocoder data to ease testing\r
-\r
-  vd = round( rand( 1, nbitspervocoderframe*nvocoderframes) );\r
-\r
-  % pad data with zeros the size of UW\r
-\r
-  vdpad = [vd zeros(1, length(uw))];\r
-\r
-  % LDPC encode\r
-\r
-  [codewordpad, s] = ldpc_enc(vdpad, code_param);\r
-  code_param.code_bits_per_frame = length(codewordpad);\r
-  code_param.symbols_per_frame = length(s);\r
-\r
-  % remove padded zeros after encoding to leave room for UW bits (code\r
-  % is systematic)\r
-\r
-  codeword = [ codewordpad(1:length(vd)) codewordpad((length(vd)+length(uw)+1):length(codewordpad)) ];\r
-\r
-  % interleave, insert UW bits, and pack bits (as C modulator likes packed bits)\r
-\r
-  codeword_interleaved = interleave_bits(interleaver, codeword);\r
-  codeword_interleaved_uw = [insert_uw(codeword_interleaved(1:length(vd)), uw) codeword_interleaved(length(vd)+1:length(codeword_interleaved)) ];\r
-  packedcodeword = packmsb(codeword_interleaved_uw);\r
-\r
-  cwfilename = strcat(filename,"_codeword.bin");\r
-  fc=fopen(cwfilename,"wb");\r
-  for nn = 1: Nframes        \r
-      fwrite(fc,packedcodeword,"uchar");\r
-  end\r
-  fclose(fc);\r
-\r
-  %printf("framesize: %d data_bits_per_frame: %d code_bits_per_frame: %d\n", ...\r
-  %        framesize, code_param.data_bits_per_frame,  code_param.code_bits_per_frame);\r
-\r
-  printf("Encoded %d LDPC codewords, saved in packed file: %s\n", Nframes, cwfilename);\r
-\r
-  % Modulator: Modulate to QPSK symbols ------------------------------------------\r
-\r
-  nbytespackedcodeword=length(packedcodeword);\r
-  fc=fopen(cwfilename,"rb");\r
-  mcwfilename = strcat(filename,"_modcodeword.bin");\r
-  fm=fopen(mcwfilename,"wb");\r
-  nbytespackedmodemframe = nbitspermodemframe/8;\r
-  n = 0;\r
-\r
-  [packedmodem, count] = fread(fc,nbytespackedmodemframe,"uchar");\r
-  while (count == nbytespackedmodemframe)\r
-      n++;\r
-      unpackedmodem = unpackmsb(packedmodem);\r
-\r
-      ii = 1;\r
-      for i=1:2:length(unpackedmodem)\r
-          mod_unpackedmodem(ii) = qpsk_mod(unpackedmodem(i:i+1));\r
-          mod_unpackedmodem_float32(i) = real(mod_unpackedmodem(ii));\r
-          mod_unpackedmodem_float32(i+1) = imag(mod_unpackedmodem(ii));\r
-          ii += 1;\r
-      end\r
-\r
-      fwrite(fm, mod_unpackedmodem_float32, "float32");\r
-      [packedmodem, count] = fread(fc,nbytespackedmodemframe,"uchar");\r
-  end\r
-  fclose(fc);\r
-  fclose(fm);\r
-  printf("Modulated %d modem frames to file: %s\n", n, mcwfilename);\r
-endfunction\r
-\r
-\r
+% ldpcenc.m
+% David Rowe 20 Dec 2013
+% 
+% LDPC encoder function. Takes a random data pattern, LDPC Encodes and
+% inserts Unique Word (UW) sync bits and ouputs this as a packed
+% binary file suitable for the Nc=18 carrier FDMDV modulator,
+% fdmdv_mod.  Also produces a "modulated" output file of QPSK
+% symbols, suitable for feeding into ldpcdec for testing.
+
+function ldpcenc(filename)
+
+  % Start CML library
+
+  currentdir = pwd;
+  addpath '/home/david/tmp/cml/mat'    % assume the source files stored here
+  cd /home/david/tmp/cml
+  CmlStartup                           % note that this is not in the cml path!
+  cd(currentdir)
+  
+  % Our LDPC library
+
+  ldpc;
+
+  % Start simulation
+
+  rand('state',1);
+
+  rate = 3/4; 
+  framesize = 576;  
+
+  mod_order = 4; 
+  modulation = 'QPSK';
+  mapping = 'gray';
+
+  demod_type = 0;
+  decoder_type = 0;
+  max_iterations = 100;
+
+  nbitspervocoderframe = 52;
+  nvocoderframes = 8;
+  nbitspermodemframe = 72;
+
+  code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);
+
+  data = [];
+  r = []; 
+  load interleaver.txt
+  interleaver = interleaver + 1;
+
+  % Encoder: Generate simulated vocoder data
+  %          LPDC encode
+  %          interleave           
+  %          insert UW bits
+
+  Nframes = 100;
+  uw = [1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0];
+
+  % repeat same simulated vocoder data to ease testing
+
+  vd = round( rand( 1, nbitspervocoderframe*nvocoderframes) );
+
+  % pad data with zeros the size of UW
+
+  vdpad = [vd zeros(1, length(uw))];
+
+  % LDPC encode
+
+  [codewordpad, s] = ldpc_enc(vdpad, code_param);
+  code_param.code_bits_per_frame = length(codewordpad);
+  code_param.symbols_per_frame = length(s);
+
+  % remove padded zeros after encoding to leave room for UW bits (code
+  % is systematic)
+
+  codeword = [ codewordpad(1:length(vd)) codewordpad((length(vd)+length(uw)+1):length(codewordpad)) ];
+
+  % interleave, insert UW bits, and pack bits (as C modulator likes packed bits)
+
+  codeword_interleaved = interleave_bits(interleaver, codeword);
+  codeword_interleaved_uw = [insert_uw(codeword_interleaved(1:length(vd)), uw) codeword_interleaved(length(vd)+1:length(codeword_interleaved)) ];
+  packedcodeword = packmsb(codeword_interleaved_uw);
+
+  cwfilename = strcat(filename,"_codeword.bin");
+  fc=fopen(cwfilename,"wb");
+  for nn = 1: Nframes        
+      fwrite(fc,packedcodeword,"uchar");
+  end
+  fclose(fc);
+
+  %printf("framesize: %d data_bits_per_frame: %d code_bits_per_frame: %d\n", ...
+  %        framesize, code_param.data_bits_per_frame,  code_param.code_bits_per_frame);
+
+  printf("Encoded %d LDPC codewords, saved in packed file: %s\n", Nframes, cwfilename);
+
+  % Modulator: Modulate to QPSK symbols ------------------------------------------
+
+  nbytespackedcodeword=length(packedcodeword);
+  fc=fopen(cwfilename,"rb");
+  mcwfilename = strcat(filename,"_modcodeword.bin");
+  fm=fopen(mcwfilename,"wb");
+  nbytespackedmodemframe = nbitspermodemframe/8;
+  n = 0;
+
+  [packedmodem, count] = fread(fc,nbytespackedmodemframe,"uchar");
+  while (count == nbytespackedmodemframe)
+      n++;
+      unpackedmodem = unpackmsb(packedmodem);
+
+      ii = 1;
+      for i=1:2:length(unpackedmodem)
+          mod_unpackedmodem(ii) = qpsk_mod(unpackedmodem(i:i+1));
+          mod_unpackedmodem_float32(i) = real(mod_unpackedmodem(ii));
+          mod_unpackedmodem_float32(i+1) = imag(mod_unpackedmodem(ii));
+          ii += 1;
+      end
+
+      fwrite(fm, mod_unpackedmodem_float32, "float32");
+      [packedmodem, count] = fread(fc,nbytespackedmodemframe,"uchar");
+  end
+  fclose(fc);
+  fclose(fm);
+  printf("Modulated %d modem frames to file: %s\n", n, mcwfilename);
+endfunction
+
+
index 0b45ff7992d2946a83267ba68aea3b698fbbf314..caa5bf2a3bd72efd284e068125de9d8534e16422 100644 (file)
-% ldpcut.m\r
-%\r
-% David Rowe 18 Dec 2013\r
-%\r
-% Octave LDPC unit test script, based on simulation by Bill Cowley VK5DSP\r
-%\r
-\r
-% Start CML library (see CML set up instructions in ldpc.m)\r
-\r
-currentdir = pwd;\r
-addpath '/home/david/tmp/cml/mat'    % assume the source files stored here\r
-cd /home/david/tmp/cml\r
-CmlStartup                           % note that this is not in the cml path!\r
-cd(currentdir)\r
-\r
-% Our LDPC library\r
-\r
-ldpc;\r
-qpsk_;\r
-\r
-function sim_out = run_simulation(sim_in)\r
-\r
-  rate = sim_in.rate; \r
-  framesize = sim_in.framesize;  \r
-  Ntrials = sim_in.Ntrials;\r
-  EsNodBvec = sim_in.EsNodBvec;\r
-  verbose = sim_in.verbose;\r
-\r
-  % Start simulation\r
-\r
-  mod_order = 4; \r
-  modulation = 'QPSK';\r
-  mapping = 'gray';\r
-\r
-  demod_type = 0;\r
-  decoder_type = 0;\r
-  max_iterations = 100;\r
-\r
-  code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);\r
-\r
-  for ne = 1:length(EsNodBvec)\r
-    EsNodB = EsNodBvec(ne);\r
-    EsNo = 10^(EsNodB/10);\r
-    variance = 1/EsNo;\r
-\r
-    Tbits = Terrs = Ferrs = 0;\r
-    \r
-    tx_bits = [];\r
-    tx_symbols = []; \r
-    rx_symbols = [];\r
-\r
-    % Encode a bunch of frames\r
-\r
-    for nn = 1: Ntrials        \r
-      atx_bits = round(rand( 1, code_param.data_bits_per_frame));\r
-      tx_bits = [tx_bits atx_bits];\r
-      [tx_codeword atx_symbols] = ldpc_enc(atx_bits, code_param);\r
-      tx_symbols = [tx_symbols atx_symbols];\r
-    end\r
-\r
-    % Add AWGN noise, 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im\r
-\r
-    noise = sqrt(variance*0.5)*(randn(1,length(tx_symbols)) + j*randn(1,length(tx_symbols)));\r
-    rx_symbols = tx_symbols + noise;\r
-\r
-    % Decode a bunch of frames\r
-\r
-    for nn = 1: Ntrials        \r
-      st = (nn-1)*code_param.symbols_per_frame + 1;\r
-      en = (nn)*code_param.symbols_per_frame;\r
-      arx_codeword = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_symbols(st:en), EsNo, ones(1,code_param.symbols_per_frame));\r
-      st = (nn-1)*code_param.data_bits_per_frame + 1;\r
-      en = (nn)*code_param.data_bits_per_frame;\r
-      error_positions = xor(arx_codeword(1:code_param.data_bits_per_frame), tx_bits(st:en));\r
-      Nerrs = sum( error_positions);\r
-        \r
-      if verbose == 2\r
-        % print "." if frame decoded without errors, 'x' if we can't decode\r
-\r
-        if Nerrs > 0, printf('x'),  else printf('.'),  end\r
-        if (rem(nn, 50)==0),  printf('\n'),  end    \r
-      end\r
-\r
-      if Nerrs > 0,  Ferrs = Ferrs + 1;  end\r
-      Terrs = Terrs + Nerrs;\r
-      Tbits = Tbits + code_param.data_bits_per_frame;        \r
-    end\r
-\r
-    if verbose\r
-      printf("\nEsNodB: %3.2f BER: %f Tbits: %d Terrs: %d Ferrs: %d\n", EsNodB, Terrs/Tbits, Tbits, Terrs,  Ferrs)\r
-    end\r
-\r
-    sim_out.Tbits(ne) = Tbits;\r
-    sim_out.Terrs(ne) = Terrs;\r
-    sim_out.Ferrs(ne) = Ferrs;\r
-    sim_out.BER(ne)   = Terrs/Tbits;\r
-    sim_out.FER(ne)   = Ferrs/Ntrials;\r
-  end\r
-\r
-endfunction\r
-\r
-% START SIMULATIONS ---------------------------------------------------------------\r
-\r
-more off;\r
-\r
-% 1/ Simplest possible one frame simulation ---------------------------------------\r
-\r
-printf("Test 1\n------\n");\r
-\r
-mod_order = 4; \r
-modulation = 'QPSK';\r
-mapping = 'gray';\r
-framesize = 576;         % CML library has a bunch of different framesizes available\r
-rate = 1/2;\r
-demod_type = 0;\r
-decoder_type = 0;\r
-max_iterations = 100;\r
-EsNo = 10;               % decoder needs an estimated channel EsNo (linear ratio, not dB)\r
-\r
-code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);\r
-tx_bits = round(rand(1, code_param.data_bits_per_frame));\r
-[tx_codeword, qpsk_symbols] = ldpc_enc(tx_bits, code_param);\r
-rx_codeword = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, qpsk_symbols, EsNo);\r
-\r
-errors_positions = xor(tx_bits, rx_codeword(1:framesize*rate));\r
-Nerr = sum(errors_positions);\r
-printf("Nerr: %d\n\n", Nerr);\r
-\r
-% 2/ Run a bunch of trials at just one EsNo point --------------------------------------\r
-\r
-printf("Test 2\n------\n");\r
-\r
-sim_in.rate = 0.5; \r
-sim_in.framesize = 2*576;  \r
-sim_in.verbose = 2;\r
-sim_in.Ntrials = 100;\r
-sim_in.EsNodBvec = 5;\r
-run_simulation(sim_in);\r
-\r
-% 3/ Lets draw a Eb/No versus BER curve -------------------------------------------------\r
-\r
-printf("\n\nTest 3\n------\n");\r
-\r
-sim_in.EsNodBvec = -2:10;\r
-sim_out = run_simulation(sim_in);\r
-\r
-EbNodB = sim_in.EsNodBvec - 10*log10(2);  % QPSK has two bits/symbol\r
-uncoded_BER_theory = 0.5*erfc(sqrt(10.^(EbNodB/10)));\r
-\r
-figure(1)\r
-clf\r
-semilogy(EbNodB, uncoded_BER_theory,'r;uncoded QPSK theory;')\r
-hold on;\r
-semilogy(EbNodB-10*log10(sim_in.rate), sim_out.BER+1E-10,'g;LDPC coded QPSK simulation;');\r
-hold off;\r
-grid('minor')\r
-xlabel('Eb/No (dB)')\r
-ylabel('BER')\r
-axis([min(EbNodB) max(EbNodB) min(uncoded_BER_theory) 1])\r
+% ldpcut.m
+%
+% David Rowe 18 Dec 2013
+%
+% Octave LDPC unit test script, based on simulation by Bill Cowley VK5DSP
+%
+
+% Start CML library (see CML set up instructions in ldpc.m)
+
+currentdir = pwd;
+addpath '/home/david/tmp/cml/mat'    % assume the source files stored here
+cd /home/david/tmp/cml
+CmlStartup                           % note that this is not in the cml path!
+cd(currentdir)
+
+% Our LDPC library
+
+ldpc;
+qpsk_;
+
+function sim_out = run_simulation(sim_in)
+
+  rate = sim_in.rate; 
+  framesize = sim_in.framesize;  
+  Ntrials = sim_in.Ntrials;
+  EsNodBvec = sim_in.EsNodBvec;
+  verbose = sim_in.verbose;
+
+  % Start simulation
+
+  mod_order = 4; 
+  modulation = 'QPSK';
+  mapping = 'gray';
+
+  demod_type = 0;
+  decoder_type = 0;
+  max_iterations = 100;
+
+  code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);
+
+  for ne = 1:length(EsNodBvec)
+    EsNodB = EsNodBvec(ne);
+    EsNo = 10^(EsNodB/10);
+    variance = 1/EsNo;
+
+    Tbits = Terrs = Ferrs = 0;
+    
+    tx_bits = [];
+    tx_symbols = []; 
+    rx_symbols = [];
+
+    % Encode a bunch of frames
+
+    for nn = 1: Ntrials        
+      atx_bits = round(rand( 1, code_param.data_bits_per_frame));
+      tx_bits = [tx_bits atx_bits];
+      [tx_codeword atx_symbols] = ldpc_enc(atx_bits, code_param);
+      tx_symbols = [tx_symbols atx_symbols];
+    end
+
+    % Add AWGN noise, 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im
+
+    noise = sqrt(variance*0.5)*(randn(1,length(tx_symbols)) + j*randn(1,length(tx_symbols)));
+    rx_symbols = tx_symbols + noise;
+
+    % Decode a bunch of frames
+
+    for nn = 1: Ntrials        
+      st = (nn-1)*code_param.symbols_per_frame + 1;
+      en = (nn)*code_param.symbols_per_frame;
+      arx_codeword = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_symbols(st:en), EsNo, ones(1,code_param.symbols_per_frame));
+      st = (nn-1)*code_param.data_bits_per_frame + 1;
+      en = (nn)*code_param.data_bits_per_frame;
+      error_positions = xor(arx_codeword(1:code_param.data_bits_per_frame), tx_bits(st:en));
+      Nerrs = sum( error_positions);
+        
+      if verbose == 2
+        % print "." if frame decoded without errors, 'x' if we can't decode
+
+        if Nerrs > 0, printf('x'),  else printf('.'),  end
+        if (rem(nn, 50)==0),  printf('\n'),  end    
+      end
+
+      if Nerrs > 0,  Ferrs = Ferrs + 1;  end
+      Terrs = Terrs + Nerrs;
+      Tbits = Tbits + code_param.data_bits_per_frame;        
+    end
+
+    if verbose
+      printf("\nEsNodB: %3.2f BER: %f Tbits: %d Terrs: %d Ferrs: %d\n", EsNodB, Terrs/Tbits, Tbits, Terrs,  Ferrs)
+    end
+
+    sim_out.Tbits(ne) = Tbits;
+    sim_out.Terrs(ne) = Terrs;
+    sim_out.Ferrs(ne) = Ferrs;
+    sim_out.BER(ne)   = Terrs/Tbits;
+    sim_out.FER(ne)   = Ferrs/Ntrials;
+  end
+
+endfunction
+
+% START SIMULATIONS ---------------------------------------------------------------
+
+more off;
+
+% 1/ Simplest possible one frame simulation ---------------------------------------
+
+printf("Test 1\n------\n");
+
+mod_order = 4; 
+modulation = 'QPSK';
+mapping = 'gray';
+framesize = 576;         % CML library has a bunch of different framesizes available
+rate = 1/2;
+demod_type = 0;
+decoder_type = 0;
+max_iterations = 100;
+EsNo = 10;               % decoder needs an estimated channel EsNo (linear ratio, not dB)
+
+code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);
+tx_bits = round(rand(1, code_param.data_bits_per_frame));
+[tx_codeword, qpsk_symbols] = ldpc_enc(tx_bits, code_param);
+rx_codeword = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, qpsk_symbols, EsNo);
+
+errors_positions = xor(tx_bits, rx_codeword(1:framesize*rate));
+Nerr = sum(errors_positions);
+printf("Nerr: %d\n\n", Nerr);
+
+% 2/ Run a bunch of trials at just one EsNo point --------------------------------------
+
+printf("Test 2\n------\n");
+
+sim_in.rate = 0.5; 
+sim_in.framesize = 2*576;  
+sim_in.verbose = 2;
+sim_in.Ntrials = 100;
+sim_in.EsNodBvec = 5;
+run_simulation(sim_in);
+
+% 3/ Lets draw a Eb/No versus BER curve -------------------------------------------------
+
+printf("\n\nTest 3\n------\n");
+
+sim_in.EsNodBvec = -2:10;
+sim_out = run_simulation(sim_in);
+
+EbNodB = sim_in.EsNodBvec - 10*log10(2);  % QPSK has two bits/symbol
+uncoded_BER_theory = 0.5*erfc(sqrt(10.^(EbNodB/10)));
+
+figure(1)
+clf
+semilogy(EbNodB, uncoded_BER_theory,'r;uncoded QPSK theory;')
+hold on;
+semilogy(EbNodB-10*log10(sim_in.rate), sim_out.BER+1E-10,'g;LDPC coded QPSK simulation;');
+hold off;
+grid('minor')
+xlabel('Eb/No (dB)')
+ylabel('BER')
+axis([min(EbNodB) max(EbNodB) min(uncoded_BER_theory) 1])
index 6895ca23125bd1479767abcc1d9fffbb09f0ba3f..7a5e89e1ddd7de541a7fa63a7b131a04fafc3818 100644 (file)
-function [ar,e,k]=lpcauto(s,p,t)\r
-%LPCAUTO  performs autocorrelation LPC analysis [AR,E,K]=(S,P,T)\r
-%  Inputs:\r
-%     s(ns)   is the input signal\r
-%         p       is the order (default: 12)\r
-%         t(nf,3) specifies the frames size details: each row specifies\r
-%                 up to three values per frame: [len anal skip] where:\r
-%                         len     is the length of the frame (default: length(s))\r
-%                         anal    is the analysis length (default: len)\r
-%                         skip    is the number of samples to skip at the beginning (default: 0)\r
-%                 If t contains only one row, it will be used repeatedly\r
-%                 until there are no more samples left in s.\r
-%\r
-% Outputs:\r
-%          ar(nf,p+1) are the AR coefficients with ar(1) = 1\r
-%          e(nf)      is the energy in the residual.\r
-%                     sqrt(e) is often called the 'gain' of the filter.\r
-%          k(nf,2)    gives the first and last sample of the analysis interval\r
-\r
-% Notes:\r
-%\r
-% (1) The first frame always starts at sample s(1) and the analysis window starts at s(t(1,3)+1).\r
-% (2) The elements of t need not be integers.\r
-% (3) The analysis interval is always multiplied by a hamming window\r
-% (4) As an example, if p=3 and t=[10 5 2], then the illustration below shows\r
-%     successive frames labelled a, b, c, ... with capitals for the\r
-%     analysis regions. Note that the first frame starts at s(1)\r
-%\r
-%        a a A A A A A a a a b b B B B B B b b b c c C C C C C c c c d ...\r
-%\r
-%     For speech processing, it can be advantageous to restrict the analysis regions\r
-%     to time intervals when the glottis is closed.\r
-%\r
-% (5) Frames can overlap: e.g. t=[10 20] will use analysis frames of\r
-%     length 20 overlapped by 10 samples.\r
-% (6) For speech processing p should be at least 2*f*l/c where f is the sampling\r
-%     frequency, l the vocal tract length and c the speed of sound. For a typical\r
-%     male (l=17 cm) this gives f/1000.\r
-\r
-%      Copyright (C) Mike Brookes 1997\r
-%      Version: $Id: lpcauto.m 713 2011-10-16 14:45:43Z dmb $\r
-%\r
-%   VOICEBOX is a MATLAB toolbox for speech processing.\r
-%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html\r
-%\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%   This program is free software; you can redistribute it and/or modify\r
-%   it under the terms of the GNU General Public License as published by\r
-%   the Free Software Foundation; either version 2 of the License, or\r
-%   (at your option) any later version.\r
-%\r
-%   This program is distributed in the hope that it will be useful,\r
-%   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-%   GNU General Public License for more details.\r
-%\r
-%   You can obtain a copy of the GNU General Public License from\r
-%   http://www.gnu.org/copyleft/gpl.html or by writing to\r
-%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-s = s(:); % make it a column vector\r
-if nargin < 2 p=12; end;\r
-if nargin < 3 t=length(s); end;\r
-%if nargin < 4 w='ham'; end;\r
-[nf,ng]=size(t);\r
-if ng<2 t=[t t]; end;\r
-if ng<3 t=[t zeros(nf,1)]; end;\r
-if nf==1\r
-    nf=floor(1+(length(s)-t(2)-t(3))/t(1));\r
-    tr=0;\r
-else\r
-    tr=1;\r
-end;\r
-\r
-ar=zeros(nf,p+1);\r
-ar(:,1)=1;\r
-e=zeros(nf,1);\r
-\r
-t1=1;\r
-it=1;\r
-nw=-1;\r
-zp=zeros(1,p);\r
-r=(0:p);\r
-for jf=1:nf\r
-    k(jf,1) = ceil(t1+t(it,3));\r
-    k(jf,2) = ceil(t1+t(it,3)+t(it,2)-1);\r
-    cs = (k(jf,1):k(jf,2)).';\r
-    nc = length(cs);\r
-    pp=min(p,nc);\r
-    dd=s(cs);\r
-    if nc~=nw\r
-        % possibly we should have a window whose square integral equals unity\r
-        ww=hamming(nc); nw=nc;\r
-        y=zeros(1,nc+p);\r
-        c=(1:nc)';\r
-    end\r
-    wd=dd(:).*ww;        % windowed data vector\r
-    y(1:nc)=wd;          % data vector with p appended zeros\r
-    z=zeros(nc,pp+1);    % data matrix\r
-    %  was previously  z(:)=y(c(:,ones(1,pp+1))+r(ones(nc,1),1:pp+1));\r
-    z(:)=y(repmat(c,1,pp+1)+repmat(r,nc,1));\r
-    rr=wd'*z;\r
-    rm=toeplitz(rr(1:pp));\r
-    rk=rank(rm);\r
-    if rk\r
-        if rk<pp\r
-            rm=rm(1:rk,1:rk);\r
-        end\r
-        ar(jf,2:rk+1)=-rr(2:rk+1)/rm;\r
-    end\r
-    e(jf)=rr*ar(jf,1:pp+1)';\r
-    t1=t1+t(it,1);\r
-    it=it+tr;\r
-end\r
-\r
+function [ar,e,k]=lpcauto(s,p,t)
+%LPCAUTO  performs autocorrelation LPC analysis [AR,E,K]=(S,P,T)
+%  Inputs:
+%     s(ns)   is the input signal
+%         p       is the order (default: 12)
+%         t(nf,3) specifies the frames size details: each row specifies
+%                 up to three values per frame: [len anal skip] where:
+%                         len     is the length of the frame (default: length(s))
+%                         anal    is the analysis length (default: len)
+%                         skip    is the number of samples to skip at the beginning (default: 0)
+%                 If t contains only one row, it will be used repeatedly
+%                 until there are no more samples left in s.
+%
+% Outputs:
+%          ar(nf,p+1) are the AR coefficients with ar(1) = 1
+%          e(nf)      is the energy in the residual.
+%                     sqrt(e) is often called the 'gain' of the filter.
+%          k(nf,2)    gives the first and last sample of the analysis interval
+
+% Notes:
+%
+% (1) The first frame always starts at sample s(1) and the analysis window starts at s(t(1,3)+1).
+% (2) The elements of t need not be integers.
+% (3) The analysis interval is always multiplied by a hamming window
+% (4) As an example, if p=3 and t=[10 5 2], then the illustration below shows
+%     successive frames labelled a, b, c, ... with capitals for the
+%     analysis regions. Note that the first frame starts at s(1)
+%
+%        a a A A A A A a a a b b B B B B B b b b c c C C C C C c c c d ...
+%
+%     For speech processing, it can be advantageous to restrict the analysis regions
+%     to time intervals when the glottis is closed.
+%
+% (5) Frames can overlap: e.g. t=[10 20] will use analysis frames of
+%     length 20 overlapped by 10 samples.
+% (6) For speech processing p should be at least 2*f*l/c where f is the sampling
+%     frequency, l the vocal tract length and c the speed of sound. For a typical
+%     male (l=17 cm) this gives f/1000.
+
+%      Copyright (C) Mike Brookes 1997
+%      Version: $Id: lpcauto.m 713 2011-10-16 14:45:43Z dmb $
+%
+%   VOICEBOX is a MATLAB toolbox for speech processing.
+%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%   This program is free software; you can redistribute it and/or modify
+%   it under the terms of the GNU General Public License as published by
+%   the Free Software Foundation; either version 2 of the License, or
+%   (at your option) any later version.
+%
+%   This program is distributed in the hope that it will be useful,
+%   but WITHOUT ANY WARRANTY; without even the implied warranty of
+%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%   GNU General Public License for more details.
+%
+%   You can obtain a copy of the GNU General Public License from
+%   http://www.gnu.org/copyleft/gpl.html or by writing to
+%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+s = s(:); % make it a column vector
+if nargin < 2 p=12; end;
+if nargin < 3 t=length(s); end;
+%if nargin < 4 w='ham'; end;
+[nf,ng]=size(t);
+if ng<2 t=[t t]; end;
+if ng<3 t=[t zeros(nf,1)]; end;
+if nf==1
+    nf=floor(1+(length(s)-t(2)-t(3))/t(1));
+    tr=0;
+else
+    tr=1;
+end;
+
+ar=zeros(nf,p+1);
+ar(:,1)=1;
+e=zeros(nf,1);
+
+t1=1;
+it=1;
+nw=-1;
+zp=zeros(1,p);
+r=(0:p);
+for jf=1:nf
+    k(jf,1) = ceil(t1+t(it,3));
+    k(jf,2) = ceil(t1+t(it,3)+t(it,2)-1);
+    cs = (k(jf,1):k(jf,2)).';
+    nc = length(cs);
+    pp=min(p,nc);
+    dd=s(cs);
+    if nc~=nw
+        % possibly we should have a window whose square integral equals unity
+        ww=hamming(nc); nw=nc;
+        y=zeros(1,nc+p);
+        c=(1:nc)';
+    end
+    wd=dd(:).*ww;        % windowed data vector
+    y(1:nc)=wd;          % data vector with p appended zeros
+    z=zeros(nc,pp+1);    % data matrix
+    %  was previously  z(:)=y(c(:,ones(1,pp+1))+r(ones(nc,1),1:pp+1));
+    z(:)=y(repmat(c,1,pp+1)+repmat(r,nc,1));
+    rr=wd'*z;
+    rm=toeplitz(rr(1:pp));
+    rk=rank(rm);
+    if rk
+        if rk<pp
+            rm=rm(1:rk,1:rk);
+        end
+        ar(jf,2:rk+1)=-rr(2:rk+1)/rm;
+    end
+    e(jf)=rr*ar(jf,1:pp+1)';
+    t1=t1+t(it,1);
+    it=it+tr;
+end
+
index 76beaf9c8cc27506eaefffc27817293d0f40acf6..9db9d121bce1ef598f21d16e2c067f8c6584e2e9 100644 (file)
-% test_dqpsk.m\r
-% David Rowe March 2014\r
-%\r
-% Single sample/symbol DQPSK modem simulation to test modulating modem\r
-% tx power based on speech energy.\r
-\r
-1;\r
-\r
-% main test function \r
-\r
-function sim_out = ber_test(sim_in)\r
-    Fs = 8000;\r
-\r
-    verbose          = sim_in.verbose;\r
-    framesize        = sim_in.framesize;\r
-    Ntrials          = sim_in.Ntrials;\r
-    Esvec            = sim_in.Esvec;\r
-    phase_offset     = sim_in.phase_offset;\r
-    w_offset         = sim_in.w_offset;\r
-    plot_scatter     = sim_in.plot_scatter;\r
-    Rs               = sim_in.Rs;\r
-    hf_sim           = sim_in.hf_sim;\r
-    nhfdelay         = sim_in.hf_delay_ms*Rs/1000;\r
-    hf_phase_only    = sim_in.hf_phase_only;\r
-    hf_mag_only      = sim_in.hf_mag_only;\r
-    Nc               = sim_in.Nc;\r
-    symbol_amp       = sim_in.symbol_amp;\r
-\r
-    bps              = 2;\r
-    Nsymb            = framesize/bps;\r
-    for k=1:Nc\r
-      prev_sym_tx(k) = qpsk_mod([0 0]);\r
-      prev_sym_rx(k) = qpsk_mod([0 0]);\r
-    end\r
-\r
-    rate = 1;\r
-\r
-    % Init HF channel model from stored sample files of spreading signal ----------------------------------\r
-\r
-    % convert "spreading" samples from 1kHz carrier at Fs to complex\r
-    % baseband, generated by passing a 1kHz sine wave through PathSim\r
-    % with the ccir-poor model, enabling one path at a time.\r
-    \r
-    Fc = 1000; M = Fs/Rs;\r
-    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");\r
-    spread1k = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");\r
-    spread1k_2ms = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-\r
-    % down convert to complex baseband\r
-    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');\r
-    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');\r
-\r
-    % remove -2000 Hz image\r
-    b = fir1(50, 5/Fs);\r
-    spread = filter(b,1,spreadbb);\r
-    spread_2ms = filter(b,1,spreadbb_2ms);\r
-\r
-    % discard first 1000 samples as these were near 0, probably as\r
-    % PathSim states were ramping up\r
-\r
-    spread    = spread(1000:length(spread));\r
-    spread_2ms = spread_2ms(1000:length(spread_2ms));\r
-\r
-    % decimate down to Rs\r
-\r
-    spread = spread(1:M:length(spread));\r
-    spread_2ms = spread_2ms(1:M:length(spread_2ms));\r
-\r
-    % Determine "gain" of HF channel model, so we can normalise\r
-    % carrier power during HF channel sim to calibrate SNR.  I imagine\r
-    % different implementations of ccir-poor would do this in\r
-    % different ways, leading to different BER results.  Oh Well!\r
-\r
-    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));\r
-\r
-    % Start Simulation ----------------------------------------------------------------\r
-\r
-    for ne = 1:length(Esvec)\r
-        EsNodB = Esvec(ne);\r
-        EsNo = 10^(EsNodB/10);\r
-    \r
-        variance = 1/EsNo;\r
-         if verbose > 1\r
-            printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);\r
-        end\r
-        \r
-        Terrs = 0;  Tbits = 0;\r
-\r
-        tx_symb_log        = [];\r
-        rx_symb_log        = [];\r
-        noise_log          = [];\r
-        sim_out.errors_log = [];\r
-\r
-        % init HF channel\r
-\r
-        hf_n = 1;\r
-        hf_angle_log = [];\r
-        hf_fading = ones(1,Nsymb);             % default input for ldpc dec\r
-        hf_model = ones(Ntrials*Nsymb/Nc, Nc); % defaults for plotting surface\r
-\r
-        sim_out.errors_log = [];\r
-        sim_out.Nerrs = [];\r
-        sim_out.snr_log = [];\r
-        sim_out.hf_model_pwr = [];\r
-\r
-        symbol_amp_index = 1;\r
-\r
-        for nn = 1: Ntrials\r
-                  \r
-            tx_bits = round( rand( 1, framesize*rate ) );\r
\r
-            % modulate --------------------------------------------\r
-\r
-            s = zeros(1, Nsymb);\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                tx_symb = qpsk_mod(tx_bits(2*(i-1+k-1)+1:2*(i+k-1)));\r
-                tx_symb *= prev_sym_tx(k);\r
-                prev_sym_tx(k) = tx_symb;\r
-                s(i+k-1) = symbol_amp(symbol_amp_index)*tx_symb;\r
-              end\r
-            end\r
-            s_ch = s;\r
-            symbol_amp_index++;\r
-\r
-            % HF channel simulation  ------------------------------------\r
-            \r
-            if hf_sim\r
-\r
-                % separation between carriers.  Note this is\r
-                % effectively under samples at Rs, I dont think this\r
-                % matters.  Equivalent to doing freq shift at Fs, then\r
-                % decimating to Rs.\r
-\r
-                wsep = 2*pi*(1+0.5);  % e.g. 75Hz spacing at Rs=50Hz, alpha=0.5 filters\r
-\r
-                if Nsymb/Nc != floor(Nsymb/Nc)\r
-                    printf("Error: Nsymb/Nc must be an integrer\n")\r
-                    return;\r
-                end\r
-\r
-                % arrange symbols in Nsymb/Nc by Nc matrix\r
-\r
-                for i=1:Nc:Nsymb\r
-\r
-                    % Determine HF channel at each carrier for this symbol\r
-\r
-                    for k=1:Nc\r
-                        hf_model(hf_n, k) = hf_gain*(spread(hf_n) + exp(-j*k*wsep*nhfdelay)*spread_2ms(hf_n));\r
-                        hf_fading(i+k-1) = abs(hf_model(hf_n, k));\r
-                        if hf_mag_only\r
-                             s_ch(i+k-1) *= abs(hf_model(hf_n, k));\r
-                        else\r
-                             s_ch(i+k-1) *= hf_model(hf_n, k);\r
-                        end\r
-                    end\r
-                    hf_n++;\r
-                end\r
-            end\r
-            \r
-            tx_symb_log = [tx_symb_log s_ch];\r
-\r
-            % "genie" SNR estimate \r
-            \r
-            snr = (s_ch*s_ch')/(Nsymb*variance);\r
-            sim_out.snr_log = [sim_out.snr_log snr];\r
-            sim_out.hf_model_pwr = [sim_out.hf_model_pwr mean(hf_fading.^2)];\r
-\r
-            % AWGN noise and phase/freq offset channel simulation\r
-            % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im\r
-\r
-            noise = sqrt(variance*0.5)*(randn(1,Nsymb) + j*randn(1,Nsymb));\r
-            noise_log = [noise_log noise];\r
\r
-            % organise into carriers to apply frequency and phase offset\r
-\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                 s_ch(i+k-1) = s_ch(i+k-1)*exp(j*phase_offset) + noise(i+k-1);\r
-              end \r
-              phase_offset += w_offset;\r
-            end\r
-               \r
-            % de-modulate\r
-\r
-            rx_bits = zeros(1, framesize);\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                rx_symb = s_ch(i+k-1);\r
-                tmp = rx_symb;\r
-                rx_symb *= conj(prev_sym_rx(k)/abs(prev_sym_rx(k)));\r
-                prev_sym_rx(k) = tmp;\r
-                rx_bits((2*(i-1+k-1)+1):(2*(i+k-1))) = qpsk_demod(rx_symb);\r
-                rx_symb_log = [rx_symb_log rx_symb];\r
-              end\r
-            end\r
-\r
-            error_positions = xor(rx_bits, tx_bits);\r
-            Nerrs = sum(error_positions);\r
-            sim_out.Nerrs = [sim_out.Nerrs Nerrs];\r
-            Terrs += Nerrs;\r
-            Tbits += length(tx_bits);\r
-            \r
-            sim_out.errors_log = [sim_out.errors_log error_positions];\r
-        end\r
-\r
-        TERvec(ne) = Terrs;\r
-        BERvec(ne) = Terrs/Tbits;\r
-\r
-        if verbose \r
-            printf("EsNo (dB): %f  Terrs: %d BER %f ", EsNodB, Terrs, Terrs/Tbits);\r
-            printf("\n");\r
-        end\r
-        if verbose > 1\r
-            printf("Terrs: %d BER %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,\r
-                   Terrs/Tbits, var(tx_symb_log), var(noise_log),\r
-                   var(tx_symb_log), var(noise_log), var(tx_symb_log)/var(noise_log));\r
-        end\r
-    end\r
-    \r
-    Ebvec = Esvec - 10*log10(bps);\r
-\r
-    sim_out.BERvec = BERvec;\r
-    sim_out.Ebvec  = Ebvec;\r
-    sim_out.TERvec = TERvec;\r
-\r
-    if plot_scatter\r
-        figure(2);\r
-        clf;\r
-        scat = rx_symb_log .* exp(j*pi/4);\r
-        plot(real(scat), imag(scat),'+');\r
-        title('Scatter plot');\r
-\r
-        figure(3);\r
-        clf;        \r
-        y = 1:Rs*2;\r
-        x = 1:Nc;\r
-        EsNodBSurface = 20*log10(abs(hf_model(y,:))) - 10*log10(variance);\r
-        mesh(x,y,EsNodBSurface);\r
-        grid\r
-        title('HF Channel Es/No');\r
-\r
-        if 0 \r
-        figure(4);\r
-        clf;\r
-        subplot(211)\r
-        plot(y,abs(hf_model(y,1)))\r
-        title('HF Channel Carrier 1 Mag');\r
-        subplot(212)\r
-        plot(y,angle(hf_model(y,1)))\r
-        title('HF Channel Carrier 1 Phase');\r
-        end\r
-    end\r
-\r
-endfunction\r
-\r
-% Gray coded QPSK modulation function\r
-\r
-function symbol = qpsk_mod(two_bits)\r
-    two_bits_decimal = sum(two_bits .* [2 1]); \r
-    switch(two_bits_decimal)\r
-        case (0) symbol =  1;\r
-        case (1) symbol =  j;\r
-        case (2) symbol = -j;\r
-        case (3) symbol = -1;\r
-    endswitch\r
-endfunction\r
-\r
-% Gray coded QPSK demodulation function\r
-\r
-function two_bits = qpsk_demod(symbol)\r
-    if isscalar(symbol) == 0\r
-        printf("only works with scalars\n");\r
-        return;\r
-    end\r
-    bit0 = real(symbol*exp(j*pi/4)) < 0;\r
-    bit1 = imag(symbol*exp(j*pi/4)) < 0;\r
-    two_bits = [bit1 bit0];\r
-endfunction\r
-\r
-function sim_in = standard_init\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 0;\r
-\r
-  sim_in.Esvec            = 5:15; \r
-  sim_in.Ntrials          = 100;\r
-  sim_in.framesize        = 64;\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 8;\r
-\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-  sim_in.phase_noise_amp  = 0;\r
-\r
-  sim_in.hf_delay_ms      = 2;\r
-  sim_in.hf_sim           = 0;\r
-  sim_in.hf_phase_only    = 0;\r
-  sim_in.hf_mag_only      = 0;\r
-endfunction\r
-\r
-function awgn_hf_ber_curves()\r
-  sim_in = standard_init();\r
-\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));\r
-\r
-  dpsk_awgn = ber_test(sim_in);\r
-  sim_in.hf_sim           = 1;\r
-  dpsk_hf   = ber_test(sim_in);\r
-\r
-  figure(1); \r
-  clf;\r
-  semilogy(Ebvec, BER_theory,'r;QPSK theory;')\r
-  hold on;\r
-  semilogy(dpsk_awgn.Ebvec, dpsk_awgn.BERvec,'g;DQPSK;')\r
-  semilogy(dpsk_hf.Ebvec, dpsk_hf.BERvec,'g;DQPSK HF;')\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-3 1])\r
-end\r
-\r
-sim_in = standard_init();\r
-\r
-% energy file sampled every 10ms\r
-\r
-load ../src/ve9qrp.txt\r
-pdB=10*log10(ve9qrp);\r
-for i=1:length(pdB)\r
-  if pdB(i) < 0\r
-    pdB(i) = 0;\r
-  end\r
-end\r
-\r
-% Down sample to 40ms rate used for 1300 bit/s codec, every 4th sample is transmitted\r
-\r
-pdB = pdB(4:4:length(pdB));\r
-\r
-% Use linear mapping function in dB domain to map to symbol power\r
-\r
-power_map_x  = [ 0 20 24 40 50 ];\r
-power_map_y  = [-6 -6  0 6  6];\r
-mapped_pdB = interp1(power_map_x, power_map_y, pdB);\r
-\r
-%sim_in.symbol_amp = 10 .^ (mapped_pdB/20);\r
-sim_in.symbol_amp = ones(1,length(pdB));\r
-sim_in.plot_scatter = 1;\r
-sim_in.verbose      = 2;\r
-sim_in.hf_sim       = 1;\r
-sim_in.Esvec        = 10;\r
-sim_in.Ntrials      = 400;\r
-\r
-dqpsk_pwr_hf = ber_test(sim_in);\r
-\r
-% note: need way to test that power is aligned with speech\r
-\r
-figure(4)\r
-clf;\r
-plot((1:sim_in.Ntrials)*80*4, pdB(1:sim_in.Ntrials));\r
-hold on;\r
-plot((1:sim_in.Ntrials)*80*4, mapped_pdB(1:sim_in.Ntrials),'r');\r
-hold off;\r
-\r
-figure(5)\r
-clf;\r
-\r
-s = load_raw("../raw/ve9qrp.raw");\r
-M=320; M_on_2 = M/2; % processing delay between input speech and centre of analysis window\r
-plot(M_on_2:(M_on_2-1+sim_in.Ntrials*M),s(1:sim_in.Ntrials*M))\r
-hold on;\r
-plot((1:sim_in.Ntrials)*M, 5000*sim_in.symbol_amp(1:sim_in.Ntrials),'r');\r
-hold off;\r
-axis([1 sim_in.Ntrials*M -3E4 3E4]);\r
-\r
-figure(6)\r
-clf;\r
-plot((1:sim_in.Ntrials)*M, 20*log10(sim_in.symbol_amp(1:sim_in.Ntrials)),'b;Es (dB);');\r
-hold on;\r
-plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.hf_model_pwr),'g;Fading (dB);');\r
-plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.snr_log),'r;Es/No (dB);');\r
-\r
-ber = dqpsk_pwr_hf.Nerrs/sim_in.framesize;\r
-ber_clip = ber;\r
-ber_clip(find(ber > 0.2)) = 0.2;\r
-plot((1:sim_in.Ntrials)*M, -20+100*ber_clip,'k;BER (0-20%);');\r
-hold off;\r
-axis([1 sim_in.Ntrials*M -20 20])\r
-\r
-fep=fopen("dqpsk_errors_pwr.bin","wb"); fwrite(fep, dqpsk_pwr_hf.errors_log, "short"); fclose(fep);\r
-fber=fopen("ber.bin","wb"); fwrite(fber, ber, "float"); fclose(fber);\r
+% test_dqpsk.m
+% David Rowe March 2014
+%
+% Single sample/symbol DQPSK modem simulation to test modulating modem
+% tx power based on speech energy.
+
+1;
+
+% main test function 
+
+function sim_out = ber_test(sim_in)
+    Fs = 8000;
+
+    verbose          = sim_in.verbose;
+    framesize        = sim_in.framesize;
+    Ntrials          = sim_in.Ntrials;
+    Esvec            = sim_in.Esvec;
+    phase_offset     = sim_in.phase_offset;
+    w_offset         = sim_in.w_offset;
+    plot_scatter     = sim_in.plot_scatter;
+    Rs               = sim_in.Rs;
+    hf_sim           = sim_in.hf_sim;
+    nhfdelay         = sim_in.hf_delay_ms*Rs/1000;
+    hf_phase_only    = sim_in.hf_phase_only;
+    hf_mag_only      = sim_in.hf_mag_only;
+    Nc               = sim_in.Nc;
+    symbol_amp       = sim_in.symbol_amp;
+
+    bps              = 2;
+    Nsymb            = framesize/bps;
+    for k=1:Nc
+      prev_sym_tx(k) = qpsk_mod([0 0]);
+      prev_sym_rx(k) = qpsk_mod([0 0]);
+    end
+
+    rate = 1;
+
+    % Init HF channel model from stored sample files of spreading signal ----------------------------------
+
+    % convert "spreading" samples from 1kHz carrier at Fs to complex
+    % baseband, generated by passing a 1kHz sine wave through PathSim
+    % with the ccir-poor model, enabling one path at a time.
+    
+    Fc = 1000; M = Fs/Rs;
+    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");
+    spread1k = fread(fspread, "int16")/10000;
+    fclose(fspread);
+    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");
+    spread1k_2ms = fread(fspread, "int16")/10000;
+    fclose(fspread);
+
+    % down convert to complex baseband
+    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');
+    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');
+
+    % remove -2000 Hz image
+    b = fir1(50, 5/Fs);
+    spread = filter(b,1,spreadbb);
+    spread_2ms = filter(b,1,spreadbb_2ms);
+
+    % discard first 1000 samples as these were near 0, probably as
+    % PathSim states were ramping up
+
+    spread    = spread(1000:length(spread));
+    spread_2ms = spread_2ms(1000:length(spread_2ms));
+
+    % decimate down to Rs
+
+    spread = spread(1:M:length(spread));
+    spread_2ms = spread_2ms(1:M:length(spread_2ms));
+
+    % Determine "gain" of HF channel model, so we can normalise
+    % carrier power during HF channel sim to calibrate SNR.  I imagine
+    % different implementations of ccir-poor would do this in
+    % different ways, leading to different BER results.  Oh Well!
+
+    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));
+
+    % Start Simulation ----------------------------------------------------------------
+
+    for ne = 1:length(Esvec)
+        EsNodB = Esvec(ne);
+        EsNo = 10^(EsNodB/10);
+    
+        variance = 1/EsNo;
+         if verbose > 1
+            printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);
+        end
+        
+        Terrs = 0;  Tbits = 0;
+
+        tx_symb_log        = [];
+        rx_symb_log        = [];
+        noise_log          = [];
+        sim_out.errors_log = [];
+
+        % init HF channel
+
+        hf_n = 1;
+        hf_angle_log = [];
+        hf_fading = ones(1,Nsymb);             % default input for ldpc dec
+        hf_model = ones(Ntrials*Nsymb/Nc, Nc); % defaults for plotting surface
+
+        sim_out.errors_log = [];
+        sim_out.Nerrs = [];
+        sim_out.snr_log = [];
+        sim_out.hf_model_pwr = [];
+
+        symbol_amp_index = 1;
+
+        for nn = 1: Ntrials
+                  
+            tx_bits = round( rand( 1, framesize*rate ) );
+            % modulate --------------------------------------------
+
+            s = zeros(1, Nsymb);
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                tx_symb = qpsk_mod(tx_bits(2*(i-1+k-1)+1:2*(i+k-1)));
+                tx_symb *= prev_sym_tx(k);
+                prev_sym_tx(k) = tx_symb;
+                s(i+k-1) = symbol_amp(symbol_amp_index)*tx_symb;
+              end
+            end
+            s_ch = s;
+            symbol_amp_index++;
+
+            % HF channel simulation  ------------------------------------
+            
+            if hf_sim
+
+                % separation between carriers.  Note this is
+                % effectively under samples at Rs, I dont think this
+                % matters.  Equivalent to doing freq shift at Fs, then
+                % decimating to Rs.
+
+                wsep = 2*pi*(1+0.5);  % e.g. 75Hz spacing at Rs=50Hz, alpha=0.5 filters
+
+                if Nsymb/Nc != floor(Nsymb/Nc)
+                    printf("Error: Nsymb/Nc must be an integrer\n")
+                    return;
+                end
+
+                % arrange symbols in Nsymb/Nc by Nc matrix
+
+                for i=1:Nc:Nsymb
+
+                    % Determine HF channel at each carrier for this symbol
+
+                    for k=1:Nc
+                        hf_model(hf_n, k) = hf_gain*(spread(hf_n) + exp(-j*k*wsep*nhfdelay)*spread_2ms(hf_n));
+                        hf_fading(i+k-1) = abs(hf_model(hf_n, k));
+                        if hf_mag_only
+                             s_ch(i+k-1) *= abs(hf_model(hf_n, k));
+                        else
+                             s_ch(i+k-1) *= hf_model(hf_n, k);
+                        end
+                    end
+                    hf_n++;
+                end
+            end
+            
+            tx_symb_log = [tx_symb_log s_ch];
+
+            % "genie" SNR estimate 
+            
+            snr = (s_ch*s_ch')/(Nsymb*variance);
+            sim_out.snr_log = [sim_out.snr_log snr];
+            sim_out.hf_model_pwr = [sim_out.hf_model_pwr mean(hf_fading.^2)];
+
+            % AWGN noise and phase/freq offset channel simulation
+            % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im
+
+            noise = sqrt(variance*0.5)*(randn(1,Nsymb) + j*randn(1,Nsymb));
+            noise_log = [noise_log noise];
+            % organise into carriers to apply frequency and phase offset
+
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                 s_ch(i+k-1) = s_ch(i+k-1)*exp(j*phase_offset) + noise(i+k-1);
+              end 
+              phase_offset += w_offset;
+            end
+               
+            % de-modulate
+
+            rx_bits = zeros(1, framesize);
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                rx_symb = s_ch(i+k-1);
+                tmp = rx_symb;
+                rx_symb *= conj(prev_sym_rx(k)/abs(prev_sym_rx(k)));
+                prev_sym_rx(k) = tmp;
+                rx_bits((2*(i-1+k-1)+1):(2*(i+k-1))) = qpsk_demod(rx_symb);
+                rx_symb_log = [rx_symb_log rx_symb];
+              end
+            end
+
+            error_positions = xor(rx_bits, tx_bits);
+            Nerrs = sum(error_positions);
+            sim_out.Nerrs = [sim_out.Nerrs Nerrs];
+            Terrs += Nerrs;
+            Tbits += length(tx_bits);
+            
+            sim_out.errors_log = [sim_out.errors_log error_positions];
+        end
+
+        TERvec(ne) = Terrs;
+        BERvec(ne) = Terrs/Tbits;
+
+        if verbose 
+            printf("EsNo (dB): %f  Terrs: %d BER %f ", EsNodB, Terrs, Terrs/Tbits);
+            printf("\n");
+        end
+        if verbose > 1
+            printf("Terrs: %d BER %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,
+                   Terrs/Tbits, var(tx_symb_log), var(noise_log),
+                   var(tx_symb_log), var(noise_log), var(tx_symb_log)/var(noise_log));
+        end
+    end
+    
+    Ebvec = Esvec - 10*log10(bps);
+
+    sim_out.BERvec = BERvec;
+    sim_out.Ebvec  = Ebvec;
+    sim_out.TERvec = TERvec;
+
+    if plot_scatter
+        figure(2);
+        clf;
+        scat = rx_symb_log .* exp(j*pi/4);
+        plot(real(scat), imag(scat),'+');
+        title('Scatter plot');
+
+        figure(3);
+        clf;        
+        y = 1:Rs*2;
+        x = 1:Nc;
+        EsNodBSurface = 20*log10(abs(hf_model(y,:))) - 10*log10(variance);
+        mesh(x,y,EsNodBSurface);
+        grid
+        title('HF Channel Es/No');
+
+        if 0 
+        figure(4);
+        clf;
+        subplot(211)
+        plot(y,abs(hf_model(y,1)))
+        title('HF Channel Carrier 1 Mag');
+        subplot(212)
+        plot(y,angle(hf_model(y,1)))
+        title('HF Channel Carrier 1 Phase');
+        end
+    end
+
+endfunction
+
+% Gray coded QPSK modulation function
+
+function symbol = qpsk_mod(two_bits)
+    two_bits_decimal = sum(two_bits .* [2 1]); 
+    switch(two_bits_decimal)
+        case (0) symbol =  1;
+        case (1) symbol =  j;
+        case (2) symbol = -j;
+        case (3) symbol = -1;
+    endswitch
+endfunction
+
+% Gray coded QPSK demodulation function
+
+function two_bits = qpsk_demod(symbol)
+    if isscalar(symbol) == 0
+        printf("only works with scalars\n");
+        return;
+    end
+    bit0 = real(symbol*exp(j*pi/4)) < 0;
+    bit1 = imag(symbol*exp(j*pi/4)) < 0;
+    two_bits = [bit1 bit0];
+endfunction
+
+function sim_in = standard_init
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 0;
+
+  sim_in.Esvec            = 5:15; 
+  sim_in.Ntrials          = 100;
+  sim_in.framesize        = 64;
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 8;
+
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+  sim_in.phase_noise_amp  = 0;
+
+  sim_in.hf_delay_ms      = 2;
+  sim_in.hf_sim           = 0;
+  sim_in.hf_phase_only    = 0;
+  sim_in.hf_mag_only      = 0;
+endfunction
+
+function awgn_hf_ber_curves()
+  sim_in = standard_init();
+
+  Ebvec = sim_in.Esvec - 10*log10(2);
+  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));
+
+  dpsk_awgn = ber_test(sim_in);
+  sim_in.hf_sim           = 1;
+  dpsk_hf   = ber_test(sim_in);
+
+  figure(1); 
+  clf;
+  semilogy(Ebvec, BER_theory,'r;QPSK theory;')
+  hold on;
+  semilogy(dpsk_awgn.Ebvec, dpsk_awgn.BERvec,'g;DQPSK;')
+  semilogy(dpsk_hf.Ebvec, dpsk_hf.BERvec,'g;DQPSK HF;')
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-3 1])
+end
+
+sim_in = standard_init();
+
+% energy file sampled every 10ms
+
+load ../src/ve9qrp.txt
+pdB=10*log10(ve9qrp);
+for i=1:length(pdB)
+  if pdB(i) < 0
+    pdB(i) = 0;
+  end
+end
+
+% Down sample to 40ms rate used for 1300 bit/s codec, every 4th sample is transmitted
+
+pdB = pdB(4:4:length(pdB));
+
+% Use linear mapping function in dB domain to map to symbol power
+
+power_map_x  = [ 0 20 24 40 50 ];
+power_map_y  = [-6 -6  0 6  6];
+mapped_pdB = interp1(power_map_x, power_map_y, pdB);
+
+%sim_in.symbol_amp = 10 .^ (mapped_pdB/20);
+sim_in.symbol_amp = ones(1,length(pdB));
+sim_in.plot_scatter = 1;
+sim_in.verbose      = 2;
+sim_in.hf_sim       = 1;
+sim_in.Esvec        = 10;
+sim_in.Ntrials      = 400;
+
+dqpsk_pwr_hf = ber_test(sim_in);
+
+% note: need way to test that power is aligned with speech
+
+figure(4)
+clf;
+plot((1:sim_in.Ntrials)*80*4, pdB(1:sim_in.Ntrials));
+hold on;
+plot((1:sim_in.Ntrials)*80*4, mapped_pdB(1:sim_in.Ntrials),'r');
+hold off;
+
+figure(5)
+clf;
+
+s = load_raw("../raw/ve9qrp.raw");
+M=320; M_on_2 = M/2; % processing delay between input speech and centre of analysis window
+plot(M_on_2:(M_on_2-1+sim_in.Ntrials*M),s(1:sim_in.Ntrials*M))
+hold on;
+plot((1:sim_in.Ntrials)*M, 5000*sim_in.symbol_amp(1:sim_in.Ntrials),'r');
+hold off;
+axis([1 sim_in.Ntrials*M -3E4 3E4]);
+
+figure(6)
+clf;
+plot((1:sim_in.Ntrials)*M, 20*log10(sim_in.symbol_amp(1:sim_in.Ntrials)),'b;Es (dB);');
+hold on;
+plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.hf_model_pwr),'g;Fading (dB);');
+plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.snr_log),'r;Es/No (dB);');
+
+ber = dqpsk_pwr_hf.Nerrs/sim_in.framesize;
+ber_clip = ber;
+ber_clip(find(ber > 0.2)) = 0.2;
+plot((1:sim_in.Ntrials)*M, -20+100*ber_clip,'k;BER (0-20%);');
+hold off;
+axis([1 sim_in.Ntrials*M -20 20])
+
+fep=fopen("dqpsk_errors_pwr.bin","wb"); fwrite(fep, dqpsk_pwr_hf.errors_log, "short"); fclose(fep);
+fber=fopen("ber.bin","wb"); fwrite(fber, ber, "float"); fclose(fber);
index 08787510c144c9430a579c2d591d1ee089f31030..d421d6241bb630005ca3ecd7549b533465d03076 100644 (file)
-% test_dqpsk2.m\r
-% David Rowe April 2014\r
-%\r
-% DQPSK modem simulation inclduing filtering to test modulating modem\r
-% tx power based on speech energy.  Unlike test_dpsk runs at sample\r
-% rate Fs.\r
-\r
-1;\r
-\r
-% main test function \r
-\r
-function sim_out = ber_test(sim_in)\r
-    Fs = 8000;\r
-\r
-    verbose          = sim_in.verbose;\r
-    framesize        = sim_in.framesize;\r
-    Ntrials          = sim_in.Ntrials;\r
-    Esvec            = sim_in.Esvec;\r
-    phase_offset     = sim_in.phase_offset;\r
-    w_offset         = sim_in.w_offset;\r
-    plot_scatter     = sim_in.plot_scatter;\r
-    Rs               = sim_in.Rs;\r
-    hf_sim           = sim_in.hf_sim;\r
-    Nhfdelay         = floor(sim_in.hf_delay_ms*Fs/1000);\r
-    Nc               = sim_in.Nc;\r
-    symbol_amp       = sim_in.symbol_amp;\r
-\r
-    bps              = 2;\r
-    Nsymb            = framesize/bps;\r
-    for k=1:Nc\r
-      prev_sym_tx(k) = qpsk_mod([0 0]);\r
-      prev_sym_rx(k) = qpsk_mod([0 0]);\r
-    end\r
-\r
-    % design root nyquist (root raised cosine) filter and init tx and rx filter states\r
-\r
-    alpha = 0.5; T=1/Fs; Nfiltsym=7; M=Fs/Rs;\r
-    if floor(Fs/Rs) != Fs/Rs\r
-        printf("oversampling ratio must be an integer\n");\r
-        return;\r
-    end\r
-    hrn = gen_rn_coeffs(alpha, T, Rs, Nfiltsym, M);\r
-    Nfilter = length(hrn);\r
-\r
-    % convert "spreading" samples from 1kHz carrier at Fs to complex\r
-    % baseband, generated by passing a 1kHz sine wave through PathSim\r
-    % with the ccir-poor model, enabling one path at a time.\r
-    \r
-    Fc = 1000;\r
-    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");\r
-    spread1k = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");\r
-    spread1k_2ms = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-\r
-    % down convert to complex baseband\r
-    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');\r
-    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');\r
-\r
-    % remove -2000 Hz image\r
-    b = fir1(50, 5/Fs);\r
-    spread = filter(b,1,spreadbb);\r
-    spread_2ms = filter(b,1,spreadbb_2ms);\r
-\r
-    % discard first 1000 samples as these were near 0, probably as\r
-    % PathSim states were ramping up.  Transpose for convenience\r
-\r
-    spread     = transpose(spread(1000:length(spread)));\r
-    spread_2ms = transpose(spread_2ms(1000:length(spread_2ms)));\r
-\r
-    % Determine "gain" of HF channel model, so we can normalise\r
-    % carrier power during HF channel sim to calibrate SNR.  I imagine\r
-    % different implementations of ccir-poor would do this in\r
-    % different ways, leading to different BER results.  Oh Well!\r
-\r
-    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));\r
-        \r
-    % Start Simulation ----------------------------------------------------------------\r
-\r
-    for ne = 1:length(Esvec)\r
-        EsNodB = Esvec(ne);\r
-        EsNo = 10^(EsNodB/10);\r
-    \r
-        variance = Fs/(Rs*EsNo);\r
-         if verbose > 1\r
-            printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);\r
-        end\r
-        \r
-        Terrs = 0;  Tbits = 0;\r
-\r
-        tx_symb_log             = [];\r
-        rx_symb_log             = [];\r
-        noise_log               = [];\r
-        sim_out.errors_log      = [];\r
-        sim_out.tx_baseband_log = [];\r
-        sim_out.rx_filt_log     = [];\r
-        symbol_amp_index        = 1;\r
-       \r
-        % init filter memories and LOs\r
-\r
-        tx_filter_memory  = zeros(Nc, Nfilter);\r
-        rx_filter_memory  = zeros(Nc, Nfilter);\r
-        s_delay_line_filt = zeros(Nc, Nfiltsym);\r
-        phase_tx = ones(1,Nc);\r
-        phase_rx = ones(1,Nc);\r
-        Fcentre = 1500; Fsep = (1+alpha)*Rs;\r
-        freq = Fcentre + Fsep*((-Nc/2+0.5):(Nc/2-0.5));\r
-        freq = exp(j*freq*2*pi/Fs);\r
-\r
-        % init HF channel\r
-\r
-        sc = 1; hf_n = 1;\r
-        hf_sim_delay_line = zeros(1,M+Nhfdelay);\r
-        freq_sample_hz = Fcentre + ((Fsep*(-Nc/2)):50:(Fsep*(Nc/2)));\r
-        freq_sample_rads = (2*pi/Fs)*freq_sample_hz;\r
-        hf_model = ones(Ntrials*Nsymb/Nc, length(freq_sample_rads));   % defaults for plotting surface\r
-\r
-        % bunch of outputs we log for graphing\r
-\r
-        sim_out.errors_log = [];\r
-        sim_out.Nerrs = [];\r
-        sim_out.snr_log = [];\r
-        sim_out.hf_model_pwr = [];\r
-        sim_out.tx_fdm_log = [];\r
-        C_log = [];\r
-\r
-        for nn = 1: Ntrials\r
-                  \r
-            tx_bits = round( rand( 1, framesize ) );\r
\r
-            % modulate --------------------------------------------\r
-\r
-            s = zeros(1, Nsymb);\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                tx_symb = qpsk_mod(tx_bits(2*(i-1+k-1)+1:2*(i+k-1)));\r
-                s_qpsk(i+k-1) = tx_symb;\r
-                tx_symb *= prev_sym_tx(k);\r
-                prev_sym_tx(k) = tx_symb;\r
-                s(i+k-1) = symbol_amp(symbol_amp_index)*tx_symb;\r
-              end\r
-            end\r
-            symbol_amp_index++;\r
-            s_ch = s;\r
-\r
-            % Now we start processing frame Nc symbols at a time to model parallel carriers\r
-\r
-            tx_fdm_sym_log = [];\r
-            for i=1:Nc:Nsymb\r
-\r
-                % Delay tx symbols to match delay due to filters. qpsk\r
-                % (rather than dqpsk) symbols used for convenience as\r
-                % it's easy to shift symbols than pairs of bits\r
-\r
-                s_delay_line_filt(:,1:Nfiltsym-1) = s_delay_line_filt(:,2:Nfiltsym);\r
-                s_delay_line_filt(:,Nfiltsym) = s_qpsk(i:i+Nc-1);\r
-                s_qpsk(i:i+Nc-1) = s_delay_line_filt(:,1);  \r
-                for k=1:Nc\r
-                    tx_bits(2*(i-1+k-1)+1:2*(i+k-1)) = qpsk_demod(s_qpsk(i+k-1));\r
-                end\r
-\r
-                % tx filter\r
-\r
-                tx_baseband = zeros(Nc,M);\r
-\r
-                % tx filter each symbol, generate M filtered output samples for each symbol.\r
-                % Efficient polyphase filter techniques used as tx_filter_memory is sparse\r
-\r
-                tx_filter_memory(:,Nfilter) = s(i:i+Nc-1);\r
-\r
-                for k=1:M\r
-                    tx_baseband(:,k) = M*tx_filter_memory(:,M:M:Nfilter) * hrn(M-k+1:M:Nfilter)';\r
-                end\r
-                tx_filter_memory(:,1:Nfilter-M) = tx_filter_memory(:,M+1:Nfilter);\r
-                tx_filter_memory(:,Nfilter-M+1:Nfilter) = zeros(Nc,M);\r
-\r
-                sim_out.tx_baseband_log = [sim_out.tx_baseband_log  tx_baseband];\r
-\r
-                % upconvert\r
\r
-                tx_fdm = zeros(1,M);\r
-\r
-                for c=1:Nc\r
-                    for k=1:M\r
-                        phase_tx(c) = phase_tx(c) * freq(c);\r
-                       tx_fdm(k) = tx_fdm(k) + tx_baseband(c,k)*phase_tx(c);\r
-                    end\r
-                end\r
\r
-                sim_out.tx_fdm_log = [sim_out.tx_fdm_log tx_fdm];\r
\r
-                % HF channel\r
-                \r
-                if hf_sim\r
-                   hf_sim_delay_line(1:Nhfdelay) = hf_sim_delay_line(M+1:M+Nhfdelay);\r
-                   hf_sim_delay_line(Nhfdelay+1:M+Nhfdelay) = tx_fdm;\r
-\r
-                   tx_fdm = tx_fdm.*spread(sc:sc+M-1) + hf_sim_delay_line(1:M).*spread_2ms(sc:sc+M-1);\r
-                   tx_fdm *= hf_gain;\r
-\r
-                   % sample HF channel spectrum in middle of this symbol for plotting\r
-\r
-                   hf_model(hf_n,:) = hf_gain*(spread(sc+M/2) + exp(-j*freq_sample_rads*Nhfdelay)*spread_2ms(sc+M/2));\r
-\r
-                   sc += M;\r
-                   hf_n++;\r
-                end\r
-\r
-                tx_fdm_sym_log = [tx_fdm_sym_log tx_fdm ];\r
-\r
-                % AWGN noise and phase/freq offset channel simulation\r
-                % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im\r
-\r
-                noise = sqrt(variance*0.5)*(randn(1,M) + j*randn(1,M));\r
-                noise_log = [noise_log noise];\r
-\r
-                % apply frequency and phase offset and noise\r
-\r
-                for k=1:M\r
-                    rx_fdm(k) = tx_fdm(k)*exp(j*phase_offset) + noise(k);\r
-                    phase_offset += w_offset;\r
-                end\r
-\r
-                % downconvert\r
-\r
-                rx_baseband = zeros(Nc,M);\r
-                for c=1:Nc\r
-                    for k=1:M\r
-                        phase_rx(c) = phase_rx(c) * freq(c);\r
-                       rx_baseband(c,k) = rx_fdm(k)*phase_rx(c)';\r
-                    end\r
-                end\r
-\r
-                % rx filter\r
-\r
-                rx_filter_memory(:,Nfilter-M+1:Nfilter) = rx_baseband;\r
-                rx_filt = rx_filter_memory * hrn';\r
-                rx_filter_memory(:,1:Nfilter-M) = rx_filter_memory(:,1+M:Nfilter);\r
-                sim_out.rx_filt_log = [sim_out.rx_filt_log rx_filt];\r
-\r
-                s_ch(i:i+Nc-1) = rx_filt;\r
-            end\r
-\r
-            % est HF model power for entire code frame (which could be several symbols)\r
-\r
-            if hf_sim\r
-              frame_hf_model = reshape(hf_model(hf_n-Nsymb/Nc:hf_n-1,:),1,(Nsymb/Nc)*length(freq_sample_hz));                       \r
-              sim_out.hf_model_pwr = [sim_out.hf_model_pwr mean(abs(frame_hf_model).^2)];\r
-            else \r
-              sim_out.hf_model_pwr = [sim_out.hf_model_pwr 1];\r
-            end\r
-\r
-            % "genie" SNR estimate \r
-            \r
-            snr = (tx_fdm_sym_log*tx_fdm_sym_log')/(M*variance);\r
-            sim_out.snr_log = [sim_out.snr_log snr];\r
-  \r
-            % de-modulate\r
-\r
-            rx_bits = zeros(1, framesize);\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                rx_symb = s_ch(i+k-1);\r
-                tmp = rx_symb;\r
-                rx_symb *= conj(prev_sym_rx(k)/abs(prev_sym_rx(k)));\r
-                prev_sym_rx(k) = tmp;\r
-                rx_bits((2*(i-1+k-1)+1):(2*(i+k-1))) = qpsk_demod(rx_symb);\r
-                rx_symb_log = [rx_symb_log rx_symb];\r
-              end\r
-            end\r
-\r
-            % ignore data until we have enough frames to fill filter memory\r
-            % then count errors\r
-\r
-            if nn > ceil(Nfiltsym/(Nsymb/Nc))\r
-                error_positions = xor(rx_bits, tx_bits);\r
-                sim_out.errors_log = [sim_out.errors_log error_positions];\r
-                Nerrs = sum(error_positions);\r
-                sim_out.Nerrs = [sim_out.Nerrs Nerrs];\r
-                Terrs += Nerrs;\r
-                Tbits += length(tx_bits);\r
-            end\r
-\r
-        end\r
-\r
-        TERvec(ne) = Terrs;\r
-        BERvec(ne) = Terrs/Tbits;\r
-\r
-        if verbose \r
-            printf("EsNo (dB): %f  Terrs: %d BER %f ", EsNodB, Terrs, Terrs/Tbits);\r
-            printf("\n");\r
-        end\r
-        if verbose > 1\r
-            printf("Terrs: %d BER %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,\r
-                   Terrs/Tbits, var(sim_out.tx_fdm_log), var(noise_log),\r
-                   var(sim_out.tx_fdm_log)/(Nc*Rs), var(noise_log)/Fs, (var(sim_out.tx_fdm_log)/(Nc*Rs))/(var(noise_log)/Fs));\r
-        end\r
-    end\r
-    \r
-    Ebvec = Esvec - 10*log10(bps);\r
-\r
-    sim_out.BERvec = BERvec;\r
-    sim_out.Ebvec  = Ebvec;\r
-    sim_out.TERvec = TERvec;\r
-\r
-    if plot_scatter\r
-        figure(2);\r
-        clf;\r
-        scat = rx_symb_log(Nfiltsym*Nc:length(rx_symb_log)) .* exp(j*pi/4);\r
-        plot(real(scat), imag(scat),'+');\r
-        title('Scatter plot');\r
-\r
-        figure(3);\r
-        clf;        \r
-        y = 1:Rs*2;\r
-        EsNodBSurface = 20*log10(abs(hf_model(y,:))) + EsNodB;\r
-        mesh(1:length(freq_sample_hz),y,EsNodBSurface);\r
-        grid\r
-        title('HF Channel Es/No');\r
-    end\r
-\r
-endfunction\r
-\r
-% Gray coded QPSK modulation function\r
-\r
-function symbol = qpsk_mod(two_bits)\r
-    two_bits_decimal = sum(two_bits .* [2 1]); \r
-    switch(two_bits_decimal)\r
-        case (0) symbol =  1;\r
-        case (1) symbol =  j;\r
-        case (2) symbol = -j;\r
-        case (3) symbol = -1;\r
-    endswitch\r
-endfunction\r
-\r
-% Gray coded QPSK demodulation function\r
-\r
-function two_bits = qpsk_demod(symbol)\r
-    if isscalar(symbol) == 0\r
-        printf("only works with scalars\n");\r
-        return;\r
-    end\r
-    bit0 = real(symbol*exp(j*pi/4)) < 0;\r
-    bit1 = imag(symbol*exp(j*pi/4)) < 0;\r
-    two_bits = [bit1 bit0];\r
-endfunction\r
-\r
-function sim_in = standard_init\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 0;\r
-\r
-  sim_in.Esvec            = 5:15; \r
-  sim_in.Ntrials          = 100;\r
-  sim_in.framesize        = 64;\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 8;\r
-\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-  sim_in.phase_noise_amp  = 0;\r
-\r
-  sim_in.hf_delay_ms      = 2;\r
-  sim_in.hf_sim           = 0;\r
-  sim_in.hf_phase_only    = 0;\r
-  sim_in.hf_mag_only      = 0;\r
-endfunction\r
-\r
-function awgn_hf_ber_curves()\r
-  sim_in = standard_init();\r
-\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));\r
-\r
-  dpsk_awgn = ber_test(sim_in);\r
-  sim_in.hf_sim           = 1;\r
-  dpsk_hf   = ber_test(sim_in);\r
-\r
-  figure(1); \r
-  clf;\r
-  semilogy(Ebvec, BER_theory,'r;QPSK theory;')\r
-  hold on;\r
-  semilogy(dpsk_awgn.Ebvec, dpsk_awgn.BERvec,'g;DQPSK;')\r
-  semilogy(dpsk_hf.Ebvec, dpsk_hf.BERvec,'g;DQPSK HF;')\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-3 1])\r
-end\r
-\r
-sim_in = standard_init();\r
-\r
-% energy file sampled every 10ms\r
-\r
-load ../src/ve9qrp.txt\r
-pdB=10*log10(ve9qrp);\r
-for i=1:length(pdB)\r
-  if pdB(i) < 0\r
-    pdB(i) = 0;\r
-  end\r
-end\r
-\r
-% Down sample to 40ms rate used for 1300 bit/s codec, every 4th sample is transmitted\r
-\r
-pdB = pdB(4:4:length(pdB));\r
-\r
-% Use linear mapping function in dB domain to map to symbol power\r
-\r
-%power_map_x  = [ 0 20 24 40 50 ];\r
-%power_map_y  = [--6 -6  0  6  6];\r
-power_map_x  = [ 0 50 ];\r
-power_map_y  = [ -15 12];\r
-mapped_pdB = interp1(power_map_x, power_map_y, pdB);\r
-\r
-sim_in.symbol_amp = 10 .^ (mapped_pdB/20);\r
-%sim_in.symbol_amp = ones(1,length(pdB));\r
-sim_in.plot_scatter = 1;\r
-sim_in.verbose      = 2;\r
-sim_in.hf_delay_ms  = 2;\r
-sim_in.hf_sim       = 1;\r
-sim_in.Esvec        = 10;\r
-sim_in.Ntrials      = 400;\r
-\r
-dqpsk_pwr_hf = ber_test(sim_in);\r
-\r
-% note: need way to test that power is aligned with speech\r
-\r
-figure(4)\r
-clf;\r
-plot((1:sim_in.Ntrials)*80*4, pdB(1:sim_in.Ntrials));\r
-hold on;\r
-plot((1:sim_in.Ntrials)*80*4, mapped_pdB(1:sim_in.Ntrials),'r');\r
-hold off;\r
-\r
-figure(5)\r
-clf;\r
-s = load_raw("../raw/ve9qrp.raw");\r
-M=320; M_on_2 = M/2; % processing delay between input speech and centre of analysis window\r
-subplot(211)\r
-plot(M_on_2:(M_on_2-1+sim_in.Ntrials*M),s(1:sim_in.Ntrials*M))\r
-hold on;\r
-plot((1:sim_in.Ntrials)*M, 5000*sim_in.symbol_amp(1:sim_in.Ntrials),'r');\r
-hold off;\r
-axis([1 sim_in.Ntrials*M -3E4 3E4]);\r
-subplot(212)\r
-plot(real(dqpsk_pwr_hf.tx_fdm_log));\r
-\r
-\r
-figure(6)\r
-clf;\r
-plot((1:sim_in.Ntrials)*M, 20*log10(sim_in.symbol_amp(1:sim_in.Ntrials)),'b;Es (dB);');\r
-hold on;\r
-plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.hf_model_pwr),'g;Fading (dB);');\r
-plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.snr_log),'r;Es/No (dB);');\r
-\r
-ber = dqpsk_pwr_hf.Nerrs/sim_in.framesize;\r
-ber_clip = ber;\r
-ber_clip(find(ber > 0.2)) = 0.2;\r
-plot((1:length(ber_clip))*M, -20+100*ber_clip,'k;BER (0-20%);');\r
-hold off;\r
-axis([1 sim_in.Ntrials*M -20 20])\r
-\r
-fep=fopen("dqpsk_errors_pwr.bin","wb"); fwrite(fep, dqpsk_pwr_hf.errors_log, "short"); fclose(fep);\r
-fber=fopen("ber.bin","wb"); fwrite(fber, ber, "float"); fclose(fber);\r
+% test_dqpsk2.m
+% David Rowe April 2014
+%
+% DQPSK modem simulation inclduing filtering to test modulating modem
+% tx power based on speech energy.  Unlike test_dpsk runs at sample
+% rate Fs.
+
+1;
+
+% main test function 
+
+function sim_out = ber_test(sim_in)
+    Fs = 8000;
+
+    verbose          = sim_in.verbose;
+    framesize        = sim_in.framesize;
+    Ntrials          = sim_in.Ntrials;
+    Esvec            = sim_in.Esvec;
+    phase_offset     = sim_in.phase_offset;
+    w_offset         = sim_in.w_offset;
+    plot_scatter     = sim_in.plot_scatter;
+    Rs               = sim_in.Rs;
+    hf_sim           = sim_in.hf_sim;
+    Nhfdelay         = floor(sim_in.hf_delay_ms*Fs/1000);
+    Nc               = sim_in.Nc;
+    symbol_amp       = sim_in.symbol_amp;
+
+    bps              = 2;
+    Nsymb            = framesize/bps;
+    for k=1:Nc
+      prev_sym_tx(k) = qpsk_mod([0 0]);
+      prev_sym_rx(k) = qpsk_mod([0 0]);
+    end
+
+    % design root nyquist (root raised cosine) filter and init tx and rx filter states
+
+    alpha = 0.5; T=1/Fs; Nfiltsym=7; M=Fs/Rs;
+    if floor(Fs/Rs) != Fs/Rs
+        printf("oversampling ratio must be an integer\n");
+        return;
+    end
+    hrn = gen_rn_coeffs(alpha, T, Rs, Nfiltsym, M);
+    Nfilter = length(hrn);
+
+    % convert "spreading" samples from 1kHz carrier at Fs to complex
+    % baseband, generated by passing a 1kHz sine wave through PathSim
+    % with the ccir-poor model, enabling one path at a time.
+    
+    Fc = 1000;
+    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");
+    spread1k = fread(fspread, "int16")/10000;
+    fclose(fspread);
+    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");
+    spread1k_2ms = fread(fspread, "int16")/10000;
+    fclose(fspread);
+
+    % down convert to complex baseband
+    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');
+    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');
+
+    % remove -2000 Hz image
+    b = fir1(50, 5/Fs);
+    spread = filter(b,1,spreadbb);
+    spread_2ms = filter(b,1,spreadbb_2ms);
+
+    % discard first 1000 samples as these were near 0, probably as
+    % PathSim states were ramping up.  Transpose for convenience
+
+    spread     = transpose(spread(1000:length(spread)));
+    spread_2ms = transpose(spread_2ms(1000:length(spread_2ms)));
+
+    % Determine "gain" of HF channel model, so we can normalise
+    % carrier power during HF channel sim to calibrate SNR.  I imagine
+    % different implementations of ccir-poor would do this in
+    % different ways, leading to different BER results.  Oh Well!
+
+    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));
+        
+    % Start Simulation ----------------------------------------------------------------
+
+    for ne = 1:length(Esvec)
+        EsNodB = Esvec(ne);
+        EsNo = 10^(EsNodB/10);
+    
+        variance = Fs/(Rs*EsNo);
+         if verbose > 1
+            printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);
+        end
+        
+        Terrs = 0;  Tbits = 0;
+
+        tx_symb_log             = [];
+        rx_symb_log             = [];
+        noise_log               = [];
+        sim_out.errors_log      = [];
+        sim_out.tx_baseband_log = [];
+        sim_out.rx_filt_log     = [];
+        symbol_amp_index        = 1;
+       
+        % init filter memories and LOs
+
+        tx_filter_memory  = zeros(Nc, Nfilter);
+        rx_filter_memory  = zeros(Nc, Nfilter);
+        s_delay_line_filt = zeros(Nc, Nfiltsym);
+        phase_tx = ones(1,Nc);
+        phase_rx = ones(1,Nc);
+        Fcentre = 1500; Fsep = (1+alpha)*Rs;
+        freq = Fcentre + Fsep*((-Nc/2+0.5):(Nc/2-0.5));
+        freq = exp(j*freq*2*pi/Fs);
+
+        % init HF channel
+
+        sc = 1; hf_n = 1;
+        hf_sim_delay_line = zeros(1,M+Nhfdelay);
+        freq_sample_hz = Fcentre + ((Fsep*(-Nc/2)):50:(Fsep*(Nc/2)));
+        freq_sample_rads = (2*pi/Fs)*freq_sample_hz;
+        hf_model = ones(Ntrials*Nsymb/Nc, length(freq_sample_rads));   % defaults for plotting surface
+
+        % bunch of outputs we log for graphing
+
+        sim_out.errors_log = [];
+        sim_out.Nerrs = [];
+        sim_out.snr_log = [];
+        sim_out.hf_model_pwr = [];
+        sim_out.tx_fdm_log = [];
+        C_log = [];
+
+        for nn = 1: Ntrials
+                  
+            tx_bits = round( rand( 1, framesize ) );
+            % modulate --------------------------------------------
+
+            s = zeros(1, Nsymb);
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                tx_symb = qpsk_mod(tx_bits(2*(i-1+k-1)+1:2*(i+k-1)));
+                s_qpsk(i+k-1) = tx_symb;
+                tx_symb *= prev_sym_tx(k);
+                prev_sym_tx(k) = tx_symb;
+                s(i+k-1) = symbol_amp(symbol_amp_index)*tx_symb;
+              end
+            end
+            symbol_amp_index++;
+            s_ch = s;
+
+            % Now we start processing frame Nc symbols at a time to model parallel carriers
+
+            tx_fdm_sym_log = [];
+            for i=1:Nc:Nsymb
+
+                % Delay tx symbols to match delay due to filters. qpsk
+                % (rather than dqpsk) symbols used for convenience as
+                % it's easy to shift symbols than pairs of bits
+
+                s_delay_line_filt(:,1:Nfiltsym-1) = s_delay_line_filt(:,2:Nfiltsym);
+                s_delay_line_filt(:,Nfiltsym) = s_qpsk(i:i+Nc-1);
+                s_qpsk(i:i+Nc-1) = s_delay_line_filt(:,1);  
+                for k=1:Nc
+                    tx_bits(2*(i-1+k-1)+1:2*(i+k-1)) = qpsk_demod(s_qpsk(i+k-1));
+                end
+
+                % tx filter
+
+                tx_baseband = zeros(Nc,M);
+
+                % tx filter each symbol, generate M filtered output samples for each symbol.
+                % Efficient polyphase filter techniques used as tx_filter_memory is sparse
+
+                tx_filter_memory(:,Nfilter) = s(i:i+Nc-1);
+
+                for k=1:M
+                    tx_baseband(:,k) = M*tx_filter_memory(:,M:M:Nfilter) * hrn(M-k+1:M:Nfilter)';
+                end
+                tx_filter_memory(:,1:Nfilter-M) = tx_filter_memory(:,M+1:Nfilter);
+                tx_filter_memory(:,Nfilter-M+1:Nfilter) = zeros(Nc,M);
+
+                sim_out.tx_baseband_log = [sim_out.tx_baseband_log  tx_baseband];
+
+                % upconvert
+                tx_fdm = zeros(1,M);
+
+                for c=1:Nc
+                    for k=1:M
+                        phase_tx(c) = phase_tx(c) * freq(c);
+                       tx_fdm(k) = tx_fdm(k) + tx_baseband(c,k)*phase_tx(c);
+                    end
+                end
+                sim_out.tx_fdm_log = [sim_out.tx_fdm_log tx_fdm];
+                % HF channel
+                
+                if hf_sim
+                   hf_sim_delay_line(1:Nhfdelay) = hf_sim_delay_line(M+1:M+Nhfdelay);
+                   hf_sim_delay_line(Nhfdelay+1:M+Nhfdelay) = tx_fdm;
+
+                   tx_fdm = tx_fdm.*spread(sc:sc+M-1) + hf_sim_delay_line(1:M).*spread_2ms(sc:sc+M-1);
+                   tx_fdm *= hf_gain;
+
+                   % sample HF channel spectrum in middle of this symbol for plotting
+
+                   hf_model(hf_n,:) = hf_gain*(spread(sc+M/2) + exp(-j*freq_sample_rads*Nhfdelay)*spread_2ms(sc+M/2));
+
+                   sc += M;
+                   hf_n++;
+                end
+
+                tx_fdm_sym_log = [tx_fdm_sym_log tx_fdm ];
+
+                % AWGN noise and phase/freq offset channel simulation
+                % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im
+
+                noise = sqrt(variance*0.5)*(randn(1,M) + j*randn(1,M));
+                noise_log = [noise_log noise];
+
+                % apply frequency and phase offset and noise
+
+                for k=1:M
+                    rx_fdm(k) = tx_fdm(k)*exp(j*phase_offset) + noise(k);
+                    phase_offset += w_offset;
+                end
+
+                % downconvert
+
+                rx_baseband = zeros(Nc,M);
+                for c=1:Nc
+                    for k=1:M
+                        phase_rx(c) = phase_rx(c) * freq(c);
+                       rx_baseband(c,k) = rx_fdm(k)*phase_rx(c)';
+                    end
+                end
+
+                % rx filter
+
+                rx_filter_memory(:,Nfilter-M+1:Nfilter) = rx_baseband;
+                rx_filt = rx_filter_memory * hrn';
+                rx_filter_memory(:,1:Nfilter-M) = rx_filter_memory(:,1+M:Nfilter);
+                sim_out.rx_filt_log = [sim_out.rx_filt_log rx_filt];
+
+                s_ch(i:i+Nc-1) = rx_filt;
+            end
+
+            % est HF model power for entire code frame (which could be several symbols)
+
+            if hf_sim
+              frame_hf_model = reshape(hf_model(hf_n-Nsymb/Nc:hf_n-1,:),1,(Nsymb/Nc)*length(freq_sample_hz));                       
+              sim_out.hf_model_pwr = [sim_out.hf_model_pwr mean(abs(frame_hf_model).^2)];
+            else 
+              sim_out.hf_model_pwr = [sim_out.hf_model_pwr 1];
+            end
+
+            % "genie" SNR estimate 
+            
+            snr = (tx_fdm_sym_log*tx_fdm_sym_log')/(M*variance);
+            sim_out.snr_log = [sim_out.snr_log snr];
+  
+            % de-modulate
+
+            rx_bits = zeros(1, framesize);
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                rx_symb = s_ch(i+k-1);
+                tmp = rx_symb;
+                rx_symb *= conj(prev_sym_rx(k)/abs(prev_sym_rx(k)));
+                prev_sym_rx(k) = tmp;
+                rx_bits((2*(i-1+k-1)+1):(2*(i+k-1))) = qpsk_demod(rx_symb);
+                rx_symb_log = [rx_symb_log rx_symb];
+              end
+            end
+
+            % ignore data until we have enough frames to fill filter memory
+            % then count errors
+
+            if nn > ceil(Nfiltsym/(Nsymb/Nc))
+                error_positions = xor(rx_bits, tx_bits);
+                sim_out.errors_log = [sim_out.errors_log error_positions];
+                Nerrs = sum(error_positions);
+                sim_out.Nerrs = [sim_out.Nerrs Nerrs];
+                Terrs += Nerrs;
+                Tbits += length(tx_bits);
+            end
+
+        end
+
+        TERvec(ne) = Terrs;
+        BERvec(ne) = Terrs/Tbits;
+
+        if verbose 
+            printf("EsNo (dB): %f  Terrs: %d BER %f ", EsNodB, Terrs, Terrs/Tbits);
+            printf("\n");
+        end
+        if verbose > 1
+            printf("Terrs: %d BER %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,
+                   Terrs/Tbits, var(sim_out.tx_fdm_log), var(noise_log),
+                   var(sim_out.tx_fdm_log)/(Nc*Rs), var(noise_log)/Fs, (var(sim_out.tx_fdm_log)/(Nc*Rs))/(var(noise_log)/Fs));
+        end
+    end
+    
+    Ebvec = Esvec - 10*log10(bps);
+
+    sim_out.BERvec = BERvec;
+    sim_out.Ebvec  = Ebvec;
+    sim_out.TERvec = TERvec;
+
+    if plot_scatter
+        figure(2);
+        clf;
+        scat = rx_symb_log(Nfiltsym*Nc:length(rx_symb_log)) .* exp(j*pi/4);
+        plot(real(scat), imag(scat),'+');
+        title('Scatter plot');
+
+        figure(3);
+        clf;        
+        y = 1:Rs*2;
+        EsNodBSurface = 20*log10(abs(hf_model(y,:))) + EsNodB;
+        mesh(1:length(freq_sample_hz),y,EsNodBSurface);
+        grid
+        title('HF Channel Es/No');
+    end
+
+endfunction
+
+% Gray coded QPSK modulation function
+
+function symbol = qpsk_mod(two_bits)
+    two_bits_decimal = sum(two_bits .* [2 1]); 
+    switch(two_bits_decimal)
+        case (0) symbol =  1;
+        case (1) symbol =  j;
+        case (2) symbol = -j;
+        case (3) symbol = -1;
+    endswitch
+endfunction
+
+% Gray coded QPSK demodulation function
+
+function two_bits = qpsk_demod(symbol)
+    if isscalar(symbol) == 0
+        printf("only works with scalars\n");
+        return;
+    end
+    bit0 = real(symbol*exp(j*pi/4)) < 0;
+    bit1 = imag(symbol*exp(j*pi/4)) < 0;
+    two_bits = [bit1 bit0];
+endfunction
+
+function sim_in = standard_init
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 0;
+
+  sim_in.Esvec            = 5:15; 
+  sim_in.Ntrials          = 100;
+  sim_in.framesize        = 64;
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 8;
+
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+  sim_in.phase_noise_amp  = 0;
+
+  sim_in.hf_delay_ms      = 2;
+  sim_in.hf_sim           = 0;
+  sim_in.hf_phase_only    = 0;
+  sim_in.hf_mag_only      = 0;
+endfunction
+
+function awgn_hf_ber_curves()
+  sim_in = standard_init();
+
+  Ebvec = sim_in.Esvec - 10*log10(2);
+  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));
+
+  dpsk_awgn = ber_test(sim_in);
+  sim_in.hf_sim           = 1;
+  dpsk_hf   = ber_test(sim_in);
+
+  figure(1); 
+  clf;
+  semilogy(Ebvec, BER_theory,'r;QPSK theory;')
+  hold on;
+  semilogy(dpsk_awgn.Ebvec, dpsk_awgn.BERvec,'g;DQPSK;')
+  semilogy(dpsk_hf.Ebvec, dpsk_hf.BERvec,'g;DQPSK HF;')
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-3 1])
+end
+
+sim_in = standard_init();
+
+% energy file sampled every 10ms
+
+load ../src/ve9qrp.txt
+pdB=10*log10(ve9qrp);
+for i=1:length(pdB)
+  if pdB(i) < 0
+    pdB(i) = 0;
+  end
+end
+
+% Down sample to 40ms rate used for 1300 bit/s codec, every 4th sample is transmitted
+
+pdB = pdB(4:4:length(pdB));
+
+% Use linear mapping function in dB domain to map to symbol power
+
+%power_map_x  = [ 0 20 24 40 50 ];
+%power_map_y  = [--6 -6  0  6  6];
+power_map_x  = [ 0 50 ];
+power_map_y  = [ -15 12];
+mapped_pdB = interp1(power_map_x, power_map_y, pdB);
+
+sim_in.symbol_amp = 10 .^ (mapped_pdB/20);
+%sim_in.symbol_amp = ones(1,length(pdB));
+sim_in.plot_scatter = 1;
+sim_in.verbose      = 2;
+sim_in.hf_delay_ms  = 2;
+sim_in.hf_sim       = 1;
+sim_in.Esvec        = 10;
+sim_in.Ntrials      = 400;
+
+dqpsk_pwr_hf = ber_test(sim_in);
+
+% note: need way to test that power is aligned with speech
+
+figure(4)
+clf;
+plot((1:sim_in.Ntrials)*80*4, pdB(1:sim_in.Ntrials));
+hold on;
+plot((1:sim_in.Ntrials)*80*4, mapped_pdB(1:sim_in.Ntrials),'r');
+hold off;
+
+figure(5)
+clf;
+s = load_raw("../raw/ve9qrp.raw");
+M=320; M_on_2 = M/2; % processing delay between input speech and centre of analysis window
+subplot(211)
+plot(M_on_2:(M_on_2-1+sim_in.Ntrials*M),s(1:sim_in.Ntrials*M))
+hold on;
+plot((1:sim_in.Ntrials)*M, 5000*sim_in.symbol_amp(1:sim_in.Ntrials),'r');
+hold off;
+axis([1 sim_in.Ntrials*M -3E4 3E4]);
+subplot(212)
+plot(real(dqpsk_pwr_hf.tx_fdm_log));
+
+
+figure(6)
+clf;
+plot((1:sim_in.Ntrials)*M, 20*log10(sim_in.symbol_amp(1:sim_in.Ntrials)),'b;Es (dB);');
+hold on;
+plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.hf_model_pwr),'g;Fading (dB);');
+plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.snr_log),'r;Es/No (dB);');
+
+ber = dqpsk_pwr_hf.Nerrs/sim_in.framesize;
+ber_clip = ber;
+ber_clip(find(ber > 0.2)) = 0.2;
+plot((1:length(ber_clip))*M, -20+100*ber_clip,'k;BER (0-20%);');
+hold off;
+axis([1 sim_in.Ntrials*M -20 20])
+
+fep=fopen("dqpsk_errors_pwr.bin","wb"); fwrite(fep, dqpsk_pwr_hf.errors_log, "short"); fclose(fep);
+fber=fopen("ber.bin","wb"); fwrite(fber, ber, "float"); fclose(fber);
index 3d26e89e0bf1ee092bdb3dc3a73d2268ad3b9518..34afed3d1e2b8560064c5bbde646c97fa6f5edc3 100644 (file)
-% test_foff.m\r
-% David Rowe April 2015\r
-%\r
-% Octave script for testing the cohpsk freq offset estimator\r
-\r
-graphics_toolkit ("gnuplot");\r
-more off;\r
-\r
-cohpsk;\r
-fdmdv;\r
-autotest;\r
-\r
-rand('state',1); \r
-randn('state',1);\r
-\r
\r
-% Core function for testing frequency offset estimator.  Performs one test\r
-\r
-function sim_out = freq_off_est_test(sim_in)\r
-  global Nfilter;\r
-  global M;\r
-\r
-  Rs = 100;\r
-  Nc = 4;\r
-  Nd = 2;\r
-  framesize = 32;\r
-  Fs = 8000;\r
-  Fcentre = 1500;\r
-  \r
-  Nsw = 3; % numbers of sync window frames we process over.  Set based\r
-           % on Nsym to flush filter memory by final frame in windw\r
-\r
-  afdmdv.Nsym = 5;\r
-  afdmdv.Nt = 5;\r
-\r
-  afdmdv.Fs = 8000;\r
-  afdmdv.Nc = Nd*Nc-1;\r
-  afdmdv.Rs = Rs;\r
-  M = afdmdv.M  = afdmdv.Fs/afdmdv.Rs;\r
-  afdmdv.Nfilter = afdmdv.Nsym*M;\r
-  afdmdv.tx_filter_memory = zeros(afdmdv.Nc+1, afdmdv.Nfilter);\r
-  excess_bw = 0.5;\r
-  afdmdv.gt_alpha5_root = gen_rn_coeffs(excess_bw, 1/Fs, Rs, afdmdv.Nsym, afdmdv.M);\r
-  afdmdv.Fsep = afdmdv.Rs*(1+excess_bw);\r
-  afdmdv.phase_tx = ones(afdmdv.Nc+1,1);\r
-  freq_hz = afdmdv.Fsep*( -Nc*Nd/2 - 0.5 + (1:Nc*Nd).^1.1 );\r
-  afdmdv.freq_pol = 2*pi*freq_hz/Fs;\r
-  afdmdv.freq = exp(j*afdmdv.freq_pol);\r
-  afdmdv.Fcentre = 1500;\r
-\r
-  afdmdv.fbb_rect = exp(j*2*pi*Fcentre/Fs);\r
-  afdmdv.fbb_phase_tx = 1;\r
-  afdmdv.fbb_phase_rx = 1;\r
-  %afdmdv.phase_rx = ones(afdmdv.Nc+1,1);\r
-  afdmdv.phase_rx = 1 - 2*(mod(1:Nc*Nd,2));\r
-  nin = M;\r
-\r
-  P = afdmdv.P = 4;\r
-  afdmdv.Nfilter = afdmdv.Nsym*afdmdv.M;\r
-  afdmdv.rx_filter_mem_timing = zeros(afdmdv.Nc+1, afdmdv.Nt*afdmdv.P);\r
-  afdmdv.Nfiltertiming = afdmdv.M + afdmdv.Nfilter + afdmdv.M;\r
-  afdmdv.rx_filter_memory = zeros(afdmdv.Nc+1, afdmdv.Nfilter);\r
-\r
-  acohpsk = standard_init();\r
-  acohpsk.framesize        = framesize;\r
-  acohpsk.ldpc_code        = 0;\r
-  acohpsk.ldpc_code_rate   = 1;\r
-  acohpsk.Nc               = Nc;\r
-  acohpsk.Rs               = Rs;\r
-  acohpsk.Ns               = 4;\r
-  acohpsk.Nd               = Nd;\r
-  acohpsk.modulation       = 'qpsk';\r
-  acohpsk.do_write_pilot_file = 0;\r
-  acohpsk = symbol_rate_init(acohpsk);\r
-  acohpsk.Ncm  = 10*acohpsk.Nsymbrowpilot*M;\r
-  acohpsk.coarse_mem  = zeros(1,acohpsk.Ncm);\r
-  acohpsk.Ndft = 2^(ceil(log2(acohpsk.Ncm)));\r
\r
-  ch_fdm_frame_buf = zeros(1, Nsw*acohpsk.Nsymbrowpilot*M);\r
-\r
-  frames    = sim_in.frames;\r
-  EsNodB    = sim_in.EsNodB;\r
-  foff      = sim_in.foff;\r
-  dfoff     = sim_in.dfoff;\r
-  fading_en = sim_in.fading_en;\r
-\r
-  EsNo = 10^(EsNodB/10);\r
-  hf_delay_ms = 2;\r
-  phase_ch = 1;\r
-\r
-  rand('state',1); \r
-  tx_bits_coh = round(rand(1,framesize*10));\r
-  ptx_bits_coh = 1;\r
-  [spread spread_2ms hf_gain] = init_hf_model(Fs, frames*acohpsk.Nsymbrowpilot*afdmdv.M);\r
-\r
-  hf_n = 1;\r
-  nhfdelay = floor(hf_delay_ms*Fs/1000);\r
-  ch_fdm_delay = zeros(1, acohpsk.Nsymbrowpilot*M + nhfdelay);\r
-  \r
-  sync = 0; next_sync = 1;\r
-  sync_start = 1;\r
-  freq_offset_log = [];\r
-  sync_time_log = [];\r
-  ch_fdm_frame_log = [];\r
-  ch_symb_log = [];\r
-  tx_fdm_frame_log = [];\r
-  ratio_log = [];\r
-\r
-  for f=1:frames\r
-\r
-    acohpsk.frame = f;\r
-\r
-    %\r
-    % Mod --------------------------------------------------------------------\r
-    %\r
-\r
-    tx_bits = tx_bits_coh(ptx_bits_coh:ptx_bits_coh+framesize-1);\r
-    ptx_bits_coh += framesize;\r
-    if ptx_bits_coh > length(tx_bits_coh)\r
-      ptx_bits_coh = 1;\r
-    end \r
-\r
-    [tx_symb tx_bits] = bits_to_qpsk_symbols(acohpsk, tx_bits, [], []);\r
-\r
-    tx_fdm_frame = [];\r
-    for r=1:acohpsk.Nsymbrowpilot\r
-      tx_onesymb = tx_symb(r,:);\r
-      [tx_baseband afdmdv] = tx_filter(afdmdv, tx_onesymb);\r
-      [tx_fdm afdmdv] = fdm_upconvert(afdmdv, tx_baseband);\r
-      tx_fdm_frame = [tx_fdm_frame tx_fdm];\r
-    end\r
-    tx_fdm_frame_log = [tx_fdm_frame_log tx_fdm_frame];\r
-\r
-    %\r
-    % Channel --------------------------------------------------------------------\r
-    %\r
-\r
-    ch_fdm_frame = zeros(1,acohpsk.Nsymbrowpilot*M);\r
-    for i=1:acohpsk.Nsymbrowpilot*M\r
-      foff_rect = exp(j*2*pi*foff/Fs);\r
-      foff += dfoff;\r
-      phase_ch *= foff_rect;\r
-      ch_fdm_frame(i) = tx_fdm_frame(i) * phase_ch;\r
-    end\r
-    phase_ch /= abs(phase_ch);\r
-\r
-    if fading_en\r
-      ch_fdm_delay(1:nhfdelay) = ch_fdm_delay(acohpsk.Nsymbrowpilot*M+1:nhfdelay+acohpsk.Nsymbrowpilot*M);\r
-      ch_fdm_delay(nhfdelay+1:nhfdelay+acohpsk.Nsymbrowpilot*M) = ch_fdm_frame;\r
-\r
-      for i=1:acohpsk.Nsymbrowpilot*M\r
-        ahf_model = hf_gain*(spread(hf_n)*ch_fdm_frame(i) + spread_2ms(hf_n)*ch_fdm_delay(i));\r
-        ch_fdm_frame(i) = ahf_model;\r
-        hf_n++;\r
-      end\r
-    end\r
-\r
-    % each carrier has power = 2, total power 2Nc, total symbol rate NcRs, noise BW B=Fs\r
-    % Es/No = (C/Rs)/(N/B), N = var = 2NcFs/NcRs(Es/No) = 2Fs/Rs(Es/No)\r
-\r
-    variance = 2*Fs/(acohpsk.Rs*EsNo);\r
-    uvnoise = sqrt(0.5)*(randn(1,acohpsk.Nsymbrowpilot*M) + j*randn(1,acohpsk.Nsymbrowpilot*M));\r
-    noise = sqrt(variance)*uvnoise;\r
-\r
-    ch_fdm_frame += noise;\r
-    ch_fdm_frame_log = [ch_fdm_frame_log ch_fdm_frame];\r
-\r
-    %\r
-    % Try to achieve sync --------------------------------------------------------------------\r
-    %\r
-\r
-    % store Nsw frames so we can rewind if we get a good candidate\r
-\r
-    ch_fdm_frame_buf(1:(Nsw-1)*acohpsk.Nsymbrowpilot*M) = ch_fdm_frame_buf(acohpsk.Nsymbrowpilot*M+1:Nsw*acohpsk.Nsymbrowpilot*M);\r
-    ch_fdm_frame_buf((Nsw-1)*acohpsk.Nsymbrowpilot*M+1:Nsw*acohpsk.Nsymbrowpilot*M) = ch_fdm_frame;\r
-\r
-    next_sync = sync;\r
-    sync = 0;\r
-\r
-    if sync == 0\r
-\r
-      % we can test +/- 20Hz, so we break this up into 3 tests to cover +/- 60Hz\r
-\r
-      max_ratio = 0;\r
-      for acohpsk.f_est = Fcentre-40:40:Fcentre+40\r
-      %for acohpsk.f_est = Fcentre\r
-        \r
-        printf("  [%d] acohpsk.f_est: %f +/- 20\n", f, acohpsk.f_est);\r
-        [ch_symb rx_timing rx_filt rx_baseband afdmdv acohpsk.f_est ] = rate_Fs_rx_processing(afdmdv, ch_fdm_frame_buf, acohpsk.f_est, Nsw*acohpsk.Nsymbrowpilot, nin, 0);\r
-\r
-        % coarse timing (frame sync) and initial fine freq est ---------------------------------------------\r
-  \r
-        for i=1:Nsw-1\r
-          acohpsk.ct_symb_buf = update_ct_symb_buf(acohpsk.ct_symb_buf, ch_symb((i-1)*acohpsk.Nsymbrowpilot+1:i*acohpsk.Nsymbrowpilot,:), acohpsk.Nct_sym_buf, acohpsk.Nsymbrowpilot);\r
-        end\r
-        [anext_sync acohpsk] = frame_sync_fine_freq_est(acohpsk, ch_symb((Nsw-1)*acohpsk.Nsymbrowpilot+1:Nsw*acohpsk.Nsymbrowpilot,:), sync, next_sync);\r
-\r
-        if anext_sync == 1\r
-          printf("  [%d] acohpsk.ratio: %f\n", f, acohpsk.ratio);\r
-          if acohpsk.ratio > max_ratio\r
-            max_ratio   = acohpsk.ratio;\r
-            f_est       = acohpsk.f_est - acohpsk.f_fine_est;\r
-            next_sync   = anext_sync;\r
-          end\r
-        end\r
-      end\r
-    end\r
-\r
-    % we've found a sync candidate\r
-\r
-    if (next_sync == 1)\r
-\r
-       % rewind and re-process last few frames with f_est\r
-\r
-       acohpsk.f_est = f_est;\r
-       printf("  [%d] trying sync and f_est: %f\n", f, acohpsk.f_est);\r
-       [ch_symb rx_timing rx_filt rx_baseband afdmdv acohpsk.f_est] = rate_Fs_rx_processing(afdmdv, ch_fdm_frame_buf, acohpsk.f_est, Nsw*acohpsk.Nsymbrowpilot, nin, 0);\r
-       ch_symb_log = ch_symb;\r
-       for i=1:Nsw-1\r
-         acohpsk.ct_symb_buf = update_ct_symb_buf(acohpsk.ct_symb_buf, ch_symb((i-1)*acohpsk.Nsymbrowpilot+1:i*acohpsk.Nsymbrowpilot,:), acohpsk.Nct_sym_buf, acohpsk.Nsymbrowpilot);\r
-       end\r
-       [next_sync acohpsk] = frame_sync_fine_freq_est(acohpsk, ch_symb((Nsw-1)*acohpsk.Nsymbrowpilot+1:Nsw*acohpsk.Nsymbrowpilot,:), sync, next_sync);\r
-       if abs(acohpsk.f_fine_est) > 2\r
-         printf("  [%d] Hmm %f is a bit big so back to coarse est ...\n", f, acohpsk.f_fine_est);\r
-         next_sync = 0;\r
-       end\r
-\r
-       % candidate checks out so log stats\r
-\r
-       if (next_sync == 1)\r
-         printf("  [%d] in sync!\n", f);\r
-         freq_offset_log = [freq_offset_log Fcentre+foff-acohpsk.f_est];\r
-         sync_time_log = [sync_time_log f-sync_start];\r
-         ratio_log = [ratio_log max_ratio];\r
-         next_sync = 0; sync_start = f;\r
-       end\r
-    end\r
-\r
-    %printf("f: %d sync: %d next_sync: %d\n", f, sync, next_sync);\r
-    [sync acohpsk] = sync_state_machine(acohpsk, sync, next_sync);\r
-\r
-  end\r
-\r
-  % ftx=fopen("coarse_tx.raw","wb"); fwrite(ftx, 1000*ch_fdm_frame_log, "short"); fclose(ftx);\r
-\r
-  sim_out.freq_offset_log = freq_offset_log;\r
-  sim_out.sync_time_log = sync_time_log;\r
-  sim_out.ch_fdm_frame_log = ch_fdm_frame_log;\r
-  sim_out.ch_symb_log = ch_symb_log;\r
-  sim_out.tx_fdm_frame_log = tx_fdm_frame_log;\r
-  sim_out.ratio_log = ratio_log;\r
-endfunction\r
-\r
-\r
-function freq_off_est_test_single\r
-  sim_in.frames    = 5;\r
-  sim_in.EsNodB    = 120;\r
-  sim_in.foff      = 0;\r
-  sim_in.dfoff     = 0;\r
-  sim_in.fading_en = 0;\r
-\r
-  sim_out = freq_off_est_test(sim_in);\r
-\r
-  figure(1)\r
-  subplot(211)\r
-  plot(sim_out.freq_offset_log)\r
-  ylabel('f est error')\r
-  xlabel('time')\r
-\r
-  subplot(212)\r
-  if length(sim_out.freq_offset_log) > 0\r
-    hist(sim_out.freq_offset_log)\r
-    xlabel('f est error')\r
-    ylabel('histogram');\r
-  end\r
-\r
-  figure(2)\r
-  subplot(211)\r
-  plot(sim_out.sync_time_log)\r
-  ylabel('time to sync (frames)')\r
-  subplot(212)\r
-  if length(sim_out.sync_time_log) > 0\r
-    hist(sim_out.sync_time_log)\r
-    xlabel('time to sync (frames)')\r
-    ylabel('histogram')\r
-  end\r
-\r
-  figure(3)\r
-  subplot(211)\r
-  plot(real(sim_out.tx_fdm_frame_log(1:2*960)))\r
-  grid;\r
-  subplot(212)\r
-  plot(real(sim_out.ch_symb_log),'+')\r
-  grid;\r
-\r
-  figure(4)\r
-  clf;\r
-  plot(sim_out.ch_symb_log,'+')\r
-\r
-  figure(5)\r
-  clf;\r
-  plot(sim_out.ratio_log)\r
-  xlabel('time')\r
-  ylabel('ratio for sync')\r
-endfunction\r
-\r
-\r
-function [freq_off_log EsNodBSet] = freq_off_est_test_curves\r
-  EsNodBSet = [20 12 8];\r
-\r
-  sim_in.frames    = 100;\r
-  sim_in.foff      = -40;\r
-  sim_in.dfoff     = 0;\r
-  sim_in.fading_en = 1;\r
-  freq_off_log = 1E6*ones(sim_in.frames, length(EsNodBSet) );\r
-  sync_time_log = 1E6*ones(sim_in.frames, length(EsNodBSet) );\r
-\r
-  for i=1:length(EsNodBSet)\r
-    sim_in.EsNodB = EsNodBSet(i);\r
-    printf("%f\n", sim_in.EsNodB);\r
-\r
-    sim_out = freq_off_est_test(sim_in);\r
-    freq_off_log(1:length(sim_out.freq_offset_log),i) = sim_out.freq_offset_log;\r
-    sync_time_log(1:length(sim_out.sync_time_log),i) = sim_out.sync_time_log;\r
-  end\r
-\r
-  figure(1)\r
-  clf\r
-  hold on;\r
-  for i=1:length(EsNodBSet)\r
-    data = freq_off_log(find(freq_off_log(:,i) < 1E6),i);\r
-    s = std(data);\r
-    m = mean(data);\r
-    stdbar = [m-s; m+s];\r
-    plot(EsNodBSet(i), data, '+')\r
-    plot([EsNodBSet(i) EsNodBSet(i)]+0.5, stdbar,'+-')\r
-  end\r
-  hold off\r
-\r
-  axis([6 22 -25 25])\r
-  if sim_in.fading_en\r
-    title_str = sprintf('foff = %d Hz Fading', sim_in.foff);\r
-  else\r
-    title_str = sprintf('foff = %d Hz AWGN', sim_in.foff);\r
-  end\r
-  title(title_str);\r
-  xlabel('Es/No (dB)')\r
-  ylabel('freq offset error (Hz)');\r
\r
-  figure(2)\r
-  clf\r
-  hold on;\r
-  for i=1:length(EsNodBSet)\r
-    leg = sprintf("%d;%d dB;", i, EsNodBSet(i));\r
-    plot(freq_off_log(find(freq_off_log(:,i) < 1E6),i),leg)\r
-  end\r
-  hold off;\r
-  title(title_str);\r
-  xlabel('test');\r
-  ylabel('freq offset error (Hz)');\r
-  legend('boxoff');\r
-\r
-  figure(3)\r
-  clf\r
-  hold on;\r
-  for i=1:length(EsNodBSet)\r
-    data = sync_time_log(find(sync_time_log(:,i) < 1E6),i);\r
-    if length(data) \r
-      s = std(data);\r
-      m = mean(data);\r
-      stdbar = [m-s; m+s];\r
-      plot(EsNodBSet(i), data, '+')\r
-      plot([EsNodBSet(i) EsNodBSet(i)]+0.5, stdbar,'+-')\r
-    end\r
-  end \r
-  hold off;\r
-  axis([6 22 0 10])\r
-  ylabel('sync time (frames)')\r
-  xlabel('Es/No (dB)');\r
-  title(title_str);\r
-\r
-  figure(4)\r
-  clf\r
-  hold on;\r
-  for i=1:length(EsNodBSet)\r
-    leg = sprintf("%d;%d dB;", i, EsNodBSet(i));\r
-    plot(sync_time_log(find(sync_time_log(:,i) < 1E6),i),leg)\r
-  end\r
-  hold off;\r
-  title(title_str);\r
-  xlabel('test');\r
-  ylabel('sync time (frames)');\r
-  legend('boxoff');\r
-\r
-endfunction\r
-\r
-\r
-% select on of these to run:\r
-\r
-freq_off_est_test_single;\r
-%freq_off_est_test_curves;\r
-\r
+% test_foff.m
+% David Rowe April 2015
+%
+% Octave script for testing the cohpsk freq offset estimator
+
+graphics_toolkit ("gnuplot");
+more off;
+
+cohpsk;
+fdmdv;
+autotest;
+
+rand('state',1); 
+randn('state',1);
+
+% Core function for testing frequency offset estimator.  Performs one test
+
+function sim_out = freq_off_est_test(sim_in)
+  global Nfilter;
+  global M;
+
+  Rs = 100;
+  Nc = 4;
+  Nd = 2;
+  framesize = 32;
+  Fs = 8000;
+  Fcentre = 1500;
+  
+  Nsw = 3; % numbers of sync window frames we process over.  Set based
+           % on Nsym to flush filter memory by final frame in windw
+
+  afdmdv.Nsym = 5;
+  afdmdv.Nt = 5;
+
+  afdmdv.Fs = 8000;
+  afdmdv.Nc = Nd*Nc-1;
+  afdmdv.Rs = Rs;
+  M = afdmdv.M  = afdmdv.Fs/afdmdv.Rs;
+  afdmdv.Nfilter = afdmdv.Nsym*M;
+  afdmdv.tx_filter_memory = zeros(afdmdv.Nc+1, afdmdv.Nfilter);
+  excess_bw = 0.5;
+  afdmdv.gt_alpha5_root = gen_rn_coeffs(excess_bw, 1/Fs, Rs, afdmdv.Nsym, afdmdv.M);
+  afdmdv.Fsep = afdmdv.Rs*(1+excess_bw);
+  afdmdv.phase_tx = ones(afdmdv.Nc+1,1);
+  freq_hz = afdmdv.Fsep*( -Nc*Nd/2 - 0.5 + (1:Nc*Nd).^1.1 );
+  afdmdv.freq_pol = 2*pi*freq_hz/Fs;
+  afdmdv.freq = exp(j*afdmdv.freq_pol);
+  afdmdv.Fcentre = 1500;
+
+  afdmdv.fbb_rect = exp(j*2*pi*Fcentre/Fs);
+  afdmdv.fbb_phase_tx = 1;
+  afdmdv.fbb_phase_rx = 1;
+  %afdmdv.phase_rx = ones(afdmdv.Nc+1,1);
+  afdmdv.phase_rx = 1 - 2*(mod(1:Nc*Nd,2));
+  nin = M;
+
+  P = afdmdv.P = 4;
+  afdmdv.Nfilter = afdmdv.Nsym*afdmdv.M;
+  afdmdv.rx_filter_mem_timing = zeros(afdmdv.Nc+1, afdmdv.Nt*afdmdv.P);
+  afdmdv.Nfiltertiming = afdmdv.M + afdmdv.Nfilter + afdmdv.M;
+  afdmdv.rx_filter_memory = zeros(afdmdv.Nc+1, afdmdv.Nfilter);
+
+  acohpsk = standard_init();
+  acohpsk.framesize        = framesize;
+  acohpsk.ldpc_code        = 0;
+  acohpsk.ldpc_code_rate   = 1;
+  acohpsk.Nc               = Nc;
+  acohpsk.Rs               = Rs;
+  acohpsk.Ns               = 4;
+  acohpsk.Nd               = Nd;
+  acohpsk.modulation       = 'qpsk';
+  acohpsk.do_write_pilot_file = 0;
+  acohpsk = symbol_rate_init(acohpsk);
+  acohpsk.Ncm  = 10*acohpsk.Nsymbrowpilot*M;
+  acohpsk.coarse_mem  = zeros(1,acohpsk.Ncm);
+  acohpsk.Ndft = 2^(ceil(log2(acohpsk.Ncm)));
+  ch_fdm_frame_buf = zeros(1, Nsw*acohpsk.Nsymbrowpilot*M);
+
+  frames    = sim_in.frames;
+  EsNodB    = sim_in.EsNodB;
+  foff      = sim_in.foff;
+  dfoff     = sim_in.dfoff;
+  fading_en = sim_in.fading_en;
+
+  EsNo = 10^(EsNodB/10);
+  hf_delay_ms = 2;
+  phase_ch = 1;
+
+  rand('state',1); 
+  tx_bits_coh = round(rand(1,framesize*10));
+  ptx_bits_coh = 1;
+  [spread spread_2ms hf_gain] = init_hf_model(Fs, frames*acohpsk.Nsymbrowpilot*afdmdv.M);
+
+  hf_n = 1;
+  nhfdelay = floor(hf_delay_ms*Fs/1000);
+  ch_fdm_delay = zeros(1, acohpsk.Nsymbrowpilot*M + nhfdelay);
+  
+  sync = 0; next_sync = 1;
+  sync_start = 1;
+  freq_offset_log = [];
+  sync_time_log = [];
+  ch_fdm_frame_log = [];
+  ch_symb_log = [];
+  tx_fdm_frame_log = [];
+  ratio_log = [];
+
+  for f=1:frames
+
+    acohpsk.frame = f;
+
+    %
+    % Mod --------------------------------------------------------------------
+    %
+
+    tx_bits = tx_bits_coh(ptx_bits_coh:ptx_bits_coh+framesize-1);
+    ptx_bits_coh += framesize;
+    if ptx_bits_coh > length(tx_bits_coh)
+      ptx_bits_coh = 1;
+    end 
+
+    [tx_symb tx_bits] = bits_to_qpsk_symbols(acohpsk, tx_bits, [], []);
+
+    tx_fdm_frame = [];
+    for r=1:acohpsk.Nsymbrowpilot
+      tx_onesymb = tx_symb(r,:);
+      [tx_baseband afdmdv] = tx_filter(afdmdv, tx_onesymb);
+      [tx_fdm afdmdv] = fdm_upconvert(afdmdv, tx_baseband);
+      tx_fdm_frame = [tx_fdm_frame tx_fdm];
+    end
+    tx_fdm_frame_log = [tx_fdm_frame_log tx_fdm_frame];
+
+    %
+    % Channel --------------------------------------------------------------------
+    %
+
+    ch_fdm_frame = zeros(1,acohpsk.Nsymbrowpilot*M);
+    for i=1:acohpsk.Nsymbrowpilot*M
+      foff_rect = exp(j*2*pi*foff/Fs);
+      foff += dfoff;
+      phase_ch *= foff_rect;
+      ch_fdm_frame(i) = tx_fdm_frame(i) * phase_ch;
+    end
+    phase_ch /= abs(phase_ch);
+
+    if fading_en
+      ch_fdm_delay(1:nhfdelay) = ch_fdm_delay(acohpsk.Nsymbrowpilot*M+1:nhfdelay+acohpsk.Nsymbrowpilot*M);
+      ch_fdm_delay(nhfdelay+1:nhfdelay+acohpsk.Nsymbrowpilot*M) = ch_fdm_frame;
+
+      for i=1:acohpsk.Nsymbrowpilot*M
+        ahf_model = hf_gain*(spread(hf_n)*ch_fdm_frame(i) + spread_2ms(hf_n)*ch_fdm_delay(i));
+        ch_fdm_frame(i) = ahf_model;
+        hf_n++;
+      end
+    end
+
+    % each carrier has power = 2, total power 2Nc, total symbol rate NcRs, noise BW B=Fs
+    % Es/No = (C/Rs)/(N/B), N = var = 2NcFs/NcRs(Es/No) = 2Fs/Rs(Es/No)
+
+    variance = 2*Fs/(acohpsk.Rs*EsNo);
+    uvnoise = sqrt(0.5)*(randn(1,acohpsk.Nsymbrowpilot*M) + j*randn(1,acohpsk.Nsymbrowpilot*M));
+    noise = sqrt(variance)*uvnoise;
+
+    ch_fdm_frame += noise;
+    ch_fdm_frame_log = [ch_fdm_frame_log ch_fdm_frame];
+
+    %
+    % Try to achieve sync --------------------------------------------------------------------
+    %
+
+    % store Nsw frames so we can rewind if we get a good candidate
+
+    ch_fdm_frame_buf(1:(Nsw-1)*acohpsk.Nsymbrowpilot*M) = ch_fdm_frame_buf(acohpsk.Nsymbrowpilot*M+1:Nsw*acohpsk.Nsymbrowpilot*M);
+    ch_fdm_frame_buf((Nsw-1)*acohpsk.Nsymbrowpilot*M+1:Nsw*acohpsk.Nsymbrowpilot*M) = ch_fdm_frame;
+
+    next_sync = sync;
+    sync = 0;
+
+    if sync == 0
+
+      % we can test +/- 20Hz, so we break this up into 3 tests to cover +/- 60Hz
+
+      max_ratio = 0;
+      for acohpsk.f_est = Fcentre-40:40:Fcentre+40
+      %for acohpsk.f_est = Fcentre
+        
+        printf("  [%d] acohpsk.f_est: %f +/- 20\n", f, acohpsk.f_est);
+        [ch_symb rx_timing rx_filt rx_baseband afdmdv acohpsk.f_est ] = rate_Fs_rx_processing(afdmdv, ch_fdm_frame_buf, acohpsk.f_est, Nsw*acohpsk.Nsymbrowpilot, nin, 0);
+
+        % coarse timing (frame sync) and initial fine freq est ---------------------------------------------
+  
+        for i=1:Nsw-1
+          acohpsk.ct_symb_buf = update_ct_symb_buf(acohpsk.ct_symb_buf, ch_symb((i-1)*acohpsk.Nsymbrowpilot+1:i*acohpsk.Nsymbrowpilot,:), acohpsk.Nct_sym_buf, acohpsk.Nsymbrowpilot);
+        end
+        [anext_sync acohpsk] = frame_sync_fine_freq_est(acohpsk, ch_symb((Nsw-1)*acohpsk.Nsymbrowpilot+1:Nsw*acohpsk.Nsymbrowpilot,:), sync, next_sync);
+
+        if anext_sync == 1
+          printf("  [%d] acohpsk.ratio: %f\n", f, acohpsk.ratio);
+          if acohpsk.ratio > max_ratio
+            max_ratio   = acohpsk.ratio;
+            f_est       = acohpsk.f_est - acohpsk.f_fine_est;
+            next_sync   = anext_sync;
+          end
+        end
+      end
+    end
+
+    % we've found a sync candidate
+
+    if (next_sync == 1)
+
+       % rewind and re-process last few frames with f_est
+
+       acohpsk.f_est = f_est;
+       printf("  [%d] trying sync and f_est: %f\n", f, acohpsk.f_est);
+       [ch_symb rx_timing rx_filt rx_baseband afdmdv acohpsk.f_est] = rate_Fs_rx_processing(afdmdv, ch_fdm_frame_buf, acohpsk.f_est, Nsw*acohpsk.Nsymbrowpilot, nin, 0);
+       ch_symb_log = ch_symb;
+       for i=1:Nsw-1
+         acohpsk.ct_symb_buf = update_ct_symb_buf(acohpsk.ct_symb_buf, ch_symb((i-1)*acohpsk.Nsymbrowpilot+1:i*acohpsk.Nsymbrowpilot,:), acohpsk.Nct_sym_buf, acohpsk.Nsymbrowpilot);
+       end
+       [next_sync acohpsk] = frame_sync_fine_freq_est(acohpsk, ch_symb((Nsw-1)*acohpsk.Nsymbrowpilot+1:Nsw*acohpsk.Nsymbrowpilot,:), sync, next_sync);
+       if abs(acohpsk.f_fine_est) > 2
+         printf("  [%d] Hmm %f is a bit big so back to coarse est ...\n", f, acohpsk.f_fine_est);
+         next_sync = 0;
+       end
+
+       % candidate checks out so log stats
+
+       if (next_sync == 1)
+         printf("  [%d] in sync!\n", f);
+         freq_offset_log = [freq_offset_log Fcentre+foff-acohpsk.f_est];
+         sync_time_log = [sync_time_log f-sync_start];
+         ratio_log = [ratio_log max_ratio];
+         next_sync = 0; sync_start = f;
+       end
+    end
+
+    %printf("f: %d sync: %d next_sync: %d\n", f, sync, next_sync);
+    [sync acohpsk] = sync_state_machine(acohpsk, sync, next_sync);
+
+  end
+
+  % ftx=fopen("coarse_tx.raw","wb"); fwrite(ftx, 1000*ch_fdm_frame_log, "short"); fclose(ftx);
+
+  sim_out.freq_offset_log = freq_offset_log;
+  sim_out.sync_time_log = sync_time_log;
+  sim_out.ch_fdm_frame_log = ch_fdm_frame_log;
+  sim_out.ch_symb_log = ch_symb_log;
+  sim_out.tx_fdm_frame_log = tx_fdm_frame_log;
+  sim_out.ratio_log = ratio_log;
+endfunction
+
+
+function freq_off_est_test_single
+  sim_in.frames    = 5;
+  sim_in.EsNodB    = 120;
+  sim_in.foff      = 0;
+  sim_in.dfoff     = 0;
+  sim_in.fading_en = 0;
+
+  sim_out = freq_off_est_test(sim_in);
+
+  figure(1)
+  subplot(211)
+  plot(sim_out.freq_offset_log)
+  ylabel('f est error')
+  xlabel('time')
+
+  subplot(212)
+  if length(sim_out.freq_offset_log) > 0
+    hist(sim_out.freq_offset_log)
+    xlabel('f est error')
+    ylabel('histogram');
+  end
+
+  figure(2)
+  subplot(211)
+  plot(sim_out.sync_time_log)
+  ylabel('time to sync (frames)')
+  subplot(212)
+  if length(sim_out.sync_time_log) > 0
+    hist(sim_out.sync_time_log)
+    xlabel('time to sync (frames)')
+    ylabel('histogram')
+  end
+
+  figure(3)
+  subplot(211)
+  plot(real(sim_out.tx_fdm_frame_log(1:2*960)))
+  grid;
+  subplot(212)
+  plot(real(sim_out.ch_symb_log),'+')
+  grid;
+
+  figure(4)
+  clf;
+  plot(sim_out.ch_symb_log,'+')
+
+  figure(5)
+  clf;
+  plot(sim_out.ratio_log)
+  xlabel('time')
+  ylabel('ratio for sync')
+endfunction
+
+
+function [freq_off_log EsNodBSet] = freq_off_est_test_curves
+  EsNodBSet = [20 12 8];
+
+  sim_in.frames    = 100;
+  sim_in.foff      = -40;
+  sim_in.dfoff     = 0;
+  sim_in.fading_en = 1;
+  freq_off_log = 1E6*ones(sim_in.frames, length(EsNodBSet) );
+  sync_time_log = 1E6*ones(sim_in.frames, length(EsNodBSet) );
+
+  for i=1:length(EsNodBSet)
+    sim_in.EsNodB = EsNodBSet(i);
+    printf("%f\n", sim_in.EsNodB);
+
+    sim_out = freq_off_est_test(sim_in);
+    freq_off_log(1:length(sim_out.freq_offset_log),i) = sim_out.freq_offset_log;
+    sync_time_log(1:length(sim_out.sync_time_log),i) = sim_out.sync_time_log;
+  end
+
+  figure(1)
+  clf
+  hold on;
+  for i=1:length(EsNodBSet)
+    data = freq_off_log(find(freq_off_log(:,i) < 1E6),i);
+    s = std(data);
+    m = mean(data);
+    stdbar = [m-s; m+s];
+    plot(EsNodBSet(i), data, '+')
+    plot([EsNodBSet(i) EsNodBSet(i)]+0.5, stdbar,'+-')
+  end
+  hold off
+
+  axis([6 22 -25 25])
+  if sim_in.fading_en
+    title_str = sprintf('foff = %d Hz Fading', sim_in.foff);
+  else
+    title_str = sprintf('foff = %d Hz AWGN', sim_in.foff);
+  end
+  title(title_str);
+  xlabel('Es/No (dB)')
+  ylabel('freq offset error (Hz)');
+  figure(2)
+  clf
+  hold on;
+  for i=1:length(EsNodBSet)
+    leg = sprintf("%d;%d dB;", i, EsNodBSet(i));
+    plot(freq_off_log(find(freq_off_log(:,i) < 1E6),i),leg)
+  end
+  hold off;
+  title(title_str);
+  xlabel('test');
+  ylabel('freq offset error (Hz)');
+  legend('boxoff');
+
+  figure(3)
+  clf
+  hold on;
+  for i=1:length(EsNodBSet)
+    data = sync_time_log(find(sync_time_log(:,i) < 1E6),i);
+    if length(data) 
+      s = std(data);
+      m = mean(data);
+      stdbar = [m-s; m+s];
+      plot(EsNodBSet(i), data, '+')
+      plot([EsNodBSet(i) EsNodBSet(i)]+0.5, stdbar,'+-')
+    end
+  end 
+  hold off;
+  axis([6 22 0 10])
+  ylabel('sync time (frames)')
+  xlabel('Es/No (dB)');
+  title(title_str);
+
+  figure(4)
+  clf
+  hold on;
+  for i=1:length(EsNodBSet)
+    leg = sprintf("%d;%d dB;", i, EsNodBSet(i));
+    plot(sync_time_log(find(sync_time_log(:,i) < 1E6),i),leg)
+  end
+  hold off;
+  title(title_str);
+  xlabel('test');
+  ylabel('sync time (frames)');
+  legend('boxoff');
+
+endfunction
+
+
+% select on of these to run:
+
+freq_off_est_test_single;
+%freq_off_est_test_curves;
+
index 6d8796e025c88ea3d87ced9c5179220b7edd3060..453302b95473d596005aae3d1b8d6a435bbe282b 100644 (file)
-% test_qpsk.m\r
-% David Rowe Feb 2014\r
-%\r
-% QPSK modem simulation, initially based on code by Bill Cowley\r
-% Generates curves BER versus E/No curves for different modems.\r
-% Design to test coherent demodulation ideas on HF channels without\r
-% building a full blown modem.  Uses 'genie provided' estimates for\r
-% timing estimation, frame sync.\r
-%\r
-\r
-1;\r
-\r
-% main test function \r
-\r
-function sim_out = ber_test(sim_in, modulation)\r
-    Fs = 8000;\r
-\r
-    verbose          = sim_in.verbose;\r
-    framesize        = sim_in.framesize;\r
-    Ntrials          = sim_in.Ntrials;\r
-    Esvec            = sim_in.Esvec;\r
-    phase_offset     = sim_in.phase_offset;\r
-    phase_est        = sim_in.phase_est;\r
-    w_offset         = sim_in.w_offset;\r
-    plot_scatter     = sim_in.plot_scatter;\r
-    Rs               = sim_in.Rs;\r
-    hf_sim           = sim_in.hf_sim;\r
-    Nhfdelay         = floor(sim_in.hf_delay_ms*1000/Fs);\r
-    hf_phase_only    = sim_in.hf_phase_only;\r
-    hf_mag_only      = sim_in.hf_mag_only;\r
-\r
-    bps              = 2;\r
-    Nsymb            = framesize/bps;\r
-    prev_sym_tx      = qpsk_mod([0 0]);\r
-    prev_sym_rx      = qpsk_mod([0 0]);\r
-    rx_symb_log      = [];\r
-\r
-    Np               = sim_in.Np;  % number of pilot symbols to use in phase est\r
-    Ns               = sim_in.Ns;  % spacing of pilot symbols, so (Nps-1) data symbols between every pilot\r
-    Nps              = Np*Ns;\r
-    r_delay_line     = zeros(1,Nps+1);\r
-    s_delay_line     = zeros(1,Nps+1);\r
-    spread_main_phi  = 0;\r
-    spread_delay_phi = 0;\r
-    spread_main_phi_log = [];\r
-\r
-    ldpc_code = sim_in.ldpc_code;\r
-\r
-    if ldpc_code\r
-        % Start CML library\r
-\r
-        currentdir = pwd;\r
-        addpath '/home/david/tmp/cml/mat'    % assume the source files stored here\r
-        cd /home/david/tmp/cml\r
-        CmlStartup                           % note that this is not in the cml path!\r
-        cd(currentdir)\r
-  \r
-        % Our LDPC library\r
-\r
-        ldpc;\r
-\r
-        rate = 3/4; \r
-        mod_order = 4; \r
-        modulation = 'QPSK';\r
-        mapping = 'gray';\r
-\r
-        demod_type = 0;\r
-        decoder_type = 0;\r
-        max_iterations = 100;\r
-\r
-        code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);\r
-        code_param.code_bits_per_frame = framesize;\r
-        code_param.symbols_per_frame = framesize/bps;\r
-    else\r
-        rate = 1;\r
-    end\r
-\r
-    % convert "spreading" samples from 1kHz carrier at Fs to complex\r
-    % baseband, generated by passing a 1kHz sine wave through PathSim\r
-    % with the ccir-poor model, enabling one path at a time.\r
-    \r
-    Fc = 1000;\r
-    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");\r
-    spread1k = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");\r
-    spread1k_2ms = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-\r
-    % down convert to complex baseband\r
-    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');\r
-    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');\r
-\r
-    % remove -2000 Hz image\r
-    b = fir1(50, 5/Fs);\r
-    spread = filter(b,1,spreadbb);\r
-    spread_2ms = filter(b,1,spreadbb_2ms);\r
-\r
-    % discard first 1000 samples as these were near 0, probably as\r
-    % PathSim states were ramping up\r
-\r
-    spread    = spread(1000:length(spread));\r
-    spread_2ms = spread_2ms(1000:length(spread_2ms));\r
-\r
-    % Determine "gain" of HF channel model, so we can normalise\r
-    % carrier power during HF channel sim to calibrate SNR.  I imagine\r
-    % different implementations of ccir-poor would do this in\r
-    % different ways, leading to different BER results.  Oh Well!\r
-\r
-    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));\r
-\r
-    % design root nyquist (root raised cosine) filter and init tx and rx filter states\r
-\r
-    alpha = 0.5; T=1/Fs; Nfiltsym=7; M=Fs/Rs;\r
-    if floor(Fs/Rs) != Fs/Rs\r
-        printf("oversampling ratio must be an integer\n");\r
-        return;\r
-    end\r
-    hrn = gen_rn_coeffs(alpha, T, Rs, Nfiltsym, M);\r
-    Nfilter = length(hrn);\r
-    tx_filter_memory = zeros(1, Nfilter);\r
-    rx_filter_memory = zeros(1, Nfilter);\r
-    s_delay_line_filt = zeros(1,Nfiltsym);\r
-    tx_bits_delay_line_filt = zeros(1,Nfiltsym*bps);\r
-    hf_sim_delay_line = zeros(1,M+Nhfdelay);\r
-\r
-    for ne = 1:length(Esvec)\r
-        Es = Esvec(ne);\r
-        EsNo = 10^(Es/10);\r
-    \r
-        % Given Es/No, determine the variance of a normal noise source:\r
-        %\r
-        %   Es = C/Rs where C is carrier power (energy per unit time) and Rs is the symbole rate\r
-        %   N  = NoB where N is the total noise power, No is the Noise spectral density is W/Hz\r
-        %        and B is the bandwidth of the noise which is Fs\r
-        %   No = N/Fs\r
-        %\r
-        % equating Es/No we get:\r
-        %\r
-        %   Es/No = (C/Rs)/(No/Fs)\r
-        %   No    = CFs/(Rs(Es/No))\r
-\r
-        variance = Fs/(Rs*EsNo);\r
-        Terrs = 0;  Tbits = 0;  Terrsldpc = 0;  Tbitsldpc = 0; Ferrsldpc = 0;\r
-        if verbose > 1\r
-            printf("EsNo (dB): %f EsNo: %f variance: %f\n", Es, EsNo, variance);\r
-        end\r
-        \r
-        % init HF channel\r
-        sc = 1;\r
-\r
-        tx_filt_log = [];\r
-        rx_filt_log = [];\r
-        rx_baseband_log = [];\r
-        tx_baseband_log = [];\r
-        noise_log = [];\r
-        hf_angle_log = [];\r
-        tx_phase = rx_phase = 0;\r
-        tx_data_buffer = zeros(1,2*framesize);\r
-        s_data_buffer = zeros(1,2*Nsymb);\r
-        C_log = [];\r
-\r
-        for nn = 1: Ntrials\r
-                  \r
-            tx_bits = round( rand( 1, framesize*rate ) );\r
-            %tx_bits = [1 0 zeros(1,framesize*rate-2)];\r
-\r
-            % modulate\r
-\r
-            if ldpc_code\r
-                [tx_bits, s] = ldpc_enc(tx_bits, code_param);\r
-                t2 = tx_bits;\r
-                s2 = s;\r
-            else\r
-                s = zeros(1, Nsymb);\r
-                for i=1:Nsymb\r
-                    tx_symb = qpsk_mod(tx_bits(2*(i-1)+1:2*i));\r
-                    %printf("shift: %f prev_sym: %f  ", tx_symb, prev_sym_tx);\r
-                    if strcmp(modulation,'dqpsk')\r
-                        tx_symb *= prev_sym_tx;\r
-                        %printf("tx_symb: %f\n", tx_symb);\r
-                        prev_sym_tx = tx_symb;\r
-                    end \r
-                    s(i) = tx_symb;\r
-                end\r
-            end\r
-            s_ch = s;\r
-\r
-            % root nyquist filter symbols\r
-\r
-            for k=1:Nsymb\r
-\r
-               % tx filter symbols\r
-\r
-               tx_filt = zeros(1,M);\r
-\r
-               % tx filter each symbol, generate M filtered output samples for each symbol.\r
-               % Efficient polyphase filter techniques used as tx_filter_memory is sparse\r
-\r
-               tx_filter_memory(Nfilter) = s_ch(k);\r
-\r
-               for i=1:M\r
-                   tx_filt(i) = M*tx_filter_memory(M:M:Nfilter) * hrn(M-i+1:M:Nfilter)';\r
-               end\r
-               tx_filter_memory(1:Nfilter-M) = tx_filter_memory(M+1:Nfilter);\r
-               tx_filter_memory(Nfilter-M+1:Nfilter) = zeros(1,M);\r
-               \r
-               % HF channel simulation\r
-\r
-               if hf_sim\r
-\r
-                   hf_sim_delay_line(1:Nhfdelay) = hf_sim_delay_line(M+1:M+Nhfdelay);\r
-                   hf_sim_delay_line(Nhfdelay+1:M+Nhfdelay) = tx_filt;\r
-\r
-                   % disable as a wrap around will cause a nasty phase jump.  Best to generate\r
-                   % longer files\r
-                   %if ((sc+M) > length(spread)) || ((sc+M) > length(spread_2ms))\r
-                   %    sc =1 ;\r
-                   %end\r
-                   comb = conj(spread(sc:sc+M-1))' + conj(spread_2ms(sc:sc+M-1))';\r
-                   if hf_phase_only\r
-                        tx_filt = tx_filt.*exp(j*angle(comb));\r
-                   else\r
-                       if hf_mag_only\r
-                           comb = conj(spread(sc:sc+M-1))' + conj(spread_2ms(sc:sc+M-1))';\r
-                           tx_filt = tx_filt.*abs(comb);   \r
-                       else\r
-                           % regular HF channel sim\r
-                           tx_filt = tx_filt.*conj(spread(sc:sc+M-1))' + hf_sim_delay_line(1:M).*conj(spread_2ms(sc:sc+M-1))';\r
-                       end\r
-                   end\r
-                   sc += M;\r
\r
-                   % normalise so average HF power C=1\r
-\r
-                   if hf_phase_only == 0   % C already 1 if we are just tweaking phase\r
-                       tx_filt *= hf_gain;\r
-                   end\r
-                   C_log = [C_log abs(comb)*hf_gain];\r
-               end\r
-               tx_filt_log = [tx_filt_log tx_filt];\r
-               hf_angle_log = [hf_angle_log angle(comb)];\r
-\r
-               % AWGN noise and phase/freq offset channel simulation\r
-               % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im\r
-\r
-               noise = sqrt(variance*0.5)*( randn(1,M) + j*randn(1,M) );\r
-               noise_log = [noise_log noise];\r
-               rx_baseband = tx_filt.*exp(j*phase_offset) + noise;\r
-               phase_offset += w_offset;\r
-               \r
-               % rx filter symbol\r
-\r
-               rx_filter_memory(Nfilter-M+1:Nfilter) = rx_baseband;\r
-               rx_filt = rx_filter_memory * hrn';\r
-               rx_filter_memory(1:Nfilter-M) = rx_filter_memory(1+M:Nfilter);\r
-               rx_filt_log = [rx_filt_log rx_filt];\r
-\r
-               % delay in tx symbols to compensate for filtering\r
-               % delay, as tx symbols are used as pilot symbols input\r
-               % to phase est\r
-\r
-               s_delay_line_filt(1:Nfiltsym-1) = s_delay_line_filt(2:Nfiltsym);\r
-               s_delay_line_filt(Nfiltsym) = s(k);\r
-               s(k) = s_delay_line_filt(1);  \r
-\r
-               % delay in tx bits to compensate for filtering delay\r
-\r
-               tx_bits_delay_line_filt(1:(Nfiltsym-1)*bps) = tx_bits_delay_line_filt(bps+1:Nfiltsym*bps);\r
-               tx_bits_delay_line_filt((Nfiltsym-1)*bps+1:Nfiltsym*bps) = tx_bits((k-1)*bps+1:k*bps);\r
-               tx_bits((k-1)*bps+1:k*bps) = tx_bits_delay_line_filt(1:bps);\r
-\r
-               s_ch(k) = rx_filt;               \r
-            end\r
-\r
-            % coherent demod phase estimation and correction using pilot symbols\r
-            % cheating a bit here, we use fact that all tx-ed symbols are known\r
-\r
-            if phase_est\r
-                for i=1:Nsymb\r
-\r
-                    % delay line for phase est window\r
-\r
-                    r_delay_line(1:Nps-1) = r_delay_line(2:Nps);\r
-                    r_delay_line(Nps) = s_ch(i);\r
-\r
-                    % delay in tx data to compensate data for phase est window\r
-\r
-                    s_delay_line(1:Nps-1) = s_delay_line(2:Nps);\r
-                    s_delay_line(Nps) = s(i);\r
-                    tx_bits(2*(i-1)+1:2*i) = qpsk_demod(s_delay_line(floor(Nps/2)+1));\r
-\r
-                    % estimate phase from surrounding known pilot symbols and correct\r
-\r
-                    corr = 0; centre = floor(Nps/2)+1;\r
-                    for k=1:Ns:(Nps+1)\r
-                        if (k != centre)\r
-                            corr += s_delay_line(k) * r_delay_line(k)';\r
-                        end\r
-                    end\r
-                    s_ch(i) = r_delay_line(centre).*exp(j*angle(corr));\r
-               end    \r
-               %printf("corr: %f angle: %f\n", corr, angle(corr));\r
-            end\r
-\r
-            % de-modulate\r
-\r
-            rx_bits = zeros(1, framesize);\r
-            for i=1:Nsymb\r
-                rx_symb = s_ch(i);\r
-                if strcmp(modulation,'dqpsk')\r
-                    tmp = rx_symb;\r
-                    rx_symb *= conj(prev_sym_rx/abs(prev_sym_rx));\r
-                    prev_sym_rx = tmp;\r
-                end\r
-                rx_bits((2*(i-1)+1):(2*i)) = qpsk_demod(rx_symb);\r
-                rx_symb_log = [rx_symb_log rx_symb];\r
-            end\r
-\r
-            % Measure BER\r
-\r
-            % discard bits from first 2*Nfiltsym+Nps+1 symbols as tx\r
-            % and rx filter and phase est memories not full\r
-\r
-            skip = bps*(2*Nfiltsym+1+Nps+1);\r
-            if nn == 1\r
-                tx_bits_tmp = tx_bits(skip:length(tx_bits));\r
-                rx_bits_tmp = rx_bits(skip:length(rx_bits));\r
-            else\r
-                tx_bits_tmp = tx_bits;\r
-                rx_bits_tmp = rx_bits;\r
-           end\r
-\r
-            error_positions = xor( rx_bits_tmp, tx_bits_tmp );\r
-            Nerrs = sum(error_positions);\r
-            Terrs += Nerrs;\r
-            Tbits += length(tx_bits_tmp);\r
-\r
-            % Optionally LDPC decode\r
-            \r
-            if ldpc_code\r
-                % filter memories etc screw up frame alignment so we need to buffer a frame\r
-\r
-                tx_data_buffer(1:framesize) = tx_data_buffer(framesize+1:2*framesize);\r
-                s_data_buffer(1:Nsymb) = s_data_buffer(Nsymb+1:2*Nsymb);\r
-                tx_data_buffer(framesize+1:2*framesize) = tx_bits;\r
-                s_data_buffer(Nsymb+1:2*Nsymb) = s_ch;\r
-\r
-                offset = Nfiltsym-1;\r
-                if (phase_est)\r
-                    offset += floor(Nps/2);\r
-                end\r
-                st_tx = offset*bps+1;\r
-                st_s = offset;\r
-\r
-                detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, ...\r
-                                s_data_buffer(st_s+1:st_s+Nsymb), min(100,EsNo));\r
-\r
-                % ignore first frame as filter, phase est memories filling up\r
-                if nn != 1\r
-                    error_positions = xor( detected_data(1:framesize*rate), ...\r
-                                           tx_data_buffer(st_tx:st_tx+framesize*rate-1) );\r
-                    Nerrs = sum(error_positions);\r
-                    if Nerrs\r
-                        Ferrsldpc++;\r
-                    end\r
-                    Terrsldpc += Nerrs;\r
-                    Tbitsldpc += framesize*rate;\r
-                end\r
-            end\r
-\r
-        end\r
-    \r
-        TERvec(ne) = Terrs;\r
-        BERvec(ne) = Terrs/Tbits;\r
-        if ldpc_code\r
-            TERldpcvec(ne) = Terrsldpc;\r
-            FERldpcvec(ne) = Ferrsldpc;\r
-            BERldpcvec(ne) = Terrsldpc/Tbitsldpc;\r
-        end\r
-\r
-        if verbose \r
-            printf("EsNo (dB): %f  Terrs: %d BER %f BER theory %f", Es, Terrs,\r
-                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)));\r
-            if ldpc_code\r
-                printf(" LDPC: Terrs: %d BER: %f Ferrs: %d FER: %f", \r
-                       Terrsldpc, Terrsldpc/Tbitsldpc, Ferrsldpc, Ferrsldpc/(Ntrials-1));\r
-            end\r
-            printf("\n");\r
-        end\r
-        if verbose > 1\r
-            printf("Terrs: %d BER %f BER theory %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,\r
-                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)), var(tx_filt_log), var(noise_log),\r
-                   var(tx_filt_log)/Rs, var(noise_log)/Fs, (var(tx_filt_log)/Rs)/(var(noise_log)/Fs));\r
-        end\r
-    end\r
-    \r
-    Ebvec = Esvec - 10*log10(bps);\r
-    sim_out.BERvec          = BERvec;\r
-    sim_out.Ebvec           = Ebvec;\r
-    sim_out.TERvec          = TERvec;\r
-    if ldpc_code\r
-        sim_out.BERldpcvec  = BERldpcvec;\r
-        sim_out.TERldpcvec  = TERldpcvec;\r
-        sim_out.FERldpcvec  = FERldpcvec;\r
-    end\r
-\r
-    if plot_scatter\r
-        figure(2);\r
-        clf;\r
-        scat = rx_symb_log(2*Nfiltsym:length(rx_symb_log)) .* exp(j*pi/4);\r
-        plot(real(scat), imag(scat),'+');\r
-\r
-        figure(3);\r
-        clf;\r
-\r
-        subplot(211)\r
-        plot(C_log);\r
-        subplot(212)\r
-        plot(hf_angle_log);\r
-        axis([1 10000 min(hf_angle_log) max(hf_angle_log)])\r
-    end\r
-endfunction\r
-\r
-% Gray coded QPSK modulation function\r
-\r
-function symbol = qpsk_mod(two_bits)\r
-    two_bits_decimal = sum(two_bits .* [2 1]); \r
-    switch(two_bits_decimal)\r
-        case (0) symbol =  1;\r
-        case (1) symbol =  j;\r
-        case (2) symbol = -j;\r
-        case (3) symbol = -1;\r
-    endswitch\r
-endfunction\r
-\r
-% Gray coded QPSK demodulation function\r
-\r
-function two_bits = qpsk_demod(symbol)\r
-    if isscalar(symbol) == 0\r
-        printf("only works with scalars\n");\r
-        return;\r
-    end\r
-    bit0 = real(symbol*exp(j*pi/4)) < 0;\r
-    bit1 = imag(symbol*exp(j*pi/4)) < 0;\r
-    two_bits = [bit1 bit0];\r
-endfunction\r
-\r
-% Start simulations ---------------------------------------\r
-\r
-more off;\r
-sim_in.verbose = 2;\r
-\r
-sim_in.Esvec            = 5; \r
-sim_in.Ntrials          = 100;\r
-sim_in.framesize        = 100;\r
-sim_in.Rs               = 400;\r
-sim_in.phase_offset     = 0;\r
-sim_in.phase_est        = 0;\r
-sim_in.w_offset         = 0;\r
-sim_in.plot_scatter     = 1;\r
-sim_in.hf_delay_ms      = 2;\r
-sim_in.hf_sim           = 1;\r
-sim_in.Np               = 6;\r
-sim_in.Ns               = 5;\r
-sim_in.hf_phase_only    = 0;\r
-sim_in.hf_mag_only      = 1;\r
-sim_in.ldpc_code        = 0;\r
-\r
-Ebvec = sim_in.Esvec - 10*log10(2);\r
-BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));\r
-\r
-sim_qpsk           = ber_test(sim_in, 'qpsk');\r
-\r
-figure(1); \r
-clf;\r
-semilogy(Ebvec, BER_theory,'r;QPSK theory;')\r
-hold on;\r
-semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK;')\r
-hold off;\r
-xlabel('Eb/N0')\r
-ylabel('BER')\r
-grid("minor")\r
-\r
-\r
-if 0\r
-sim_in.hf_mag_only      = 1;\r
-sim_qpsk_mag            = ber_test(sim_in, 'qpsk');\r
-\r
-sim_in.hf_mag_only      = 0;\r
-sim_in.hf_phase_only    = 1;\r
-sim_in.phase_est        = 1;\r
-sim_qpsk_phase          = ber_test(sim_in, 'qpsk');\r
-\r
-sim_in.hf_phase_only    = 0;\r
-sim_qpsk_coh_6_5        = ber_test(sim_in, 'qpsk');\r
-\r
-sim_in.phase_est        = 0;\r
-sim_dqpsk               = ber_test(sim_in, 'dqpsk');\r
-\r
-figure(1); \r
-clf;\r
-semilogy(Ebvec, BER_theory,'r;QPSK theory;')\r
-hold on;\r
-semilogy(sim_qpsk_mag.Ebvec, sim_qpsk_mag.BERvec,'g;QPSK CCIR poor mag;')\r
-semilogy(sim_qpsk_phase.Ebvec, sim_qpsk_phase.BERvec,'k;QPSK CCIR poor phase;')\r
-semilogy(sim_qpsk_coh_6_5.Ebvec, sim_qpsk_coh_6_5.BERvec,'c;QPSK CCIR poor Np=6 Ns=5;')\r
-semilogy(sim_dqpsk.Ebvec, sim_dqpsk.BERvec,'b;DQPSK CCIR poor;')\r
-%semilogy(sim_qpsk_coh_5_24.Ebvec, sim_qpsk_coh_5_24.BERvec,'k;QPSK Ns=5 Np=24;')\r
-%semilogy(sim_qpsk_coh_2_12.Ebvec, sim_qpsk_coh_2_12.BERvec,'c;QPSK Ns=2 Np=12;')\r
-hold off;\r
-xlabel('Eb/N0')\r
-ylabel('BER')\r
-grid("minor")\r
-axis([min(Ebvec)-1 max(Ebvec)+1 1E-2 1])\r
-end\r
+% test_qpsk.m
+% David Rowe Feb 2014
+%
+% QPSK modem simulation, initially based on code by Bill Cowley
+% Generates curves BER versus E/No curves for different modems.
+% Design to test coherent demodulation ideas on HF channels without
+% building a full blown modem.  Uses 'genie provided' estimates for
+% timing estimation, frame sync.
+%
+
+1;
+
+% main test function 
+
+function sim_out = ber_test(sim_in, modulation)
+    Fs = 8000;
+
+    verbose          = sim_in.verbose;
+    framesize        = sim_in.framesize;
+    Ntrials          = sim_in.Ntrials;
+    Esvec            = sim_in.Esvec;
+    phase_offset     = sim_in.phase_offset;
+    phase_est        = sim_in.phase_est;
+    w_offset         = sim_in.w_offset;
+    plot_scatter     = sim_in.plot_scatter;
+    Rs               = sim_in.Rs;
+    hf_sim           = sim_in.hf_sim;
+    Nhfdelay         = floor(sim_in.hf_delay_ms*1000/Fs);
+    hf_phase_only    = sim_in.hf_phase_only;
+    hf_mag_only      = sim_in.hf_mag_only;
+
+    bps              = 2;
+    Nsymb            = framesize/bps;
+    prev_sym_tx      = qpsk_mod([0 0]);
+    prev_sym_rx      = qpsk_mod([0 0]);
+    rx_symb_log      = [];
+
+    Np               = sim_in.Np;  % number of pilot symbols to use in phase est
+    Ns               = sim_in.Ns;  % spacing of pilot symbols, so (Nps-1) data symbols between every pilot
+    Nps              = Np*Ns;
+    r_delay_line     = zeros(1,Nps+1);
+    s_delay_line     = zeros(1,Nps+1);
+    spread_main_phi  = 0;
+    spread_delay_phi = 0;
+    spread_main_phi_log = [];
+
+    ldpc_code = sim_in.ldpc_code;
+
+    if ldpc_code
+        % Start CML library
+
+        currentdir = pwd;
+        addpath '/home/david/tmp/cml/mat'    % assume the source files stored here
+        cd /home/david/tmp/cml
+        CmlStartup                           % note that this is not in the cml path!
+        cd(currentdir)
+  
+        % Our LDPC library
+
+        ldpc;
+
+        rate = 3/4; 
+        mod_order = 4; 
+        modulation = 'QPSK';
+        mapping = 'gray';
+
+        demod_type = 0;
+        decoder_type = 0;
+        max_iterations = 100;
+
+        code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);
+        code_param.code_bits_per_frame = framesize;
+        code_param.symbols_per_frame = framesize/bps;
+    else
+        rate = 1;
+    end
+
+    % convert "spreading" samples from 1kHz carrier at Fs to complex
+    % baseband, generated by passing a 1kHz sine wave through PathSim
+    % with the ccir-poor model, enabling one path at a time.
+    
+    Fc = 1000;
+    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");
+    spread1k = fread(fspread, "int16")/10000;
+    fclose(fspread);
+    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");
+    spread1k_2ms = fread(fspread, "int16")/10000;
+    fclose(fspread);
+
+    % down convert to complex baseband
+    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');
+    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');
+
+    % remove -2000 Hz image
+    b = fir1(50, 5/Fs);
+    spread = filter(b,1,spreadbb);
+    spread_2ms = filter(b,1,spreadbb_2ms);
+
+    % discard first 1000 samples as these were near 0, probably as
+    % PathSim states were ramping up
+
+    spread    = spread(1000:length(spread));
+    spread_2ms = spread_2ms(1000:length(spread_2ms));
+
+    % Determine "gain" of HF channel model, so we can normalise
+    % carrier power during HF channel sim to calibrate SNR.  I imagine
+    % different implementations of ccir-poor would do this in
+    % different ways, leading to different BER results.  Oh Well!
+
+    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));
+
+    % design root nyquist (root raised cosine) filter and init tx and rx filter states
+
+    alpha = 0.5; T=1/Fs; Nfiltsym=7; M=Fs/Rs;
+    if floor(Fs/Rs) != Fs/Rs
+        printf("oversampling ratio must be an integer\n");
+        return;
+    end
+    hrn = gen_rn_coeffs(alpha, T, Rs, Nfiltsym, M);
+    Nfilter = length(hrn);
+    tx_filter_memory = zeros(1, Nfilter);
+    rx_filter_memory = zeros(1, Nfilter);
+    s_delay_line_filt = zeros(1,Nfiltsym);
+    tx_bits_delay_line_filt = zeros(1,Nfiltsym*bps);
+    hf_sim_delay_line = zeros(1,M+Nhfdelay);
+
+    for ne = 1:length(Esvec)
+        Es = Esvec(ne);
+        EsNo = 10^(Es/10);
+    
+        % Given Es/No, determine the variance of a normal noise source:
+        %
+        %   Es = C/Rs where C is carrier power (energy per unit time) and Rs is the symbole rate
+        %   N  = NoB where N is the total noise power, No is the Noise spectral density is W/Hz
+        %        and B is the bandwidth of the noise which is Fs
+        %   No = N/Fs
+        %
+        % equating Es/No we get:
+        %
+        %   Es/No = (C/Rs)/(No/Fs)
+        %   No    = CFs/(Rs(Es/No))
+
+        variance = Fs/(Rs*EsNo);
+        Terrs = 0;  Tbits = 0;  Terrsldpc = 0;  Tbitsldpc = 0; Ferrsldpc = 0;
+        if verbose > 1
+            printf("EsNo (dB): %f EsNo: %f variance: %f\n", Es, EsNo, variance);
+        end
+        
+        % init HF channel
+        sc = 1;
+
+        tx_filt_log = [];
+        rx_filt_log = [];
+        rx_baseband_log = [];
+        tx_baseband_log = [];
+        noise_log = [];
+        hf_angle_log = [];
+        tx_phase = rx_phase = 0;
+        tx_data_buffer = zeros(1,2*framesize);
+        s_data_buffer = zeros(1,2*Nsymb);
+        C_log = [];
+
+        for nn = 1: Ntrials
+                  
+            tx_bits = round( rand( 1, framesize*rate ) );
+            %tx_bits = [1 0 zeros(1,framesize*rate-2)];
+
+            % modulate
+
+            if ldpc_code
+                [tx_bits, s] = ldpc_enc(tx_bits, code_param);
+                t2 = tx_bits;
+                s2 = s;
+            else
+                s = zeros(1, Nsymb);
+                for i=1:Nsymb
+                    tx_symb = qpsk_mod(tx_bits(2*(i-1)+1:2*i));
+                    %printf("shift: %f prev_sym: %f  ", tx_symb, prev_sym_tx);
+                    if strcmp(modulation,'dqpsk')
+                        tx_symb *= prev_sym_tx;
+                        %printf("tx_symb: %f\n", tx_symb);
+                        prev_sym_tx = tx_symb;
+                    end 
+                    s(i) = tx_symb;
+                end
+            end
+            s_ch = s;
+
+            % root nyquist filter symbols
+
+            for k=1:Nsymb
+
+               % tx filter symbols
+
+               tx_filt = zeros(1,M);
+
+               % tx filter each symbol, generate M filtered output samples for each symbol.
+               % Efficient polyphase filter techniques used as tx_filter_memory is sparse
+
+               tx_filter_memory(Nfilter) = s_ch(k);
+
+               for i=1:M
+                   tx_filt(i) = M*tx_filter_memory(M:M:Nfilter) * hrn(M-i+1:M:Nfilter)';
+               end
+               tx_filter_memory(1:Nfilter-M) = tx_filter_memory(M+1:Nfilter);
+               tx_filter_memory(Nfilter-M+1:Nfilter) = zeros(1,M);
+               
+               % HF channel simulation
+
+               if hf_sim
+
+                   hf_sim_delay_line(1:Nhfdelay) = hf_sim_delay_line(M+1:M+Nhfdelay);
+                   hf_sim_delay_line(Nhfdelay+1:M+Nhfdelay) = tx_filt;
+
+                   % disable as a wrap around will cause a nasty phase jump.  Best to generate
+                   % longer files
+                   %if ((sc+M) > length(spread)) || ((sc+M) > length(spread_2ms))
+                   %    sc =1 ;
+                   %end
+                   comb = conj(spread(sc:sc+M-1))' + conj(spread_2ms(sc:sc+M-1))';
+                   if hf_phase_only
+                        tx_filt = tx_filt.*exp(j*angle(comb));
+                   else
+                       if hf_mag_only
+                           comb = conj(spread(sc:sc+M-1))' + conj(spread_2ms(sc:sc+M-1))';
+                           tx_filt = tx_filt.*abs(comb);   
+                       else
+                           % regular HF channel sim
+                           tx_filt = tx_filt.*conj(spread(sc:sc+M-1))' + hf_sim_delay_line(1:M).*conj(spread_2ms(sc:sc+M-1))';
+                       end
+                   end
+                   sc += M;
+                   % normalise so average HF power C=1
+
+                   if hf_phase_only == 0   % C already 1 if we are just tweaking phase
+                       tx_filt *= hf_gain;
+                   end
+                   C_log = [C_log abs(comb)*hf_gain];
+               end
+               tx_filt_log = [tx_filt_log tx_filt];
+               hf_angle_log = [hf_angle_log angle(comb)];
+
+               % AWGN noise and phase/freq offset channel simulation
+               % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im
+
+               noise = sqrt(variance*0.5)*( randn(1,M) + j*randn(1,M) );
+               noise_log = [noise_log noise];
+               rx_baseband = tx_filt.*exp(j*phase_offset) + noise;
+               phase_offset += w_offset;
+               
+               % rx filter symbol
+
+               rx_filter_memory(Nfilter-M+1:Nfilter) = rx_baseband;
+               rx_filt = rx_filter_memory * hrn';
+               rx_filter_memory(1:Nfilter-M) = rx_filter_memory(1+M:Nfilter);
+               rx_filt_log = [rx_filt_log rx_filt];
+
+               % delay in tx symbols to compensate for filtering
+               % delay, as tx symbols are used as pilot symbols input
+               % to phase est
+
+               s_delay_line_filt(1:Nfiltsym-1) = s_delay_line_filt(2:Nfiltsym);
+               s_delay_line_filt(Nfiltsym) = s(k);
+               s(k) = s_delay_line_filt(1);  
+
+               % delay in tx bits to compensate for filtering delay
+
+               tx_bits_delay_line_filt(1:(Nfiltsym-1)*bps) = tx_bits_delay_line_filt(bps+1:Nfiltsym*bps);
+               tx_bits_delay_line_filt((Nfiltsym-1)*bps+1:Nfiltsym*bps) = tx_bits((k-1)*bps+1:k*bps);
+               tx_bits((k-1)*bps+1:k*bps) = tx_bits_delay_line_filt(1:bps);
+
+               s_ch(k) = rx_filt;               
+            end
+
+            % coherent demod phase estimation and correction using pilot symbols
+            % cheating a bit here, we use fact that all tx-ed symbols are known
+
+            if phase_est
+                for i=1:Nsymb
+
+                    % delay line for phase est window
+
+                    r_delay_line(1:Nps-1) = r_delay_line(2:Nps);
+                    r_delay_line(Nps) = s_ch(i);
+
+                    % delay in tx data to compensate data for phase est window
+
+                    s_delay_line(1:Nps-1) = s_delay_line(2:Nps);
+                    s_delay_line(Nps) = s(i);
+                    tx_bits(2*(i-1)+1:2*i) = qpsk_demod(s_delay_line(floor(Nps/2)+1));
+
+                    % estimate phase from surrounding known pilot symbols and correct
+
+                    corr = 0; centre = floor(Nps/2)+1;
+                    for k=1:Ns:(Nps+1)
+                        if (k != centre)
+                            corr += s_delay_line(k) * r_delay_line(k)';
+                        end
+                    end
+                    s_ch(i) = r_delay_line(centre).*exp(j*angle(corr));
+               end    
+               %printf("corr: %f angle: %f\n", corr, angle(corr));
+            end
+
+            % de-modulate
+
+            rx_bits = zeros(1, framesize);
+            for i=1:Nsymb
+                rx_symb = s_ch(i);
+                if strcmp(modulation,'dqpsk')
+                    tmp = rx_symb;
+                    rx_symb *= conj(prev_sym_rx/abs(prev_sym_rx));
+                    prev_sym_rx = tmp;
+                end
+                rx_bits((2*(i-1)+1):(2*i)) = qpsk_demod(rx_symb);
+                rx_symb_log = [rx_symb_log rx_symb];
+            end
+
+            % Measure BER
+
+            % discard bits from first 2*Nfiltsym+Nps+1 symbols as tx
+            % and rx filter and phase est memories not full
+
+            skip = bps*(2*Nfiltsym+1+Nps+1);
+            if nn == 1
+                tx_bits_tmp = tx_bits(skip:length(tx_bits));
+                rx_bits_tmp = rx_bits(skip:length(rx_bits));
+            else
+                tx_bits_tmp = tx_bits;
+                rx_bits_tmp = rx_bits;
+           end
+
+            error_positions = xor( rx_bits_tmp, tx_bits_tmp );
+            Nerrs = sum(error_positions);
+            Terrs += Nerrs;
+            Tbits += length(tx_bits_tmp);
+
+            % Optionally LDPC decode
+            
+            if ldpc_code
+                % filter memories etc screw up frame alignment so we need to buffer a frame
+
+                tx_data_buffer(1:framesize) = tx_data_buffer(framesize+1:2*framesize);
+                s_data_buffer(1:Nsymb) = s_data_buffer(Nsymb+1:2*Nsymb);
+                tx_data_buffer(framesize+1:2*framesize) = tx_bits;
+                s_data_buffer(Nsymb+1:2*Nsymb) = s_ch;
+
+                offset = Nfiltsym-1;
+                if (phase_est)
+                    offset += floor(Nps/2);
+                end
+                st_tx = offset*bps+1;
+                st_s = offset;
+
+                detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, ...
+                                s_data_buffer(st_s+1:st_s+Nsymb), min(100,EsNo));
+
+                % ignore first frame as filter, phase est memories filling up
+                if nn != 1
+                    error_positions = xor( detected_data(1:framesize*rate), ...
+                                           tx_data_buffer(st_tx:st_tx+framesize*rate-1) );
+                    Nerrs = sum(error_positions);
+                    if Nerrs
+                        Ferrsldpc++;
+                    end
+                    Terrsldpc += Nerrs;
+                    Tbitsldpc += framesize*rate;
+                end
+            end
+
+        end
+    
+        TERvec(ne) = Terrs;
+        BERvec(ne) = Terrs/Tbits;
+        if ldpc_code
+            TERldpcvec(ne) = Terrsldpc;
+            FERldpcvec(ne) = Ferrsldpc;
+            BERldpcvec(ne) = Terrsldpc/Tbitsldpc;
+        end
+
+        if verbose 
+            printf("EsNo (dB): %f  Terrs: %d BER %f BER theory %f", Es, Terrs,
+                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)));
+            if ldpc_code
+                printf(" LDPC: Terrs: %d BER: %f Ferrs: %d FER: %f", 
+                       Terrsldpc, Terrsldpc/Tbitsldpc, Ferrsldpc, Ferrsldpc/(Ntrials-1));
+            end
+            printf("\n");
+        end
+        if verbose > 1
+            printf("Terrs: %d BER %f BER theory %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,
+                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)), var(tx_filt_log), var(noise_log),
+                   var(tx_filt_log)/Rs, var(noise_log)/Fs, (var(tx_filt_log)/Rs)/(var(noise_log)/Fs));
+        end
+    end
+    
+    Ebvec = Esvec - 10*log10(bps);
+    sim_out.BERvec          = BERvec;
+    sim_out.Ebvec           = Ebvec;
+    sim_out.TERvec          = TERvec;
+    if ldpc_code
+        sim_out.BERldpcvec  = BERldpcvec;
+        sim_out.TERldpcvec  = TERldpcvec;
+        sim_out.FERldpcvec  = FERldpcvec;
+    end
+
+    if plot_scatter
+        figure(2);
+        clf;
+        scat = rx_symb_log(2*Nfiltsym:length(rx_symb_log)) .* exp(j*pi/4);
+        plot(real(scat), imag(scat),'+');
+
+        figure(3);
+        clf;
+
+        subplot(211)
+        plot(C_log);
+        subplot(212)
+        plot(hf_angle_log);
+        axis([1 10000 min(hf_angle_log) max(hf_angle_log)])
+    end
+endfunction
+
+% Gray coded QPSK modulation function
+
+function symbol = qpsk_mod(two_bits)
+    two_bits_decimal = sum(two_bits .* [2 1]); 
+    switch(two_bits_decimal)
+        case (0) symbol =  1;
+        case (1) symbol =  j;
+        case (2) symbol = -j;
+        case (3) symbol = -1;
+    endswitch
+endfunction
+
+% Gray coded QPSK demodulation function
+
+function two_bits = qpsk_demod(symbol)
+    if isscalar(symbol) == 0
+        printf("only works with scalars\n");
+        return;
+    end
+    bit0 = real(symbol*exp(j*pi/4)) < 0;
+    bit1 = imag(symbol*exp(j*pi/4)) < 0;
+    two_bits = [bit1 bit0];
+endfunction
+
+% Start simulations ---------------------------------------
+
+more off;
+sim_in.verbose = 2;
+
+sim_in.Esvec            = 5; 
+sim_in.Ntrials          = 100;
+sim_in.framesize        = 100;
+sim_in.Rs               = 400;
+sim_in.phase_offset     = 0;
+sim_in.phase_est        = 0;
+sim_in.w_offset         = 0;
+sim_in.plot_scatter     = 1;
+sim_in.hf_delay_ms      = 2;
+sim_in.hf_sim           = 1;
+sim_in.Np               = 6;
+sim_in.Ns               = 5;
+sim_in.hf_phase_only    = 0;
+sim_in.hf_mag_only      = 1;
+sim_in.ldpc_code        = 0;
+
+Ebvec = sim_in.Esvec - 10*log10(2);
+BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));
+
+sim_qpsk           = ber_test(sim_in, 'qpsk');
+
+figure(1); 
+clf;
+semilogy(Ebvec, BER_theory,'r;QPSK theory;')
+hold on;
+semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK;')
+hold off;
+xlabel('Eb/N0')
+ylabel('BER')
+grid("minor")
+
+
+if 0
+sim_in.hf_mag_only      = 1;
+sim_qpsk_mag            = ber_test(sim_in, 'qpsk');
+
+sim_in.hf_mag_only      = 0;
+sim_in.hf_phase_only    = 1;
+sim_in.phase_est        = 1;
+sim_qpsk_phase          = ber_test(sim_in, 'qpsk');
+
+sim_in.hf_phase_only    = 0;
+sim_qpsk_coh_6_5        = ber_test(sim_in, 'qpsk');
+
+sim_in.phase_est        = 0;
+sim_dqpsk               = ber_test(sim_in, 'dqpsk');
+
+figure(1); 
+clf;
+semilogy(Ebvec, BER_theory,'r;QPSK theory;')
+hold on;
+semilogy(sim_qpsk_mag.Ebvec, sim_qpsk_mag.BERvec,'g;QPSK CCIR poor mag;')
+semilogy(sim_qpsk_phase.Ebvec, sim_qpsk_phase.BERvec,'k;QPSK CCIR poor phase;')
+semilogy(sim_qpsk_coh_6_5.Ebvec, sim_qpsk_coh_6_5.BERvec,'c;QPSK CCIR poor Np=6 Ns=5;')
+semilogy(sim_dqpsk.Ebvec, sim_dqpsk.BERvec,'b;DQPSK CCIR poor;')
+%semilogy(sim_qpsk_coh_5_24.Ebvec, sim_qpsk_coh_5_24.BERvec,'k;QPSK Ns=5 Np=24;')
+%semilogy(sim_qpsk_coh_2_12.Ebvec, sim_qpsk_coh_2_12.BERvec,'c;QPSK Ns=2 Np=12;')
+hold off;
+xlabel('Eb/N0')
+ylabel('BER')
+grid("minor")
+axis([min(Ebvec)-1 max(Ebvec)+1 1E-2 1])
+end
index dbb43cbf0bb54f82a3ad8abeb84a5abfbd4976e1..978abfa9482b97c96611bb48aba2f5a681647bcb 100644 (file)
-% test_qps2k.m\r
-% David Rowe Feb 2014\r
-%\r
-% QPSK modem simulation, version 2.  Simplifed version of\r
-% test_qpsk. initially based on code by Bill Cowley Generates curves\r
-% BER versus E/No curves for different modems.  Design to test\r
-% coherent demodulation ideas on HF channels without building a full\r
-% blown modem.  Uses 'genie provided' estimates for timing estimation,\r
-% frame sync.\r
-\r
-1;\r
-\r
-% main test function \r
-\r
-function sim_out = ber_test(sim_in, modulation)\r
-    Fs = 8000;\r
-\r
-    verbose          = sim_in.verbose;\r
-    framesize        = sim_in.framesize;\r
-    Ntrials          = sim_in.Ntrials;\r
-    Esvec            = sim_in.Esvec;\r
-    phase_offset     = sim_in.phase_offset;\r
-    phase_est        = sim_in.phase_est;\r
-    w_offset         = sim_in.w_offset;\r
-    plot_scatter     = sim_in.plot_scatter;\r
-    Rs               = sim_in.Rs;\r
-    hf_sim           = sim_in.hf_sim;\r
-    nhfdelay         = sim_in.hf_delay_ms*Rs/1000;\r
-    hf_phase_only    = sim_in.hf_phase_only;\r
-    hf_mag_only      = sim_in.hf_mag_only;\r
-    Nc               = sim_in.Nc;\r
-\r
-    bps              = 2;\r
-    Nsymb            = framesize/bps;\r
-    prev_sym_tx      = qpsk_mod([0 0]);\r
-    prev_sym_rx      = qpsk_mod([0 0]);\r
-\r
-    phase_est_method = sim_in.phase_est_method;\r
-    if phase_est_method == 1\r
-      Nps            = sim_in.Np; \r
-    else\r
-      Np             = sim_in.Np;\r
-      Ns             = sim_in.Ns;\r
-      if Np/2 == floor(Np/2)\r
-        printf("Np must be odd\n");\r
-        return;\r
-      end\r
-      Nps            = (Np-1)*Ns+1; \r
-    end\r
-    r_delay_line     = zeros(Nc, Nps);\r
-    s_delay_line     = zeros(Nc, Nps);\r
-    ph_est_log       = [];\r
-\r
-    phase_noise_amp  = sim_in.phase_noise_amp;\r
-\r
-    ldpc_code = sim_in.ldpc_code;\r
-\r
-    tx_bits_buf = zeros(1,2*framesize);\r
-    rx_bits_buf = zeros(1,2*framesize);\r
-    rx_symb_buf = zeros(1,2*Nsymb);\r
-\r
-    % Init LDPC --------------------------------------------------------------------\r
-\r
-    if ldpc_code\r
-        % Start CML library\r
-\r
-        currentdir = pwd;\r
-        addpath '/home/david/tmp/cml/mat'    % assume the source files stored here\r
-        cd /home/david/tmp/cml\r
-        CmlStartup                           % note that this is not in the cml path!\r
-        cd(currentdir)\r
-  \r
-        % Our LDPC library\r
-\r
-        ldpc;\r
-\r
-        rate = sim_in.ldpc_code_rate; \r
-        mod_order = 4; \r
-        modulation = 'QPSK';\r
-        mapping = 'gray';\r
-\r
-        demod_type = 0;\r
-        decoder_type = 0;\r
-        max_iterations = 100;\r
-\r
-        code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);\r
-        code_param.code_bits_per_frame = framesize;\r
-        code_param.symbols_per_frame = framesize/bps;\r
-    else\r
-        rate = 1;\r
-    end\r
-\r
-    % Init HF channel model from stored sample files of spreading signal ----------------------------------\r
-\r
-    % convert "spreading" samples from 1kHz carrier at Fs to complex\r
-    % baseband, generated by passing a 1kHz sine wave through PathSim\r
-    % with the ccir-poor model, enabling one path at a time.\r
-    \r
-    Fc = 1000; M = Fs/Rs;\r
-    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");\r
-    spread1k = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");\r
-    spread1k_2ms = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-\r
-    % down convert to complex baseband\r
-    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');\r
-    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');\r
-\r
-    % remove -2000 Hz image\r
-    b = fir1(50, 5/Fs);\r
-    spread = filter(b,1,spreadbb);\r
-    spread_2ms = filter(b,1,spreadbb_2ms);\r
-\r
-    % discard first 1000 samples as these were near 0, probably as\r
-    % PathSim states were ramping up\r
-\r
-    spread    = spread(1000:length(spread));\r
-    spread_2ms = spread_2ms(1000:length(spread_2ms));\r
-\r
-    % decimate down to Rs\r
-\r
-    spread = spread(1:M:length(spread));\r
-    spread_2ms = spread_2ms(1:M:length(spread_2ms));\r
-\r
-    % Determine "gain" of HF channel model, so we can normalise\r
-    % carrier power during HF channel sim to calibrate SNR.  I imagine\r
-    % different implementations of ccir-poor would do this in\r
-    % different ways, leading to different BER results.  Oh Well!\r
-\r
-    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));\r
-\r
-    % Start Simulation ----------------------------------------------------------------\r
-\r
-    for ne = 1:length(Esvec)\r
-        EsNodB = Esvec(ne);\r
-        EsNo = 10^(EsNodB/10);\r
-    \r
-        variance = 1/EsNo;\r
-         if verbose > 1\r
-            printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);\r
-        end\r
-        \r
-        Terrs = 0;  Tbits = 0;  Terrsldpc = 0;  Tbitsldpc = 0; Ferrsldpc = 0;\r
-\r
-        tx_symb_log      = [];\r
-        rx_symb_log      = [];\r
-        noise_log        = [];\r
-        mod_strip_log    = [];\r
-\r
-        % init HF channel\r
-\r
-        hf_n = 1;\r
-        hf_angle_log = [];\r
-        hf_fading = ones(1,Nsymb);             % default input for ldpc dec\r
-        hf_model = ones(Ntrials*Nsymb/Nc, Nc); % defaults for plotting surface\r
-\r
-        for nn = 1: Ntrials\r
-                  \r
-            tx_bits = round( rand( 1, framesize*rate ) );\r
\r
-            % modulate --------------------------------------------\r
-\r
-            if ldpc_code\r
-                [tx_bits, s] = ldpc_enc(tx_bits, code_param);\r
-            else\r
-                s = zeros(1, Nsymb);\r
-                for i=1:Nsymb\r
-                    tx_symb = qpsk_mod(tx_bits(2*(i-1)+1:2*i));\r
-                    if strcmp(modulation,'dqpsk')\r
-                        tx_symb *= prev_sym_tx;\r
-                        prev_sym_tx = tx_symb;\r
-                    end \r
-                    s(i) = tx_symb;\r
-                end\r
-            end\r
-            tx_bits_buf(1:framesize) = tx_bits_buf(framesize+1:2*framesize);\r
-            tx_bits_buf(framesize+1:2*framesize) = tx_bits;\r
-            s_ch = s;\r
-\r
-            % HF channel simulation  ------------------------------------\r
-            \r
-            if hf_sim\r
-\r
-                % separation between carriers.  Note this is\r
-                % effectively under samples at Rs, I dont think this\r
-                % matters.  Equivalent to doing freq shift at Fs, then\r
-                % decimating to Rs.\r
-\r
-                wsep = 2*pi*(1+0.5);  % e.g. 75Hz spacing at Rs=50Hz, alpha=0.5 filters\r
-\r
-                if Nsymb/Nc != floor(Nsymb/Nc)\r
-                    printf("Error: Nsymb/Nc must be an integrer\n")\r
-                    return;\r
-                end\r
-\r
-                % arrange symbols in Nsymb/Nc by Nc matrix\r
-\r
-                for i=1:Nc:Nsymb\r
-\r
-                    % Determine HF channel at each carrier for this symbol\r
-\r
-                    for k=1:Nc\r
-                        hf_model(hf_n, k) = hf_gain*(spread(hf_n) + exp(-j*k*wsep*nhfdelay)*spread_2ms(hf_n));\r
-                        hf_fading(i+k-1) = abs(hf_model(hf_n, k));\r
-                        if hf_mag_only\r
-                             s_ch(i+k-1) *= abs(hf_model(hf_n, k));\r
-                        else\r
-                             s_ch(i+k-1) *= hf_model(hf_n, k);\r
-                        end\r
-                    end\r
-                    hf_n++;\r
-                end\r
-            end\r
-            \r
-            tx_symb_log = [tx_symb_log s_ch];\r
-\r
-            % AWGN noise and phase/freq offset channel simulation\r
-            % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im\r
-\r
-            noise = sqrt(variance*0.5)*(randn(1,Nsymb) + j*randn(1,Nsymb));\r
-            noise_log = [noise_log noise];\r
-            phase_noise = phase_noise_amp*(2.0*rand(1,Nsymb)-1.0);\r
\r
-            % organise into carriers to apply frequency and phase offset\r
-\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                 s_ch(i+k-1) = s_ch(i+k-1)*exp(j*(phase_offset+phase_noise(i+k-1))) + noise(i+k-1);\r
-              end \r
-              phase_offset += w_offset;\r
-            end\r
-               \r
-            % phase estimation\r
-            \r
-            ph_est = zeros(Nc,1);\r
-\r
-            if phase_est\r
-\r
-                % organise into carriers\r
-\r
-                for i=1:Nc:Nsymb\r
-\r
-                  for k=1:Nc\r
-                      centre = floor(Nps/2)+1;\r
-\r
-                      % delay line for phase est window\r
-\r
-                      r_delay_line(k,1:Nps-1) = r_delay_line(k,2:Nps);\r
-                      r_delay_line(k,Nps) = s_ch(i+k-1);\r
-\r
-                      % delay in tx data to compensate data for phase est window\r
-\r
-                      s_delay_line(k,1:Nps-1) = s_delay_line(k,2:Nps);\r
-                      s_delay_line(k,Nps) = s(i+k-1);\r
-                      %tx_bits(2*(i+k-1-1)+1:2*(i+k-1)) = qpsk_demod(s_delay_line(k,centre));\r
\r
-                      if phase_est_method == 1\r
-                        % QPSK modulation strip and phase est\r
-\r
-                        mod_strip_pol  = angle(r_delay_line(k,:)) * 4;\r
-                        mod_strip_rect = exp(j*mod_strip_pol);\r
-\r
-                        ph_est_pol = atan2(sum(imag(mod_strip_rect)),sum(real(mod_strip_rect)))/4;\r
-                        ph_est(k)  = exp(j*ph_est_pol);\r
-\r
-                        s_ch(i+k-1) = r_delay_line(k,centre).*exp(-j*ph_est_pol);\r
-                      else\r
-\r
-                        % estimate phase from surrounding known pilot symbols and correct\r
-\r
-                        corr = 0;\r
-                        for m=1:Ns:Nps\r
-                          if (m != centre)\r
-                            corr += s_delay_line(k,m) * r_delay_line(k,m)';\r
-                          end\r
-                        end\r
-                        ph_est(k)  = conj(corr/(1E-6+abs(corr)));\r
-                        s_ch(i+k-1) = r_delay_line(k,centre).*exp(j*angle(corr));\r
-                      end\r
-\r
-                  end\r
-                  \r
-                  ph_est_log = [ph_est_log ph_est];\r
-               end    \r
-               %printf("corr: %f angle: %f\n", corr, angle(corr));\r
-            end\r
-\r
-            % de-modulate\r
-\r
-            rx_bits = zeros(1, framesize);\r
-            for i=1:Nsymb\r
-                rx_symb = s_ch(i);\r
-                if strcmp(modulation,'dqpsk')\r
-                    tmp = rx_symb;\r
-                    rx_symb *= conj(prev_sym_rx/abs(prev_sym_rx));\r
-                    prev_sym_rx = tmp;\r
-                end\r
-                rx_bits((2*(i-1)+1):(2*i)) = qpsk_demod(rx_symb);\r
-                rx_symb_log = [rx_symb_log rx_symb];\r
-            end\r
-\r
-            rx_bits_buf(1:framesize) = rx_bits_buf(framesize+1:2*framesize);\r
-            rx_bits_buf(framesize+1:2*framesize) = rx_bits;\r
-            rx_symb_buf(1:Nsymb) = rx_symb_buf(Nsymb+1:2*Nsymb);\r
-            rx_symb_buf(Nsymb+1:2*Nsymb) = s_ch;\r
-\r
-            % determine location of start and end of frame depending on processing delays\r
-\r
-            if phase_est\r
-              st_rx_bits = 1+(floor(Nps/2)+1-1)*Nc*2;\r
-              st_rx_symb = 1+(floor(Nps/2)+1-1)*Nc;\r
-           else\r
-              st_rx_bits = 1;\r
-              st_rx_symb = 1;\r
-            end\r
-            en_rx_bits = st_rx_bits+framesize-1;\r
-            en_rx_symb = st_rx_symb+Nsymb-1;\r
-\r
-            if nn > 1\r
-              % Measure BER\r
-\r
-              %printf("nn: %d centre: %d\n", nn, floor(Nps/2)+1);\r
-              %tx_bits_buf(1:20)\r
-              %rx_bits_buf(st_rx_bits:st_rx_bits+20-1)\r
-              error_positions = xor(rx_bits_buf(st_rx_bits:en_rx_bits), tx_bits_buf(1:framesize));\r
-              Nerrs = sum(error_positions);\r
-              Terrs += Nerrs;\r
-              Tbits += length(tx_bits);\r
-\r
-              % Optionally LDPC decode\r
-            \r
-              if ldpc_code\r
-                detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_symb_buf(st_rx_symb:en_rx_symb), min(100,EsNo), hf_fading);\r
-                %for m=1:20\r
-                %  printf("%f ", qpsk_demod(rx_symb_buf(m)));\r
-                %end\r
-                %detected_data(1:19)\r
-                error_positions = xor( detected_data(1:framesize*rate), tx_bits_buf(1:framesize*rate) );\r
-                Nerrs = sum(error_positions);\r
-                if Nerrs\r
-                    Ferrsldpc++;\r
-                end\r
-                Terrsldpc += Nerrs;\r
-                Tbitsldpc += framesize*rate;\r
-              end\r
-            end\r
-        end\r
-    \r
-        TERvec(ne) = Terrs;\r
-        BERvec(ne) = Terrs/Tbits;\r
-        if ldpc_code\r
-            TERldpcvec(ne) = Terrsldpc;\r
-            FERldpcvec(ne) = Ferrsldpc;\r
-            BERldpcvec(ne) = Terrsldpc/Tbitsldpc;\r
-        end\r
-\r
-        if verbose \r
-            printf("EsNo (dB): %f  Terrs: %d BER %f BER theory %f", EsNodB, Terrs,\r
-                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)));\r
-            if ldpc_code\r
-                printf(" LDPC: Terrs: %d BER: %f Ferrs: %d FER: %f", \r
-                       Terrsldpc, Terrsldpc/Tbitsldpc, Ferrsldpc, Ferrsldpc/(Ntrials-1));\r
-            end\r
-            printf("\n");\r
-        end\r
-        if verbose > 1\r
-            printf("Terrs: %d BER %f BER theory %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,\r
-                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)), var(tx_symb_log), var(noise_log),\r
-                   var(tx_symb_log), var(noise_log), var(tx_symb_log)/var(noise_log));\r
-        end\r
-    end\r
-    \r
-    Ebvec = Esvec - 10*log10(bps);\r
-    sim_out.BERvec          = BERvec;\r
-    sim_out.Ebvec           = Ebvec;\r
-    sim_out.TERvec          = TERvec;\r
-    if ldpc_code\r
-        sim_out.BERldpcvec  = BERldpcvec;\r
-        sim_out.TERldpcvec  = TERldpcvec;\r
-        sim_out.FERldpcvec  = FERldpcvec;\r
-    end\r
-\r
-    if plot_scatter\r
-        figure(2);\r
-        clf;\r
-        scat = rx_symb_log .* exp(j*pi/4);\r
-        plot(real(scat(Nps*Nc:length(scat))), imag(scat(Nps*Nc:length(scat))),'+');\r
-        title('Scatter plot');\r
-\r
-        figure(3);\r
-        clf;\r
-        \r
-        y = 1:Rs*2;\r
-        x = 1:Nc;\r
-        EsNodBSurface = 20*log10(abs(hf_model(y,:))) - 10*log10(variance);\r
-        mesh(x,y,EsNodBSurface);\r
-        grid\r
-        %axis([1 Nc 1 Rs*2 -10 10])\r
-        title('HF Channel Es/No');\r
-\r
-        figure(4);\r
-        clf;\r
-        %mesh(x,y,unwrap(angle(hf_model(y,:))));\r
-        subplot(211)\r
-        plot(y,abs(hf_model(y,1)))\r
-        title('HF Channel Carrier 1 Mag');\r
-        subplot(212)\r
-        plot(y,angle(hf_model(y,1)))\r
-        title('HF Channel Carrier 1 Phase');\r
-\r
-        if phase_est\r
-          scat = ph_est_log(1,floor(Nps/2):Rs*2+floor(Nps/2)-1);\r
-          hold on;\r
-          plot(angle(scat),'r');\r
-          hold off;\r
-\r
-          figure(5)\r
-          clf;\r
-          scat = ph_est_log(1,y);\r
-          plot(real(scat), imag(scat),'+');\r
-          title('Carrier 1 Phase Est');\r
-          axis([-1 1 -1 1])\r
-        end\r
-if 0        \r
-        figure(5);\r
-        clf;\r
-        subplot(211)\r
-        plot(real(spread));\r
-        hold on;\r
-        plot(imag(spread),'g');     \r
-        hold off;   \r
-        subplot(212)\r
-        plot(real(spread_2ms));\r
-        hold on;\r
-        plot(imag(spread_2ms),'g');     \r
-        hold off;   \r
-\r
-        figure(6)\r
-        tmp = [];\r
-        for i = 1:hf_n-1\r
-            tmp = [tmp abs(hf_model(i,:))];\r
-        end\r
-        hist(tmp);\r
-end\r
-     end\r
-\r
-endfunction\r
-\r
-% Gray coded QPSK modulation function\r
-\r
-function symbol = qpsk_mod(two_bits)\r
-    two_bits_decimal = sum(two_bits .* [2 1]); \r
-    switch(two_bits_decimal)\r
-        case (0) symbol =  1;\r
-        case (1) symbol =  j;\r
-        case (2) symbol = -j;\r
-        case (3) symbol = -1;\r
-    endswitch\r
-endfunction\r
-\r
-% Gray coded QPSK demodulation function\r
-\r
-function two_bits = qpsk_demod(symbol)\r
-    if isscalar(symbol) == 0\r
-        printf("only works with scalars\n");\r
-        return;\r
-    end\r
-    bit0 = real(symbol*exp(j*pi/4)) < 0;\r
-    bit1 = imag(symbol*exp(j*pi/4)) < 0;\r
-    two_bits = [bit1 bit0];\r
-endfunction\r
-\r
-function sim_in = standard_init\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 0;\r
-\r
-  sim_in.Esvec            = 5; \r
-  sim_in.Ntrials          = 30;\r
-  sim_in.framesize        = 576;\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 8;\r
-\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-  sim_in.phase_noise_amp  = 0;\r
-\r
-  sim_in.hf_delay_ms      = 2;\r
-  sim_in.hf_sim           = 0;\r
-  sim_in.hf_phase_only    = 0;\r
-  sim_in.hf_mag_only      = 1;\r
-\r
-  sim_in.phase_est        = 0;\r
-  sim_in.phase_est_method = 1;\r
-  sim_in.Np               = 5;\r
-  sim_in.Ns               = 5;\r
-\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-endfunction\r
-\r
-function ideal\r
-\r
-  sim_in = standard_init();\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 1;\r
-\r
-  sim_in.Esvec            = 5; \r
-  sim_in.hf_sim           = 1;\r
-  sim_in.Ntrials          = 30;\r
-\r
-  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.hf_sim           = 0;\r
-  sim_in.plot_scatter     = 0;\r
-  sim_in.Esvec            = 2:10; \r
-  sim_in.ldpc_code        = 0;\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));\r
-  sim_qpsk                = ber_test(sim_in, 'qpsk');\r
-  sim_dqpsk               = ber_test(sim_in, 'dqpsk');\r
-\r
-  sim_in.hf_sim           = 1;\r
-  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');\r
-  sim_dqpsk_hf            = ber_test(sim_in, 'dqpsk');\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-\r
-  sim_in.hf_sim           = 0;\r
-  sim_qpsk_ldpc           = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.hf_sim           = 1;\r
-  sim_qpsk_hf_ldpc        = ber_test(sim_in, 'qpsk');\r
-  sim_in.hf_mag_only      = 0;\r
-  sim_dqpsk_hf_ldpc       = ber_test(sim_in, 'dqpsk');\r
-\r
-  figure(1); \r
-  clf;\r
-  semilogy(Ebvec, BER_theory,'r;QPSK theory;')\r
-  hold on;\r
-  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK AWGN;')\r
-  semilogy(sim_qpsk_hf.Ebvec, sim_qpsk_hf.BERvec,'r;QPSK HF;')\r
-  semilogy(sim_qpsk_ldpc.Ebvec, sim_qpsk_ldpc.BERldpcvec,'bk;QPSK HF;')\r
-  semilogy(sim_dqpsk.Ebvec, sim_dqpsk.BERvec,'g;DQPSK AWGN;')\r
-  semilogy(sim_dqpsk_hf.Ebvec, sim_dqpsk_hf.BERvec,'r;DQPSK HF;')\r
-  semilogy(sim_qpsk_hf_ldpc.Ebvec, sim_qpsk_hf_ldpc.BERldpcvec,'b;QPSK HF LDPC 1/2;')\r
-  semilogy(sim_dqpsk_hf_ldpc.Ebvec, sim_dqpsk_hf_ldpc.BERldpcvec,'b;DQPSK HF LDPC 1/2;')\r
-\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-3 1])\r
-endfunction\r
-\r
-function phase_noise\r
-  sim_in = standard_init();\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 1;\r
-\r
-  sim_in.Esvec            = 100; \r
-  sim_in.Ntrials          = 30;\r
-\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-\r
-  sim_in.phase_noise_amp  = pi/16;\r
-  tmp                     = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.plot_scatter     = 0;\r
-  sim_in.Esvec            = 2:8; \r
-  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');\r
-\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));\r
-\r
-  sim_in.phase_noise_amp = 0;\r
-  sim_qpsk               = ber_test(sim_in, 'qpsk');\r
-  sim_in.phase_noise_amp = pi/8;\r
-  sim_qpsk_pn8           = ber_test(sim_in, 'qpsk');\r
-  sim_in.phase_noise_amp = pi/16;\r
-  sim_qpsk_pn16          = ber_test(sim_in, 'qpsk');\r
-  sim_in.phase_noise_amp = pi/32;\r
-  sim_qpsk_pn32          = ber_test(sim_in, 'qpsk');\r
-\r
-  figure(1); \r
-  clf;\r
-  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK phase noise 0;')\r
-  hold on;\r
-  semilogy(sim_qpsk_pn8.Ebvec, sim_qpsk_pn8.BERvec,'c;QPSK phase noise +/- pi/8;')\r
-  semilogy(sim_qpsk_pn16.Ebvec, sim_qpsk_pn16.BERvec,'b;QPSK phase noise +/- pi/16;')\r
-  semilogy(sim_qpsk_pn32.Ebvec, sim_qpsk_pn32.BERvec,'k;QPSK phase noise +/- pi/32;')\r
-\r
-  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERldpcvec,'g;QPSK phase noise 0 ldpc;')\r
-  semilogy(sim_qpsk_pn8.Ebvec, sim_qpsk_pn8.BERldpcvec,'c;QPSK phase noise +/- pi/8 ldpc;')\r
-  semilogy(sim_qpsk_pn16.Ebvec, sim_qpsk_pn16.BERldpcvec,'b;QPSK phase noise +/- pi/16 ldpc;')\r
-  semilogy(sim_qpsk_pn32.Ebvec, sim_qpsk_pn32.BERldpcvec,'k;QPSK phase noise +/- pi/32 ldpc;')\r
-\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-2 1])\r
-endfunction\r
-\r
-function test_phase_est\r
-  sim_in = standard_init();\r
-\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 8;\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 1;\r
-\r
-  sim_in.Esvec            = 5; \r
-  sim_in.Ntrials          = 30;\r
-\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-\r
-  sim_in.phase_est        = 1;\r
-  sim_in.phase_est_method = 2;\r
-  sim_in.Np               = 3;\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-\r
-  sim_in.hf_sim           = 1;\r
-  sim_in.hf_mag_only      = 0;\r
-\r
-  tmp                     = ber_test(sim_in, 'qpsk');\r
-\r
-endfunction\r
-\r
-% Start simulations ---------------------------------------\r
-\r
-more off;\r
-\r
-ideal();\r
+% test_qps2k.m
+% David Rowe Feb 2014
+%
+% QPSK modem simulation, version 2.  Simplifed version of
+% test_qpsk. initially based on code by Bill Cowley Generates curves
+% BER versus E/No curves for different modems.  Design to test
+% coherent demodulation ideas on HF channels without building a full
+% blown modem.  Uses 'genie provided' estimates for timing estimation,
+% frame sync.
+
+1;
+
+% main test function 
+
+function sim_out = ber_test(sim_in, modulation)
+    Fs = 8000;
+
+    verbose          = sim_in.verbose;
+    framesize        = sim_in.framesize;
+    Ntrials          = sim_in.Ntrials;
+    Esvec            = sim_in.Esvec;
+    phase_offset     = sim_in.phase_offset;
+    phase_est        = sim_in.phase_est;
+    w_offset         = sim_in.w_offset;
+    plot_scatter     = sim_in.plot_scatter;
+    Rs               = sim_in.Rs;
+    hf_sim           = sim_in.hf_sim;
+    nhfdelay         = sim_in.hf_delay_ms*Rs/1000;
+    hf_phase_only    = sim_in.hf_phase_only;
+    hf_mag_only      = sim_in.hf_mag_only;
+    Nc               = sim_in.Nc;
+
+    bps              = 2;
+    Nsymb            = framesize/bps;
+    prev_sym_tx      = qpsk_mod([0 0]);
+    prev_sym_rx      = qpsk_mod([0 0]);
+
+    phase_est_method = sim_in.phase_est_method;
+    if phase_est_method == 1
+      Nps            = sim_in.Np; 
+    else
+      Np             = sim_in.Np;
+      Ns             = sim_in.Ns;
+      if Np/2 == floor(Np/2)
+        printf("Np must be odd\n");
+        return;
+      end
+      Nps            = (Np-1)*Ns+1; 
+    end
+    r_delay_line     = zeros(Nc, Nps);
+    s_delay_line     = zeros(Nc, Nps);
+    ph_est_log       = [];
+
+    phase_noise_amp  = sim_in.phase_noise_amp;
+
+    ldpc_code = sim_in.ldpc_code;
+
+    tx_bits_buf = zeros(1,2*framesize);
+    rx_bits_buf = zeros(1,2*framesize);
+    rx_symb_buf = zeros(1,2*Nsymb);
+
+    % Init LDPC --------------------------------------------------------------------
+
+    if ldpc_code
+        % Start CML library
+
+        currentdir = pwd;
+        addpath '/home/david/tmp/cml/mat'    % assume the source files stored here
+        cd /home/david/tmp/cml
+        CmlStartup                           % note that this is not in the cml path!
+        cd(currentdir)
+  
+        % Our LDPC library
+
+        ldpc;
+
+        rate = sim_in.ldpc_code_rate; 
+        mod_order = 4; 
+        modulation = 'QPSK';
+        mapping = 'gray';
+
+        demod_type = 0;
+        decoder_type = 0;
+        max_iterations = 100;
+
+        code_param = ldpc_init(rate, framesize, modulation, mod_order, mapping);
+        code_param.code_bits_per_frame = framesize;
+        code_param.symbols_per_frame = framesize/bps;
+    else
+        rate = 1;
+    end
+
+    % Init HF channel model from stored sample files of spreading signal ----------------------------------
+
+    % convert "spreading" samples from 1kHz carrier at Fs to complex
+    % baseband, generated by passing a 1kHz sine wave through PathSim
+    % with the ccir-poor model, enabling one path at a time.
+    
+    Fc = 1000; M = Fs/Rs;
+    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");
+    spread1k = fread(fspread, "int16")/10000;
+    fclose(fspread);
+    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");
+    spread1k_2ms = fread(fspread, "int16")/10000;
+    fclose(fspread);
+
+    % down convert to complex baseband
+    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');
+    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');
+
+    % remove -2000 Hz image
+    b = fir1(50, 5/Fs);
+    spread = filter(b,1,spreadbb);
+    spread_2ms = filter(b,1,spreadbb_2ms);
+
+    % discard first 1000 samples as these were near 0, probably as
+    % PathSim states were ramping up
+
+    spread    = spread(1000:length(spread));
+    spread_2ms = spread_2ms(1000:length(spread_2ms));
+
+    % decimate down to Rs
+
+    spread = spread(1:M:length(spread));
+    spread_2ms = spread_2ms(1:M:length(spread_2ms));
+
+    % Determine "gain" of HF channel model, so we can normalise
+    % carrier power during HF channel sim to calibrate SNR.  I imagine
+    % different implementations of ccir-poor would do this in
+    % different ways, leading to different BER results.  Oh Well!
+
+    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));
+
+    % Start Simulation ----------------------------------------------------------------
+
+    for ne = 1:length(Esvec)
+        EsNodB = Esvec(ne);
+        EsNo = 10^(EsNodB/10);
+    
+        variance = 1/EsNo;
+         if verbose > 1
+            printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);
+        end
+        
+        Terrs = 0;  Tbits = 0;  Terrsldpc = 0;  Tbitsldpc = 0; Ferrsldpc = 0;
+
+        tx_symb_log      = [];
+        rx_symb_log      = [];
+        noise_log        = [];
+        mod_strip_log    = [];
+
+        % init HF channel
+
+        hf_n = 1;
+        hf_angle_log = [];
+        hf_fading = ones(1,Nsymb);             % default input for ldpc dec
+        hf_model = ones(Ntrials*Nsymb/Nc, Nc); % defaults for plotting surface
+
+        for nn = 1: Ntrials
+                  
+            tx_bits = round( rand( 1, framesize*rate ) );
+            % modulate --------------------------------------------
+
+            if ldpc_code
+                [tx_bits, s] = ldpc_enc(tx_bits, code_param);
+            else
+                s = zeros(1, Nsymb);
+                for i=1:Nsymb
+                    tx_symb = qpsk_mod(tx_bits(2*(i-1)+1:2*i));
+                    if strcmp(modulation,'dqpsk')
+                        tx_symb *= prev_sym_tx;
+                        prev_sym_tx = tx_symb;
+                    end 
+                    s(i) = tx_symb;
+                end
+            end
+            tx_bits_buf(1:framesize) = tx_bits_buf(framesize+1:2*framesize);
+            tx_bits_buf(framesize+1:2*framesize) = tx_bits;
+            s_ch = s;
+
+            % HF channel simulation  ------------------------------------
+            
+            if hf_sim
+
+                % separation between carriers.  Note this is
+                % effectively under samples at Rs, I dont think this
+                % matters.  Equivalent to doing freq shift at Fs, then
+                % decimating to Rs.
+
+                wsep = 2*pi*(1+0.5);  % e.g. 75Hz spacing at Rs=50Hz, alpha=0.5 filters
+
+                if Nsymb/Nc != floor(Nsymb/Nc)
+                    printf("Error: Nsymb/Nc must be an integrer\n")
+                    return;
+                end
+
+                % arrange symbols in Nsymb/Nc by Nc matrix
+
+                for i=1:Nc:Nsymb
+
+                    % Determine HF channel at each carrier for this symbol
+
+                    for k=1:Nc
+                        hf_model(hf_n, k) = hf_gain*(spread(hf_n) + exp(-j*k*wsep*nhfdelay)*spread_2ms(hf_n));
+                        hf_fading(i+k-1) = abs(hf_model(hf_n, k));
+                        if hf_mag_only
+                             s_ch(i+k-1) *= abs(hf_model(hf_n, k));
+                        else
+                             s_ch(i+k-1) *= hf_model(hf_n, k);
+                        end
+                    end
+                    hf_n++;
+                end
+            end
+            
+            tx_symb_log = [tx_symb_log s_ch];
+
+            % AWGN noise and phase/freq offset channel simulation
+            % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im
+
+            noise = sqrt(variance*0.5)*(randn(1,Nsymb) + j*randn(1,Nsymb));
+            noise_log = [noise_log noise];
+            phase_noise = phase_noise_amp*(2.0*rand(1,Nsymb)-1.0);
+            % organise into carriers to apply frequency and phase offset
+
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                 s_ch(i+k-1) = s_ch(i+k-1)*exp(j*(phase_offset+phase_noise(i+k-1))) + noise(i+k-1);
+              end 
+              phase_offset += w_offset;
+            end
+               
+            % phase estimation
+            
+            ph_est = zeros(Nc,1);
+
+            if phase_est
+
+                % organise into carriers
+
+                for i=1:Nc:Nsymb
+
+                  for k=1:Nc
+                      centre = floor(Nps/2)+1;
+
+                      % delay line for phase est window
+
+                      r_delay_line(k,1:Nps-1) = r_delay_line(k,2:Nps);
+                      r_delay_line(k,Nps) = s_ch(i+k-1);
+
+                      % delay in tx data to compensate data for phase est window
+
+                      s_delay_line(k,1:Nps-1) = s_delay_line(k,2:Nps);
+                      s_delay_line(k,Nps) = s(i+k-1);
+                      %tx_bits(2*(i+k-1-1)+1:2*(i+k-1)) = qpsk_demod(s_delay_line(k,centre));
+                      if phase_est_method == 1
+                        % QPSK modulation strip and phase est
+
+                        mod_strip_pol  = angle(r_delay_line(k,:)) * 4;
+                        mod_strip_rect = exp(j*mod_strip_pol);
+
+                        ph_est_pol = atan2(sum(imag(mod_strip_rect)),sum(real(mod_strip_rect)))/4;
+                        ph_est(k)  = exp(j*ph_est_pol);
+
+                        s_ch(i+k-1) = r_delay_line(k,centre).*exp(-j*ph_est_pol);
+                      else
+
+                        % estimate phase from surrounding known pilot symbols and correct
+
+                        corr = 0;
+                        for m=1:Ns:Nps
+                          if (m != centre)
+                            corr += s_delay_line(k,m) * r_delay_line(k,m)';
+                          end
+                        end
+                        ph_est(k)  = conj(corr/(1E-6+abs(corr)));
+                        s_ch(i+k-1) = r_delay_line(k,centre).*exp(j*angle(corr));
+                      end
+
+                  end
+                  
+                  ph_est_log = [ph_est_log ph_est];
+               end    
+               %printf("corr: %f angle: %f\n", corr, angle(corr));
+            end
+
+            % de-modulate
+
+            rx_bits = zeros(1, framesize);
+            for i=1:Nsymb
+                rx_symb = s_ch(i);
+                if strcmp(modulation,'dqpsk')
+                    tmp = rx_symb;
+                    rx_symb *= conj(prev_sym_rx/abs(prev_sym_rx));
+                    prev_sym_rx = tmp;
+                end
+                rx_bits((2*(i-1)+1):(2*i)) = qpsk_demod(rx_symb);
+                rx_symb_log = [rx_symb_log rx_symb];
+            end
+
+            rx_bits_buf(1:framesize) = rx_bits_buf(framesize+1:2*framesize);
+            rx_bits_buf(framesize+1:2*framesize) = rx_bits;
+            rx_symb_buf(1:Nsymb) = rx_symb_buf(Nsymb+1:2*Nsymb);
+            rx_symb_buf(Nsymb+1:2*Nsymb) = s_ch;
+
+            % determine location of start and end of frame depending on processing delays
+
+            if phase_est
+              st_rx_bits = 1+(floor(Nps/2)+1-1)*Nc*2;
+              st_rx_symb = 1+(floor(Nps/2)+1-1)*Nc;
+           else
+              st_rx_bits = 1;
+              st_rx_symb = 1;
+            end
+            en_rx_bits = st_rx_bits+framesize-1;
+            en_rx_symb = st_rx_symb+Nsymb-1;
+
+            if nn > 1
+              % Measure BER
+
+              %printf("nn: %d centre: %d\n", nn, floor(Nps/2)+1);
+              %tx_bits_buf(1:20)
+              %rx_bits_buf(st_rx_bits:st_rx_bits+20-1)
+              error_positions = xor(rx_bits_buf(st_rx_bits:en_rx_bits), tx_bits_buf(1:framesize));
+              Nerrs = sum(error_positions);
+              Terrs += Nerrs;
+              Tbits += length(tx_bits);
+
+              % Optionally LDPC decode
+            
+              if ldpc_code
+                detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_symb_buf(st_rx_symb:en_rx_symb), min(100,EsNo), hf_fading);
+                %for m=1:20
+                %  printf("%f ", qpsk_demod(rx_symb_buf(m)));
+                %end
+                %detected_data(1:19)
+                error_positions = xor( detected_data(1:framesize*rate), tx_bits_buf(1:framesize*rate) );
+                Nerrs = sum(error_positions);
+                if Nerrs
+                    Ferrsldpc++;
+                end
+                Terrsldpc += Nerrs;
+                Tbitsldpc += framesize*rate;
+              end
+            end
+        end
+    
+        TERvec(ne) = Terrs;
+        BERvec(ne) = Terrs/Tbits;
+        if ldpc_code
+            TERldpcvec(ne) = Terrsldpc;
+            FERldpcvec(ne) = Ferrsldpc;
+            BERldpcvec(ne) = Terrsldpc/Tbitsldpc;
+        end
+
+        if verbose 
+            printf("EsNo (dB): %f  Terrs: %d BER %f BER theory %f", EsNodB, Terrs,
+                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)));
+            if ldpc_code
+                printf(" LDPC: Terrs: %d BER: %f Ferrs: %d FER: %f", 
+                       Terrsldpc, Terrsldpc/Tbitsldpc, Ferrsldpc, Ferrsldpc/(Ntrials-1));
+            end
+            printf("\n");
+        end
+        if verbose > 1
+            printf("Terrs: %d BER %f BER theory %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,
+                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)), var(tx_symb_log), var(noise_log),
+                   var(tx_symb_log), var(noise_log), var(tx_symb_log)/var(noise_log));
+        end
+    end
+    
+    Ebvec = Esvec - 10*log10(bps);
+    sim_out.BERvec          = BERvec;
+    sim_out.Ebvec           = Ebvec;
+    sim_out.TERvec          = TERvec;
+    if ldpc_code
+        sim_out.BERldpcvec  = BERldpcvec;
+        sim_out.TERldpcvec  = TERldpcvec;
+        sim_out.FERldpcvec  = FERldpcvec;
+    end
+
+    if plot_scatter
+        figure(2);
+        clf;
+        scat = rx_symb_log .* exp(j*pi/4);
+        plot(real(scat(Nps*Nc:length(scat))), imag(scat(Nps*Nc:length(scat))),'+');
+        title('Scatter plot');
+
+        figure(3);
+        clf;
+        
+        y = 1:Rs*2;
+        x = 1:Nc;
+        EsNodBSurface = 20*log10(abs(hf_model(y,:))) - 10*log10(variance);
+        mesh(x,y,EsNodBSurface);
+        grid
+        %axis([1 Nc 1 Rs*2 -10 10])
+        title('HF Channel Es/No');
+
+        figure(4);
+        clf;
+        %mesh(x,y,unwrap(angle(hf_model(y,:))));
+        subplot(211)
+        plot(y,abs(hf_model(y,1)))
+        title('HF Channel Carrier 1 Mag');
+        subplot(212)
+        plot(y,angle(hf_model(y,1)))
+        title('HF Channel Carrier 1 Phase');
+
+        if phase_est
+          scat = ph_est_log(1,floor(Nps/2):Rs*2+floor(Nps/2)-1);
+          hold on;
+          plot(angle(scat),'r');
+          hold off;
+
+          figure(5)
+          clf;
+          scat = ph_est_log(1,y);
+          plot(real(scat), imag(scat),'+');
+          title('Carrier 1 Phase Est');
+          axis([-1 1 -1 1])
+        end
+if 0        
+        figure(5);
+        clf;
+        subplot(211)
+        plot(real(spread));
+        hold on;
+        plot(imag(spread),'g');     
+        hold off;   
+        subplot(212)
+        plot(real(spread_2ms));
+        hold on;
+        plot(imag(spread_2ms),'g');     
+        hold off;   
+
+        figure(6)
+        tmp = [];
+        for i = 1:hf_n-1
+            tmp = [tmp abs(hf_model(i,:))];
+        end
+        hist(tmp);
+end
+     end
+
+endfunction
+
+% Gray coded QPSK modulation function
+
+function symbol = qpsk_mod(two_bits)
+    two_bits_decimal = sum(two_bits .* [2 1]); 
+    switch(two_bits_decimal)
+        case (0) symbol =  1;
+        case (1) symbol =  j;
+        case (2) symbol = -j;
+        case (3) symbol = -1;
+    endswitch
+endfunction
+
+% Gray coded QPSK demodulation function
+
+function two_bits = qpsk_demod(symbol)
+    if isscalar(symbol) == 0
+        printf("only works with scalars\n");
+        return;
+    end
+    bit0 = real(symbol*exp(j*pi/4)) < 0;
+    bit1 = imag(symbol*exp(j*pi/4)) < 0;
+    two_bits = [bit1 bit0];
+endfunction
+
+function sim_in = standard_init
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 0;
+
+  sim_in.Esvec            = 5; 
+  sim_in.Ntrials          = 30;
+  sim_in.framesize        = 576;
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 8;
+
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+  sim_in.phase_noise_amp  = 0;
+
+  sim_in.hf_delay_ms      = 2;
+  sim_in.hf_sim           = 0;
+  sim_in.hf_phase_only    = 0;
+  sim_in.hf_mag_only      = 1;
+
+  sim_in.phase_est        = 0;
+  sim_in.phase_est_method = 1;
+  sim_in.Np               = 5;
+  sim_in.Ns               = 5;
+
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+endfunction
+
+function ideal
+
+  sim_in = standard_init();
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 1;
+
+  sim_in.Esvec            = 5; 
+  sim_in.hf_sim           = 1;
+  sim_in.Ntrials          = 30;
+
+  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');
+
+  sim_in.hf_sim           = 0;
+  sim_in.plot_scatter     = 0;
+  sim_in.Esvec            = 2:10; 
+  sim_in.ldpc_code        = 0;
+  Ebvec = sim_in.Esvec - 10*log10(2);
+  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));
+  sim_qpsk                = ber_test(sim_in, 'qpsk');
+  sim_dqpsk               = ber_test(sim_in, 'dqpsk');
+
+  sim_in.hf_sim           = 1;
+  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');
+  sim_dqpsk_hf            = ber_test(sim_in, 'dqpsk');
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+
+  sim_in.hf_sim           = 0;
+  sim_qpsk_ldpc           = ber_test(sim_in, 'qpsk');
+
+  sim_in.hf_sim           = 1;
+  sim_qpsk_hf_ldpc        = ber_test(sim_in, 'qpsk');
+  sim_in.hf_mag_only      = 0;
+  sim_dqpsk_hf_ldpc       = ber_test(sim_in, 'dqpsk');
+
+  figure(1); 
+  clf;
+  semilogy(Ebvec, BER_theory,'r;QPSK theory;')
+  hold on;
+  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK AWGN;')
+  semilogy(sim_qpsk_hf.Ebvec, sim_qpsk_hf.BERvec,'r;QPSK HF;')
+  semilogy(sim_qpsk_ldpc.Ebvec, sim_qpsk_ldpc.BERldpcvec,'bk;QPSK HF;')
+  semilogy(sim_dqpsk.Ebvec, sim_dqpsk.BERvec,'g;DQPSK AWGN;')
+  semilogy(sim_dqpsk_hf.Ebvec, sim_dqpsk_hf.BERvec,'r;DQPSK HF;')
+  semilogy(sim_qpsk_hf_ldpc.Ebvec, sim_qpsk_hf_ldpc.BERldpcvec,'b;QPSK HF LDPC 1/2;')
+  semilogy(sim_dqpsk_hf_ldpc.Ebvec, sim_dqpsk_hf_ldpc.BERldpcvec,'b;DQPSK HF LDPC 1/2;')
+
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-3 1])
+endfunction
+
+function phase_noise
+  sim_in = standard_init();
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 1;
+
+  sim_in.Esvec            = 100; 
+  sim_in.Ntrials          = 30;
+
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+
+  sim_in.phase_noise_amp  = pi/16;
+  tmp                     = ber_test(sim_in, 'qpsk');
+
+  sim_in.plot_scatter     = 0;
+  sim_in.Esvec            = 2:8; 
+  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');
+
+  Ebvec = sim_in.Esvec - 10*log10(2);
+  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));
+
+  sim_in.phase_noise_amp = 0;
+  sim_qpsk               = ber_test(sim_in, 'qpsk');
+  sim_in.phase_noise_amp = pi/8;
+  sim_qpsk_pn8           = ber_test(sim_in, 'qpsk');
+  sim_in.phase_noise_amp = pi/16;
+  sim_qpsk_pn16          = ber_test(sim_in, 'qpsk');
+  sim_in.phase_noise_amp = pi/32;
+  sim_qpsk_pn32          = ber_test(sim_in, 'qpsk');
+
+  figure(1); 
+  clf;
+  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK phase noise 0;')
+  hold on;
+  semilogy(sim_qpsk_pn8.Ebvec, sim_qpsk_pn8.BERvec,'c;QPSK phase noise +/- pi/8;')
+  semilogy(sim_qpsk_pn16.Ebvec, sim_qpsk_pn16.BERvec,'b;QPSK phase noise +/- pi/16;')
+  semilogy(sim_qpsk_pn32.Ebvec, sim_qpsk_pn32.BERvec,'k;QPSK phase noise +/- pi/32;')
+
+  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERldpcvec,'g;QPSK phase noise 0 ldpc;')
+  semilogy(sim_qpsk_pn8.Ebvec, sim_qpsk_pn8.BERldpcvec,'c;QPSK phase noise +/- pi/8 ldpc;')
+  semilogy(sim_qpsk_pn16.Ebvec, sim_qpsk_pn16.BERldpcvec,'b;QPSK phase noise +/- pi/16 ldpc;')
+  semilogy(sim_qpsk_pn32.Ebvec, sim_qpsk_pn32.BERldpcvec,'k;QPSK phase noise +/- pi/32 ldpc;')
+
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-2 1])
+endfunction
+
+function test_phase_est
+  sim_in = standard_init();
+
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 8;
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 1;
+
+  sim_in.Esvec            = 5; 
+  sim_in.Ntrials          = 30;
+
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+
+  sim_in.phase_est        = 1;
+  sim_in.phase_est_method = 2;
+  sim_in.Np               = 3;
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+
+  sim_in.hf_sim           = 1;
+  sim_in.hf_mag_only      = 0;
+
+  tmp                     = ber_test(sim_in, 'qpsk');
+
+endfunction
+
+% Start simulations ---------------------------------------
+
+more off;
+
+ideal();
index eaf699958a5fadc9cdfae103c421dd92ab571198..447a20591331913b13f0bf9b6f0e1ab37e1a9007 100644 (file)
-% test_qps3k.m\r
-% David Rowe March 2014\r
-%\r
-% QPSK modem simulation, version 2.  Simplifed version of\r
-% test_qpsk. Initially based on code by Bill Cowley Generates curves\r
-% BER versus E/No curves for different modems.  Design to test\r
-% coherent demodulation ideas on HF channels without building a full\r
-% blown modem.  Uses 'genie provided' estimates for timing estimation,\r
-% frame sync.\r
-%\r
-% Compared to test_qsk2.m this version supports phase estimation\r
-% (coherent demod)\r
-\r
-1;\r
-\r
-% main test function \r
-\r
-function sim_out = ber_test(sim_in, modulation)\r
-    Fs = 8000;\r
-\r
-    newldpc          = sim_in.newldpc;\r
-    verbose          = sim_in.verbose;\r
-    framesize        = sim_in.framesize;\r
-    Ntrials          = sim_in.Ntrials;\r
-    Esvec            = sim_in.Esvec;\r
-    phase_offset     = sim_in.phase_offset;\r
-    phase_est        = sim_in.phase_est;\r
-    w_offset         = sim_in.w_offset;\r
-    plot_scatter     = sim_in.plot_scatter;\r
-    Rs               = sim_in.Rs;\r
-    hf_sim           = sim_in.hf_sim;\r
-    nhfdelay         = sim_in.hf_delay_ms*Rs/1000;\r
-    hf_phase_only    = sim_in.hf_phase_only;\r
-    hf_mag_only      = sim_in.hf_mag_only;\r
-    Nc               = sim_in.Nc;\r
-    sim_coh_dpsk     = sim_in.sim_coh_dpsk;\r
-\r
-    bps              = 2;\r
-    Nsymb            = framesize/bps;\r
-    for k=1:Nc\r
-      prev_sym_tx(k) = qpsk_mod([0 0]);\r
-      prev_sym_rx(k) = qpsk_mod([0 0]);\r
-    end\r
-\r
-    phase_est_method = sim_in.phase_est_method;\r
-    if phase_est_method == 2\r
-      Np             = sim_in.Np;\r
-      Ns             = sim_in.Ns;\r
-      if Np/2 == floor(Np/2)\r
-        printf("Np must be odd\n");\r
-        return;\r
-      end\r
-      Nps            = (Np-1)*Ns+1; \r
-    else\r
-      Nps            = sim_in.Np; \r
-    end\r
-    r_delay_line     = zeros(Nc, Nps);\r
-    s_delay_line     = zeros(Nc, Nps);\r
-    ph_est_log       = [];\r
-\r
-    phase_noise_amp  = sim_in.phase_noise_amp;\r
-\r
-    ldpc_code = sim_in.ldpc_code;\r
-\r
-    tx_bits_buf = zeros(1,2*framesize);\r
-    rx_bits_buf = zeros(1,2*framesize);\r
-    rx_symb_buf = zeros(1,2*Nsymb);\r
-    hf_fading_buf = zeros(1,2*Nsymb);\r
-\r
-    % Init LDPC --------------------------------------------------------------------\r
-\r
-    if ldpc_code\r
-        % Start CML library\r
-\r
-        currentdir = pwd;\r
-        addpath '/home/david/tmp/cml/mat'    % assume the source files stored here\r
-        cd /home/david/tmp/cml\r
-        CmlStartup                           % note that this is not in the cml path!\r
-        cd(currentdir)\r
-  \r
-        % Our LDPC library\r
-\r
-        ldpc;\r
-\r
-        rate = sim_in.ldpc_code_rate; \r
-        mod_order = 4; \r
-        modulation2 = 'QPSK';\r
-        mapping = 'gray';\r
-\r
-        demod_type = 0;\r
-        decoder_type = 0;\r
-        max_iterations = 100;\r
-\r
-        code_param = ldpc_init(rate, framesize, modulation2, mod_order, mapping);\r
-        code_param.code_bits_per_frame = framesize;\r
-        code_param.symbols_per_frame = framesize/bps;\r
-    else\r
-        rate = 1;\r
-    end\r
-\r
-    % Init HF channel model from stored sample files of spreading signal ----------------------------------\r
-\r
-    % convert "spreading" samples from 1kHz carrier at Fs to complex\r
-    % baseband, generated by passing a 1kHz sine wave through PathSim\r
-    % with the ccir-poor model, enabling one path at a time.\r
-    \r
-    Fc = 1000; M = Fs/Rs;\r
-    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");\r
-    spread1k = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");\r
-    spread1k_2ms = fread(fspread, "int16")/10000;\r
-    fclose(fspread);\r
-\r
-    % down convert to complex baseband\r
-    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');\r
-    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');\r
-\r
-    % remove -2000 Hz image\r
-    b = fir1(50, 5/Fs);\r
-    spread = filter(b,1,spreadbb);\r
-    spread_2ms = filter(b,1,spreadbb_2ms);\r
-\r
-    % discard first 1000 samples as these were near 0, probably as\r
-    % PathSim states were ramping up\r
-\r
-    spread    = spread(1000:length(spread));\r
-    spread_2ms = spread_2ms(1000:length(spread_2ms));\r
-\r
-    % decimate down to Rs\r
-\r
-    spread = spread(1:M:length(spread));\r
-    spread_2ms = spread_2ms(1:M:length(spread_2ms));\r
-\r
-    % Determine "gain" of HF channel model, so we can normalise\r
-    % carrier power during HF channel sim to calibrate SNR.  I imagine\r
-    % different implementations of ccir-poor would do this in\r
-    % different ways, leading to different BER results.  Oh Well!\r
-\r
-    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));\r
-\r
-    % Start Simulation ----------------------------------------------------------------\r
-\r
-    for ne = 1:length(Esvec)\r
-        EsNodB = Esvec(ne);\r
-        EsNo = 10^(EsNodB/10);\r
-    \r
-        variance = 1/EsNo;\r
-         if verbose > 1\r
-            printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);\r
-        end\r
-        \r
-        Terrs = 0;  Tbits = 0;  Terrsldpc = 0;  Tbitsldpc = 0; Ferrsldpc = 0;\r
-\r
-        tx_symb_log      = [];\r
-        rx_symb_log      = [];\r
-        noise_log        = [];\r
-        mod_strip_log    = [];\r
-        \r
-        % init HF channel\r
-\r
-        hf_n = 1;\r
-        hf_angle_log = [];\r
-        hf_fading = ones(1,Nsymb);             % default input for ldpc dec\r
-        hf_model = ones(Ntrials*Nsymb/Nc, Nc); % defaults for plotting surface\r
-\r
-        sim_out.errors_log = [];\r
-        sim_out.ldpc_errors_log = [];\r
-\r
-        for nn = 1: Ntrials\r
-                  \r
-            tx_bits = round( rand( 1, framesize*rate ) );\r
\r
-            % modulate --------------------------------------------\r
-\r
-            if ldpc_code\r
-                [tx_bits, s] = ldpc_enc(tx_bits, code_param);\r
-            end\r
-            s = zeros(1, Nsymb);\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                tx_symb = qpsk_mod(tx_bits(2*(i-1+k-1)+1:2*(i+k-1)));\r
-                if strcmp(modulation,'dqpsk')\r
-                    tx_symb *= prev_sym_tx(k);\r
-                    prev_sym_tx(k) = tx_symb;\r
-                end \r
-                s(i+k-1) = tx_symb;\r
-              end\r
-            end\r
-            tx_bits_buf(1:framesize) = tx_bits_buf(framesize+1:2*framesize);\r
-            tx_bits_buf(framesize+1:2*framesize) = tx_bits;\r
-            s_ch = s;\r
-\r
-            % HF channel simulation  ------------------------------------\r
-            \r
-            if hf_sim\r
-\r
-                % separation between carriers.  Note this is\r
-                % effectively under samples at Rs, I dont think this\r
-                % matters.  Equivalent to doing freq shift at Fs, then\r
-                % decimating to Rs.\r
-\r
-                wsep = 2*pi*(1+0.5);  % e.g. 75Hz spacing at Rs=50Hz, alpha=0.5 filters\r
-\r
-                if Nsymb/Nc != floor(Nsymb/Nc)\r
-                    printf("Error: Nsymb/Nc must be an integrer\n")\r
-                    return;\r
-                end\r
-\r
-                % arrange symbols in Nsymb/Nc by Nc matrix\r
-\r
-                for i=1:Nc:Nsymb\r
-\r
-                    % Determine HF channel at each carrier for this symbol\r
-\r
-                    for k=1:Nc\r
-                        hf_model(hf_n, k) = hf_gain*(spread(hf_n) + exp(-j*k*wsep*nhfdelay)*spread_2ms(hf_n));\r
-                        hf_fading(i+k-1) = abs(hf_model(hf_n, k));\r
-                        if hf_mag_only\r
-                             s_ch(i+k-1) *= abs(hf_model(hf_n, k));\r
-                        else\r
-                             s_ch(i+k-1) *= hf_model(hf_n, k);\r
-                        end\r
-                    end\r
-                    hf_n++;\r
-                end\r
-            end\r
-            \r
-            tx_symb_log = [tx_symb_log s_ch];\r
-\r
-            % AWGN noise and phase/freq offset channel simulation\r
-            % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im\r
-\r
-            noise = sqrt(variance*0.5)*(randn(1,Nsymb) + j*randn(1,Nsymb));\r
-            noise_log = [noise_log noise];\r
-            phase_noise = phase_noise_amp*(2.0*rand(1,Nsymb)-1.0);\r
\r
-            % organise into carriers to apply frequency and phase offset\r
-\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                 s_ch(i+k-1) = s_ch(i+k-1)*exp(j*(phase_offset+phase_noise(i+k-1))) + noise(i+k-1);\r
-              end \r
-              phase_offset += w_offset;\r
-            end\r
-               \r
-            % phase estimation\r
-            \r
-            ph_est = zeros(Nc,1);\r
-\r
-            if phase_est\r
-\r
-                % organise into carriers\r
-\r
-                for i=1:Nc:Nsymb\r
-\r
-                  for k=1:Nc\r
-                      centre = floor(Nps/2)+1;\r
-\r
-                      % delay line for phase est window\r
-\r
-                      r_delay_line(k,1:Nps-1) = r_delay_line(k,2:Nps);\r
-                      r_delay_line(k,Nps) = s_ch(i+k-1);\r
-\r
-                      % delay in tx data to compensate data for phase est window\r
-\r
-                      s_delay_line(k,1:Nps-1) = s_delay_line(k,2:Nps);\r
-                      s_delay_line(k,Nps) = s(i+k-1);\r
\r
-                      if phase_est_method == 1\r
-                        % QPSK modulation strip and phase est\r
-\r
-                        mod_strip_pol  = angle(r_delay_line(k,:)) * 4;\r
-                        mod_strip_rect = exp(j*mod_strip_pol);\r
-\r
-                        ph_est_pol = atan2(sum(imag(mod_strip_rect)),sum(real(mod_strip_rect)))/4;\r
-                        ph_est(k)  = exp(j*ph_est_pol);\r
-\r
-                        s_ch(i+k-1) = r_delay_line(k,centre).*exp(-j*ph_est_pol);\r
-                        % s_ch(i+k-1) = r_delay_line(k,centre);\r
-                     end\r
-\r
-                     if phase_est_method == 3\r
-                        % QPSK modulation strip and phase est with original symbol mags\r
-\r
-                        mod_strip_pol  = angle(r_delay_line(k,:)) * 4;\r
-                        mod_strip_rect = abs(r_delay_line(k,:)) .* exp(j*mod_strip_pol);\r
-\r
-                        ph_est_pol = atan2(sum(imag(mod_strip_rect)),sum(real(mod_strip_rect)))/4;\r
-                        ph_est(k)  = exp(j*ph_est_pol);\r
-\r
-                        s_ch(i+k-1) = r_delay_line(k,centre).*exp(-j*ph_est_pol);\r
-                        % s_ch(i+k-1) = r_delay_line(k,centre);\r
-                     end\r
-\r
-                     if phase_est_method == 2\r
-\r
-                        % estimate phase from surrounding known pilot symbols and correct\r
-\r
-                        corr = 0;\r
-                        for m=1:Ns:Nps\r
-                          if (m != centre)\r
-                            corr += s_delay_line(k,m) * r_delay_line(k,m)';\r
-                          end\r
-                        end\r
-                         ph_est(k)  = conj(corr/(1E-6+abs(corr)));\r
-                         s_ch(i+k-1) = r_delay_line(k,centre).*exp(j*angle(corr));\r
-                         %s_ch(i+k-1) = r_delay_line(k,centre);\r
-                     end\r
-\r
-                 end\r
-                  \r
-                  ph_est_log = [ph_est_log ph_est];\r
-               end    \r
-               %printf("corr: %f angle: %f\n", corr, angle(corr));\r
-            end\r
-\r
-            % de-modulate\r
-\r
-            rx_bits = zeros(1, framesize);\r
-            for i=1:Nc:Nsymb\r
-              for k=1:Nc\r
-                rx_symb = s_ch(i+k-1);\r
-                if strcmp(modulation,'dqpsk')\r
-                    tmp = rx_symb;\r
-                    rx_symb *= conj(prev_sym_rx(k)/abs(prev_sym_rx(k)));\r
-                    if sim_coh_dpsk\r
-                      prev_sym_rx(k) = qpsk_mod(qpsk_demod(tmp));\r
-                    else\r
-                      prev_sym_rx(k) = tmp;\r
-                    end\r
-                    s_ch(i+k-1) = rx_symb;\r
-                end\r
-                rx_bits((2*(i-1+k-1)+1):(2*(i+k-1))) = qpsk_demod(rx_symb);\r
-                rx_symb_log = [rx_symb_log rx_symb];\r
-              end\r
-            end\r
-\r
-if newldpc\r
-            rx_bits_buf(1:framesize) = rx_bits_buf(framesize+1:2*framesize);\r
-            rx_bits_buf(framesize+1:2*framesize) = rx_bits;\r
-            rx_symb_buf(1:Nsymb) = rx_symb_buf(Nsymb+1:2*Nsymb);\r
-            rx_symb_buf(Nsymb+1:2*Nsymb) = s_ch;\r
-            hf_fading_buf(1:Nsymb) = hf_fading_buf(Nsymb+1:2*Nsymb);\r
-            hf_fading_buf(Nsymb+1:2*Nsymb) = hf_fading;\r
-\r
-            % determine location of start and end of frame depending on processing delays\r
-\r
-            if phase_est\r
-              st_rx_bits = 1+(floor(Nps/2)+1-1)*Nc*2;\r
-              st_rx_symb = 1+(floor(Nps/2)+1-1)*Nc;\r
-            else\r
-              st_rx_bits = 1;\r
-              st_rx_symb = 1;\r
-            end\r
-            en_rx_bits = st_rx_bits+framesize-1;\r
-            en_rx_symb = st_rx_symb+Nsymb-1;\r
-\r
-            if nn > 1\r
-              % Measure BER\r
-\r
-              %printf("nn: %d centre: %d\n", nn, floor(Nps/2)+1);\r
-              %tx_bits_buf(1:20)\r
-              %rx_bits_buf(st_rx_bits:st_rx_bits+20-1)\r
-              error_positions = xor(rx_bits_buf(st_rx_bits:en_rx_bits), tx_bits_buf(1:framesize));\r
-              Nerrs = sum(error_positions);\r
-              sim_out.errors_log = [sim_out.errors_log error_positions];\r
-              Terrs += Nerrs;\r
-              Tbits += length(tx_bits);\r
-\r
-              % Optionally LDPC decode\r
-            \r
-              if ldpc_code\r
-                detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, ...\r
-                                         rx_symb_buf(st_rx_symb:en_rx_symb), min(100,EsNo), hf_fading_buf(1:Nsymb));\r
-                error_positions = xor( detected_data(1:framesize*rate), tx_bits_buf(1:framesize*rate) );\r
-                %detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, s_ch, min(100,EsNo), hf_fading);\r
-                %error_positions = xor( detected_data(1:framesize*rate), tx_bits(1:framesize*rate) );\r
-                Nerrs = sum(error_positions);\r
-                sim_out.ldpc_errors_log = [sim_out.ldpc_errors_log error_positions];\r
-                if Nerrs\r
-                    Ferrsldpc++;\r
-                end\r
-                Terrsldpc += Nerrs;\r
-                Tbitsldpc += framesize*rate;\r
-              end\r
-            end\r
-\r
-else    \r
-            error_positions = xor(rx_bits, tx_bits);\r
-            Nerrs = sum(error_positions);\r
-            Terrs += Nerrs;\r
-            Tbits += length(tx_bits);\r
-\r
-            % Optionally LDPC decode\r
-            \r
-            if ldpc_code\r
-                detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, s_ch, min(100,EsNo), hf_fading);\r
-                error_positions = xor( detected_data(1:framesize*rate), tx_bits(1:framesize*rate) );\r
-                Nerrs = sum(error_positions);\r
-                if Nerrs\r
-                    Ferrsldpc++;\r
-                end\r
-                Terrsldpc += Nerrs;\r
-                Tbitsldpc += framesize*rate;\r
-\r
-            end\r
-        end\r
-end\r
-\r
-        TERvec(ne) = Terrs;\r
-        BERvec(ne) = Terrs/Tbits;\r
-        if ldpc_code\r
-            TERldpcvec(ne) = Terrsldpc;\r
-            FERldpcvec(ne) = Ferrsldpc;\r
-            BERldpcvec(ne) = Terrsldpc/Tbitsldpc;\r
-        end\r
-\r
-        if verbose \r
-            printf("EsNo (dB): %f  Terrs: %d BER %f BER theory %f", EsNodB, Terrs,\r
-                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)));\r
-            if ldpc_code\r
-                printf(" LDPC: Terrs: %d BER: %f Ferrs: %d FER: %f", \r
-                       Terrsldpc, Terrsldpc/Tbitsldpc, Ferrsldpc, Ferrsldpc/(Ntrials-1));\r
-            end\r
-            printf("\n");\r
-        end\r
-        if verbose > 1\r
-            printf("Terrs: %d BER %f BER theory %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,\r
-                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)), var(tx_symb_log), var(noise_log),\r
-                   var(tx_symb_log), var(noise_log), var(tx_symb_log)/var(noise_log));\r
-        end\r
-    end\r
-    \r
-    Ebvec = Esvec - 10*log10(bps);\r
-\r
-    % account for extra power rqd for pilot symbols\r
-\r
-    if (phase_est_method == 2) && (phase_est)\r
-      Ebvec += 10*log10(Ns/(Ns-1));\r
-    end\r
-\r
-    sim_out.BERvec          = BERvec;\r
-    sim_out.Ebvec           = Ebvec;\r
-    sim_out.TERvec          = TERvec;\r
-    if ldpc_code\r
-        sim_out.BERldpcvec  = BERldpcvec;\r
-        sim_out.TERldpcvec  = TERldpcvec;\r
-        sim_out.FERldpcvec  = FERldpcvec;\r
-    end\r
-\r
-    if plot_scatter\r
-        figure(2);\r
-        clf;\r
-        scat = rx_symb_log .* exp(j*pi/4);\r
-        plot(real(scat(Nps*Nc:length(scat))), imag(scat(Nps*Nc:length(scat))),'+');\r
-        title('Scatter plot');\r
-\r
-        figure(3);\r
-        clf;\r
-        \r
-        y = 1:Rs*2;\r
-        x = 1:Nc;\r
-        EsNodBSurface = 20*log10(abs(hf_model(y,:))) - 10*log10(variance);\r
-        mesh(x,y,EsNodBSurface);\r
-        grid\r
-        %axis([1 Nc 1 Rs*2 -10 10])\r
-        title('HF Channel Es/No');\r
-\r
-        figure(4);\r
-        clf;\r
-        %mesh(x,y,unwrap(angle(hf_model(y,:))));\r
-        subplot(211)\r
-        plot(y,abs(hf_model(y,1)))\r
-        title('HF Channel Carrier 1 Mag');\r
-        subplot(212)\r
-        plot(y,angle(hf_model(y,1)))\r
-        title('HF Channel Carrier 1 Phase');\r
-\r
-        if phase_est\r
-          scat = ph_est_log(1,floor(Nps/2):Rs*2+floor(Nps/2)-1);\r
-          hold on;\r
-          plot(angle(scat),'r');\r
-          hold off;\r
-\r
-          figure(5)\r
-          clf;\r
-          scat = ph_est_log(1,y);\r
-          plot(real(scat), imag(scat),'+');\r
-          title('Carrier 1 Phase Est');\r
-          axis([-1 1 -1 1])\r
-        end\r
-if 0        \r
-        figure(5);\r
-        clf;\r
-        subplot(211)\r
-        plot(real(spread));\r
-        hold on;\r
-        plot(imag(spread),'g');     \r
-        hold off;   \r
-        subplot(212)\r
-        plot(real(spread_2ms));\r
-        hold on;\r
-        plot(imag(spread_2ms),'g');     \r
-        hold off;   \r
-\r
-        figure(6)\r
-        tmp = [];\r
-        for i = 1:hf_n-1\r
-            tmp = [tmp abs(hf_model(i,:))];\r
-        end\r
-        hist(tmp);\r
-end\r
-     end\r
-\r
-size(sim_out.errors_log)\r
-\r
-endfunction\r
-\r
-% Gray coded QPSK modulation function\r
-\r
-function symbol = qpsk_mod(two_bits)\r
-    two_bits_decimal = sum(two_bits .* [2 1]); \r
-    switch(two_bits_decimal)\r
-        case (0) symbol =  1;\r
-        case (1) symbol =  j;\r
-        case (2) symbol = -j;\r
-        case (3) symbol = -1;\r
-    endswitch\r
-endfunction\r
-\r
-% Gray coded QPSK demodulation function\r
-\r
-function two_bits = qpsk_demod(symbol)\r
-    if isscalar(symbol) == 0\r
-        printf("only works with scalars\n");\r
-        return;\r
-    end\r
-    bit0 = real(symbol*exp(j*pi/4)) < 0;\r
-    bit1 = imag(symbol*exp(j*pi/4)) < 0;\r
-    two_bits = [bit1 bit0];\r
-endfunction\r
-\r
-function sim_in = standard_init\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 0;\r
-\r
-  sim_in.Esvec            = 5; \r
-  sim_in.Ntrials          = 30;\r
-  sim_in.framesize        = 576;\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 8;\r
-\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-  sim_in.phase_noise_amp  = 0;\r
-\r
-  sim_in.hf_delay_ms      = 2;\r
-  sim_in.hf_sim           = 0;\r
-  sim_in.hf_phase_only    = 0;\r
-  sim_in.hf_mag_only      = 1;\r
-\r
-  sim_in.phase_est        = 0;\r
-  sim_in.phase_est_method = 1;\r
-  sim_in.Np               = 5;\r
-  sim_in.Ns               = 5;\r
-\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-endfunction\r
-\r
-function ideal\r
-\r
-  sim_in = standard_init();\r
-\r
-  sim_in.sim_coh_dpsk     = 0;\r
-  sim_in.newldpc          = 1;\r
-  sim_in.verbose          = 2;\r
-  sim_in.plot_scatter     = 1;\r
-\r
-  sim_in.Esvec            = 5; \r
-  sim_in.hf_sim           = 1;\r
-  sim_in.Ntrials          = 30;\r
-\r
-  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.hf_sim           = 0;\r
-  sim_in.plot_scatter     = 0;\r
-  sim_in.Esvec            = 2:15; \r
-  sim_in.ldpc_code        = 0;\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));\r
-  sim_qpsk                = ber_test(sim_in, 'qpsk');\r
-  sim_dqpsk               = ber_test(sim_in, 'dqpsk');\r
-\r
-  sim_in.hf_sim           = 1;\r
-  sim_in.Esvec            = 2:15; \r
-  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');\r
-  sim_dqpsk_hf            = ber_test(sim_in, 'dqpsk');\r
-  sim_in.ldpc_code        = 1;\r
-  sim_in.ldpc_code_rate   = 3/4;\r
-  sim_qpsk_hf_ldpc1       = ber_test(sim_in, 'qpsk');\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_qpsk_hf_ldpc2       = ber_test(sim_in, 'qpsk');\r
-  sim_in.ldpc_code_rate   = 3/4;\r
-  sim_in.hf_sim           = 0;\r
-  sim_qpsk_awgn_ldpc      = ber_test(sim_in, 'qpsk');\r
-\r
-  figure(1); \r
-  clf;\r
-  semilogy(Ebvec, BER_theory,'r;QPSK theory;')\r
-  hold on;\r
-  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK AWGN;')\r
-  semilogy(sim_qpsk_hf.Ebvec, sim_qpsk_hf.BERvec,'r;QPSK HF;')\r
-  semilogy(sim_dqpsk.Ebvec, sim_dqpsk.BERvec,'c;DQPSK AWGN;')\r
-  semilogy(sim_dqpsk_hf.Ebvec, sim_dqpsk_hf.BERvec,'m;DQPSK HF;')\r
-  semilogy(sim_qpsk_hf_ldpc1.Ebvec, sim_qpsk_hf_ldpc1.BERldpcvec,'k;QPSK HF LDPC 3/4;')\r
-  semilogy(sim_qpsk_hf_ldpc2.Ebvec, sim_qpsk_hf_ldpc2.BERldpcvec,'b;QPSK HF LDPC 1/2;')\r
-  semilogy(sim_qpsk_awgn_ldpc.Ebvec, sim_qpsk_awgn_ldpc.BERldpcvec,'k;QPSK AWGN LDPC 3/4;')\r
-\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-3 1])\r
-endfunction\r
-\r
-function phase_noise\r
-  sim_in = standard_init();\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 1;\r
-\r
-  sim_in.Esvec            = 100; \r
-  sim_in.Ntrials          = 100;\r
-\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-\r
-  sim_in.phase_noise_amp  = pi/16;\r
-  tmp                     = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.plot_scatter     = 0;\r
-  sim_in.Esvec            = 2:8; \r
-  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');\r
-\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));\r
-\r
-  sim_in.phase_noise_amp = 0;\r
-  sim_qpsk               = ber_test(sim_in, 'qpsk');\r
-  sim_in.phase_noise_amp = pi/8;\r
-  sim_qpsk_pn8           = ber_test(sim_in, 'qpsk');\r
-  sim_in.phase_noise_amp = pi/16;\r
-  sim_qpsk_pn16          = ber_test(sim_in, 'qpsk');\r
-  sim_in.phase_noise_amp = pi/32;\r
-  sim_qpsk_pn32          = ber_test(sim_in, 'qpsk');\r
-\r
-  figure(1); \r
-  clf;\r
-  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK phase noise 0;')\r
-  hold on;\r
-  semilogy(sim_qpsk_pn8.Ebvec, sim_qpsk_pn8.BERvec,'c;QPSK phase noise +/- pi/8;')\r
-  semilogy(sim_qpsk_pn16.Ebvec, sim_qpsk_pn16.BERvec,'b;QPSK phase noise +/- pi/16;')\r
-  semilogy(sim_qpsk_pn32.Ebvec, sim_qpsk_pn32.BERvec,'k;QPSK phase noise +/- pi/32;')\r
-\r
-  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERldpcvec,'g;QPSK phase noise 0 ldpc;')\r
-  semilogy(sim_qpsk_pn8.Ebvec, sim_qpsk_pn8.BERldpcvec,'c;QPSK phase noise +/- pi/8 ldpc;')\r
-  semilogy(sim_qpsk_pn16.Ebvec, sim_qpsk_pn16.BERldpcvec,'b;QPSK phase noise +/- pi/16 ldpc;')\r
-  semilogy(sim_qpsk_pn32.Ebvec, sim_qpsk_pn32.BERldpcvec,'k;QPSK phase noise +/- pi/32 ldpc;')\r
-\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-2 1])\r
-endfunction\r
-\r
-function phase_est_hf\r
-  sim_in = standard_init();\r
-\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 8;\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 0;\r
-\r
-  sim_in.Esvec            = 5:15; \r
-  sim_in.Ntrials          = 100;\r
-\r
-  sim_in.newldpc          = 1;\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-\r
-  sim_in.phase_est        = 0;\r
-  sim_in.sim_coh_dpsk     = 0;\r
-  sim_in.phase_est_method = 2;\r
-  sim_in.Np               = 3;\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-\r
-  sim_in.hf_sim           = 1;\r
-  sim_in.hf_mag_only      = 1;\r
-\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-\r
-  baseline                = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.hf_mag_only      = 0;\r
-  sim_in.phase_est_method = 2;\r
-  sim_in.phase_est        = 1;\r
-  sim_in.Np               = 3;\r
-  pilot_3                 = ber_test(sim_in, 'qpsk');\r
-  sim_in.Np               = 5;\r
-  pilot_5                 = ber_test(sim_in, 'qpsk');\r
-  sim_in.Np               = 7;\r
-  pilot_7                 = ber_test(sim_in, 'qpsk');\r
-\r
-if 1\r
-  sim_in.phase_est        = 0;\r
-  dqpsk                   = ber_test(sim_in, 'dqpsk');\r
-\r
-  figure(1); \r
-  clf;\r
-  semilogy(baseline.Ebvec, baseline.BERvec,'r;QPSK CCIR poor;')\r
-  hold on;\r
-  semilogy(baseline.Ebvec, baseline.BERldpcvec,'r;QPSK CCIR poor ldpc;')\r
-  semilogy(pilot_3.Ebvec, pilot_3.BERvec,'b;QPSK CCIR poor ldpc pilot 3;')\r
-  semilogy(pilot_3.Ebvec, pilot_3.BERldpcvec,'b;QPSK CCIR poor ldpc pilot 3;')\r
-  semilogy(pilot_5.Ebvec, pilot_5.BERvec,'g;QPSK CCIR poor ldpc pilot 5;')\r
-  semilogy(pilot_5.Ebvec, pilot_5.BERldpcvec,'g;QPSK CCIR poor ldpc pilot 5;')\r
-  semilogy(pilot_7.Ebvec, pilot_7.BERvec,'m;QPSK CCIR poor ldpc pilot 7;')\r
-  semilogy(pilot_7.Ebvec, pilot_7.BERldpcvec,'m;QPSK CCIR poor ldpc pilot 7;')\r
-  semilogy(dqpsk.Ebvec, dqpsk.BERvec,'k;DQPSK CCIR poor ldpc;')\r
-  semilogy(dqpsk.Ebvec, dqpsk.BERldpcvec,'k;DQPSK CCIR poor ldpc;')\r
-\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-2 1])\r
-end\r
-endfunction\r
-\r
-function phase_est_awgn\r
-  sim_in = standard_init();\r
-\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 8;\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 0;\r
-\r
-  sim_in.Esvec            = 0:0.5:3; \r
-  sim_in.Ntrials          = 30;\r
-\r
-  sim_in.newldpc          = 1;\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-\r
-  sim_in.phase_est        = 0;\r
-  sim_in.phase_est_method = 1;\r
-  sim_in.Np               = 3;\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-\r
-  sim_in.hf_sim           = 0;\r
-  sim_in.hf_mag_only      = 1;\r
-\r
-  ideal                   = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.phase_est        = 1;\r
-  sim_in.Np               = 21;\r
-  sim_in.phase_est_method = 3;\r
-  strip_21_mag            = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.Np               = 41;\r
-  strip_41_mag            = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.phase_est_method = 1;\r
-  sim_in.Np               = 21;\r
-  strip_21                = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.Np               = 41;\r
-  strip_41                = ber_test(sim_in, 'qpsk');\r
-\r
-  sim_in.Np               = 7;\r
-  sim_in.phase_est_method = 2;\r
-  pilot_7                 = ber_test(sim_in, 'qpsk');\r
-\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-\r
-  figure(1); \r
-  clf;\r
-  semilogy(ideal.Ebvec, ideal.BERvec,'r;QPSK;')\r
-  hold on;\r
-  semilogy(ideal.Ebvec, ideal.BERldpcvec,'r;QPSK LDPC;')\r
-  semilogy(strip_21.Ebvec, strip_21.BERvec,'g;QPSK strip 21;')\r
-  semilogy(strip_21.Ebvec, strip_21.BERldpcvec,'g;QPSK LDPC strip 21;')\r
-  semilogy(strip_41.Ebvec, strip_41.BERvec,'b;QPSK strip 41;')\r
-  semilogy(strip_41.Ebvec, strip_41.BERldpcvec,'b;QPSK LDPC strip 41;')\r
-  semilogy(strip_21_mag.Ebvec, strip_21_mag.BERvec,'m;QPSK strip 21 mag;')\r
-  semilogy(strip_21_mag.Ebvec, strip_21_mag.BERldpcvec,'m;QPSK LDPC strip 21 mag;')\r
-  semilogy(strip_41_mag.Ebvec, strip_41_mag.BERvec,'c;QPSK strip 41 mag;')\r
-  semilogy(strip_41_mag.Ebvec, strip_41_mag.BERldpcvec,'c;QPSK LDPC strip 41 mag;')\r
-  semilogy(pilot_7.Ebvec, pilot_7.BERvec,'k;QPSK pilot 7;')\r
-  semilogy(pilot_7.Ebvec, pilot_7.BERldpcvec,'k;QPSK LDPC pilot 7;')\r
-\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-2 1])\r
-endfunction\r
-\r
-function test_dpsk\r
-  sim_in = standard_init();\r
-\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 8;\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 0;\r
-\r
-  sim_in.Esvec            = 5; \r
-  sim_in.Ntrials          = 30;\r
-\r
-  sim_in.newldpc          = 1;\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-\r
-  sim_in.phase_est        = 0;\r
-  sim_in.phase_est_method = 3;\r
-  sim_in.Np               = 41;\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-  sim_in.sim_coh_dpsk     = 0;\r
-\r
-  sim_in.hf_sim           = 0;\r
-  sim_in.hf_mag_only      = 1;\r
-\r
-  Ebvec = sim_in.Esvec - 10*log10(2);\r
-\r
-  baseline                = ber_test(sim_in, 'qpsk');\r
-  sim_in.phase_est        = 0;\r
-  dqpsk                   = ber_test(sim_in, 'dqpsk');\r
-\r
-  sim_in.phase_est        = 1;\r
-  sim_in.phase_est_method = 3;\r
-  sim_in.sim_coh_dpsk     = 1;\r
-  sim_in.Np               = 41;\r
-  dqpsk_strip_41          = ber_test(sim_in, 'dqpsk');\r
-  \r
-  figure(1); \r
-  clf;\r
-  semilogy(baseline.Ebvec, baseline.BERvec,'r;QPSK CCIR poor;')\r
-  hold on;\r
-  semilogy(baseline.Ebvec, baseline.BERldpcvec,'r;QPSK CCIR poor ldpc;')\r
-  semilogy(dqpsk.Ebvec, dqpsk.BERvec,'c;DQPSK CCIR poor ldpc;')\r
-  semilogy(dqpsk.Ebvec, dqpsk.BERldpcvec,'c;DQPSK CCIR poor ldpc;')\r
-  semilogy(dqpsk_strip_41.Ebvec, dqpsk_strip_41.BERvec,'m;DQPSK CCIR poor ldpc strip 41;')\r
-  semilogy(dqpsk_strip_41.Ebvec, dqpsk_strip_41.BERldpcvec,'m;DQPSK CCIR poor ldpc strip 41;')\r
-\r
-  hold off;\r
-  xlabel('Eb/N0')\r
-  ylabel('BER')\r
-  grid("minor")\r
-  axis([min(Ebvec) max(Ebvec) 1E-2 1])\r
-\r
-endfunction\r
-\r
-function gen_error_pattern_qpsk()\r
-  sim_in = standard_init();\r
-\r
-  % model codec and uncoded streams as 1000 bit/s each\r
-\r
-  sim_in.Rs               = 100;\r
-  sim_in.Nc               = 4;\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 0;\r
-\r
-  sim_in.Esvec            = 10; % Eb/No=2dB\r
-  sim_in.Ntrials          = 30;\r
-\r
-  sim_in.newldpc          = 1;\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 1;\r
-\r
-  sim_in.phase_est        = 1;\r
-  sim_in.phase_est_method = 2;\r
-  sim_in.Np               = 5;\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-  sim_in.sim_coh_dpsk     = 0;\r
-\r
-  sim_in.hf_sim           = 1;\r
-  sim_in.hf_mag_only      = 0;\r
-\r
-  qpsk                    = ber_test(sim_in, 'qpsk');\r
\r
-  length(qpsk.errors_log) \r
-  length(qpsk.ldpc_errors_log)\r
-  % multiplex errors into prot and unprot halves of 52 bit codec frames\r
-\r
-  error_pattern = [];\r
-  for i=1:26:length(qpsk.ldpc_errors_log)-52\r
-    error_pattern = [error_pattern qpsk.ldpc_errors_log(i:i+25) qpsk.errors_log(i:i+25)  zeros(1,4)];\r
-    %error_pattern = [error_pattern qpsk.ldpc_errors_log(i:i+25) zeros(1,26)  zeros(1,4)];\r
-    %error_pattern = [error_pattern zeros(1,26) qpsk.errors_log(i:i+25)  zeros(1,4)];\r
-  end\r
-\r
-  fep=fopen("qpsk_errors_2dB.bin","wb"); fwrite(fep, error_pattern, "short"); fclose(fep);\r
-\r
-endfunction\r
-\r
-function gen_error_pattern_dpsk()\r
-  sim_in = standard_init();\r
-\r
-  sim_in.Rs               = 50;\r
-  sim_in.Nc               = 16;\r
-\r
-  sim_in.verbose          = 1;\r
-  sim_in.plot_scatter     = 1;\r
-\r
-  sim_in.Esvec            = 10; % Eb/No=Es/No-3\r
-  sim_in.Ntrials          = 30;\r
-\r
-  sim_in.newldpc          = 1;\r
-  sim_in.ldpc_code_rate   = 1/2;\r
-  sim_in.ldpc_code        = 0;\r
-\r
-  sim_in.phase_est        = 0;\r
-  sim_in.phase_est_method = 3;\r
-  sim_in.Np               = 41;\r
-  sim_in.phase_offset     = 0;\r
-  sim_in.w_offset         = 0;\r
-  sim_in.sim_coh_dpsk     = 0;\r
-\r
-  sim_in.hf_sim           = 1;\r
-  sim_in.hf_mag_only      = 1;\r
-\r
-  dqpsk                    = ber_test(sim_in, 'dqpsk');\r
\r
-  fep=fopen("dqpsk_errors_12dB.bin","wb"); fwrite(fep, dqpsk.errors_log, "short"); fclose(fep);\r
-\r
-endfunction\r
-\r
-% Start simulations ---------------------------------------\r
-\r
-more off;\r
-\r
-ideal();\r
-%phase_est_hf();\r
-%phase_est_awgn();\r
-%test_dpsk();\r
-%gen_error_pattern_qpsk\r
+% test_qps3k.m
+% David Rowe March 2014
+%
+% QPSK modem simulation, version 2.  Simplifed version of
+% test_qpsk. Initially based on code by Bill Cowley Generates curves
+% BER versus E/No curves for different modems.  Design to test
+% coherent demodulation ideas on HF channels without building a full
+% blown modem.  Uses 'genie provided' estimates for timing estimation,
+% frame sync.
+%
+% Compared to test_qsk2.m this version supports phase estimation
+% (coherent demod)
+
+1;
+
+% main test function 
+
+function sim_out = ber_test(sim_in, modulation)
+    Fs = 8000;
+
+    newldpc          = sim_in.newldpc;
+    verbose          = sim_in.verbose;
+    framesize        = sim_in.framesize;
+    Ntrials          = sim_in.Ntrials;
+    Esvec            = sim_in.Esvec;
+    phase_offset     = sim_in.phase_offset;
+    phase_est        = sim_in.phase_est;
+    w_offset         = sim_in.w_offset;
+    plot_scatter     = sim_in.plot_scatter;
+    Rs               = sim_in.Rs;
+    hf_sim           = sim_in.hf_sim;
+    nhfdelay         = sim_in.hf_delay_ms*Rs/1000;
+    hf_phase_only    = sim_in.hf_phase_only;
+    hf_mag_only      = sim_in.hf_mag_only;
+    Nc               = sim_in.Nc;
+    sim_coh_dpsk     = sim_in.sim_coh_dpsk;
+
+    bps              = 2;
+    Nsymb            = framesize/bps;
+    for k=1:Nc
+      prev_sym_tx(k) = qpsk_mod([0 0]);
+      prev_sym_rx(k) = qpsk_mod([0 0]);
+    end
+
+    phase_est_method = sim_in.phase_est_method;
+    if phase_est_method == 2
+      Np             = sim_in.Np;
+      Ns             = sim_in.Ns;
+      if Np/2 == floor(Np/2)
+        printf("Np must be odd\n");
+        return;
+      end
+      Nps            = (Np-1)*Ns+1; 
+    else
+      Nps            = sim_in.Np; 
+    end
+    r_delay_line     = zeros(Nc, Nps);
+    s_delay_line     = zeros(Nc, Nps);
+    ph_est_log       = [];
+
+    phase_noise_amp  = sim_in.phase_noise_amp;
+
+    ldpc_code = sim_in.ldpc_code;
+
+    tx_bits_buf = zeros(1,2*framesize);
+    rx_bits_buf = zeros(1,2*framesize);
+    rx_symb_buf = zeros(1,2*Nsymb);
+    hf_fading_buf = zeros(1,2*Nsymb);
+
+    % Init LDPC --------------------------------------------------------------------
+
+    if ldpc_code
+        % Start CML library
+
+        currentdir = pwd;
+        addpath '/home/david/tmp/cml/mat'    % assume the source files stored here
+        cd /home/david/tmp/cml
+        CmlStartup                           % note that this is not in the cml path!
+        cd(currentdir)
+  
+        % Our LDPC library
+
+        ldpc;
+
+        rate = sim_in.ldpc_code_rate; 
+        mod_order = 4; 
+        modulation2 = 'QPSK';
+        mapping = 'gray';
+
+        demod_type = 0;
+        decoder_type = 0;
+        max_iterations = 100;
+
+        code_param = ldpc_init(rate, framesize, modulation2, mod_order, mapping);
+        code_param.code_bits_per_frame = framesize;
+        code_param.symbols_per_frame = framesize/bps;
+    else
+        rate = 1;
+    end
+
+    % Init HF channel model from stored sample files of spreading signal ----------------------------------
+
+    % convert "spreading" samples from 1kHz carrier at Fs to complex
+    % baseband, generated by passing a 1kHz sine wave through PathSim
+    % with the ccir-poor model, enabling one path at a time.
+    
+    Fc = 1000; M = Fs/Rs;
+    fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");
+    spread1k = fread(fspread, "int16")/10000;
+    fclose(fspread);
+    fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");
+    spread1k_2ms = fread(fspread, "int16")/10000;
+    fclose(fspread);
+
+    % down convert to complex baseband
+    spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');
+    spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');
+
+    % remove -2000 Hz image
+    b = fir1(50, 5/Fs);
+    spread = filter(b,1,spreadbb);
+    spread_2ms = filter(b,1,spreadbb_2ms);
+
+    % discard first 1000 samples as these were near 0, probably as
+    % PathSim states were ramping up
+
+    spread    = spread(1000:length(spread));
+    spread_2ms = spread_2ms(1000:length(spread_2ms));
+
+    % decimate down to Rs
+
+    spread = spread(1:M:length(spread));
+    spread_2ms = spread_2ms(1:M:length(spread_2ms));
+
+    % Determine "gain" of HF channel model, so we can normalise
+    % carrier power during HF channel sim to calibrate SNR.  I imagine
+    % different implementations of ccir-poor would do this in
+    % different ways, leading to different BER results.  Oh Well!
+
+    hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));
+
+    % Start Simulation ----------------------------------------------------------------
+
+    for ne = 1:length(Esvec)
+        EsNodB = Esvec(ne);
+        EsNo = 10^(EsNodB/10);
+    
+        variance = 1/EsNo;
+         if verbose > 1
+            printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);
+        end
+        
+        Terrs = 0;  Tbits = 0;  Terrsldpc = 0;  Tbitsldpc = 0; Ferrsldpc = 0;
+
+        tx_symb_log      = [];
+        rx_symb_log      = [];
+        noise_log        = [];
+        mod_strip_log    = [];
+        
+        % init HF channel
+
+        hf_n = 1;
+        hf_angle_log = [];
+        hf_fading = ones(1,Nsymb);             % default input for ldpc dec
+        hf_model = ones(Ntrials*Nsymb/Nc, Nc); % defaults for plotting surface
+
+        sim_out.errors_log = [];
+        sim_out.ldpc_errors_log = [];
+
+        for nn = 1: Ntrials
+                  
+            tx_bits = round( rand( 1, framesize*rate ) );
+            % modulate --------------------------------------------
+
+            if ldpc_code
+                [tx_bits, s] = ldpc_enc(tx_bits, code_param);
+            end
+            s = zeros(1, Nsymb);
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                tx_symb = qpsk_mod(tx_bits(2*(i-1+k-1)+1:2*(i+k-1)));
+                if strcmp(modulation,'dqpsk')
+                    tx_symb *= prev_sym_tx(k);
+                    prev_sym_tx(k) = tx_symb;
+                end 
+                s(i+k-1) = tx_symb;
+              end
+            end
+            tx_bits_buf(1:framesize) = tx_bits_buf(framesize+1:2*framesize);
+            tx_bits_buf(framesize+1:2*framesize) = tx_bits;
+            s_ch = s;
+
+            % HF channel simulation  ------------------------------------
+            
+            if hf_sim
+
+                % separation between carriers.  Note this is
+                % effectively under samples at Rs, I dont think this
+                % matters.  Equivalent to doing freq shift at Fs, then
+                % decimating to Rs.
+
+                wsep = 2*pi*(1+0.5);  % e.g. 75Hz spacing at Rs=50Hz, alpha=0.5 filters
+
+                if Nsymb/Nc != floor(Nsymb/Nc)
+                    printf("Error: Nsymb/Nc must be an integrer\n")
+                    return;
+                end
+
+                % arrange symbols in Nsymb/Nc by Nc matrix
+
+                for i=1:Nc:Nsymb
+
+                    % Determine HF channel at each carrier for this symbol
+
+                    for k=1:Nc
+                        hf_model(hf_n, k) = hf_gain*(spread(hf_n) + exp(-j*k*wsep*nhfdelay)*spread_2ms(hf_n));
+                        hf_fading(i+k-1) = abs(hf_model(hf_n, k));
+                        if hf_mag_only
+                             s_ch(i+k-1) *= abs(hf_model(hf_n, k));
+                        else
+                             s_ch(i+k-1) *= hf_model(hf_n, k);
+                        end
+                    end
+                    hf_n++;
+                end
+            end
+            
+            tx_symb_log = [tx_symb_log s_ch];
+
+            % AWGN noise and phase/freq offset channel simulation
+            % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im
+
+            noise = sqrt(variance*0.5)*(randn(1,Nsymb) + j*randn(1,Nsymb));
+            noise_log = [noise_log noise];
+            phase_noise = phase_noise_amp*(2.0*rand(1,Nsymb)-1.0);
+            % organise into carriers to apply frequency and phase offset
+
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                 s_ch(i+k-1) = s_ch(i+k-1)*exp(j*(phase_offset+phase_noise(i+k-1))) + noise(i+k-1);
+              end 
+              phase_offset += w_offset;
+            end
+               
+            % phase estimation
+            
+            ph_est = zeros(Nc,1);
+
+            if phase_est
+
+                % organise into carriers
+
+                for i=1:Nc:Nsymb
+
+                  for k=1:Nc
+                      centre = floor(Nps/2)+1;
+
+                      % delay line for phase est window
+
+                      r_delay_line(k,1:Nps-1) = r_delay_line(k,2:Nps);
+                      r_delay_line(k,Nps) = s_ch(i+k-1);
+
+                      % delay in tx data to compensate data for phase est window
+
+                      s_delay_line(k,1:Nps-1) = s_delay_line(k,2:Nps);
+                      s_delay_line(k,Nps) = s(i+k-1);
+                      if phase_est_method == 1
+                        % QPSK modulation strip and phase est
+
+                        mod_strip_pol  = angle(r_delay_line(k,:)) * 4;
+                        mod_strip_rect = exp(j*mod_strip_pol);
+
+                        ph_est_pol = atan2(sum(imag(mod_strip_rect)),sum(real(mod_strip_rect)))/4;
+                        ph_est(k)  = exp(j*ph_est_pol);
+
+                        s_ch(i+k-1) = r_delay_line(k,centre).*exp(-j*ph_est_pol);
+                        % s_ch(i+k-1) = r_delay_line(k,centre);
+                     end
+
+                     if phase_est_method == 3
+                        % QPSK modulation strip and phase est with original symbol mags
+
+                        mod_strip_pol  = angle(r_delay_line(k,:)) * 4;
+                        mod_strip_rect = abs(r_delay_line(k,:)) .* exp(j*mod_strip_pol);
+
+                        ph_est_pol = atan2(sum(imag(mod_strip_rect)),sum(real(mod_strip_rect)))/4;
+                        ph_est(k)  = exp(j*ph_est_pol);
+
+                        s_ch(i+k-1) = r_delay_line(k,centre).*exp(-j*ph_est_pol);
+                        % s_ch(i+k-1) = r_delay_line(k,centre);
+                     end
+
+                     if phase_est_method == 2
+
+                        % estimate phase from surrounding known pilot symbols and correct
+
+                        corr = 0;
+                        for m=1:Ns:Nps
+                          if (m != centre)
+                            corr += s_delay_line(k,m) * r_delay_line(k,m)';
+                          end
+                        end
+                         ph_est(k)  = conj(corr/(1E-6+abs(corr)));
+                         s_ch(i+k-1) = r_delay_line(k,centre).*exp(j*angle(corr));
+                         %s_ch(i+k-1) = r_delay_line(k,centre);
+                     end
+
+                 end
+                  
+                  ph_est_log = [ph_est_log ph_est];
+               end    
+               %printf("corr: %f angle: %f\n", corr, angle(corr));
+            end
+
+            % de-modulate
+
+            rx_bits = zeros(1, framesize);
+            for i=1:Nc:Nsymb
+              for k=1:Nc
+                rx_symb = s_ch(i+k-1);
+                if strcmp(modulation,'dqpsk')
+                    tmp = rx_symb;
+                    rx_symb *= conj(prev_sym_rx(k)/abs(prev_sym_rx(k)));
+                    if sim_coh_dpsk
+                      prev_sym_rx(k) = qpsk_mod(qpsk_demod(tmp));
+                    else
+                      prev_sym_rx(k) = tmp;
+                    end
+                    s_ch(i+k-1) = rx_symb;
+                end
+                rx_bits((2*(i-1+k-1)+1):(2*(i+k-1))) = qpsk_demod(rx_symb);
+                rx_symb_log = [rx_symb_log rx_symb];
+              end
+            end
+
+if newldpc
+            rx_bits_buf(1:framesize) = rx_bits_buf(framesize+1:2*framesize);
+            rx_bits_buf(framesize+1:2*framesize) = rx_bits;
+            rx_symb_buf(1:Nsymb) = rx_symb_buf(Nsymb+1:2*Nsymb);
+            rx_symb_buf(Nsymb+1:2*Nsymb) = s_ch;
+            hf_fading_buf(1:Nsymb) = hf_fading_buf(Nsymb+1:2*Nsymb);
+            hf_fading_buf(Nsymb+1:2*Nsymb) = hf_fading;
+
+            % determine location of start and end of frame depending on processing delays
+
+            if phase_est
+              st_rx_bits = 1+(floor(Nps/2)+1-1)*Nc*2;
+              st_rx_symb = 1+(floor(Nps/2)+1-1)*Nc;
+            else
+              st_rx_bits = 1;
+              st_rx_symb = 1;
+            end
+            en_rx_bits = st_rx_bits+framesize-1;
+            en_rx_symb = st_rx_symb+Nsymb-1;
+
+            if nn > 1
+              % Measure BER
+
+              %printf("nn: %d centre: %d\n", nn, floor(Nps/2)+1);
+              %tx_bits_buf(1:20)
+              %rx_bits_buf(st_rx_bits:st_rx_bits+20-1)
+              error_positions = xor(rx_bits_buf(st_rx_bits:en_rx_bits), tx_bits_buf(1:framesize));
+              Nerrs = sum(error_positions);
+              sim_out.errors_log = [sim_out.errors_log error_positions];
+              Terrs += Nerrs;
+              Tbits += length(tx_bits);
+
+              % Optionally LDPC decode
+            
+              if ldpc_code
+                detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, ...
+                                         rx_symb_buf(st_rx_symb:en_rx_symb), min(100,EsNo), hf_fading_buf(1:Nsymb));
+                error_positions = xor( detected_data(1:framesize*rate), tx_bits_buf(1:framesize*rate) );
+                %detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, s_ch, min(100,EsNo), hf_fading);
+                %error_positions = xor( detected_data(1:framesize*rate), tx_bits(1:framesize*rate) );
+                Nerrs = sum(error_positions);
+                sim_out.ldpc_errors_log = [sim_out.ldpc_errors_log error_positions];
+                if Nerrs
+                    Ferrsldpc++;
+                end
+                Terrsldpc += Nerrs;
+                Tbitsldpc += framesize*rate;
+              end
+            end
+
+else    
+            error_positions = xor(rx_bits, tx_bits);
+            Nerrs = sum(error_positions);
+            Terrs += Nerrs;
+            Tbits += length(tx_bits);
+
+            % Optionally LDPC decode
+            
+            if ldpc_code
+                detected_data = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, s_ch, min(100,EsNo), hf_fading);
+                error_positions = xor( detected_data(1:framesize*rate), tx_bits(1:framesize*rate) );
+                Nerrs = sum(error_positions);
+                if Nerrs
+                    Ferrsldpc++;
+                end
+                Terrsldpc += Nerrs;
+                Tbitsldpc += framesize*rate;
+
+            end
+        end
+end
+
+        TERvec(ne) = Terrs;
+        BERvec(ne) = Terrs/Tbits;
+        if ldpc_code
+            TERldpcvec(ne) = Terrsldpc;
+            FERldpcvec(ne) = Ferrsldpc;
+            BERldpcvec(ne) = Terrsldpc/Tbitsldpc;
+        end
+
+        if verbose 
+            printf("EsNo (dB): %f  Terrs: %d BER %f BER theory %f", EsNodB, Terrs,
+                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)));
+            if ldpc_code
+                printf(" LDPC: Terrs: %d BER: %f Ferrs: %d FER: %f", 
+                       Terrsldpc, Terrsldpc/Tbitsldpc, Ferrsldpc, Ferrsldpc/(Ntrials-1));
+            end
+            printf("\n");
+        end
+        if verbose > 1
+            printf("Terrs: %d BER %f BER theory %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,
+                   Terrs/Tbits, 0.5*erfc(sqrt(EsNo/2)), var(tx_symb_log), var(noise_log),
+                   var(tx_symb_log), var(noise_log), var(tx_symb_log)/var(noise_log));
+        end
+    end
+    
+    Ebvec = Esvec - 10*log10(bps);
+
+    % account for extra power rqd for pilot symbols
+
+    if (phase_est_method == 2) && (phase_est)
+      Ebvec += 10*log10(Ns/(Ns-1));
+    end
+
+    sim_out.BERvec          = BERvec;
+    sim_out.Ebvec           = Ebvec;
+    sim_out.TERvec          = TERvec;
+    if ldpc_code
+        sim_out.BERldpcvec  = BERldpcvec;
+        sim_out.TERldpcvec  = TERldpcvec;
+        sim_out.FERldpcvec  = FERldpcvec;
+    end
+
+    if plot_scatter
+        figure(2);
+        clf;
+        scat = rx_symb_log .* exp(j*pi/4);
+        plot(real(scat(Nps*Nc:length(scat))), imag(scat(Nps*Nc:length(scat))),'+');
+        title('Scatter plot');
+
+        figure(3);
+        clf;
+        
+        y = 1:Rs*2;
+        x = 1:Nc;
+        EsNodBSurface = 20*log10(abs(hf_model(y,:))) - 10*log10(variance);
+        mesh(x,y,EsNodBSurface);
+        grid
+        %axis([1 Nc 1 Rs*2 -10 10])
+        title('HF Channel Es/No');
+
+        figure(4);
+        clf;
+        %mesh(x,y,unwrap(angle(hf_model(y,:))));
+        subplot(211)
+        plot(y,abs(hf_model(y,1)))
+        title('HF Channel Carrier 1 Mag');
+        subplot(212)
+        plot(y,angle(hf_model(y,1)))
+        title('HF Channel Carrier 1 Phase');
+
+        if phase_est
+          scat = ph_est_log(1,floor(Nps/2):Rs*2+floor(Nps/2)-1);
+          hold on;
+          plot(angle(scat),'r');
+          hold off;
+
+          figure(5)
+          clf;
+          scat = ph_est_log(1,y);
+          plot(real(scat), imag(scat),'+');
+          title('Carrier 1 Phase Est');
+          axis([-1 1 -1 1])
+        end
+if 0        
+        figure(5);
+        clf;
+        subplot(211)
+        plot(real(spread));
+        hold on;
+        plot(imag(spread),'g');     
+        hold off;   
+        subplot(212)
+        plot(real(spread_2ms));
+        hold on;
+        plot(imag(spread_2ms),'g');     
+        hold off;   
+
+        figure(6)
+        tmp = [];
+        for i = 1:hf_n-1
+            tmp = [tmp abs(hf_model(i,:))];
+        end
+        hist(tmp);
+end
+     end
+
+size(sim_out.errors_log)
+
+endfunction
+
+% Gray coded QPSK modulation function
+
+function symbol = qpsk_mod(two_bits)
+    two_bits_decimal = sum(two_bits .* [2 1]); 
+    switch(two_bits_decimal)
+        case (0) symbol =  1;
+        case (1) symbol =  j;
+        case (2) symbol = -j;
+        case (3) symbol = -1;
+    endswitch
+endfunction
+
+% Gray coded QPSK demodulation function
+
+function two_bits = qpsk_demod(symbol)
+    if isscalar(symbol) == 0
+        printf("only works with scalars\n");
+        return;
+    end
+    bit0 = real(symbol*exp(j*pi/4)) < 0;
+    bit1 = imag(symbol*exp(j*pi/4)) < 0;
+    two_bits = [bit1 bit0];
+endfunction
+
+function sim_in = standard_init
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 0;
+
+  sim_in.Esvec            = 5; 
+  sim_in.Ntrials          = 30;
+  sim_in.framesize        = 576;
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 8;
+
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+  sim_in.phase_noise_amp  = 0;
+
+  sim_in.hf_delay_ms      = 2;
+  sim_in.hf_sim           = 0;
+  sim_in.hf_phase_only    = 0;
+  sim_in.hf_mag_only      = 1;
+
+  sim_in.phase_est        = 0;
+  sim_in.phase_est_method = 1;
+  sim_in.Np               = 5;
+  sim_in.Ns               = 5;
+
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+endfunction
+
+function ideal
+
+  sim_in = standard_init();
+
+  sim_in.sim_coh_dpsk     = 0;
+  sim_in.newldpc          = 1;
+  sim_in.verbose          = 2;
+  sim_in.plot_scatter     = 1;
+
+  sim_in.Esvec            = 5; 
+  sim_in.hf_sim           = 1;
+  sim_in.Ntrials          = 30;
+
+  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');
+
+  sim_in.hf_sim           = 0;
+  sim_in.plot_scatter     = 0;
+  sim_in.Esvec            = 2:15; 
+  sim_in.ldpc_code        = 0;
+  Ebvec = sim_in.Esvec - 10*log10(2);
+  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));
+  sim_qpsk                = ber_test(sim_in, 'qpsk');
+  sim_dqpsk               = ber_test(sim_in, 'dqpsk');
+
+  sim_in.hf_sim           = 1;
+  sim_in.Esvec            = 2:15; 
+  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');
+  sim_dqpsk_hf            = ber_test(sim_in, 'dqpsk');
+  sim_in.ldpc_code        = 1;
+  sim_in.ldpc_code_rate   = 3/4;
+  sim_qpsk_hf_ldpc1       = ber_test(sim_in, 'qpsk');
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_qpsk_hf_ldpc2       = ber_test(sim_in, 'qpsk');
+  sim_in.ldpc_code_rate   = 3/4;
+  sim_in.hf_sim           = 0;
+  sim_qpsk_awgn_ldpc      = ber_test(sim_in, 'qpsk');
+
+  figure(1); 
+  clf;
+  semilogy(Ebvec, BER_theory,'r;QPSK theory;')
+  hold on;
+  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK AWGN;')
+  semilogy(sim_qpsk_hf.Ebvec, sim_qpsk_hf.BERvec,'r;QPSK HF;')
+  semilogy(sim_dqpsk.Ebvec, sim_dqpsk.BERvec,'c;DQPSK AWGN;')
+  semilogy(sim_dqpsk_hf.Ebvec, sim_dqpsk_hf.BERvec,'m;DQPSK HF;')
+  semilogy(sim_qpsk_hf_ldpc1.Ebvec, sim_qpsk_hf_ldpc1.BERldpcvec,'k;QPSK HF LDPC 3/4;')
+  semilogy(sim_qpsk_hf_ldpc2.Ebvec, sim_qpsk_hf_ldpc2.BERldpcvec,'b;QPSK HF LDPC 1/2;')
+  semilogy(sim_qpsk_awgn_ldpc.Ebvec, sim_qpsk_awgn_ldpc.BERldpcvec,'k;QPSK AWGN LDPC 3/4;')
+
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-3 1])
+endfunction
+
+function phase_noise
+  sim_in = standard_init();
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 1;
+
+  sim_in.Esvec            = 100; 
+  sim_in.Ntrials          = 100;
+
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+
+  sim_in.phase_noise_amp  = pi/16;
+  tmp                     = ber_test(sim_in, 'qpsk');
+
+  sim_in.plot_scatter     = 0;
+  sim_in.Esvec            = 2:8; 
+  sim_qpsk_hf             = ber_test(sim_in, 'qpsk');
+
+  Ebvec = sim_in.Esvec - 10*log10(2);
+  BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));
+
+  sim_in.phase_noise_amp = 0;
+  sim_qpsk               = ber_test(sim_in, 'qpsk');
+  sim_in.phase_noise_amp = pi/8;
+  sim_qpsk_pn8           = ber_test(sim_in, 'qpsk');
+  sim_in.phase_noise_amp = pi/16;
+  sim_qpsk_pn16          = ber_test(sim_in, 'qpsk');
+  sim_in.phase_noise_amp = pi/32;
+  sim_qpsk_pn32          = ber_test(sim_in, 'qpsk');
+
+  figure(1); 
+  clf;
+  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERvec,'g;QPSK phase noise 0;')
+  hold on;
+  semilogy(sim_qpsk_pn8.Ebvec, sim_qpsk_pn8.BERvec,'c;QPSK phase noise +/- pi/8;')
+  semilogy(sim_qpsk_pn16.Ebvec, sim_qpsk_pn16.BERvec,'b;QPSK phase noise +/- pi/16;')
+  semilogy(sim_qpsk_pn32.Ebvec, sim_qpsk_pn32.BERvec,'k;QPSK phase noise +/- pi/32;')
+
+  semilogy(sim_qpsk.Ebvec, sim_qpsk.BERldpcvec,'g;QPSK phase noise 0 ldpc;')
+  semilogy(sim_qpsk_pn8.Ebvec, sim_qpsk_pn8.BERldpcvec,'c;QPSK phase noise +/- pi/8 ldpc;')
+  semilogy(sim_qpsk_pn16.Ebvec, sim_qpsk_pn16.BERldpcvec,'b;QPSK phase noise +/- pi/16 ldpc;')
+  semilogy(sim_qpsk_pn32.Ebvec, sim_qpsk_pn32.BERldpcvec,'k;QPSK phase noise +/- pi/32 ldpc;')
+
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-2 1])
+endfunction
+
+function phase_est_hf
+  sim_in = standard_init();
+
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 8;
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 0;
+
+  sim_in.Esvec            = 5:15; 
+  sim_in.Ntrials          = 100;
+
+  sim_in.newldpc          = 1;
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+
+  sim_in.phase_est        = 0;
+  sim_in.sim_coh_dpsk     = 0;
+  sim_in.phase_est_method = 2;
+  sim_in.Np               = 3;
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+
+  sim_in.hf_sim           = 1;
+  sim_in.hf_mag_only      = 1;
+
+  Ebvec = sim_in.Esvec - 10*log10(2);
+
+  baseline                = ber_test(sim_in, 'qpsk');
+
+  sim_in.hf_mag_only      = 0;
+  sim_in.phase_est_method = 2;
+  sim_in.phase_est        = 1;
+  sim_in.Np               = 3;
+  pilot_3                 = ber_test(sim_in, 'qpsk');
+  sim_in.Np               = 5;
+  pilot_5                 = ber_test(sim_in, 'qpsk');
+  sim_in.Np               = 7;
+  pilot_7                 = ber_test(sim_in, 'qpsk');
+
+if 1
+  sim_in.phase_est        = 0;
+  dqpsk                   = ber_test(sim_in, 'dqpsk');
+
+  figure(1); 
+  clf;
+  semilogy(baseline.Ebvec, baseline.BERvec,'r;QPSK CCIR poor;')
+  hold on;
+  semilogy(baseline.Ebvec, baseline.BERldpcvec,'r;QPSK CCIR poor ldpc;')
+  semilogy(pilot_3.Ebvec, pilot_3.BERvec,'b;QPSK CCIR poor ldpc pilot 3;')
+  semilogy(pilot_3.Ebvec, pilot_3.BERldpcvec,'b;QPSK CCIR poor ldpc pilot 3;')
+  semilogy(pilot_5.Ebvec, pilot_5.BERvec,'g;QPSK CCIR poor ldpc pilot 5;')
+  semilogy(pilot_5.Ebvec, pilot_5.BERldpcvec,'g;QPSK CCIR poor ldpc pilot 5;')
+  semilogy(pilot_7.Ebvec, pilot_7.BERvec,'m;QPSK CCIR poor ldpc pilot 7;')
+  semilogy(pilot_7.Ebvec, pilot_7.BERldpcvec,'m;QPSK CCIR poor ldpc pilot 7;')
+  semilogy(dqpsk.Ebvec, dqpsk.BERvec,'k;DQPSK CCIR poor ldpc;')
+  semilogy(dqpsk.Ebvec, dqpsk.BERldpcvec,'k;DQPSK CCIR poor ldpc;')
+
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-2 1])
+end
+endfunction
+
+function phase_est_awgn
+  sim_in = standard_init();
+
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 8;
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 0;
+
+  sim_in.Esvec            = 0:0.5:3; 
+  sim_in.Ntrials          = 30;
+
+  sim_in.newldpc          = 1;
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+
+  sim_in.phase_est        = 0;
+  sim_in.phase_est_method = 1;
+  sim_in.Np               = 3;
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+
+  sim_in.hf_sim           = 0;
+  sim_in.hf_mag_only      = 1;
+
+  ideal                   = ber_test(sim_in, 'qpsk');
+
+  sim_in.phase_est        = 1;
+  sim_in.Np               = 21;
+  sim_in.phase_est_method = 3;
+  strip_21_mag            = ber_test(sim_in, 'qpsk');
+
+  sim_in.Np               = 41;
+  strip_41_mag            = ber_test(sim_in, 'qpsk');
+
+  sim_in.phase_est_method = 1;
+  sim_in.Np               = 21;
+  strip_21                = ber_test(sim_in, 'qpsk');
+
+  sim_in.Np               = 41;
+  strip_41                = ber_test(sim_in, 'qpsk');
+
+  sim_in.Np               = 7;
+  sim_in.phase_est_method = 2;
+  pilot_7                 = ber_test(sim_in, 'qpsk');
+
+  Ebvec = sim_in.Esvec - 10*log10(2);
+
+  figure(1); 
+  clf;
+  semilogy(ideal.Ebvec, ideal.BERvec,'r;QPSK;')
+  hold on;
+  semilogy(ideal.Ebvec, ideal.BERldpcvec,'r;QPSK LDPC;')
+  semilogy(strip_21.Ebvec, strip_21.BERvec,'g;QPSK strip 21;')
+  semilogy(strip_21.Ebvec, strip_21.BERldpcvec,'g;QPSK LDPC strip 21;')
+  semilogy(strip_41.Ebvec, strip_41.BERvec,'b;QPSK strip 41;')
+  semilogy(strip_41.Ebvec, strip_41.BERldpcvec,'b;QPSK LDPC strip 41;')
+  semilogy(strip_21_mag.Ebvec, strip_21_mag.BERvec,'m;QPSK strip 21 mag;')
+  semilogy(strip_21_mag.Ebvec, strip_21_mag.BERldpcvec,'m;QPSK LDPC strip 21 mag;')
+  semilogy(strip_41_mag.Ebvec, strip_41_mag.BERvec,'c;QPSK strip 41 mag;')
+  semilogy(strip_41_mag.Ebvec, strip_41_mag.BERldpcvec,'c;QPSK LDPC strip 41 mag;')
+  semilogy(pilot_7.Ebvec, pilot_7.BERvec,'k;QPSK pilot 7;')
+  semilogy(pilot_7.Ebvec, pilot_7.BERldpcvec,'k;QPSK LDPC pilot 7;')
+
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-2 1])
+endfunction
+
+function test_dpsk
+  sim_in = standard_init();
+
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 8;
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 0;
+
+  sim_in.Esvec            = 5; 
+  sim_in.Ntrials          = 30;
+
+  sim_in.newldpc          = 1;
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+
+  sim_in.phase_est        = 0;
+  sim_in.phase_est_method = 3;
+  sim_in.Np               = 41;
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+  sim_in.sim_coh_dpsk     = 0;
+
+  sim_in.hf_sim           = 0;
+  sim_in.hf_mag_only      = 1;
+
+  Ebvec = sim_in.Esvec - 10*log10(2);
+
+  baseline                = ber_test(sim_in, 'qpsk');
+  sim_in.phase_est        = 0;
+  dqpsk                   = ber_test(sim_in, 'dqpsk');
+
+  sim_in.phase_est        = 1;
+  sim_in.phase_est_method = 3;
+  sim_in.sim_coh_dpsk     = 1;
+  sim_in.Np               = 41;
+  dqpsk_strip_41          = ber_test(sim_in, 'dqpsk');
+  
+  figure(1); 
+  clf;
+  semilogy(baseline.Ebvec, baseline.BERvec,'r;QPSK CCIR poor;')
+  hold on;
+  semilogy(baseline.Ebvec, baseline.BERldpcvec,'r;QPSK CCIR poor ldpc;')
+  semilogy(dqpsk.Ebvec, dqpsk.BERvec,'c;DQPSK CCIR poor ldpc;')
+  semilogy(dqpsk.Ebvec, dqpsk.BERldpcvec,'c;DQPSK CCIR poor ldpc;')
+  semilogy(dqpsk_strip_41.Ebvec, dqpsk_strip_41.BERvec,'m;DQPSK CCIR poor ldpc strip 41;')
+  semilogy(dqpsk_strip_41.Ebvec, dqpsk_strip_41.BERldpcvec,'m;DQPSK CCIR poor ldpc strip 41;')
+
+  hold off;
+  xlabel('Eb/N0')
+  ylabel('BER')
+  grid("minor")
+  axis([min(Ebvec) max(Ebvec) 1E-2 1])
+
+endfunction
+
+function gen_error_pattern_qpsk()
+  sim_in = standard_init();
+
+  % model codec and uncoded streams as 1000 bit/s each
+
+  sim_in.Rs               = 100;
+  sim_in.Nc               = 4;
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 0;
+
+  sim_in.Esvec            = 10; % Eb/No=2dB
+  sim_in.Ntrials          = 30;
+
+  sim_in.newldpc          = 1;
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 1;
+
+  sim_in.phase_est        = 1;
+  sim_in.phase_est_method = 2;
+  sim_in.Np               = 5;
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+  sim_in.sim_coh_dpsk     = 0;
+
+  sim_in.hf_sim           = 1;
+  sim_in.hf_mag_only      = 0;
+
+  qpsk                    = ber_test(sim_in, 'qpsk');
+  length(qpsk.errors_log) 
+  length(qpsk.ldpc_errors_log)
+  % multiplex errors into prot and unprot halves of 52 bit codec frames
+
+  error_pattern = [];
+  for i=1:26:length(qpsk.ldpc_errors_log)-52
+    error_pattern = [error_pattern qpsk.ldpc_errors_log(i:i+25) qpsk.errors_log(i:i+25)  zeros(1,4)];
+    %error_pattern = [error_pattern qpsk.ldpc_errors_log(i:i+25) zeros(1,26)  zeros(1,4)];
+    %error_pattern = [error_pattern zeros(1,26) qpsk.errors_log(i:i+25)  zeros(1,4)];
+  end
+
+  fep=fopen("qpsk_errors_2dB.bin","wb"); fwrite(fep, error_pattern, "short"); fclose(fep);
+
+endfunction
+
+function gen_error_pattern_dpsk()
+  sim_in = standard_init();
+
+  sim_in.Rs               = 50;
+  sim_in.Nc               = 16;
+
+  sim_in.verbose          = 1;
+  sim_in.plot_scatter     = 1;
+
+  sim_in.Esvec            = 10; % Eb/No=Es/No-3
+  sim_in.Ntrials          = 30;
+
+  sim_in.newldpc          = 1;
+  sim_in.ldpc_code_rate   = 1/2;
+  sim_in.ldpc_code        = 0;
+
+  sim_in.phase_est        = 0;
+  sim_in.phase_est_method = 3;
+  sim_in.Np               = 41;
+  sim_in.phase_offset     = 0;
+  sim_in.w_offset         = 0;
+  sim_in.sim_coh_dpsk     = 0;
+
+  sim_in.hf_sim           = 1;
+  sim_in.hf_mag_only      = 1;
+
+  dqpsk                    = ber_test(sim_in, 'dqpsk');
+  fep=fopen("dqpsk_errors_12dB.bin","wb"); fwrite(fep, dqpsk.errors_log, "short"); fclose(fep);
+
+endfunction
+
+% Start simulations ---------------------------------------
+
+more off;
+
+ideal();
+%phase_est_hf();
+%phase_est_awgn();
+%test_dpsk();
+%gen_error_pattern_qpsk
index a791166d5abf40d28845a47d341ad172412e2cf4..74447a8f81da627343c8b3490ca137204938aed2 100644 (file)
@@ -1,94 +1,94 @@
-/**\r
-  ******************************************************************************\r
-  * @file    stm32f4xx_conf.h  \r
-  * @author  MCD Application Team\r
-  * @version V1.0.0\r
-  * @date    19-September-2011\r
-  * @brief   Library configuration file.\r
-  ******************************************************************************\r
-  * @attention\r
-  *\r
-  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
-  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
-  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
-  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
-  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
-  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
-  *\r
-  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>\r
-  ******************************************************************************\r
-  */ \r
-\r
-/* Define to prevent recursive inclusion -------------------------------------*/\r
-#ifndef __STM32F4xx_CONF_H\r
-#define __STM32F4xx_CONF_H\r
-\r
-#if defined  (HSE_VALUE)\r
-/* Redefine the HSE value; it's equal to 8 MHz on the STM32F4-DISCOVERY Kit */\r
- #undef HSE_VALUE\r
- #define HSE_VALUE    ((uint32_t)8000000) \r
-#endif /* HSE_VALUE */\r
-\r
-/* Includes ------------------------------------------------------------------*/\r
-/* Uncomment the line below to enable peripheral header file inclusion */\r
-#include "stm32f4xx_adc.h"\r
-#include "stm32f4xx_can.h"\r
-#include "stm32f4xx_crc.h"\r
-#include "stm32f4xx_cryp.h"\r
-#include "stm32f4xx_dac.h"\r
-#include "stm32f4xx_dbgmcu.h"\r
-#include "stm32f4xx_dcmi.h"\r
-#include "stm32f4xx_dma.h"\r
-#include "stm32f4xx_exti.h"\r
-#include "stm32f4xx_flash.h"\r
-#include "stm32f4xx_fsmc.h"\r
-#include "stm32f4xx_hash.h"\r
-#include "stm32f4xx_gpio.h"\r
-#include "stm32f4xx_i2c.h"\r
-#include "stm32f4xx_iwdg.h"\r
-#include "stm32f4xx_pwr.h"\r
-#include "stm32f4xx_rcc.h"\r
-#include "stm32f4xx_rng.h"\r
-#include "stm32f4xx_rtc.h"\r
-#include "stm32f4xx_sdio.h"\r
-#include "stm32f4xx_spi.h"\r
-#include "stm32f4xx_syscfg.h"\r
-#include "stm32f4xx_tim.h"\r
-#include "stm32f4xx_usart.h"\r
-#include "stm32f4xx_wwdg.h"\r
-#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */\r
-\r
-/* Exported types ------------------------------------------------------------*/\r
-/* Exported constants --------------------------------------------------------*/\r
-\r
-/* If an external clock source is used, then the value of the following define \r
-   should be set to the value of the external clock source, else, if no external \r
-   clock is used, keep this define commented */\r
-/*#define I2S_EXTERNAL_CLOCK_VAL   12288000 */ /* Value of the external clock in Hz */\r
-\r
-\r
-/* Uncomment the line below to expanse the "assert_param" macro in the \r
-   Standard Peripheral Library drivers code */\r
-/* #define USE_FULL_ASSERT    1 */\r
-\r
-/* Exported macro ------------------------------------------------------------*/\r
-#ifdef  USE_FULL_ASSERT\r
-\r
-/**\r
-  * @brief  The assert_param macro is used for function's parameters check.\r
-  * @param  expr: If expr is false, it calls assert_failed function\r
-  *   which reports the name of the source file and the source\r
-  *   line number of the call that failed. \r
-  *   If expr is true, it returns no value.\r
-  * @retval None\r
-  */\r
-  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))\r
-/* Exported functions ------------------------------------------------------- */\r
-  void assert_failed(uint8_t* file, uint32_t line);\r
-#else\r
-  #define assert_param(expr) ((void)0)\r
-#endif /* USE_FULL_ASSERT */\r
-\r
-#endif /* __STM32F4xx_CONF_H */\r
-\r
-/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/\r
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_conf.h  
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    19-September-2011
+  * @brief   Library configuration file.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_CONF_H
+#define __STM32F4xx_CONF_H
+
+#if defined  (HSE_VALUE)
+/* Redefine the HSE value; it's equal to 8 MHz on the STM32F4-DISCOVERY Kit */
+ #undef HSE_VALUE
+ #define HSE_VALUE    ((uint32_t)8000000) 
+#endif /* HSE_VALUE */
+
+/* Includes ------------------------------------------------------------------*/
+/* Uncomment the line below to enable peripheral header file inclusion */
+#include "stm32f4xx_adc.h"
+#include "stm32f4xx_can.h"
+#include "stm32f4xx_crc.h"
+#include "stm32f4xx_cryp.h"
+#include "stm32f4xx_dac.h"
+#include "stm32f4xx_dbgmcu.h"
+#include "stm32f4xx_dcmi.h"
+#include "stm32f4xx_dma.h"
+#include "stm32f4xx_exti.h"
+#include "stm32f4xx_flash.h"
+#include "stm32f4xx_fsmc.h"
+#include "stm32f4xx_hash.h"
+#include "stm32f4xx_gpio.h"
+#include "stm32f4xx_i2c.h"
+#include "stm32f4xx_iwdg.h"
+#include "stm32f4xx_pwr.h"
+#include "stm32f4xx_rcc.h"
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_rtc.h"
+#include "stm32f4xx_sdio.h"
+#include "stm32f4xx_spi.h"
+#include "stm32f4xx_syscfg.h"
+#include "stm32f4xx_tim.h"
+#include "stm32f4xx_usart.h"
+#include "stm32f4xx_wwdg.h"
+#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* If an external clock source is used, then the value of the following define 
+   should be set to the value of the external clock source, else, if no external 
+   clock is used, keep this define commented */
+/*#define I2S_EXTERNAL_CLOCK_VAL   12288000 */ /* Value of the external clock in Hz */
+
+
+/* Uncomment the line below to expanse the "assert_param" macro in the 
+   Standard Peripheral Library drivers code */
+/* #define USE_FULL_ASSERT    1 */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef  USE_FULL_ASSERT
+
+/**
+  * @brief  The assert_param macro is used for function's parameters check.
+  * @param  expr: If expr is false, it calls assert_failed function
+  *   which reports the name of the source file and the source
+  *   line number of the call that failed. 
+  *   If expr is true, it returns no value.
+  * @retval None
+  */
+  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+  void assert_failed(uint8_t* file, uint32_t line);
+#else
+  #define assert_param(expr) ((void)0)
+#endif /* USE_FULL_ASSERT */
+
+#endif /* __STM32F4xx_CONF_H */
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
index c31c899d9567d6d6f7412e8d2dbbff816d708ab3..4f6574bd9ef404719f977d9d7cfb65c7c9dc484b 100644 (file)
@@ -1,76 +1,76 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: adc_rec.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 30 May 2014\r
-\r
-  Records a 16 kHz sample rate raw file from one of the ADC channels,\r
-  which are connected to pins PA1 (ADC1) and PA2 (ADC2).\r
-\r
-  Note the semi-hosting system isn't fast enough to transfer 2 16 kHz\r
-  streams at once.\r
-  \r
-  ~/stlink$ sudo ./st-util -f ~/codec2-dev/stm32/adc_rec.elf\r
-  ~/codec2-dev/stm32$ ~/gcc-arm-none-eabi-4_7-2013q1/bin/arm-none-eabi-gdb adc_rec.elf\r
-  \r
-  (when finished) \r
-  $ play -r 16000 -s -2 ~/stlink/adc.raw\r
-\r
-  adc1 -> "from radio"  \r
-  adc2 -> "mic amp"\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <stdlib.h>\r
-#include "stm32f4_adc.h"\r
-#include "gdb_stdio.h"\r
-#include "stm32f4xx_gpio.h"\r
-\r
-#define REC_TIME_SECS 10\r
-#define  N  (ADC_BUF_SZ*6)\r
-#define FS  16000\r
-\r
-extern int adc_overflow1;\r
-extern int adc_overflow2;\r
-\r
-int main(void){\r
-    short  buf[N];\r
-    FILE  *fadc;\r
-    int    i, bufs;\r
-\r
-    fadc = fopen("adc.raw", "wb");\r
-    if (fadc == NULL) {\r
-        printf("Error opening input file: adc.raw\n\nTerminating....\n");\r
-        exit(1);\r
-    }\r
-    bufs = FS*REC_TIME_SECS/N;\r
-\r
-    printf("Starting!\n");\r
-    adc_open(4*N);\r
-\r
-    for(i=0; i<bufs; i++) {\r
-        while(adc2_read(buf, N) == -1);\r
-        fwrite(buf, sizeof(short), N, fadc);  \r
-        printf("adc_overflow1: %d  adc_overflow2: %d   \n", adc_overflow1, adc_overflow2);\r
-    }\r
-    fclose(fadc);\r
-\r
-    printf("Finished!\n");\r
-}\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: adc_rec.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 30 May 2014
+
+  Records a 16 kHz sample rate raw file from one of the ADC channels,
+  which are connected to pins PA1 (ADC1) and PA2 (ADC2).
+
+  Note the semi-hosting system isn't fast enough to transfer 2 16 kHz
+  streams at once.
+  
+  ~/stlink$ sudo ./st-util -f ~/codec2-dev/stm32/adc_rec.elf
+  ~/codec2-dev/stm32$ ~/gcc-arm-none-eabi-4_7-2013q1/bin/arm-none-eabi-gdb adc_rec.elf
+  
+  (when finished) 
+  $ play -r 16000 -s -2 ~/stlink/adc.raw
+
+  adc1 -> "from radio"  
+  adc2 -> "mic amp"
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "stm32f4_adc.h"
+#include "gdb_stdio.h"
+#include "stm32f4xx_gpio.h"
+
+#define REC_TIME_SECS 10
+#define  N  (ADC_BUF_SZ*6)
+#define FS  16000
+
+extern int adc_overflow1;
+extern int adc_overflow2;
+
+int main(void){
+    short  buf[N];
+    FILE  *fadc;
+    int    i, bufs;
+
+    fadc = fopen("adc.raw", "wb");
+    if (fadc == NULL) {
+        printf("Error opening input file: adc.raw\n\nTerminating....\n");
+        exit(1);
+    }
+    bufs = FS*REC_TIME_SECS/N;
+
+    printf("Starting!\n");
+    adc_open(4*N);
+
+    for(i=0; i<bufs; i++) {
+        while(adc2_read(buf, N) == -1);
+        fwrite(buf, sizeof(short), N, fadc);  
+        printf("adc_overflow1: %d  adc_overflow2: %d   \n", adc_overflow1, adc_overflow2);
+    }
+    fclose(fadc);
+
+    printf("Finished!\n");
+}
index 91414d2c4a10deca21ab638f35cdab11bc18f7e2..d812a0c7d170746de95d5f469273af5514bf57b2 100644 (file)
@@ -1,75 +1,75 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: adc_sd.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 30 May 2014\r
-\r
-  Measures the std deviation of the ADC signals.  Used to check noise\r
-  levels on each ADC.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <stdlib.h>\r
-#include <math.h>\r
-#include "stm32f4_adc.h"\r
-#include "stm32f4_dac.h"\r
-#include "gdb_stdio.h"\r
-\r
-#define REC_TIME_SECS 10\r
-#define  N  (ADC_BUF_SZ*4)\r
-#define FS  16000\r
-\r
-static float calc_sd(short x[], int n) {\r
-    float sum, mean, sum_diff, sd;\r
-    int   i;\r
-\r
-    sum = 0.0;\r
-    for(i=0; i<n;i++) {\r
-        sum += (float)x[i];\r
-    }\r
-    mean = sum/n;\r
-\r
-    sum_diff = 0.0;\r
-    for(i=0; i<n;i++) {\r
-        sum_diff += ((float)x[i] - mean)*((float)x[i] - mean);\r
-    }\r
-    \r
-    sd = sqrtf(sum_diff/n);\r
-\r
-    return sd;\r
-}\r
-\r
-int main(void){\r
-    short  buf[N];\r
-    float  sd1, sd2;\r
-\r
-    adc_open(2*N);\r
-\r
-    printf("Starting!\n");\r
-    while(1) {\r
-        while(adc1_read(buf, N) == -1);\r
-        sd1 = calc_sd(buf, N);\r
-        while(adc2_read(buf, N) == -1);\r
-        sd2 = calc_sd(buf, N);\r
-\r
-        printf("adc1: %5.1f adc2: %5.1f\n", (double)sd1, (double)sd2);\r
-    }\r
-\r
-}\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: adc_sd.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 30 May 2014
+
+  Measures the std deviation of the ADC signals.  Used to check noise
+  levels on each ADC.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <math.h>
+#include "stm32f4_adc.h"
+#include "stm32f4_dac.h"
+#include "gdb_stdio.h"
+
+#define REC_TIME_SECS 10
+#define  N  (ADC_BUF_SZ*4)
+#define FS  16000
+
+static float calc_sd(short x[], int n) {
+    float sum, mean, sum_diff, sd;
+    int   i;
+
+    sum = 0.0;
+    for(i=0; i<n;i++) {
+        sum += (float)x[i];
+    }
+    mean = sum/n;
+
+    sum_diff = 0.0;
+    for(i=0; i<n;i++) {
+        sum_diff += ((float)x[i] - mean)*((float)x[i] - mean);
+    }
+    
+    sd = sqrtf(sum_diff/n);
+
+    return sd;
+}
+
+int main(void){
+    short  buf[N];
+    float  sd1, sd2;
+
+    adc_open(2*N);
+
+    printf("Starting!\n");
+    while(1) {
+        while(adc1_read(buf, N) == -1);
+        sd1 = calc_sd(buf, N);
+        while(adc2_read(buf, N) == -1);
+        sd2 = calc_sd(buf, N);
+
+        printf("adc1: %5.1f adc2: %5.1f\n", (double)sd1, (double)sd2);
+    }
+
+}
index 2b3a1165a9ea8cdc5acd4537c0626a0d4b388cc5..da71710377bf4188fbb71cc1797f7eceb0a6d656 100644 (file)
@@ -1,90 +1,90 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: adc_sfdr_ut.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: August 2015\r
-\r
-  Unit test for high speed ADC SFDR testing.  Samples ADC1 from in PA1 at \r
-  Fs=2 MHz and write raw samples to a file, in discontinuus blocks of \r
-  ADC_TUNER_BUF_SZ/2 samples.  The blocks are discontinuous as we \r
-  don'thave the bandwitdh back to the host to support continuous sampling.\r
-\r
-  To process the blocks, fread() ADC_TUNER_BUF_SZ/2 samples at a time,\r
-  abs(fft) and sum results from next block.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2015 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include <stdlib.h>\r
-#include "gdb_stdio.h"\r
-#include "stm32f4_dac.h"\r
-#include "stm32f4_adc_tuner.h"\r
-#include "iir_tuner.h"\r
-#include "sm1000_leds_switches.h"\r
-#include "../src/codec2_fm.h"\r
-#include "stm32f4xx.h"\r
-\r
-#define BUFS          10\r
-#define FS            2E6\r
-#define N             1024\r
-\r
-extern int adc_overflow1;\r
-\r
-int main(void) {\r
-    unsigned short unsigned_buf[N];\r
-    short          buf[N];\r
-    int            sam;\r
-    int            i, j, fifo_sz;\r
-    FILE          *fadc;\r
-\r
-    fadc = fopen("adc.raw", "wb");\r
-    if (fadc == NULL) {\r
-        printf("Error opening output file: adc.raw\n\nTerminating....\n");\r
-        exit(1);\r
-    }\r
-    fifo_sz = ADC_TUNER_BUF_SZ;\r
-    printf("Starting! bufs: %d %d\n", BUFS, fifo_sz);\r
\r
-    adc_open(fifo_sz);\r
-    adc_set_tuner_en(0); /* dump raw samples, no tuner */\r
-\r
-    sm1000_leds_switches_init();\r
-\r
-    for (i=0; i<BUFS; i++) {\r
-        while(adc1_read((short*)unsigned_buf, N) == -1);\r
-\r
-        /* convert to signed */\r
-\r
-        for(j=0; j<N; j++) {\r
-            sam = (int)unsigned_buf[j] - 32768;\r
-            buf[j] = sam;\r
-        }\r
-\r
-        /* most of the time will be spent here */\r
-\r
-        GPIOE->ODR |= (1 << 3);\r
-        fwrite(buf, sizeof(short), N, fadc);\r
-        GPIOE->ODR &= ~(1 << 3);\r
-    }\r
-    fclose(fadc);\r
-\r
-    printf("Finished!\n");\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: adc_sfdr_ut.c
+  AUTHOR......: David Rowe
+  DATE CREATED: August 2015
+
+  Unit test for high speed ADC SFDR testing.  Samples ADC1 from in PA1 at 
+  Fs=2 MHz and write raw samples to a file, in discontinuus blocks of 
+  ADC_TUNER_BUF_SZ/2 samples.  The blocks are discontinuous as we 
+  don'thave the bandwitdh back to the host to support continuous sampling.
+
+  To process the blocks, fread() ADC_TUNER_BUF_SZ/2 samples at a time,
+  abs(fft) and sum results from next block.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2015 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include "gdb_stdio.h"
+#include "stm32f4_dac.h"
+#include "stm32f4_adc_tuner.h"
+#include "iir_tuner.h"
+#include "sm1000_leds_switches.h"
+#include "../src/codec2_fm.h"
+#include "stm32f4xx.h"
+
+#define BUFS          10
+#define FS            2E6
+#define N             1024
+
+extern int adc_overflow1;
+
+int main(void) {
+    unsigned short unsigned_buf[N];
+    short          buf[N];
+    int            sam;
+    int            i, j, fifo_sz;
+    FILE          *fadc;
+
+    fadc = fopen("adc.raw", "wb");
+    if (fadc == NULL) {
+        printf("Error opening output file: adc.raw\n\nTerminating....\n");
+        exit(1);
+    }
+    fifo_sz = ADC_TUNER_BUF_SZ;
+    printf("Starting! bufs: %d %d\n", BUFS, fifo_sz);
+    adc_open(fifo_sz);
+    adc_set_tuner_en(0); /* dump raw samples, no tuner */
+
+    sm1000_leds_switches_init();
+
+    for (i=0; i<BUFS; i++) {
+        while(adc1_read((short*)unsigned_buf, N) == -1);
+
+        /* convert to signed */
+
+        for(j=0; j<N; j++) {
+            sam = (int)unsigned_buf[j] - 32768;
+            buf[j] = sam;
+        }
+
+        /* most of the time will be spent here */
+
+        GPIOE->ODR |= (1 << 3);
+        fwrite(buf, sizeof(short), N, fadc);
+        GPIOE->ODR &= ~(1 << 3);
+    }
+    fclose(fadc);
+
+    printf("Finished!\n");
+}
+
index 423f45aacdc20120f9fac4aa3a979790b2e7d9a6..e79fc5a21043c8e98dee679b2ce3296fae328e08 100644 (file)
@@ -1,70 +1,70 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: adcdac_ut.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: May 31 201310 Aug 2014\r
-\r
-  Echoes ADC2 input (mic) to DAC2 output (speaker) on SM1000.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2013 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include "stm32f4_dac.h"\r
-#include "stm32f4_adc.h"\r
-#include "sm1000_leds_switches.h"\r
-\r
-#define SINE_SAMPLES   32\r
-\r
-\r
-/* 32 sample sine wave which at Fs=16kHz will be 500Hz.  Note samples\r
-   are 16 bit 2's complement, the DAC driver convertsto 12 bit\r
-   unsigned. */\r
-\r
-short aSine[] = {\r
-     -16,    6384,   12528,   18192,   23200,   27232,   30256,   32128,\r
-   32752,   32128,   30256,   27232,   23152,   18192,   12528,    6384,\r
-     -16,   -6416,  -12560,  -18224,  -23184,  -27264,  -30288,  -32160,\r
-  -32768,  -32160,  -30288,  -27264,  -23184,  -18224,  -12560,   -6416\r
-};\r
-\r
-int main(void) {\r
-    short buf[SINE_SAMPLES];\r
-    int   i;\r
-\r
-    dac_open(4*DAC_BUF_SZ);\r
-    adc_open(4*ADC_BUF_SZ);\r
-    sm1000_leds_switches_init();\r
-\r
-    while (1) {\r
-\r
-        /* keep DAC FIFOs topped up */\r
-\r
-        while(adc2_read(buf, SINE_SAMPLES) == -1);\r
-        \r
-        if (!switch_select()) {\r
-            for(i=0; i<SINE_SAMPLES; i++)\r
-                buf[i] = aSine[i];\r
-        }\r
-            \r
-        dac2_write(buf, SINE_SAMPLES);\r
-    }\r
-   \r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: adcdac_ut.c
+  AUTHOR......: David Rowe
+  DATE CREATED: May 31 201310 Aug 2014
+
+  Echoes ADC2 input (mic) to DAC2 output (speaker) on SM1000.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2013 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include "stm32f4_dac.h"
+#include "stm32f4_adc.h"
+#include "sm1000_leds_switches.h"
+
+#define SINE_SAMPLES   32
+
+
+/* 32 sample sine wave which at Fs=16kHz will be 500Hz.  Note samples
+   are 16 bit 2's complement, the DAC driver convertsto 12 bit
+   unsigned. */
+
+short aSine[] = {
+     -16,    6384,   12528,   18192,   23200,   27232,   30256,   32128,
+   32752,   32128,   30256,   27232,   23152,   18192,   12528,    6384,
+     -16,   -6416,  -12560,  -18224,  -23184,  -27264,  -30288,  -32160,
+  -32768,  -32160,  -30288,  -27264,  -23184,  -18224,  -12560,   -6416
+};
+
+int main(void) {
+    short buf[SINE_SAMPLES];
+    int   i;
+
+    dac_open(4*DAC_BUF_SZ);
+    adc_open(4*ADC_BUF_SZ);
+    sm1000_leds_switches_init();
+
+    while (1) {
+
+        /* keep DAC FIFOs topped up */
+
+        while(adc2_read(buf, SINE_SAMPLES) == -1);
+        
+        if (!switch_select()) {
+            for(i=0; i<SINE_SAMPLES; i++)
+                buf[i] = aSine[i];
+        }
+            
+        dac2_write(buf, SINE_SAMPLES);
+    }
+   
+}
+
index c8c6e0ef29810a805161fb603af384178aa58190..f32b6e0e9b56aae7ac4495adee1b8752a75976bf 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: codec2_profile.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 30 May 2013\r
-\r
-  Profiling Codec 2 operation on the STM32F4.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdint.h>\r
-#include <math.h>\r
-\r
-#include "stm32f4xx_conf.h"\r
-#include "stm32f4xx.h"\r
-#include "gdb_stdio.h"\r
-#include "codec2.h"\r
-#include "dump.h"\r
-#include "sine.h"\r
-#include "machdep.h"\r
-\r
-#ifdef __EMBEDDED__\r
-#define printf gdb_stdio_printf\r
-#define fopen gdb_stdio_fopen\r
-#define fclose gdb_stdio_fclose\r
-#define fread gdb_stdio_fread\r
-#define fwrite gdb_stdio_fwrite\r
-#endif\r
-\r
-static void c2demo(int mode, char inputfile[], char outputfile[])\r
-{\r
-    struct CODEC2 *codec2;\r
-    short         *inbuf, *outbuf;\r
-    unsigned char *bits;\r
-    int            nsam, nbit;\r
-    FILE          *fin, *fout;\r
-    int            frame;\r
-    PROFILE_VAR(enc_start, dec_start);\r
-\r
-    codec2 = codec2_create(mode);\r
-    nsam = codec2_samples_per_frame(codec2);\r
-    outbuf = (short*)malloc(nsam*sizeof(short));\r
-    inbuf = (short*)malloc(nsam*sizeof(short));\r
-    nbit = codec2_bits_per_frame(codec2);\r
-    bits = (unsigned char*)malloc(nbit*sizeof(char));\r
-\r
-    fin = fopen(inputfile, "rb");\r
-    if (fin == NULL) {\r
-        printf("Error opening input file: %s\n\nTerminating....\n",inputfile);\r
-        exit(1);\r
-    }\r
-\r
-    fout = fopen(outputfile, "wb");\r
-    if (fout == NULL) {\r
-        printf("Error opening output file: %s\n\nTerminating....\n",outputfile);\r
-        exit(1);\r
-    }\r
-\r
-    #ifdef DUMP\r
-    dump_on("stm32f4");\r
-    #endif\r
-    frame = 0;\r
-\r
-    while (fread(inbuf, sizeof(short), nsam, fin) == nsam) {\r
-        PROFILE_SAMPLE(enc_start);\r
-        codec2_encode(codec2, bits, inbuf);\r
-        PROFILE_SAMPLE_AND_LOG(dec_start, enc_start, "  enc");     \r
-       codec2_decode(codec2, outbuf, bits);\r
-        PROFILE_SAMPLE_AND_LOG2(dec_start, "  dec");     \r
-        PROFILE_SAMPLE_AND_LOG2(enc_start, "  enc & dec");     \r
-        fwrite((char*)outbuf, sizeof(short), nsam, fout);\r
-        printf("frame: %d\n", ++frame);\r
-        machdep_profile_print_logged_samples();\r
-    }\r
-\r
-    #ifdef DUMP\r
-    dump_off("sm32f4");\r
-    #endif\r
-\r
-    fclose(fin);\r
-    fclose(fout);\r
-    free(inbuf);\r
-    free(outbuf);\r
-    free(bits);\r
-    codec2_destroy(codec2);\r
-}\r
-\r
-#define SPEED_TEST_SAMPLES 24000\r
-\r
-static void c2speedtest(int mode, char inputfile[])\r
-{\r
-    struct CODEC2 *codec2;\r
-    short         *inbuf, *outbuf, *pinbuf;\r
-    unsigned char *bits;\r
-    int            nsam, nbit, nframes;\r
-    FILE          *fin;\r
-    int            f, nread;\r
-\r
-    codec2 = codec2_create(mode);\r
-    nsam = codec2_samples_per_frame(codec2);\r
-    nframes = SPEED_TEST_SAMPLES/nsam;\r
-    outbuf = (short*)malloc(nsam*sizeof(short));\r
-    inbuf = (short*)malloc(SPEED_TEST_SAMPLES*sizeof(short));\r
-    nbit = codec2_bits_per_frame(codec2);\r
-    bits = (unsigned char*)malloc(nbit*sizeof(char));\r
-\r
-    fin = fopen(inputfile, "rb");\r
-    if (fin == NULL) {\r
-        printf("Error opening input file: %s\nTerminating....\n",inputfile);\r
-        exit(1);\r
-    }\r
-\r
-    nread = fread(inbuf, sizeof(short), SPEED_TEST_SAMPLES, fin);\r
-    if (nread != SPEED_TEST_SAMPLES) {\r
-        printf("error reading %s, %d samples reqd, %d read\n", \r
-               inputfile, SPEED_TEST_SAMPLES, nread);\r
-    }\r
-    fclose(fin);\r
-    \r
-    pinbuf = inbuf;\r
-    for(f=0; f<nframes; f++) {\r
-       GPIOD->ODR = (1 << 13);\r
-        codec2_encode(codec2, bits, pinbuf);\r
-        pinbuf += nsam;\r
-       GPIOD->ODR &= ~(1 << 13);\r
-       codec2_decode(codec2, outbuf, bits);\r
-    }\r
-\r
-    free(inbuf);\r
-    free(outbuf);\r
-    free(bits);\r
-    codec2_destroy(codec2);\r
-}\r
-\r
-void gpio_init() {\r
-    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // enable the clock to GPIOD \r
-    GPIOD->MODER = (1 << 26);            // set pin 13 to be general \r
-                                         // purpose output\r
-}\r
-\r
-int main(int argc, char *argv[]) {\r
-    gpio_init();\r
-    machdep_profile_init ();\r
\r
-    printf("Starting c2demo\n");\r
-\r
-    /* File I/O test for profiling or (with #define DUMP)\r
-       dumping states for optimisation and tiuning */\r
-\r
-    c2demo(CODEC2_MODE_1600, "stm_in.raw", "stm_out.raw");\r
-\r
-    printf("Starting c2 speed test\n");\r
-    \r
-    /* Another test of execution speed. Look at PD13 with a\r
-       oscilliscope.  On time is enc, off is dec */\r
-\r
-    c2speedtest(CODEC2_MODE_1600, "stm_in.raw");\r
-\r
-    printf("Finished\n");\r
-\r
-    return 0;\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: codec2_profile.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 30 May 2013
+
+  Profiling Codec 2 operation on the STM32F4.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include "stm32f4xx_conf.h"
+#include "stm32f4xx.h"
+#include "gdb_stdio.h"
+#include "codec2.h"
+#include "dump.h"
+#include "sine.h"
+#include "machdep.h"
+
+#ifdef __EMBEDDED__
+#define printf gdb_stdio_printf
+#define fopen gdb_stdio_fopen
+#define fclose gdb_stdio_fclose
+#define fread gdb_stdio_fread
+#define fwrite gdb_stdio_fwrite
+#endif
+
+static void c2demo(int mode, char inputfile[], char outputfile[])
+{
+    struct CODEC2 *codec2;
+    short         *inbuf, *outbuf;
+    unsigned char *bits;
+    int            nsam, nbit;
+    FILE          *fin, *fout;
+    int            frame;
+    PROFILE_VAR(enc_start, dec_start);
+
+    codec2 = codec2_create(mode);
+    nsam = codec2_samples_per_frame(codec2);
+    outbuf = (short*)malloc(nsam*sizeof(short));
+    inbuf = (short*)malloc(nsam*sizeof(short));
+    nbit = codec2_bits_per_frame(codec2);
+    bits = (unsigned char*)malloc(nbit*sizeof(char));
+
+    fin = fopen(inputfile, "rb");
+    if (fin == NULL) {
+        printf("Error opening input file: %s\n\nTerminating....\n",inputfile);
+        exit(1);
+    }
+
+    fout = fopen(outputfile, "wb");
+    if (fout == NULL) {
+        printf("Error opening output file: %s\n\nTerminating....\n",outputfile);
+        exit(1);
+    }
+
+    #ifdef DUMP
+    dump_on("stm32f4");
+    #endif
+    frame = 0;
+
+    while (fread(inbuf, sizeof(short), nsam, fin) == nsam) {
+        PROFILE_SAMPLE(enc_start);
+        codec2_encode(codec2, bits, inbuf);
+        PROFILE_SAMPLE_AND_LOG(dec_start, enc_start, "  enc");     
+       codec2_decode(codec2, outbuf, bits);
+        PROFILE_SAMPLE_AND_LOG2(dec_start, "  dec");     
+        PROFILE_SAMPLE_AND_LOG2(enc_start, "  enc & dec");     
+        fwrite((char*)outbuf, sizeof(short), nsam, fout);
+        printf("frame: %d\n", ++frame);
+        machdep_profile_print_logged_samples();
+    }
+
+    #ifdef DUMP
+    dump_off("sm32f4");
+    #endif
+
+    fclose(fin);
+    fclose(fout);
+    free(inbuf);
+    free(outbuf);
+    free(bits);
+    codec2_destroy(codec2);
+}
+
+#define SPEED_TEST_SAMPLES 24000
+
+static void c2speedtest(int mode, char inputfile[])
+{
+    struct CODEC2 *codec2;
+    short         *inbuf, *outbuf, *pinbuf;
+    unsigned char *bits;
+    int            nsam, nbit, nframes;
+    FILE          *fin;
+    int            f, nread;
+
+    codec2 = codec2_create(mode);
+    nsam = codec2_samples_per_frame(codec2);
+    nframes = SPEED_TEST_SAMPLES/nsam;
+    outbuf = (short*)malloc(nsam*sizeof(short));
+    inbuf = (short*)malloc(SPEED_TEST_SAMPLES*sizeof(short));
+    nbit = codec2_bits_per_frame(codec2);
+    bits = (unsigned char*)malloc(nbit*sizeof(char));
+
+    fin = fopen(inputfile, "rb");
+    if (fin == NULL) {
+        printf("Error opening input file: %s\nTerminating....\n",inputfile);
+        exit(1);
+    }
+
+    nread = fread(inbuf, sizeof(short), SPEED_TEST_SAMPLES, fin);
+    if (nread != SPEED_TEST_SAMPLES) {
+        printf("error reading %s, %d samples reqd, %d read\n", 
+               inputfile, SPEED_TEST_SAMPLES, nread);
+    }
+    fclose(fin);
+    
+    pinbuf = inbuf;
+    for(f=0; f<nframes; f++) {
+       GPIOD->ODR = (1 << 13);
+        codec2_encode(codec2, bits, pinbuf);
+        pinbuf += nsam;
+       GPIOD->ODR &= ~(1 << 13);
+       codec2_decode(codec2, outbuf, bits);
+    }
+
+    free(inbuf);
+    free(outbuf);
+    free(bits);
+    codec2_destroy(codec2);
+}
+
+void gpio_init() {
+    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // enable the clock to GPIOD 
+    GPIOD->MODER = (1 << 26);            // set pin 13 to be general 
+                                         // purpose output
+}
+
+int main(int argc, char *argv[]) {
+    gpio_init();
+    machdep_profile_init ();
+    printf("Starting c2demo\n");
+
+    /* File I/O test for profiling or (with #define DUMP)
+       dumping states for optimisation and tiuning */
+
+    c2demo(CODEC2_MODE_1600, "stm_in.raw", "stm_out.raw");
+
+    printf("Starting c2 speed test\n");
+    
+    /* Another test of execution speed. Look at PD13 with a
+       oscilliscope.  On time is enc, off is dec */
+
+    c2speedtest(CODEC2_MODE_1600, "stm_in.raw");
+
+    printf("Finished\n");
+
+    return 0;
+}
+
index 2b614fc4cd8c963685c6efda50aafbf68e8ab4c6..8380375264842165a3ed72f66014e6da3251b12a 100644 (file)
-/**\r
-  ******************************************************************************\r
-  * @file    DMA/DMA_FLASHToRAM/stm32f4xx_it.c \r
-  * @author  MCD Application Team\r
-  * @version V1.1.0\r
-  * @date    18-January-2013\r
-  * @brief   Main Interrupt Service Routines.\r
-  *          This file provides template for all exceptions handler and \r
-  *          peripherals interrupt service routine.\r
-  ******************************************************************************\r
-  * @attention\r
-  *\r
-  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>\r
-  *\r
-  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");\r
-  * You may not use this file except in compliance with the License.\r
-  * You may obtain a copy of the License at:\r
-  *\r
-  *        http://www.st.com/software_license_agreement_liberty_v2\r
-  *\r
-  * Unless required by applicable law or agreed to in writing, software \r
-  * distributed under the License is distributed on an "AS IS" BASIS, \r
-  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-  * See the License for the specific language governing permissions and\r
-  * limitations under the License.\r
-  *\r
-  ******************************************************************************\r
-  */\r
-int interrupts;\r
-\r
-\r
-/* Includes ------------------------------------------------------------------*/\r
-#include "dac_it.h"\r
-\r
-/** @addtogroup STM32F4xx_StdPeriph_Examples\r
-  * @{\r
-  */\r
-\r
-/** @addtogroup DMA_FLASHToRAM\r
-  * @{\r
-  */  \r
-\r
-/* Private typedef -----------------------------------------------------------*/\r
-/* Private define ------------------------------------------------------------*/\r
-/* Private macro -------------------------------------------------------------*/\r
-/* Private variables ---------------------------------------------------------*/\r
-/* Private function prototypes -----------------------------------------------*/\r
-/* Private functions ---------------------------------------------------------*/\r
-\r
-/******************************************************************************/\r
-/*            Cortex-M4 Processor Exceptions Handlers                         */\r
-/******************************************************************************/\r
-\r
-/**\r
-  * @brief   This function handles NMI exception.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void NMI_Handler(void)\r
-{\r
-}\r
-\r
-/**\r
-  * @brief  This function handles Hard Fault exception.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void HardFault_Handler(void)\r
-{\r
-  /* Go to infinite loop when Hard Fault exception occurs */\r
-  while (1)\r
-  {\r
-  }\r
-}\r
-\r
-/**\r
-  * @brief  This function handles Memory Manage exception.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void MemManage_Handler(void)\r
-{\r
-  /* Go to infinite loop when Memory Manage exception occurs */\r
-  while (1)\r
-  {\r
-  }\r
-}\r
-\r
-/**\r
-  * @brief  This function handles Bus Fault exception.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void BusFault_Handler(void)\r
-{\r
-  /* Go to infinite loop when Bus Fault exception occurs */\r
-  while (1)\r
-  {\r
-  }\r
-}\r
-\r
-/**\r
-  * @brief  This function handles Usage Fault exception.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void UsageFault_Handler(void)\r
-{\r
-  /* Go to infinite loop when Usage Fault exception occurs */\r
-  while (1)\r
-  {\r
-  }\r
-}\r
-\r
-/**\r
-  * @brief  This function handles SVCall exception.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void SVC_Handler(void)\r
-{\r
-}\r
-\r
-/**\r
-  * @brief  This function handles Debug Monitor exception.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void DebugMon_Handler(void)\r
-{\r
-}\r
-\r
-/**\r
-  * @brief  This function handles PendSVC exception.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void PendSV_Handler(void)\r
-{\r
-}\r
-\r
-/**\r
-  * @brief  This function handles SysTick Handler.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void SysTick_Handler(void)\r
-{\r
-}\r
-\r
-/******************************************************************************/\r
-/*                 STM32F4xx Peripherals Interrupt Handlers                   */\r
-/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */\r
-/*  available peripheral interrupt handler's name please refer to the startup */\r
-/*  file (startup_stm32f40xx.s/startup_stm32f427x.s).                         */\r
-/******************************************************************************/\r
-\r
-/**\r
-  * @brief  This function handles DMA Stream interrupt request.\r
-  * @param  None\r
-  * @retval None\r
-  */\r
-void DMA1_Stream6_IRQHandler(void)\r
-{\r
-\r
-  /* Transfer half empty interrupt */\r
-\r
-  if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_HTIF6) != RESET))\r
-  {\r
-      /* fill first half from fifo */\r
-\r
-      fifo_read(DMA1_Stream6_fifo, dac_buf, DAC_BUF_SZ/2);\r
-\r
-      /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
-      DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_HTIF6);  \r
-\r
-      interrupts++;\r
-  }\r
-\r
-  /* Transfer complete interrupt */\r
-\r
-  if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) != RESET))\r
-  {\r
-      /* fill second half from fifo */\r
-\r
-      fifo_read(DMA1_Stream6_fifo, &dac_buf[DAC_BUF_SZ/2], DAC_BUF_SZ/2);\r
-\r
-      /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
-      DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);  \r
-\r
-      interrupts++;\r
-  }\r
-}\r
-\r
-/**\r
-  * @}\r
-  */ \r
-\r
-/**\r
-  * @}\r
-  */\r
-\r
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/\r
+/**
+  ******************************************************************************
+  * @file    DMA/DMA_FLASHToRAM/stm32f4xx_it.c 
+  * @author  MCD Application Team
+  * @version V1.1.0
+  * @date    18-January-2013
+  * @brief   Main Interrupt Service Routines.
+  *          This file provides template for all exceptions handler and 
+  *          peripherals interrupt service routine.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+int interrupts;
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "dac_it.h"
+
+/** @addtogroup STM32F4xx_StdPeriph_Examples
+  * @{
+  */
+
+/** @addtogroup DMA_FLASHToRAM
+  * @{
+  */  
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/******************************************************************************/
+/*            Cortex-M4 Processor Exceptions Handlers                         */
+/******************************************************************************/
+
+/**
+  * @brief   This function handles NMI exception.
+  * @param  None
+  * @retval None
+  */
+void NMI_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles Hard Fault exception.
+  * @param  None
+  * @retval None
+  */
+void HardFault_Handler(void)
+{
+  /* Go to infinite loop when Hard Fault exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles Memory Manage exception.
+  * @param  None
+  * @retval None
+  */
+void MemManage_Handler(void)
+{
+  /* Go to infinite loop when Memory Manage exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles Bus Fault exception.
+  * @param  None
+  * @retval None
+  */
+void BusFault_Handler(void)
+{
+  /* Go to infinite loop when Bus Fault exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles Usage Fault exception.
+  * @param  None
+  * @retval None
+  */
+void UsageFault_Handler(void)
+{
+  /* Go to infinite loop when Usage Fault exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles SVCall exception.
+  * @param  None
+  * @retval None
+  */
+void SVC_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles Debug Monitor exception.
+  * @param  None
+  * @retval None
+  */
+void DebugMon_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles PendSVC exception.
+  * @param  None
+  * @retval None
+  */
+void PendSV_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles SysTick Handler.
+  * @param  None
+  * @retval None
+  */
+void SysTick_Handler(void)
+{
+}
+
+/******************************************************************************/
+/*                 STM32F4xx Peripherals Interrupt Handlers                   */
+/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
+/*  available peripheral interrupt handler's name please refer to the startup */
+/*  file (startup_stm32f40xx.s/startup_stm32f427x.s).                         */
+/******************************************************************************/
+
+/**
+  * @brief  This function handles DMA Stream interrupt request.
+  * @param  None
+  * @retval None
+  */
+void DMA1_Stream6_IRQHandler(void)
+{
+
+  /* Transfer half empty interrupt */
+
+  if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_HTIF6) != RESET))
+  {
+      /* fill first half from fifo */
+
+      fifo_read(DMA1_Stream6_fifo, dac_buf, DAC_BUF_SZ/2);
+
+      /* Clear DMA Stream Transfer Complete interrupt pending bit */
+
+      DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_HTIF6);  
+
+      interrupts++;
+  }
+
+  /* Transfer complete interrupt */
+
+  if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) != RESET))
+  {
+      /* fill second half from fifo */
+
+      fifo_read(DMA1_Stream6_fifo, &dac_buf[DAC_BUF_SZ/2], DAC_BUF_SZ/2);
+
+      /* Clear DMA Stream Transfer Complete interrupt pending bit */
+
+      DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);  
+
+      interrupts++;
+  }
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
index 96777ebb9d5ccef1e8373ea3be21f4005828a0ed..644c6859354780f38e927623990185669ec04c22 100644 (file)
@@ -1,63 +1,63 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: dac_play.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 1 June 2013\r
-\r
-  Plays a 16 kHz sample rate raw file to the STM32F4 DACs. DAC1 is\r
-  connected to pin PA4, DAC2 is connected to pin PA5.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2013 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <stdlib.h>\r
-#include "stm32f4_dac.h"\r
-#include "gdb_stdio.h"\r
-\r
-#define N    (5*DAC_BUF_SZ)\r
-\r
-int main(void) {\r
-    short  buf[N];\r
-    FILE  *fplay;\r
-\r
-    dac_open(2*N);\r
-\r
-    while(1) {\r
-        fplay = fopen("stm_in.raw", "rb");\r
-        if (fplay == NULL) {\r
-            printf("Error opening input file: stm_in.raw\n\nTerminating....\n");\r
-            exit(1);\r
-        }\r
-    \r
-        printf("Starting!\n");\r
-\r
-        while(fread(buf, sizeof(short), N, fplay) == N) {\r
-            while(dac1_write(buf, N) == -1);\r
-            while(dac2_write(buf, N) == -1);\r
-        }  \r
-\r
-        printf("Finished!\n");\r
-        fclose(fplay);\r
-    }\r
-\r
-    /* let FIFO empty */\r
-\r
-    while(1);\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: dac_play.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 1 June 2013
+
+  Plays a 16 kHz sample rate raw file to the STM32F4 DACs. DAC1 is
+  connected to pin PA4, DAC2 is connected to pin PA5.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2013 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "stm32f4_dac.h"
+#include "gdb_stdio.h"
+
+#define N    (5*DAC_BUF_SZ)
+
+int main(void) {
+    short  buf[N];
+    FILE  *fplay;
+
+    dac_open(2*N);
+
+    while(1) {
+        fplay = fopen("stm_in.raw", "rb");
+        if (fplay == NULL) {
+            printf("Error opening input file: stm_in.raw\n\nTerminating....\n");
+            exit(1);
+        }
+    
+        printf("Starting!\n");
+
+        while(fread(buf, sizeof(short), N, fplay) == N) {
+            while(dac1_write(buf, N) == -1);
+            while(dac2_write(buf, N) == -1);
+        }  
+
+        printf("Finished!\n");
+        fclose(fplay);
+    }
+
+    /* let FIFO empty */
+
+    while(1);
+}
+
index bfe9def1417a3770df8cc897c813d2be550c9f91..b660f0cad30dab526f658e39c1552234f9f4f73e 100644 (file)
@@ -1,59 +1,59 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: dac_ut.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: May 31 2013\r
-\r
-  Plays a 500 Hz sine wave sampled at 16 kHz out of PA5 on a Discovery board,\r
-  or the speaker output of the SM1000.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2013 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include "stm32f4_dac.h"\r
-\r
-#define SINE_SAMPLES   32\r
-\r
-\r
-/* 32 sample sine wave which at Fs=16kHz will be 500Hz.  Note samples\r
-   are 16 bit 2's complement, the DAC driver convertsto 12 bit\r
-   unsigned. */\r
-\r
-short aSine[] = {\r
-     -16,    6384,   12528,   18192,   23200,   27232,   30256,   32128,\r
-   32752,   32128,   30256,   27232,   23152,   18192,   12528,    6384,\r
-     -16,   -6416,  -12560,  -18224,  -23184,  -27264,  -30288,  -32160,\r
-  -32768,  -32160,  -30288,  -27264,  -23184,  -18224,  -12560,   -6416\r
-};\r
-\r
-int main(void) {\r
-\r
-    dac_open(4*DAC_BUF_SZ);\r
-\r
-    while (1) {\r
-\r
-        /* keep DAC FIFOs topped up */\r
-\r
-        dac1_write((short*)aSine, SINE_SAMPLES);\r
-        dac2_write((short*)aSine, SINE_SAMPLES);\r
-    }\r
-   \r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: dac_ut.c
+  AUTHOR......: David Rowe
+  DATE CREATED: May 31 2013
+
+  Plays a 500 Hz sine wave sampled at 16 kHz out of PA5 on a Discovery board,
+  or the speaker output of the SM1000.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2013 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include "stm32f4_dac.h"
+
+#define SINE_SAMPLES   32
+
+
+/* 32 sample sine wave which at Fs=16kHz will be 500Hz.  Note samples
+   are 16 bit 2's complement, the DAC driver convertsto 12 bit
+   unsigned. */
+
+short aSine[] = {
+     -16,    6384,   12528,   18192,   23200,   27232,   30256,   32128,
+   32752,   32128,   30256,   27232,   23152,   18192,   12528,    6384,
+     -16,   -6416,  -12560,  -18224,  -23184,  -27264,  -30288,  -32160,
+  -32768,  -32160,  -30288,  -27264,  -23184,  -18224,  -12560,   -6416
+};
+
+int main(void) {
+
+    dac_open(4*DAC_BUF_SZ);
+
+    while (1) {
+
+        /* keep DAC FIFOs topped up */
+
+        dac1_write((short*)aSine, SINE_SAMPLES);
+        dac2_write((short*)aSine, SINE_SAMPLES);
+    }
+   
+}
+
index 7e38fd170b2f7a33fc63ba702ca290bbbe50c866..2c694fdff2985c5da7764820baa516b84a4d2682 100644 (file)
@@ -1,45 +1,45 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: debugblinky.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 12 August 2014\r
-\r
-  Configures GPIO pins used for debug blinkies\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include "stm32f4xx.h"\r
-\r
-void init_debug_blinky(void) {\r
-    GPIO_InitTypeDef GPIO_InitStruct;\r
-\r
-    /* PE0-3 used to indicate activity */\r
-\r
-    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);\r
-\r
-    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;\r
-    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;                 \r
-    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;     \r
-    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;         \r
-    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;      \r
-    GPIO_Init(GPIOE, &GPIO_InitStruct);                \r
-\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: debugblinky.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 12 August 2014
+
+  Configures GPIO pins used for debug blinkies
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stm32f4xx.h"
+
+void init_debug_blinky(void) {
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    /* PE0-3 used to indicate activity */
+
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
+
+    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
+    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;                 
+    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;     
+    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;         
+    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;      
+    GPIO_Init(GPIOE, &GPIO_InitStruct);                
+
+}
+
index faa8865cdab7aac5d59c9816eb21f32d54ce330e..7678a3d9776c824df09ed4575b67be819d097458 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: dac_ut.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: May 31 2013\r
-\r
-  Plays a 500 Hz sine wave sampled at 16 kHz out of PA5 on a Discovery board,\r
-  or the speaker output of the SM1000.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2013 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include <stdlib.h>\r
-#include "stm32f4_dacduc.h"\r
-#include "iir_duc.h"\r
-#include "stm32f4xx.h"\r
-#include <stm32f4xx_tim.h>\r
-#include <stm32f4xx_rcc.h>\r
-#include "gdb_stdio.h"\r
-#include "comp.h"\r
-//#include "gmsk_test_dat_m4.h"\r
-#define SINE_SAMPLES  32\r
-\r
-\r
-/* 32 sample sine wave which at Fs=16kHz will be 500Hz.  Note samples\r
-   are 16 bit 2's complement, the DAC driver convertsto 12 bit\r
-   unsigned. */\r
-   \r
-short aWave[] = {4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,\r
-       4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,};\r
-\r
-short aSine[] = {1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1600, 0, 1600, 3200, 1601, 0\r
-};\r
-\r
-//Sine at Fs/4\r
-float f4sine[] = {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,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,\r
-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,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,\r
-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,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,\r
-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,1,0,-1,0,};\r
-\r
-//Intermediate 80k real before tx\r
-int tx_imm[DUC_N];\r
-\r
-//Complex input to chain\r
-COMP comp_in[DUC_N/10];\r
-\r
-unsigned short outbuf[DAC_DUC_BUF_SZ];\r
-\r
-void setup_timer()\r
-{\r
-    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);\r
-\r
-    TIM_TimeBaseInitTypeDef timerInitStructure; \r
-    timerInitStructure.TIM_Prescaler = 84;\r
-    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;\r
-    timerInitStructure.TIM_Period = 0x8FFFFFFF;\r
-    timerInitStructure.TIM_ClockDivision = 0;\r
-    timerInitStructure.TIM_RepetitionCounter = 0;\r
-    TIM_TimeBaseInit(TIM2, &timerInitStructure);\r
-    TIM_Cmd(TIM2, ENABLE);\r
-}\r
-\r
-int main(void) {\r
-    int tstart,tup,tend,cyc,i;\r
-\r
-    memset((void*)outbuf,0,sizeof(short)*DAC_DUC_BUF_SZ);\r
-    setup_timer();\r
-    fast_dac_open(2*DAC_DUC_BUF_SZ,2*DAC_BUF_SZ);\r
-    tstart=tend=tup=cyc=0;\r
-    //Initalize complex input with signal at zero\r
-    for(i=0;i<DUC_48N;i++){\r
-        comp_in[i].real=1;\r
-        comp_in[i].imag=0;\r
-    }\r
-    while (1) {\r
-       cyc++;\r
-        //if(cyc>GMSK_TEST_LEN)\r
-        //    cyc=0;\r
-       if(cyc%10000==0){\r
-                printf("48c80r takes %d uSecs\n",tup-tstart);\r
-               printf("iir upconvert takes %d uSecs\n",tend-tup);\r
-       }\r
-        tstart = TIM_GetCounter(TIM2);\r
-\r
-        upconv_48c_80r(comp_in,tx_imm,1);\r
-\r
-       tup = TIM_GetCounter(TIM2);\r
-\r
-       iir_upconv_fixp(tx_imm,outbuf);\r
-\r
-       tend = TIM_GetCounter(TIM2);\r
-\r
-        //Sit and spin until we can get more samples into the dac \r
-       while(dac1_write((short*)outbuf,DAC_DUC_BUF_SZ)<0);\r
-    }\r
-   \r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: dac_ut.c
+  AUTHOR......: David Rowe
+  DATE CREATED: May 31 2013
+
+  Plays a 500 Hz sine wave sampled at 16 kHz out of PA5 on a Discovery board,
+  or the speaker output of the SM1000.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2013 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include "stm32f4_dacduc.h"
+#include "iir_duc.h"
+#include "stm32f4xx.h"
+#include <stm32f4xx_tim.h>
+#include <stm32f4xx_rcc.h>
+#include "gdb_stdio.h"
+#include "comp.h"
+//#include "gmsk_test_dat_m4.h"
+#define SINE_SAMPLES  32
+
+
+/* 32 sample sine wave which at Fs=16kHz will be 500Hz.  Note samples
+   are 16 bit 2's complement, the DAC driver convertsto 12 bit
+   unsigned. */
+   
+short aWave[] = {4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,
+       4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,};
+
+short aSine[] = {1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1600, 0, 1600, 3200, 1601, 0
+};
+
+//Sine at Fs/4
+float f4sine[] = {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,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,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,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,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,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,1,0,-1,0,1,0,-1,0,};
+
+//Intermediate 80k real before tx
+int tx_imm[DUC_N];
+
+//Complex input to chain
+COMP comp_in[DUC_N/10];
+
+unsigned short outbuf[DAC_DUC_BUF_SZ];
+
+void setup_timer()
+{
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
+
+    TIM_TimeBaseInitTypeDef timerInitStructure; 
+    timerInitStructure.TIM_Prescaler = 84;
+    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
+    timerInitStructure.TIM_Period = 0x8FFFFFFF;
+    timerInitStructure.TIM_ClockDivision = 0;
+    timerInitStructure.TIM_RepetitionCounter = 0;
+    TIM_TimeBaseInit(TIM2, &timerInitStructure);
+    TIM_Cmd(TIM2, ENABLE);
+}
+
+int main(void) {
+    int tstart,tup,tend,cyc,i;
+
+    memset((void*)outbuf,0,sizeof(short)*DAC_DUC_BUF_SZ);
+    setup_timer();
+    fast_dac_open(2*DAC_DUC_BUF_SZ,2*DAC_BUF_SZ);
+    tstart=tend=tup=cyc=0;
+    //Initalize complex input with signal at zero
+    for(i=0;i<DUC_48N;i++){
+        comp_in[i].real=1;
+        comp_in[i].imag=0;
+    }
+    while (1) {
+       cyc++;
+        //if(cyc>GMSK_TEST_LEN)
+        //    cyc=0;
+       if(cyc%10000==0){
+                printf("48c80r takes %d uSecs\n",tup-tstart);
+               printf("iir upconvert takes %d uSecs\n",tend-tup);
+       }
+        tstart = TIM_GetCounter(TIM2);
+
+        upconv_48c_80r(comp_in,tx_imm,1);
+
+       tup = TIM_GetCounter(TIM2);
+
+       iir_upconv_fixp(tx_imm,outbuf);
+
+       tend = TIM_GetCounter(TIM2);
+
+        //Sit and spin until we can get more samples into the dac 
+       while(dac1_write((short*)outbuf,DAC_DUC_BUF_SZ)<0);
+    }
+   
+}
+
index 00cdccad9ab803a548c61a51e68423d57feb1cc0..d4926cf238dafd48c47ce286e12c9069b981b520 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: fdmdv_dump_rt.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 9 Sep 2014\r
-\r
- Runs the fdmdv demod in real time for a few seconds then dumps some\r
- modem info to a text file for plotting in Octave.  Way to verify the\r
- "from radio" SM1000 hardware, ADC, and demod on the SM1000.\r
-\r
- Requires FreeDV signal to be sent to CN6 of SM1000.\r
-\r
- Octave:\r
-\r
-   load scatter.txt\r
-   l=length(scatter)\r
-   plot(scatter(:,1:2:l),scatter(:,2:2:l),'+')\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdint.h>\r
-#include <math.h>\r
-\r
-#include <stm32f4xx_gpio.h>\r
-#include "stm32f4_adc.h"\r
-#include "stm32f4_dac.h"\r
-#include "freedv_api.h"\r
-#include "codec2_fdmdv.h"\r
-#include "sm1000_leds_switches.h"\r
-#include "gdb_stdio.h"\r
-\r
-#ifdef __EMBEDDED__\r
-#define printf gdb_stdio_printf\r
-#define fprintf gdb_stdio_fprintf\r
-#define fopen gdb_stdio_fopen\r
-#define fclose gdb_stdio_fclose\r
-#define fread gdb_stdio_fread\r
-#define fwrite gdb_stdio_fwrite\r
-#endif\r
-\r
-#define FREEDV_NSAMPLES_16K (2*FREEDV_NSAMPLES)\r
-#define START_LOG_FRAMES 100\r
-#define LOG_FRAMES       10\r
-#define STOP_LOG_FRAMES  (START_LOG_FRAMES+LOG_FRAMES)\r
-#define NC  16\r
-\r
-int main(void) {\r
-    struct freedv *f;\r
-    short          adc16k[FDMDV_OS_TAPS_16K+FREEDV_NSAMPLES_16K];\r
-    short          dac16k[FREEDV_NSAMPLES_16K];\r
-    short          adc8k[FREEDV_NSAMPLES];\r
-    short          dac8k[FDMDV_OS_TAPS_8K+FREEDV_NSAMPLES];\r
\r
-    int            nin, nout, i, j, frames, lines;\r
-\r
-    COMP          *symb, *psymb;\r
-\r
-    /* init all the drivers for various peripherals */\r
-\r
-    sm1000_leds_switches_init();\r
-    dac_open(4*DAC_BUF_SZ);\r
-    adc_open(4*ADC_BUF_SZ);\r
-    f = freedv_open(FREEDV_MODE_1600);\r
-\r
-    /* clear filter memories */\r
-\r
-    for(i=0; i<FDMDV_OS_TAPS_16K; i++)\r
-       adc16k[i] = 0.0;\r
-    for(i=0; i<FDMDV_OS_TAPS_8K; i++)\r
-       dac8k[i] = 0.0;\r
-\r
-    /* allocate storage for the symbols */\r
-\r
-#define TMP\r
-#ifdef TMP\r
-    symb = (COMP*)malloc(sizeof(COMP)*(NC+1)*(STOP_LOG_FRAMES - START_LOG_FRAMES));\r
-    assert(symb != NULL);\r
-    psymb = symb;\r
-    frames = 0;\r
-    lines = 0;\r
-#endif\r
-    while(1)  {\r
-\r
-        /* Receive --------------------------------------------------------------------------*/\r
-\r
-        /* ADC1 is the demod in signal from the radio rx, DAC2 is the SM1000 speaker */\r
-\r
-        nin = freedv_nin(f);   \r
-        nout = nin;\r
-        f->total_bit_errors = 0;\r
-\r
-        if (adc1_read(&adc16k[FDMDV_OS_TAPS_16K], 2*nin) == 0) {\r
-            GPIOE->ODR = (1 << 3);\r
-            fdmdv_16_to_8_short(adc8k, &adc16k[FDMDV_OS_TAPS_16K], nin);\r
-            nout = freedv_rx(f, &dac8k[FDMDV_OS_TAPS_8K], adc8k);\r
-            fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], nout);              \r
-            dac2_write(dac16k, 2*nout);\r
-            led_ptt(0); led_rt(f->fdmdv_stats.sync); led_err(f->total_bit_errors);\r
-            GPIOE->ODR &= ~(1 << 3);\r
-\r
-#define TMP1\r
-#ifdef TMP1\r
-            if (f->fdmdv_stats.sync)\r
-                frames++;\r
-            if ((frames >= START_LOG_FRAMES) && (lines < LOG_FRAMES)) {\r
-                for(i=0; i<=f->fdmdv_stats.Nc; i++)\r
-                    psymb[i] = f->fdmdv_stats.rx_symbols[i];\r
-                psymb += (f->fdmdv_stats.Nc+1);\r
-                lines++;\r
-            }\r
\r
-            if (frames >= STOP_LOG_FRAMES) {\r
-                FILE *ft = fopen("scatter.txt", "wt");\r
-                assert(ft != NULL);\r
-                printf("Writing scatter file....\n");\r
-                for(j=0; j<LOG_FRAMES; j++) {\r
-                    for(i=0; i<=f->fdmdv_stats.Nc; i++) {\r
-                        fprintf(ft, "%f\t%f\t", \r
-                                (double)symb[j*(f->fdmdv_stats.Nc+1)+i].real,\r
-                                (double)symb[j*(f->fdmdv_stats.Nc+1)+i].imag);\r
-                        printf("line: %d\n", j);\r
-                    }\r
-                    fprintf(ft, "\n");\r
-                }\r
-                fclose(ft);\r
-                printf("SNR = %3.2f dB\nfinished!\n", (double)f->fdmdv_stats.snr_est);\r
-                while(1);\r
-            }\r
-#endif\r
-        }\r
-      \r
-    } /* while(1) ... */\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: fdmdv_dump_rt.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 9 Sep 2014
+
+ Runs the fdmdv demod in real time for a few seconds then dumps some
+ modem info to a text file for plotting in Octave.  Way to verify the
+ "from radio" SM1000 hardware, ADC, and demod on the SM1000.
+
+ Requires FreeDV signal to be sent to CN6 of SM1000.
+
+ Octave:
+
+   load scatter.txt
+   l=length(scatter)
+   plot(scatter(:,1:2:l),scatter(:,2:2:l),'+')
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include <stm32f4xx_gpio.h>
+#include "stm32f4_adc.h"
+#include "stm32f4_dac.h"
+#include "freedv_api.h"
+#include "codec2_fdmdv.h"
+#include "sm1000_leds_switches.h"
+#include "gdb_stdio.h"
+
+#ifdef __EMBEDDED__
+#define printf gdb_stdio_printf
+#define fprintf gdb_stdio_fprintf
+#define fopen gdb_stdio_fopen
+#define fclose gdb_stdio_fclose
+#define fread gdb_stdio_fread
+#define fwrite gdb_stdio_fwrite
+#endif
+
+#define FREEDV_NSAMPLES_16K (2*FREEDV_NSAMPLES)
+#define START_LOG_FRAMES 100
+#define LOG_FRAMES       10
+#define STOP_LOG_FRAMES  (START_LOG_FRAMES+LOG_FRAMES)
+#define NC  16
+
+int main(void) {
+    struct freedv *f;
+    short          adc16k[FDMDV_OS_TAPS_16K+FREEDV_NSAMPLES_16K];
+    short          dac16k[FREEDV_NSAMPLES_16K];
+    short          adc8k[FREEDV_NSAMPLES];
+    short          dac8k[FDMDV_OS_TAPS_8K+FREEDV_NSAMPLES];
+    int            nin, nout, i, j, frames, lines;
+
+    COMP          *symb, *psymb;
+
+    /* init all the drivers for various peripherals */
+
+    sm1000_leds_switches_init();
+    dac_open(4*DAC_BUF_SZ);
+    adc_open(4*ADC_BUF_SZ);
+    f = freedv_open(FREEDV_MODE_1600);
+
+    /* clear filter memories */
+
+    for(i=0; i<FDMDV_OS_TAPS_16K; i++)
+       adc16k[i] = 0.0;
+    for(i=0; i<FDMDV_OS_TAPS_8K; i++)
+       dac8k[i] = 0.0;
+
+    /* allocate storage for the symbols */
+
+#define TMP
+#ifdef TMP
+    symb = (COMP*)malloc(sizeof(COMP)*(NC+1)*(STOP_LOG_FRAMES - START_LOG_FRAMES));
+    assert(symb != NULL);
+    psymb = symb;
+    frames = 0;
+    lines = 0;
+#endif
+    while(1)  {
+
+        /* Receive --------------------------------------------------------------------------*/
+
+        /* ADC1 is the demod in signal from the radio rx, DAC2 is the SM1000 speaker */
+
+        nin = freedv_nin(f);   
+        nout = nin;
+        f->total_bit_errors = 0;
+
+        if (adc1_read(&adc16k[FDMDV_OS_TAPS_16K], 2*nin) == 0) {
+            GPIOE->ODR = (1 << 3);
+            fdmdv_16_to_8_short(adc8k, &adc16k[FDMDV_OS_TAPS_16K], nin);
+            nout = freedv_rx(f, &dac8k[FDMDV_OS_TAPS_8K], adc8k);
+            fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], nout);              
+            dac2_write(dac16k, 2*nout);
+            led_ptt(0); led_rt(f->fdmdv_stats.sync); led_err(f->total_bit_errors);
+            GPIOE->ODR &= ~(1 << 3);
+
+#define TMP1
+#ifdef TMP1
+            if (f->fdmdv_stats.sync)
+                frames++;
+            if ((frames >= START_LOG_FRAMES) && (lines < LOG_FRAMES)) {
+                for(i=0; i<=f->fdmdv_stats.Nc; i++)
+                    psymb[i] = f->fdmdv_stats.rx_symbols[i];
+                psymb += (f->fdmdv_stats.Nc+1);
+                lines++;
+            }
+            if (frames >= STOP_LOG_FRAMES) {
+                FILE *ft = fopen("scatter.txt", "wt");
+                assert(ft != NULL);
+                printf("Writing scatter file....\n");
+                for(j=0; j<LOG_FRAMES; j++) {
+                    for(i=0; i<=f->fdmdv_stats.Nc; i++) {
+                        fprintf(ft, "%f\t%f\t", 
+                                (double)symb[j*(f->fdmdv_stats.Nc+1)+i].real,
+                                (double)symb[j*(f->fdmdv_stats.Nc+1)+i].imag);
+                        printf("line: %d\n", j);
+                    }
+                    fprintf(ft, "\n");
+                }
+                fclose(ft);
+                printf("SNR = %3.2f dB\nfinished!\n", (double)f->fdmdv_stats.snr_est);
+                while(1);
+            }
+#endif
+        }
+      
+    } /* while(1) ... */
+}
+
index 05b8d62389790841eb321c2fd60cb5121ba97176..ee4f8b8b7ed402e7600d58d58c0806c38406828a 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: fdmdv_profile.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 18 July 2014\r
-\r
-  Profiling FDMDV modem operation on the STM32F4.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdint.h>\r
-#include <math.h>\r
-\r
-#include "stm32f4xx_conf.h"\r
-#include "stm32f4xx.h"\r
-#include "gdb_stdio.h"\r
-#include "codec2_fdmdv.h"\r
-#include "dump.h"\r
-#include "sine.h"\r
-#include "machdep.h"\r
-\r
-#ifdef __EMBEDDED__\r
-#define printf gdb_stdio_printf\r
-#define fopen gdb_stdio_fopen\r
-#define fclose gdb_stdio_fclose\r
-#define fread gdb_stdio_fread\r
-#define fwrite gdb_stdio_fwrite\r
-#endif\r
-\r
-#define TEST_FRAMES 25\r
-#define CHANNEL_BUF_SIZE (10*FDMDV_NOM_SAMPLES_PER_FRAME)\r
-\r
-static int  channel_count = 0;\r
-static COMP channel[CHANNEL_BUF_SIZE];\r
-\r
-static void channel_in(COMP tx_fdm[], int nout) {\r
-    int i;\r
-\r
-    /* add M tx samples to end of buffer */\r
-\r
-    assert((channel_count + nout) < CHANNEL_BUF_SIZE);\r
-    for(i=0; i<nout; i++)\r
-        channel[channel_count+i] = tx_fdm[i];\r
-    channel_count += M;\r
-}\r
-\r
-static void channel_out(COMP rx_fdm[], int nin) {\r
-    int i,j;\r
-\r
-    /* take nin samples from start of buffer */\r
-\r
-    for(i=0; i<nin; i++) {\r
-        rx_fdm[i] = channel[i];\r
-    }\r
-\r
-    /* shift buffer back */\r
-\r
-    for(i=0,j=nin; j<channel_count; i++,j++)\r
-        channel[i] = channel[j];\r
-    channel_count -= nin;\r
-}\r
-\r
-int main(int argc, char *argv[]) {\r
-    struct FDMDV       *fdmdv;\r
-    int                 bits_per_fdmdv_frame,  bits_per_codec_frame;\r
-    int                *tx_bits;\r
-    int                *rx_bits;\r
-    int                *codec_bits;\r
-    COMP                tx_fdm[2*FDMDV_NOM_SAMPLES_PER_FRAME];\r
-    COMP                rx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME];\r
-    int                 i, j, nin, reliable_sync_bit[2], sync_bit, bit_errors, ntest_bits, test_frame_sync;\r
-    short              *error_pattern;\r
-    struct MODEM_STATS  stats;\r
-    PROFILE_VAR(mod_start, demod_start);\r
-\r
-    machdep_profile_init ();\r
-    fdmdv = fdmdv_create(FDMDV_NC);\r
-\r
-    bits_per_fdmdv_frame = fdmdv_bits_per_frame(fdmdv);\r
-    bits_per_codec_frame = 2*fdmdv_bits_per_frame(fdmdv);\r
-    tx_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(tx_bits != NULL);\r
-    rx_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(rx_bits != NULL);\r
-    codec_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(rx_bits != NULL);\r
-    error_pattern = (short*)malloc(fdmdv_error_pattern_size(fdmdv)*sizeof(int)); assert(error_pattern != NULL);\r
-\r
-    nin = FDMDV_NOM_SAMPLES_PER_FRAME;\r
-    test_frame_sync = 0;\r
-\r
-    for(i=0; i<TEST_FRAMES; i++) {\r
-       fdmdv_get_test_bits(fdmdv, tx_bits);\r
-       fdmdv_get_test_bits(fdmdv, &tx_bits[bits_per_fdmdv_frame]);\r
-\r
-        PROFILE_SAMPLE(mod_start);\r
-\r
-       fdmdv_mod(fdmdv, tx_fdm, tx_bits, &sync_bit);\r
-       assert(sync_bit == 1);\r
-       fdmdv_mod(fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &tx_bits[bits_per_fdmdv_frame], &sync_bit);\r
-       assert(sync_bit == 0);\r
-        channel_in(tx_fdm, 2*FDMDV_NOM_SAMPLES_PER_FRAME);\r
-\r
-        PROFILE_SAMPLE_AND_LOG(demod_start, mod_start, "  mod");     \r
-\r
-        for(j=0; j<2; j++) {\r
-            channel_out(rx_fdm, nin);\r
-            fdmdv_demod(fdmdv, rx_bits, &reliable_sync_bit[j], rx_fdm, &nin);\r
-            if (reliable_sync_bit[j] == 0)\r
-                memcpy(codec_bits, rx_bits, bits_per_fdmdv_frame*sizeof(int));\r
-            else {\r
-                memcpy(&codec_bits[bits_per_fdmdv_frame], rx_bits, bits_per_fdmdv_frame*sizeof(int));\r
-                fdmdv_put_test_bits(fdmdv, &test_frame_sync, error_pattern, &bit_errors, &ntest_bits, codec_bits);\r
-                fdmdv_put_test_bits(fdmdv, &test_frame_sync, error_pattern, &bit_errors, &ntest_bits, &codec_bits[bits_per_fdmdv_frame]);\r
-            }\r
-        }\r
-        PROFILE_SAMPLE_AND_LOG2(demod_start, "  demod");     \r
-        PROFILE_SAMPLE_AND_LOG2(mod_start, "  mod & demod");     \r
-\r
-        fdmdv_get_demod_stats(fdmdv, &stats);\r
-\r
-        printf("frame: %d sync: %d reliable_sync_bit: %d %d SNR: %3.2f test_frame_sync: %d\n", \r
-               i, stats.sync, reliable_sync_bit[0], reliable_sync_bit[1], (double)stats.snr_est, \r
-               test_frame_sync);\r
-        machdep_profile_print_logged_samples();\r
-    }\r
-\r
-    fdmdv_destroy(fdmdv);\r
-\r
-    return 0;\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: fdmdv_profile.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 18 July 2014
+
+  Profiling FDMDV modem operation on the STM32F4.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include "stm32f4xx_conf.h"
+#include "stm32f4xx.h"
+#include "gdb_stdio.h"
+#include "codec2_fdmdv.h"
+#include "dump.h"
+#include "sine.h"
+#include "machdep.h"
+
+#ifdef __EMBEDDED__
+#define printf gdb_stdio_printf
+#define fopen gdb_stdio_fopen
+#define fclose gdb_stdio_fclose
+#define fread gdb_stdio_fread
+#define fwrite gdb_stdio_fwrite
+#endif
+
+#define TEST_FRAMES 25
+#define CHANNEL_BUF_SIZE (10*FDMDV_NOM_SAMPLES_PER_FRAME)
+
+static int  channel_count = 0;
+static COMP channel[CHANNEL_BUF_SIZE];
+
+static void channel_in(COMP tx_fdm[], int nout) {
+    int i;
+
+    /* add M tx samples to end of buffer */
+
+    assert((channel_count + nout) < CHANNEL_BUF_SIZE);
+    for(i=0; i<nout; i++)
+        channel[channel_count+i] = tx_fdm[i];
+    channel_count += M;
+}
+
+static void channel_out(COMP rx_fdm[], int nin) {
+    int i,j;
+
+    /* take nin samples from start of buffer */
+
+    for(i=0; i<nin; i++) {
+        rx_fdm[i] = channel[i];
+    }
+
+    /* shift buffer back */
+
+    for(i=0,j=nin; j<channel_count; i++,j++)
+        channel[i] = channel[j];
+    channel_count -= nin;
+}
+
+int main(int argc, char *argv[]) {
+    struct FDMDV       *fdmdv;
+    int                 bits_per_fdmdv_frame,  bits_per_codec_frame;
+    int                *tx_bits;
+    int                *rx_bits;
+    int                *codec_bits;
+    COMP                tx_fdm[2*FDMDV_NOM_SAMPLES_PER_FRAME];
+    COMP                rx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME];
+    int                 i, j, nin, reliable_sync_bit[2], sync_bit, bit_errors, ntest_bits, test_frame_sync;
+    short              *error_pattern;
+    struct MODEM_STATS  stats;
+    PROFILE_VAR(mod_start, demod_start);
+
+    machdep_profile_init ();
+    fdmdv = fdmdv_create(FDMDV_NC);
+
+    bits_per_fdmdv_frame = fdmdv_bits_per_frame(fdmdv);
+    bits_per_codec_frame = 2*fdmdv_bits_per_frame(fdmdv);
+    tx_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(tx_bits != NULL);
+    rx_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(rx_bits != NULL);
+    codec_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(rx_bits != NULL);
+    error_pattern = (short*)malloc(fdmdv_error_pattern_size(fdmdv)*sizeof(int)); assert(error_pattern != NULL);
+
+    nin = FDMDV_NOM_SAMPLES_PER_FRAME;
+    test_frame_sync = 0;
+
+    for(i=0; i<TEST_FRAMES; i++) {
+       fdmdv_get_test_bits(fdmdv, tx_bits);
+       fdmdv_get_test_bits(fdmdv, &tx_bits[bits_per_fdmdv_frame]);
+
+        PROFILE_SAMPLE(mod_start);
+
+       fdmdv_mod(fdmdv, tx_fdm, tx_bits, &sync_bit);
+       assert(sync_bit == 1);
+       fdmdv_mod(fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &tx_bits[bits_per_fdmdv_frame], &sync_bit);
+       assert(sync_bit == 0);
+        channel_in(tx_fdm, 2*FDMDV_NOM_SAMPLES_PER_FRAME);
+
+        PROFILE_SAMPLE_AND_LOG(demod_start, mod_start, "  mod");     
+
+        for(j=0; j<2; j++) {
+            channel_out(rx_fdm, nin);
+            fdmdv_demod(fdmdv, rx_bits, &reliable_sync_bit[j], rx_fdm, &nin);
+            if (reliable_sync_bit[j] == 0)
+                memcpy(codec_bits, rx_bits, bits_per_fdmdv_frame*sizeof(int));
+            else {
+                memcpy(&codec_bits[bits_per_fdmdv_frame], rx_bits, bits_per_fdmdv_frame*sizeof(int));
+                fdmdv_put_test_bits(fdmdv, &test_frame_sync, error_pattern, &bit_errors, &ntest_bits, codec_bits);
+                fdmdv_put_test_bits(fdmdv, &test_frame_sync, error_pattern, &bit_errors, &ntest_bits, &codec_bits[bits_per_fdmdv_frame]);
+            }
+        }
+        PROFILE_SAMPLE_AND_LOG2(demod_start, "  demod");     
+        PROFILE_SAMPLE_AND_LOG2(mod_start, "  mod & demod");     
+
+        fdmdv_get_demod_stats(fdmdv, &stats);
+
+        printf("frame: %d sync: %d reliable_sync_bit: %d %d SNR: %3.2f test_frame_sync: %d\n", 
+               i, stats.sync, reliable_sync_bit[0], reliable_sync_bit[1], (double)stats.snr_est, 
+               test_frame_sync);
+        machdep_profile_print_logged_samples();
+    }
+
+    fdmdv_destroy(fdmdv);
+
+    return 0;
+}
+
index cc838d15deafeab30df1713acb3df5b272999a79..e511a84573e590a38b4dc206a20125460afa758c 100644 (file)
-/* ---------------------------------------------------------------------- \r
-* Copyright (C) 2010 ARM Limited. All rights reserved.   \r
-*  \r
-* $Date:        29. November 2010  \r
-* $Revision:   V1.0.3  \r
-*  \r
-* Project:         CMSIS DSP Library  \r
-* Title:           arm_fft_bin_example_f32.c             \r
-*  \r
-* Description: Example code demonstrating calculation of Max energy bin of  \r
-*                              frequency domain of input signal. \r
-* \r
-* Target Processor: Cortex-M4/Cortex-M3  \r
-*\r
-*\r
-* Version 1.0.3 2010/11/29 \r
-*    Re-organized the CMSIS folders and updated documentation. \r
-* \r
-* Version 1.0.1 2010/10/05 KK \r
-*    Production release and review comments incorporated.  \r
-*\r
-* Version 1.0.0 2010/09/20 KK\r
-*    Production release and review comments incorporated.\r
-* ------------------------------------------------------------------- */ \r
\r
-/** \r
- * @ingroup groupExamples \r
- */ \r
\r
-/**    \r
- * @defgroup FrequencyBin Frequency Bin Example    \r
- * \r
- * \par Description\r
- * \par\r
- * Demonstrates the calculation of the maximum energy bin in the frequency \r
- * domain of the input signal with the use of Complex FFT, Complex \r
- * Magnitude, and Maximum functions. \r
- * \r
- * \par Algorithm:\r
- * \par\r
- * The input test signal contains a 10 kHz signal with uniformly distributed white noise.  \r
- * Calculating the FFT of the input signal will give us the maximum energy of the \r
- * bin corresponding to the input frequency of 10 kHz.  \r
- * \r
- * \par Block Diagram:\r
- * \image html FFTBin.gif "Block Diagram"\r
- * \par\r
- * The figure below shows the time domain signal of 10 kHz signal with \r
- * uniformly distributed white noise, and the next figure shows the input\r
- * in the frequency domain. The bin with maximum energy corresponds to 10 kHz signal. \r
- * \par\r
- * \image html FFTBinInput.gif "Input signal in Time domain" \r
- * \image html FFTBinOutput.gif "Input signal in Frequency domain"\r
- *\r
- * \par Variables Description:\r
- * \par\r
- * \li \c testInput_f32_10khz points to the input data\r
- * \li \c testOutput points to the output data\r
- * \li \c fftSize length of FFT\r
- * \li \c ifftFlag flag for the selection of CFFT/CIFFT\r
- * \li \c doBitReverse Flag for selection of normal order or bit reversed order\r
- * \li \c refIndex reference index value at which maximum energy of bin ocuurs\r
- * \li \c testIndex calculated index value at which maximum energy of bin ocuurs\r
- * \r
- * \par CMSIS DSP Software Library Functions Used:\r
- * \par\r
- * - arm_cfft_radix4_init_f32()\r
- * - arm_cfft_radix4_f32()\r
- * - arm_cmplx_mag_f32()\r
- * - arm_max_f32()\r
- *\r
- * <b> Refer  </b> \r
- * \link arm_fft_bin_example_f32.c \endlink\r
- * \r
- */ \r
\r
\r
-/** \example arm_fft_bin_example_f32.c \r
-  */  \r
-\r
-     \r
-#include "arm_math.h" \r
-#include "gdb_stdio.h"\r
-#include "machdep.h"\r
-#include "kiss_fft.h"\r
\r
-#define TEST_LENGTH_SAMPLES 1024\r
\r
-/* ------------------------------------------------------------------- \r
-* External Input and Output buffer Declarations for FFT Bin Example \r
-* ------------------------------------------------------------------- */ \r
-extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES]; \r
-static float32_t testOutput[TEST_LENGTH_SAMPLES/2]; \r
-static float32_t kiss_complex_out[TEST_LENGTH_SAMPLES]; \r
\r
-/* ------------------------------------------------------------------ \r
-* Global variables for FFT Bin Example \r
-* ------------------------------------------------------------------- */ \r
-uint32_t fftSize = TEST_LENGTH_SAMPLES/2; \r
-uint32_t ifftFlag = 0; \r
-uint32_t doBitReverse = 1; \r
\r
-/* Reference index at which max energy of bin ocuurs */ \r
-uint32_t refIndex = 213, testIndex = 0; \r
\r
-/* ---------------------------------------------------------------------- \r
-* Max magnitude FFT Bin test \r
-* ------------------------------------------------------------------- */ \r
\r
-void SystemInit(void);\r
-\r
-int main(void) \r
-{ \r
-   \r
-       arm_status status; \r
-       arm_cfft_radix2_instance_f32 S; \r
-       float32_t maxValue; \r
-        unsigned int fft_start, kiss_fft_start;\r
-        kiss_fft_cfg fft_fwd_cfg;\r
-\r
-        SystemInit();\r
-        machdep_profile_init();\r
-        fft_fwd_cfg = kiss_fft_alloc(fftSize, 0, NULL, NULL);\r
-        kiss_fft_start = machdep_profile_sample();     \r
-        kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)testInput_f32_10khz, \r
-                 (kiss_fft_cpx *)kiss_complex_out);\r
-        machdep_profile_sample_and_log(kiss_fft_start, "  kiss_fft");     \r
\r
-       status = ARM_MATH_SUCCESS; \r
-        \r
-       /* Initialize the CFFT/CIFFT module */  \r
-       status = arm_cfft_radix2_init_f32(&S, fftSize, ifftFlag, doBitReverse);          \r
-\r
-       /* Process the data through the CFFT/CIFFT module */ \r
-        fft_start = machdep_profile_sample();  \r
-        arm_cfft_radix2_f32(&S, testInput_f32_10khz); \r
-        machdep_profile_sample_and_log(fft_start, "  fft");     \r
-        machdep_profile_print_logged_samples();\r
-\r
-       /* Process the data through the Complex Magnitude Module for  \r
-       calculating the magnitude at each bin */ \r
-       arm_cmplx_mag_f32(testInput_f32_10khz, testOutput,fftSize);  \r
-        \r
-       /* Calculates maxValue and returns corresponding BIN value */ \r
-       arm_max_f32(testOutput, fftSize, &maxValue, &testIndex); \r
-        \r
-       if(testIndex !=  refIndex) \r
-       { \r
-               status = ARM_MATH_TEST_FAILURE; \r
-       } \r
-        \r
-       /* ---------------------------------------------------------------------- \r
-       ** Loop here if the signals fail the PASS check. \r
-       ** This denotes a test failure \r
-       ** ------------------------------------------------------------------- */ \r
-        \r
-       if( status != ARM_MATH_SUCCESS) \r
-       { \r
-               while(1); \r
-       } \r
-\r
-    while(1);                             /* main function does not return */\r
-\r
-    return 0;\r
-} \r
\r
- /** \endlink */ \r
\r
\r
-/*\r
- * Dummy function to avoid compiler error\r
- */\r
-void _init() { }\r
-\r
-\r
\r
+/* ---------------------------------------------------------------------- 
+* Copyright (C) 2010 ARM Limited. All rights reserved.   
+*  
+* $Date:        29. November 2010  
+* $Revision:   V1.0.3  
+*  
+* Project:         CMSIS DSP Library  
+* Title:           arm_fft_bin_example_f32.c             
+*  
+* Description: Example code demonstrating calculation of Max energy bin of  
+*                              frequency domain of input signal. 
+* 
+* Target Processor: Cortex-M4/Cortex-M3  
+*
+*
+* Version 1.0.3 2010/11/29 
+*    Re-organized the CMSIS folders and updated documentation. 
+* 
+* Version 1.0.1 2010/10/05 KK 
+*    Production release and review comments incorporated.  
+*
+* Version 1.0.0 2010/09/20 KK
+*    Production release and review comments incorporated.
+* ------------------------------------------------------------------- */ 
+/** 
+ * @ingroup groupExamples 
+ */ 
+/**    
+ * @defgroup FrequencyBin Frequency Bin Example    
+ * 
+ * \par Description
+ * \par
+ * Demonstrates the calculation of the maximum energy bin in the frequency 
+ * domain of the input signal with the use of Complex FFT, Complex 
+ * Magnitude, and Maximum functions. 
+ * 
+ * \par Algorithm:
+ * \par
+ * The input test signal contains a 10 kHz signal with uniformly distributed white noise.  
+ * Calculating the FFT of the input signal will give us the maximum energy of the 
+ * bin corresponding to the input frequency of 10 kHz.  
+ * 
+ * \par Block Diagram:
+ * \image html FFTBin.gif "Block Diagram"
+ * \par
+ * The figure below shows the time domain signal of 10 kHz signal with 
+ * uniformly distributed white noise, and the next figure shows the input
+ * in the frequency domain. The bin with maximum energy corresponds to 10 kHz signal. 
+ * \par
+ * \image html FFTBinInput.gif "Input signal in Time domain" 
+ * \image html FFTBinOutput.gif "Input signal in Frequency domain"
+ *
+ * \par Variables Description:
+ * \par
+ * \li \c testInput_f32_10khz points to the input data
+ * \li \c testOutput points to the output data
+ * \li \c fftSize length of FFT
+ * \li \c ifftFlag flag for the selection of CFFT/CIFFT
+ * \li \c doBitReverse Flag for selection of normal order or bit reversed order
+ * \li \c refIndex reference index value at which maximum energy of bin ocuurs
+ * \li \c testIndex calculated index value at which maximum energy of bin ocuurs
+ * 
+ * \par CMSIS DSP Software Library Functions Used:
+ * \par
+ * - arm_cfft_radix4_init_f32()
+ * - arm_cfft_radix4_f32()
+ * - arm_cmplx_mag_f32()
+ * - arm_max_f32()
+ *
+ * <b> Refer  </b> 
+ * \link arm_fft_bin_example_f32.c \endlink
+ * 
+ */ 
+/** \example arm_fft_bin_example_f32.c 
+  */  
+
+     
+#include "arm_math.h" 
+#include "gdb_stdio.h"
+#include "machdep.h"
+#include "kiss_fft.h"
+#define TEST_LENGTH_SAMPLES 1024
+/* ------------------------------------------------------------------- 
+* External Input and Output buffer Declarations for FFT Bin Example 
+* ------------------------------------------------------------------- */ 
+extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES]; 
+static float32_t testOutput[TEST_LENGTH_SAMPLES/2]; 
+static float32_t kiss_complex_out[TEST_LENGTH_SAMPLES]; 
+/* ------------------------------------------------------------------ 
+* Global variables for FFT Bin Example 
+* ------------------------------------------------------------------- */ 
+uint32_t fftSize = TEST_LENGTH_SAMPLES/2; 
+uint32_t ifftFlag = 0; 
+uint32_t doBitReverse = 1; 
+/* Reference index at which max energy of bin ocuurs */ 
+uint32_t refIndex = 213, testIndex = 0; 
+/* ---------------------------------------------------------------------- 
+* Max magnitude FFT Bin test 
+* ------------------------------------------------------------------- */ 
+void SystemInit(void);
+
+int main(void) 
+{ 
+   
+       arm_status status; 
+       arm_cfft_radix2_instance_f32 S; 
+       float32_t maxValue; 
+        unsigned int fft_start, kiss_fft_start;
+        kiss_fft_cfg fft_fwd_cfg;
+
+        SystemInit();
+        machdep_profile_init();
+        fft_fwd_cfg = kiss_fft_alloc(fftSize, 0, NULL, NULL);
+        kiss_fft_start = machdep_profile_sample();     
+        kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)testInput_f32_10khz, 
+                 (kiss_fft_cpx *)kiss_complex_out);
+        machdep_profile_sample_and_log(kiss_fft_start, "  kiss_fft");     
+       status = ARM_MATH_SUCCESS; 
+        
+       /* Initialize the CFFT/CIFFT module */  
+       status = arm_cfft_radix2_init_f32(&S, fftSize, ifftFlag, doBitReverse);          
+
+       /* Process the data through the CFFT/CIFFT module */ 
+        fft_start = machdep_profile_sample();  
+        arm_cfft_radix2_f32(&S, testInput_f32_10khz); 
+        machdep_profile_sample_and_log(fft_start, "  fft");     
+        machdep_profile_print_logged_samples();
+
+       /* Process the data through the Complex Magnitude Module for  
+       calculating the magnitude at each bin */ 
+       arm_cmplx_mag_f32(testInput_f32_10khz, testOutput,fftSize);  
+        
+       /* Calculates maxValue and returns corresponding BIN value */ 
+       arm_max_f32(testOutput, fftSize, &maxValue, &testIndex); 
+        
+       if(testIndex !=  refIndex) 
+       { 
+               status = ARM_MATH_TEST_FAILURE; 
+       } 
+        
+       /* ---------------------------------------------------------------------- 
+       ** Loop here if the signals fail the PASS check. 
+       ** This denotes a test failure 
+       ** ------------------------------------------------------------------- */ 
+        
+       if( status != ARM_MATH_SUCCESS) 
+       { 
+               while(1); 
+       } 
+
+    while(1);                             /* main function does not return */
+
+    return 0;
+} 
+ /** \endlink */ 
+/*
+ * Dummy function to avoid compiler error
+ */
+void _init() { }
+
+
index 65b43ae1d51e865a493672314f47e8c7730ed832..f91fc4fe8136c16e22dafafd7befa89b9dacdc91 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: freedv_rx_profile.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 13 August 2014\r
-\r
-  Profiling freedv_rx() operation on the STM32F4.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#define PROFILE\r
-\r
-#include <assert.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdint.h>\r
-#include <math.h>\r
-\r
-#include "stm32f4xx_conf.h"\r
-#include "stm32f4xx.h"\r
-#include "gdb_stdio.h"\r
-#include "freedv_api.h"\r
-#include "machdep.h"\r
-#include "codec2_fdmdv.h"\r
-\r
-#ifdef __EMBEDDED__\r
-#define printf gdb_stdio_printf\r
-#define fopen gdb_stdio_fopen\r
-#define fclose gdb_stdio_fclose\r
-#define fread gdb_stdio_fread\r
-#define fwrite gdb_stdio_fwrite\r
-#define fprintf gdb_stdio_fprintf\r
-#endif\r
-\r
-#define FREEDV_NSAMPLES_16K (2*FREEDV_NSAMPLES)\r
-\r
-int main(int argc, char *argv[]) {\r
-    struct freedv *f;\r
-    FILE          *fin, *fout, *ftotal;\r
-    int            frame, nin_16k, nin, i, nout = 0;\r
-    int            n_samples, n_samples_16k;\r
-    int            sync;\r
-    float          snr_est;\r
-\r
-    PROFILE_VAR(fdmdv_16_to_8_start, freedv_rx_start, fdmdv_8_to_16_start);\r
-\r
-    machdep_profile_init();\r
-\r
-    f = freedv_open(FREEDV_MODE_1600);\r
-    n_samples = freedv_get_n_speech_samples(f);\r
-    n_samples_16k = 2*n_samples;\r
-\r
-    short          adc16k[FDMDV_OS_TAPS_16K+n_samples_16k];\r
-    short          dac16k[n_samples_16k];\r
-    short          adc8k[n_samples];\r
-    short          dac8k[FDMDV_OS_TAPS_8K+n_samples];\r
-\r
-    // Receive ---------------------------------------------------------------------\r
-\r
-    frame = 0;\r
-\r
-    fin = fopen("mod_16k.raw", "rb");\r
-    if (fin == NULL) {\r
-        printf("Error opening input file\n");\r
-        exit(1);\r
-    }\r
-\r
-    fout = fopen("speechout_16k.raw", "wb");\r
-    if (fout == NULL) {\r
-        printf("Error opening output file\n");\r
-        exit(1);\r
-    }\r
-\r
-    ftotal = fopen("total.txt", "wt");\r
-    assert(ftotal != NULL);\r
-\r
-    /* clear filter memories */\r
-\r
-    for(i=0; i<FDMDV_OS_TAPS_16K; i++)\r
-       adc16k[i] = 0.0;\r
-    for(i=0; i<FDMDV_OS_TAPS_8K; i++)\r
-       dac8k[i] = 0.0;\r
-    \r
-    nin = freedv_nin(f);\r
-    nin_16k = 2*nin;\r
-    nout = nin;\r
-    while (fread(&adc16k[FDMDV_OS_TAPS_16K], sizeof(short), nin_16k, fin) == nin_16k) {\r
-\r
-        PROFILE_SAMPLE(fdmdv_16_to_8_start);\r
-\r
-        fdmdv_16_to_8_short(adc8k, &adc16k[FDMDV_OS_TAPS_16K], nin);\r
-\r
-        PROFILE_SAMPLE_AND_LOG(freedv_rx_start, fdmdv_16_to_8_start, "  fdmdv_16_to_8");\r
-\r
-        nout = freedv_rx(f, &dac8k[FDMDV_OS_TAPS_8K], adc8k);\r
-        nin = freedv_nin(f); nin_16k = 2*nin;\r
-\r
-        PROFILE_SAMPLE_AND_LOG(fdmdv_8_to_16_start, freedv_rx_start, "  freedv_rx");     \r
-\r
-        fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], nout);              \r
-\r
-        PROFILE_SAMPLE_AND_LOG2(fdmdv_8_to_16_start, "  fdmdv_8_to_16");\r
-\r
-        fprintf(ftotal, "%d\n", machdep_profile_sample() - fdmdv_16_to_8_start);\r
-        machdep_profile_print_logged_samples();\r
-\r
-        fwrite(dac16k, sizeof(short), 2*nout, fout);\r
-        freedv_get_modem_stats(f, &sync, &snr_est);\r
-        printf("frame: %d nin_16k: %d sync: %d SNR: %3.2f \n", \r
-               ++frame, nin_16k, sync, (double)snr_est);\r
-    }\r
-\r
-    fclose(fin);\r
-    fclose(fout);\r
-    fclose(ftotal);\r
-\r
-    return 0;\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: freedv_rx_profile.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 13 August 2014
+
+  Profiling freedv_rx() operation on the STM32F4.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define PROFILE
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include "stm32f4xx_conf.h"
+#include "stm32f4xx.h"
+#include "gdb_stdio.h"
+#include "freedv_api.h"
+#include "machdep.h"
+#include "codec2_fdmdv.h"
+
+#ifdef __EMBEDDED__
+#define printf gdb_stdio_printf
+#define fopen gdb_stdio_fopen
+#define fclose gdb_stdio_fclose
+#define fread gdb_stdio_fread
+#define fwrite gdb_stdio_fwrite
+#define fprintf gdb_stdio_fprintf
+#endif
+
+#define FREEDV_NSAMPLES_16K (2*FREEDV_NSAMPLES)
+
+int main(int argc, char *argv[]) {
+    struct freedv *f;
+    FILE          *fin, *fout, *ftotal;
+    int            frame, nin_16k, nin, i, nout = 0;
+    int            n_samples, n_samples_16k;
+    int            sync;
+    float          snr_est;
+
+    PROFILE_VAR(fdmdv_16_to_8_start, freedv_rx_start, fdmdv_8_to_16_start);
+
+    machdep_profile_init();
+
+    f = freedv_open(FREEDV_MODE_1600);
+    n_samples = freedv_get_n_speech_samples(f);
+    n_samples_16k = 2*n_samples;
+
+    short          adc16k[FDMDV_OS_TAPS_16K+n_samples_16k];
+    short          dac16k[n_samples_16k];
+    short          adc8k[n_samples];
+    short          dac8k[FDMDV_OS_TAPS_8K+n_samples];
+
+    // Receive ---------------------------------------------------------------------
+
+    frame = 0;
+
+    fin = fopen("mod_16k.raw", "rb");
+    if (fin == NULL) {
+        printf("Error opening input file\n");
+        exit(1);
+    }
+
+    fout = fopen("speechout_16k.raw", "wb");
+    if (fout == NULL) {
+        printf("Error opening output file\n");
+        exit(1);
+    }
+
+    ftotal = fopen("total.txt", "wt");
+    assert(ftotal != NULL);
+
+    /* clear filter memories */
+
+    for(i=0; i<FDMDV_OS_TAPS_16K; i++)
+       adc16k[i] = 0.0;
+    for(i=0; i<FDMDV_OS_TAPS_8K; i++)
+       dac8k[i] = 0.0;
+    
+    nin = freedv_nin(f);
+    nin_16k = 2*nin;
+    nout = nin;
+    while (fread(&adc16k[FDMDV_OS_TAPS_16K], sizeof(short), nin_16k, fin) == nin_16k) {
+
+        PROFILE_SAMPLE(fdmdv_16_to_8_start);
+
+        fdmdv_16_to_8_short(adc8k, &adc16k[FDMDV_OS_TAPS_16K], nin);
+
+        PROFILE_SAMPLE_AND_LOG(freedv_rx_start, fdmdv_16_to_8_start, "  fdmdv_16_to_8");
+
+        nout = freedv_rx(f, &dac8k[FDMDV_OS_TAPS_8K], adc8k);
+        nin = freedv_nin(f); nin_16k = 2*nin;
+
+        PROFILE_SAMPLE_AND_LOG(fdmdv_8_to_16_start, freedv_rx_start, "  freedv_rx");     
+
+        fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], nout);              
+
+        PROFILE_SAMPLE_AND_LOG2(fdmdv_8_to_16_start, "  fdmdv_8_to_16");
+
+        fprintf(ftotal, "%d\n", machdep_profile_sample() - fdmdv_16_to_8_start);
+        machdep_profile_print_logged_samples();
+
+        fwrite(dac16k, sizeof(short), 2*nout, fout);
+        freedv_get_modem_stats(f, &sync, &snr_est);
+        printf("frame: %d nin_16k: %d sync: %d SNR: %3.2f \n", 
+               ++frame, nin_16k, sync, (double)snr_est);
+    }
+
+    fclose(fin);
+    fclose(fout);
+    fclose(ftotal);
+
+    return 0;
+}
+
index 54b589150d8234c882579f0dcb284081b37049cd..9fe49d23d1b8b09ed14bf1d73fa0eae1169e17ed 100644 (file)
@@ -1,90 +1,90 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: freedv_tx_profile.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 13 August 2014\r
-\r
-  Profiling freedv_tx() operation on the STM32F4.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdint.h>\r
-#include <math.h>\r
-\r
-#include "stm32f4xx_conf.h"\r
-#include "stm32f4xx.h"\r
-#include "gdb_stdio.h"\r
-#include "freedv_api.h"\r
-#include "machdep.h"\r
-\r
-#ifdef __EMBEDDED__\r
-#define printf gdb_stdio_printf\r
-#define fopen gdb_stdio_fopen\r
-#define fclose gdb_stdio_fclose\r
-#define fread gdb_stdio_fread\r
-#define fwrite gdb_stdio_fwrite\r
-#endif\r
-\r
-int main(int argc, char *argv[]) {\r
-    struct freedv *f;\r
-    FILE          *fin, *fout;\r
-    int            frame, n_samples;\r
-    PROFILE_VAR(freedv_start);\r
-\r
-    machdep_profile_init();\r
-\r
-    f = freedv_open(FREEDV_MODE_1600);\r
-    n_samples = freedv_get_n_speech_samples(f);\r
-    short inbuf[n_samples], outbuf[n_samples];\r
-\r
-    // Transmit ---------------------------------------------------------------------\r
-\r
-    fin = fopen("stm_in.raw", "rb");\r
-    if (fin == NULL) {\r
-        printf("Error opening input file\n");\r
-        exit(1);\r
-    }\r
-\r
-    fout = fopen("mod.raw", "wb");\r
-    if (fout == NULL) {\r
-        printf("Error opening output file\n");\r
-        exit(1);\r
-    }\r
-\r
-    frame = 0;\r
-\r
-    while (fread(inbuf, sizeof(short), n_samples, fin) == n_samples) {\r
-        PROFILE_SAMPLE(freedv_start);\r
-        freedv_tx(f, outbuf, inbuf);\r
-        PROFILE_SAMPLE_AND_LOG2(freedv_start, "  freedv_tx");     \r
-       \r
-        fwrite(outbuf, sizeof(short), n_samples, fout);\r
-        printf("frame: %d\n", ++frame);\r
-        machdep_profile_print_logged_samples();\r
-   }\r
-\r
-    fclose(fin);\r
-    fclose(fout);\r
-\r
-    return 0;\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: freedv_tx_profile.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 13 August 2014
+
+  Profiling freedv_tx() operation on the STM32F4.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include "stm32f4xx_conf.h"
+#include "stm32f4xx.h"
+#include "gdb_stdio.h"
+#include "freedv_api.h"
+#include "machdep.h"
+
+#ifdef __EMBEDDED__
+#define printf gdb_stdio_printf
+#define fopen gdb_stdio_fopen
+#define fclose gdb_stdio_fclose
+#define fread gdb_stdio_fread
+#define fwrite gdb_stdio_fwrite
+#endif
+
+int main(int argc, char *argv[]) {
+    struct freedv *f;
+    FILE          *fin, *fout;
+    int            frame, n_samples;
+    PROFILE_VAR(freedv_start);
+
+    machdep_profile_init();
+
+    f = freedv_open(FREEDV_MODE_1600);
+    n_samples = freedv_get_n_speech_samples(f);
+    short inbuf[n_samples], outbuf[n_samples];
+
+    // Transmit ---------------------------------------------------------------------
+
+    fin = fopen("stm_in.raw", "rb");
+    if (fin == NULL) {
+        printf("Error opening input file\n");
+        exit(1);
+    }
+
+    fout = fopen("mod.raw", "wb");
+    if (fout == NULL) {
+        printf("Error opening output file\n");
+        exit(1);
+    }
+
+    frame = 0;
+
+    while (fread(inbuf, sizeof(short), n_samples, fin) == n_samples) {
+        PROFILE_SAMPLE(freedv_start);
+        freedv_tx(f, outbuf, inbuf);
+        PROFILE_SAMPLE_AND_LOG2(freedv_start, "  freedv_tx");     
+       
+        fwrite(outbuf, sizeof(short), n_samples, fout);
+        printf("frame: %d\n", ++frame);
+        machdep_profile_print_logged_samples();
+   }
+
+    fclose(fin);
+    fclose(fout);
+
+    return 0;
+}
+
index 267d5f9937dc07a8f41f71c0d73d97996aaa5452..c52cef4dd799b1c99551502fa97274bfe0fb53d0 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: power_ut.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 30 May 2014\r
-\r
-  Runs Codec 2, ADC, and DAC, to fully exercise STM32C so we can a feel for\r
-  run-time power consumption for SM1000 and hence dimension regulators.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdint.h>\r
-#include <math.h>\r
-\r
-#include "stm32f4xx_conf.h"\r
-#include "stm32f4xx.h"\r
-#include "stm32f4_adc.h"\r
-#include "stm32f4_dac.h"\r
-#include "gdb_stdio.h"\r
-#include "codec2.h"\r
-#include "dump.h"\r
-#include "sine.h"\r
-#include "machdep.h"\r
-\r
-#ifdef __EMBEDDED__\r
-#define printf gdb_stdio_printf\r
-#define fopen gdb_stdio_fopen\r
-#define fclose gdb_stdio_fclose\r
-#define fread gdb_stdio_fread\r
-#define fwrite gdb_stdio_fwrite\r
-#endif\r
-\r
-#define SPEED_TEST_SAMPLES 24000\r
-\r
-/* modification of test used to measure codec2 execuation speed.  We read/write ADC/DAC\r
-   but dont do anything with the samples, as they are at 16 kHz and codec needs 8 kHz.  Just\r
-   trying to exercise everything to get a feel for power consumption */\r
-\r
-static void c2speedtest(int mode, char inputfile[])\r
-{\r
-    struct CODEC2 *codec2;\r
-    short         *inbuf, *outbuf, *pinbuf, *dummy_buf;\r
-    unsigned char *bits;\r
-    int            nsam, nbit, nframes;\r
-    FILE          *fin;\r
-    int            f, nread;\r
-\r
-    codec2 = codec2_create(mode);\r
-    nsam = codec2_samples_per_frame(codec2);\r
-    nframes = SPEED_TEST_SAMPLES/nsam;\r
-    outbuf = (short*)malloc(nsam*sizeof(short));\r
-    inbuf = (short*)malloc(SPEED_TEST_SAMPLES*sizeof(short));\r
-    nbit = codec2_bits_per_frame(codec2);\r
-    bits = (unsigned char*)malloc(nbit*sizeof(char));\r
-    dummy_buf = (short*)malloc(2*nsam*sizeof(short));\r
-\r
-    fin = fopen(inputfile, "rb");\r
-    if (fin == NULL) {\r
-        printf("Error opening input file: %s\nTerminating....\n",inputfile);\r
-        exit(1);\r
-    }\r
-\r
-    printf("reading samples ....\n");\r
-    nread = fread(inbuf, sizeof(short), SPEED_TEST_SAMPLES, fin);\r
-    if (nread != SPEED_TEST_SAMPLES) {\r
-        printf("error reading %s, %d samples reqd, %d read\n", \r
-               inputfile, SPEED_TEST_SAMPLES, nread);\r
-    }\r
-    fclose(fin);\r
-    \r
-    pinbuf = inbuf;\r
-    for(f=0; f<nframes; f++) {\r
-        //printf("read ADC\n");\r
-        while(adc1_read(dummy_buf, nsam*2) == -1);  /* runs at Fs = 16kHz */\r
-\r
-        //printf("Codec 2 enc\n");\r
-       GPIOD->ODR = (1 << 13);\r
-        codec2_encode(codec2, bits, pinbuf);\r
-        pinbuf += nsam;\r
-       GPIOD->ODR &= ~(1 << 13);\r
-        //printf("Codec 2 dec\n");\r
-       codec2_decode(codec2, outbuf, bits);\r
-        \r
-        //printf("write to DAC\n");\r
-        while(dac1_write(dummy_buf, nsam*2) == -1); /* runs at Fs = 16kHz */\r
-        //printf(".");\r
-    }\r
-\r
-    free(inbuf);\r
-    free(outbuf);\r
-    free(bits);\r
-    codec2_destroy(codec2);\r
-}\r
-\r
-void gpio_init() {\r
-    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // enable the clock to GPIOD \r
-    GPIOD->MODER = (1 << 26);            // set pin 13 to be general \r
-                                         // purpose output\r
-}\r
-\r
-int main(int argc, char *argv[]) {\r
-    SystemInit();\r
-    gpio_init();\r
-    machdep_profile_init ();\r
-    adc_open(4*DAC_BUF_SZ);\r
-    dac_open(4*DAC_BUF_SZ);\r
-\r
-    printf("Starting power_ut\n");\r
-\r
-    c2speedtest(CODEC2_MODE_1600, "stm_in.raw");\r
-\r
-    printf("Finished\n");\r
-\r
-    return 0;\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: power_ut.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 30 May 2014
+
+  Runs Codec 2, ADC, and DAC, to fully exercise STM32C so we can a feel for
+  run-time power consumption for SM1000 and hence dimension regulators.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include "stm32f4xx_conf.h"
+#include "stm32f4xx.h"
+#include "stm32f4_adc.h"
+#include "stm32f4_dac.h"
+#include "gdb_stdio.h"
+#include "codec2.h"
+#include "dump.h"
+#include "sine.h"
+#include "machdep.h"
+
+#ifdef __EMBEDDED__
+#define printf gdb_stdio_printf
+#define fopen gdb_stdio_fopen
+#define fclose gdb_stdio_fclose
+#define fread gdb_stdio_fread
+#define fwrite gdb_stdio_fwrite
+#endif
+
+#define SPEED_TEST_SAMPLES 24000
+
+/* modification of test used to measure codec2 execuation speed.  We read/write ADC/DAC
+   but dont do anything with the samples, as they are at 16 kHz and codec needs 8 kHz.  Just
+   trying to exercise everything to get a feel for power consumption */
+
+static void c2speedtest(int mode, char inputfile[])
+{
+    struct CODEC2 *codec2;
+    short         *inbuf, *outbuf, *pinbuf, *dummy_buf;
+    unsigned char *bits;
+    int            nsam, nbit, nframes;
+    FILE          *fin;
+    int            f, nread;
+
+    codec2 = codec2_create(mode);
+    nsam = codec2_samples_per_frame(codec2);
+    nframes = SPEED_TEST_SAMPLES/nsam;
+    outbuf = (short*)malloc(nsam*sizeof(short));
+    inbuf = (short*)malloc(SPEED_TEST_SAMPLES*sizeof(short));
+    nbit = codec2_bits_per_frame(codec2);
+    bits = (unsigned char*)malloc(nbit*sizeof(char));
+    dummy_buf = (short*)malloc(2*nsam*sizeof(short));
+
+    fin = fopen(inputfile, "rb");
+    if (fin == NULL) {
+        printf("Error opening input file: %s\nTerminating....\n",inputfile);
+        exit(1);
+    }
+
+    printf("reading samples ....\n");
+    nread = fread(inbuf, sizeof(short), SPEED_TEST_SAMPLES, fin);
+    if (nread != SPEED_TEST_SAMPLES) {
+        printf("error reading %s, %d samples reqd, %d read\n", 
+               inputfile, SPEED_TEST_SAMPLES, nread);
+    }
+    fclose(fin);
+    
+    pinbuf = inbuf;
+    for(f=0; f<nframes; f++) {
+        //printf("read ADC\n");
+        while(adc1_read(dummy_buf, nsam*2) == -1);  /* runs at Fs = 16kHz */
+
+        //printf("Codec 2 enc\n");
+       GPIOD->ODR = (1 << 13);
+        codec2_encode(codec2, bits, pinbuf);
+        pinbuf += nsam;
+       GPIOD->ODR &= ~(1 << 13);
+        //printf("Codec 2 dec\n");
+       codec2_decode(codec2, outbuf, bits);
+        
+        //printf("write to DAC\n");
+        while(dac1_write(dummy_buf, nsam*2) == -1); /* runs at Fs = 16kHz */
+        //printf(".");
+    }
+
+    free(inbuf);
+    free(outbuf);
+    free(bits);
+    codec2_destroy(codec2);
+}
+
+void gpio_init() {
+    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // enable the clock to GPIOD 
+    GPIOD->MODER = (1 << 26);            // set pin 13 to be general 
+                                         // purpose output
+}
+
+int main(int argc, char *argv[]) {
+    SystemInit();
+    gpio_init();
+    machdep_profile_init ();
+    adc_open(4*DAC_BUF_SZ);
+    dac_open(4*DAC_BUF_SZ);
+
+    printf("Starting power_ut\n");
+
+    c2speedtest(CODEC2_MODE_1600, "stm_in.raw");
+
+    printf("Finished\n");
+
+    return 0;
+}
+
index ae0e8fe7c3f5cf1bf0c16d91f5758d9654f214c4..9209bfc0aa7e9b829a34e6bfe97341759ab9113f 100644 (file)
@@ -1,41 +1,41 @@
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: sm1000_leds_switches_ut.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: August 5 2014\r
-\r
-  Unit Test program for the SM1000 switches and LEDs driver.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2014 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include "sm1000_leds_switches.h"\r
-\r
-int main(void) {\r
-    sm1000_leds_switches_init();\r
-\r
-    while(1) {\r
-        led_pwr(switch_select());\r
-        led_ptt(switch_ptt());\r
-        led_rt(switch_back());\r
-        led_err(!switch_back());\r
-    }\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: sm1000_leds_switches_ut.c
+  AUTHOR......: David Rowe
+  DATE CREATED: August 5 2014
+
+  Unit Test program for the SM1000 switches and LEDs driver.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include "sm1000_leds_switches.h"
+
+int main(void) {
+    sm1000_leds_switches_init();
+
+    while(1) {
+        led_pwr(switch_select());
+        led_ptt(switch_ptt());
+        led_rt(switch_back());
+        led_err(!switch_back());
+    }
+}
+
index 658ab363ce3784fa4558ae93f34244a8915bb989..c5c67707eab2864e32c9c0422527c7bcd3a4c344 100644 (file)
-/**\r
-  ******************************************************************************\r
-  * @file      startup_stm32f4xx.s\r
-  * @author    MCD Application Team\r
-  * @version   V1.0.0\r
-  * @date      30-September-2011\r
-  * @brief     STM32F4xx Devices vector table for Atollic TrueSTUDIO toolchain.\r
-  *            This module performs:\r
-  *                - Set the initial SP\r
-  *                - Set the initial PC == Reset_Handler,\r
-  *                - Set the vector table entries with the exceptions ISR address\r
-  *                - Configure the clock system and the external SRAM mounted on\r
-  *                  STM324xG-EVAL board to be used as data memory (optional,\r
-  *                  to be enabled by user)\r
-  *                - Branches to main in the C library (which eventually\r
-  *                  calls main()).\r
-  *            After Reset the Cortex-M4 processor is in Thread mode,\r
-  *            priority is Privileged, and the Stack is set to Main.\r
-  ******************************************************************************\r
-  * @attention\r
-  *\r
-  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
-  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
-  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
-  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
-  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
-  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
-  *\r
-  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>\r
-  ******************************************************************************\r
-  */\r
-\r
-  .syntax unified\r
-  .cpu cortex-m3\r
-  .fpu softvfp\r
-  .thumb\r
-\r
-.global  g_pfnVectors\r
-.global  Default_Handler\r
-\r
-/* start address for the initialization values of the .data section.\r
-defined in linker script */\r
-.word  _sidata\r
-/* start address for the .data section. defined in linker script */\r
-.word  _sdata\r
-/* end address for the .data section. defined in linker script */\r
-.word  _edata\r
-/* start address for the .bss section. defined in linker script */\r
-.word  _sbss\r
-/* end address for the .bss section. defined in linker script */\r
-.word  _ebss\r
-/* stack used for SystemInit_ExtMemCtl; always internal RAM used */\r
-\r
-/**\r
- * @brief  This is the code that gets called when the processor first\r
- *          starts execution following a reset event. Only the absolutely\r
- *          necessary set is performed, after which the application\r
- *          supplied main() routine is called.\r
- * @param  None\r
- * @retval : None\r
-*/\r
-\r
-    .section  .text.Reset_Handler\r
-  .weak  Reset_Handler\r
-  .type  Reset_Handler, %function\r
-Reset_Handler:\r
-\r
-/* Copy the data segment initializers from flash to SRAM */\r
-  movs  r1, #0\r
-  b  LoopCopyDataInit\r
-\r
-CopyDataInit:\r
-  ldr  r3, =_sidata\r
-  ldr  r3, [r3, r1]\r
-  str  r3, [r0, r1]\r
-  adds  r1, r1, #4\r
-\r
-LoopCopyDataInit:\r
-  ldr  r0, =_sdata\r
-  ldr  r3, =_edata\r
-  adds  r2, r0, r1\r
-  cmp  r2, r3\r
-  bcc  CopyDataInit\r
-  ldr  r2, =_sbss\r
-  b  LoopFillZerobss\r
-/* Zero fill the bss segment. */\r
-FillZerobss:\r
-  movs  r3, #0\r
-  str  r3, [r2], #4\r
-\r
-LoopFillZerobss:\r
-  ldr  r3, = _ebss\r
-  cmp  r2, r3\r
-  bcc  FillZerobss\r
-\r
-/* Call the clock system intitialization function.*/\r
-  bl  SystemInit\r
-/* Call static constructors */\r
-    bl __libc_init_array\r
-/* Call the application's entry point.*/\r
-  bl  main\r
-  bx  lr\r
-.size  Reset_Handler, .-Reset_Handler\r
-\r
-/**\r
- * @brief  This is the code that gets called when the processor receives an\r
- *         unexpected interrupt.  This simply enters an infinite loop, preserving\r
- *         the system state for examination by a debugger.\r
- * @param  None\r
- * @retval None\r
-*/\r
-    .section  .text.Default_Handler,"ax",%progbits\r
-Default_Handler:\r
-Infinite_Loop:\r
-  b  Infinite_Loop\r
-  .size  Default_Handler, .-Default_Handler\r
-/******************************************************************************\r
-*\r
-* The minimal vector table for a Cortex M3. Note that the proper constructs\r
-* must be placed on this to ensure that it ends up at physical address\r
-* 0x0000.0000.\r
-*\r
-*******************************************************************************/\r
-   .section  .isr_vector,"a",%progbits\r
-  .type  g_pfnVectors, %object\r
-  .size  g_pfnVectors, .-g_pfnVectors\r
-\r
-\r
-g_pfnVectors:\r
-  .word  _estack\r
-  .word  Reset_Handler\r
-  .word  NMI_Handler\r
-  .word  HardFault_Handler\r
-  .word  MemManage_Handler\r
-  .word  BusFault_Handler\r
-  .word  UsageFault_Handler\r
-  .word  0\r
-  .word  0\r
-  .word  0\r
-  .word  0\r
-  .word  SVC_Handler\r
-  .word  DebugMon_Handler\r
-  .word  0\r
-  .word  PendSV_Handler\r
-  .word  SysTick_Handler\r
-\r
-  /* External Interrupts */\r
-  .word     WWDG_IRQHandler                   /* Window WatchDog              */\r
-  .word     PVD_IRQHandler                    /* PVD through EXTI Line detection */\r
-  .word     TAMP_STAMP_IRQHandler             /* Tamper and TimeStamps through the EXTI line */\r
-  .word     RTC_WKUP_IRQHandler               /* RTC Wakeup through the EXTI line */\r
-  .word     FLASH_IRQHandler                  /* FLASH                        */\r
-  .word     RCC_IRQHandler                    /* RCC                          */\r
-  .word     EXTI0_IRQHandler                  /* EXTI Line0                   */\r
-  .word     EXTI1_IRQHandler                  /* EXTI Line1                   */\r
-  .word     EXTI2_IRQHandler                  /* EXTI Line2                   */\r
-  .word     EXTI3_IRQHandler                  /* EXTI Line3                   */\r
-  .word     EXTI4_IRQHandler                  /* EXTI Line4                   */\r
-  .word     DMA1_Stream0_IRQHandler           /* DMA1 Stream 0                */\r
-  .word     DMA1_Stream1_IRQHandler           /* DMA1 Stream 1                */\r
-  .word     DMA1_Stream2_IRQHandler           /* DMA1 Stream 2                */\r
-  .word     DMA1_Stream3_IRQHandler           /* DMA1 Stream 3                */\r
-  .word     DMA1_Stream4_IRQHandler           /* DMA1 Stream 4                */\r
-  .word     DMA1_Stream5_IRQHandler           /* DMA1 Stream 5                */\r
-  .word     DMA1_Stream6_IRQHandler           /* DMA1 Stream 6                */\r
-  .word     ADC_IRQHandler                    /* ADC1, ADC2 and ADC3s         */\r
-  .word     CAN1_TX_IRQHandler                /* CAN1 TX                      */\r
-  .word     CAN1_RX0_IRQHandler               /* CAN1 RX0                     */\r
-  .word     CAN1_RX1_IRQHandler               /* CAN1 RX1                     */\r
-  .word     CAN1_SCE_IRQHandler               /* CAN1 SCE                     */\r
-  .word     EXTI9_5_IRQHandler                /* External Line[9:5]s          */\r
-  .word     TIM1_BRK_TIM9_IRQHandler          /* TIM1 Break and TIM9          */\r
-  .word     TIM1_UP_TIM10_IRQHandler          /* TIM1 Update and TIM10        */\r
-  .word     TIM1_TRG_COM_TIM11_IRQHandler     /* TIM1 Trigger and Commutation and TIM11 */\r
-  .word     TIM1_CC_IRQHandler                /* TIM1 Capture Compare         */\r
-  .word     TIM2_IRQHandler                   /* TIM2                         */\r
-  .word     TIM3_IRQHandler                   /* TIM3                         */\r
-  .word     TIM4_IRQHandler                   /* TIM4                         */\r
-  .word     I2C1_EV_IRQHandler                /* I2C1 Event                   */\r
-  .word     I2C1_ER_IRQHandler                /* I2C1 Error                   */\r
-  .word     I2C2_EV_IRQHandler                /* I2C2 Event                   */\r
-  .word     I2C2_ER_IRQHandler                /* I2C2 Error                   */\r
-  .word     SPI1_IRQHandler                   /* SPI1                         */\r
-  .word     SPI2_IRQHandler                   /* SPI2                         */\r
-  .word     USART1_IRQHandler                 /* USART1                       */\r
-  .word     USART2_IRQHandler                 /* USART2                       */\r
-  .word     USART3_IRQHandler                 /* USART3                       */\r
-  .word     EXTI15_10_IRQHandler              /* External Line[15:10]s        */\r
-  .word     RTC_Alarm_IRQHandler              /* RTC Alarm (A and B) through EXTI Line */\r
-  .word     OTG_FS_WKUP_IRQHandler            /* USB OTG FS Wakeup through EXTI line */\r
-  .word     TIM8_BRK_TIM12_IRQHandler         /* TIM8 Break and TIM12         */\r
-  .word     TIM8_UP_TIM13_IRQHandler          /* TIM8 Update and TIM13        */\r
-  .word     TIM8_TRG_COM_TIM14_IRQHandler     /* TIM8 Trigger and Commutation and TIM14 */\r
-  .word     TIM8_CC_IRQHandler                /* TIM8 Capture Compare         */\r
-  .word     DMA1_Stream7_IRQHandler           /* DMA1 Stream7                 */\r
-  .word     FSMC_IRQHandler                   /* FSMC                         */\r
-  .word     SDIO_IRQHandler                   /* SDIO                         */\r
-  .word     TIM5_IRQHandler                   /* TIM5                         */\r
-  .word     SPI3_IRQHandler                   /* SPI3                         */\r
-  .word     UART4_IRQHandler                  /* UART4                        */\r
-  .word     UART5_IRQHandler                  /* UART5                        */\r
-  .word     TIM6_DAC_IRQHandler               /* TIM6 and DAC1&2 underrun errors */\r
-  .word     TIM7_IRQHandler                   /* TIM7                         */\r
-  .word     DMA2_Stream0_IRQHandler           /* DMA2 Stream 0                */\r
-  .word     DMA2_Stream1_IRQHandler           /* DMA2 Stream 1                */\r
-  .word     DMA2_Stream2_IRQHandler           /* DMA2 Stream 2                */\r
-  .word     DMA2_Stream3_IRQHandler           /* DMA2 Stream 3                */\r
-  .word     DMA2_Stream4_IRQHandler           /* DMA2 Stream 4                */\r
-  .word     ETH_IRQHandler                    /* Ethernet                     */\r
-  .word     ETH_WKUP_IRQHandler               /* Ethernet Wakeup through EXTI line */\r
-  .word     CAN2_TX_IRQHandler                /* CAN2 TX                      */\r
-  .word     CAN2_RX0_IRQHandler               /* CAN2 RX0                     */\r
-  .word     CAN2_RX1_IRQHandler               /* CAN2 RX1                     */\r
-  .word     CAN2_SCE_IRQHandler               /* CAN2 SCE                     */\r
-  .word     OTG_FS_IRQHandler                 /* USB OTG FS                   */\r
-  .word     DMA2_Stream5_IRQHandler           /* DMA2 Stream 5                */\r
-  .word     DMA2_Stream6_IRQHandler           /* DMA2 Stream 6                */\r
-  .word     DMA2_Stream7_IRQHandler           /* DMA2 Stream 7                */\r
-  .word     USART6_IRQHandler                 /* USART6                       */\r
-  .word     I2C3_EV_IRQHandler                /* I2C3 event                   */\r
-  .word     I2C3_ER_IRQHandler                /* I2C3 error                   */\r
-  .word     OTG_HS_EP1_OUT_IRQHandler         /* USB OTG HS End Point 1 Out   */\r
-  .word     OTG_HS_EP1_IN_IRQHandler          /* USB OTG HS End Point 1 In    */\r
-  .word     OTG_HS_WKUP_IRQHandler            /* USB OTG HS Wakeup through EXTI */\r
-  .word     OTG_HS_IRQHandler                 /* USB OTG HS                   */\r
-  .word     DCMI_IRQHandler                   /* DCMI                         */\r
-  .word     CRYP_IRQHandler                   /* CRYP crypto                  */\r
-  .word     HASH_RNG_IRQHandler               /* Hash and Rng                 */\r
-  .word     FPU_IRQHandler                    /* FPU                          */\r
-\r
-\r
-/*******************************************************************************\r
-*\r
-* Provide weak aliases for each Exception handler to the Default_Handler.\r
-* As they are weak aliases, any function with the same name will override\r
-* this definition.\r
-*\r
-*******************************************************************************/\r
-   .weak      NMI_Handler\r
-   .thumb_set NMI_Handler,Default_Handler\r
-\r
-   .weak      HardFault_Handler\r
-   .thumb_set HardFault_Handler,Default_Handler\r
-\r
-   .weak      MemManage_Handler\r
-   .thumb_set MemManage_Handler,Default_Handler\r
-\r
-   .weak      BusFault_Handler\r
-   .thumb_set BusFault_Handler,Default_Handler\r
-\r
-   .weak      UsageFault_Handler\r
-   .thumb_set UsageFault_Handler,Default_Handler\r
-\r
-   .weak      SVC_Handler\r
-   .thumb_set SVC_Handler,Default_Handler\r
-\r
-   .weak      DebugMon_Handler\r
-   .thumb_set DebugMon_Handler,Default_Handler\r
-\r
-   .weak      PendSV_Handler\r
-   .thumb_set PendSV_Handler,Default_Handler\r
-\r
-   .weak      SysTick_Handler\r
-   .thumb_set SysTick_Handler,Default_Handler\r
-\r
-   .weak      WWDG_IRQHandler\r
-   .thumb_set WWDG_IRQHandler,Default_Handler\r
-\r
-   .weak      PVD_IRQHandler\r
-   .thumb_set PVD_IRQHandler,Default_Handler\r
-\r
-   .weak      TAMP_STAMP_IRQHandler\r
-   .thumb_set TAMP_STAMP_IRQHandler,Default_Handler\r
-\r
-   .weak      RTC_WKUP_IRQHandler\r
-   .thumb_set RTC_WKUP_IRQHandler,Default_Handler\r
-\r
-   .weak      FLASH_IRQHandler\r
-   .thumb_set FLASH_IRQHandler,Default_Handler\r
-\r
-   .weak      RCC_IRQHandler\r
-   .thumb_set RCC_IRQHandler,Default_Handler\r
-\r
-   .weak      EXTI0_IRQHandler\r
-   .thumb_set EXTI0_IRQHandler,Default_Handler\r
-\r
-   .weak      EXTI1_IRQHandler\r
-   .thumb_set EXTI1_IRQHandler,Default_Handler\r
-\r
-   .weak      EXTI2_IRQHandler\r
-   .thumb_set EXTI2_IRQHandler,Default_Handler\r
-\r
-   .weak      EXTI3_IRQHandler\r
-   .thumb_set EXTI3_IRQHandler,Default_Handler\r
-\r
-   .weak      EXTI4_IRQHandler\r
-   .thumb_set EXTI4_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA1_Stream0_IRQHandler\r
-   .thumb_set DMA1_Stream0_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA1_Stream1_IRQHandler\r
-   .thumb_set DMA1_Stream1_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA1_Stream2_IRQHandler\r
-   .thumb_set DMA1_Stream2_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA1_Stream3_IRQHandler\r
-   .thumb_set DMA1_Stream3_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA1_Stream4_IRQHandler\r
-   .thumb_set DMA1_Stream4_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA1_Stream5_IRQHandler\r
-   .thumb_set DMA1_Stream5_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA1_Stream6_IRQHandler\r
-   .thumb_set DMA1_Stream6_IRQHandler,Default_Handler\r
-\r
-   .weak      ADC_IRQHandler\r
-   .thumb_set ADC_IRQHandler,Default_Handler\r
-\r
-   .weak      CAN1_TX_IRQHandler\r
-   .thumb_set CAN1_TX_IRQHandler,Default_Handler\r
-\r
-   .weak      CAN1_RX0_IRQHandler\r
-   .thumb_set CAN1_RX0_IRQHandler,Default_Handler\r
-\r
-   .weak      CAN1_RX1_IRQHandler\r
-   .thumb_set CAN1_RX1_IRQHandler,Default_Handler\r
-\r
-   .weak      CAN1_SCE_IRQHandler\r
-   .thumb_set CAN1_SCE_IRQHandler,Default_Handler\r
-\r
-   .weak      EXTI9_5_IRQHandler\r
-   .thumb_set EXTI9_5_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM1_BRK_TIM9_IRQHandler\r
-   .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM1_UP_TIM10_IRQHandler\r
-   .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM1_TRG_COM_TIM11_IRQHandler\r
-   .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM1_CC_IRQHandler\r
-   .thumb_set TIM1_CC_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM2_IRQHandler\r
-   .thumb_set TIM2_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM3_IRQHandler\r
-   .thumb_set TIM3_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM4_IRQHandler\r
-   .thumb_set TIM4_IRQHandler,Default_Handler\r
-\r
-   .weak      I2C1_EV_IRQHandler\r
-   .thumb_set I2C1_EV_IRQHandler,Default_Handler\r
-\r
-   .weak      I2C1_ER_IRQHandler\r
-   .thumb_set I2C1_ER_IRQHandler,Default_Handler\r
-\r
-   .weak      I2C2_EV_IRQHandler\r
-   .thumb_set I2C2_EV_IRQHandler,Default_Handler\r
-\r
-   .weak      I2C2_ER_IRQHandler\r
-   .thumb_set I2C2_ER_IRQHandler,Default_Handler\r
-\r
-   .weak      SPI1_IRQHandler\r
-   .thumb_set SPI1_IRQHandler,Default_Handler\r
-\r
-   .weak      SPI2_IRQHandler\r
-   .thumb_set SPI2_IRQHandler,Default_Handler\r
-\r
-   .weak      USART1_IRQHandler\r
-   .thumb_set USART1_IRQHandler,Default_Handler\r
-\r
-   .weak      USART2_IRQHandler\r
-   .thumb_set USART2_IRQHandler,Default_Handler\r
-\r
-   .weak      USART3_IRQHandler\r
-   .thumb_set USART3_IRQHandler,Default_Handler\r
-\r
-   .weak      EXTI15_10_IRQHandler\r
-   .thumb_set EXTI15_10_IRQHandler,Default_Handler\r
-\r
-   .weak      RTC_Alarm_IRQHandler\r
-   .thumb_set RTC_Alarm_IRQHandler,Default_Handler\r
-\r
-   .weak      OTG_FS_WKUP_IRQHandler\r
-   .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM8_BRK_TIM12_IRQHandler\r
-   .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM8_UP_TIM13_IRQHandler\r
-   .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM8_TRG_COM_TIM14_IRQHandler\r
-   .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM8_CC_IRQHandler\r
-   .thumb_set TIM8_CC_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA1_Stream7_IRQHandler\r
-   .thumb_set DMA1_Stream7_IRQHandler,Default_Handler\r
-\r
-   .weak      FSMC_IRQHandler\r
-   .thumb_set FSMC_IRQHandler,Default_Handler\r
-\r
-   .weak      SDIO_IRQHandler\r
-   .thumb_set SDIO_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM5_IRQHandler\r
-   .thumb_set TIM5_IRQHandler,Default_Handler\r
-\r
-   .weak      SPI3_IRQHandler\r
-   .thumb_set SPI3_IRQHandler,Default_Handler\r
-\r
-   .weak      UART4_IRQHandler\r
-   .thumb_set UART4_IRQHandler,Default_Handler\r
-\r
-   .weak      UART5_IRQHandler\r
-   .thumb_set UART5_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM6_DAC_IRQHandler\r
-   .thumb_set TIM6_DAC_IRQHandler,Default_Handler\r
-\r
-   .weak      TIM7_IRQHandler\r
-   .thumb_set TIM7_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA2_Stream0_IRQHandler\r
-   .thumb_set DMA2_Stream0_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA2_Stream1_IRQHandler\r
-   .thumb_set DMA2_Stream1_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA2_Stream2_IRQHandler\r
-   .thumb_set DMA2_Stream2_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA2_Stream3_IRQHandler\r
-   .thumb_set DMA2_Stream3_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA2_Stream4_IRQHandler\r
-   .thumb_set DMA2_Stream4_IRQHandler,Default_Handler\r
-\r
-   .weak      ETH_IRQHandler\r
-   .thumb_set ETH_IRQHandler,Default_Handler\r
-\r
-   .weak      ETH_WKUP_IRQHandler\r
-   .thumb_set ETH_WKUP_IRQHandler,Default_Handler\r
-\r
-   .weak      CAN2_TX_IRQHandler\r
-   .thumb_set CAN2_TX_IRQHandler,Default_Handler\r
-\r
-   .weak      CAN2_RX0_IRQHandler\r
-   .thumb_set CAN2_RX0_IRQHandler,Default_Handler\r
-\r
-   .weak      CAN2_RX1_IRQHandler\r
-   .thumb_set CAN2_RX1_IRQHandler,Default_Handler\r
-\r
-   .weak      CAN2_SCE_IRQHandler\r
-   .thumb_set CAN2_SCE_IRQHandler,Default_Handler\r
-\r
-   .weak      OTG_FS_IRQHandler\r
-   .thumb_set OTG_FS_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA2_Stream5_IRQHandler\r
-   .thumb_set DMA2_Stream5_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA2_Stream6_IRQHandler\r
-   .thumb_set DMA2_Stream6_IRQHandler,Default_Handler\r
-\r
-   .weak      DMA2_Stream7_IRQHandler\r
-   .thumb_set DMA2_Stream7_IRQHandler,Default_Handler\r
-\r
-   .weak      USART6_IRQHandler\r
-   .thumb_set USART6_IRQHandler,Default_Handler\r
-\r
-   .weak      I2C3_EV_IRQHandler\r
-   .thumb_set I2C3_EV_IRQHandler,Default_Handler\r
-\r
-   .weak      I2C3_ER_IRQHandler\r
-   .thumb_set I2C3_ER_IRQHandler,Default_Handler\r
-\r
-   .weak      OTG_HS_EP1_OUT_IRQHandler\r
-   .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler\r
-\r
-   .weak      OTG_HS_EP1_IN_IRQHandler\r
-   .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler\r
-\r
-   .weak      OTG_HS_WKUP_IRQHandler\r
-   .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler\r
-\r
-   .weak      OTG_HS_IRQHandler\r
-   .thumb_set OTG_HS_IRQHandler,Default_Handler\r
-\r
-   .weak      DCMI_IRQHandler\r
-   .thumb_set DCMI_IRQHandler,Default_Handler\r
-\r
-   .weak      CRYP_IRQHandler\r
-   .thumb_set CRYP_IRQHandler,Default_Handler\r
-\r
-   .weak      HASH_RNG_IRQHandler\r
-   .thumb_set HASH_RNG_IRQHandler,Default_Handler\r
-\r
-   .weak      FPU_IRQHandler\r
-   .thumb_set FPU_IRQHandler,Default_Handler\r
-\r
-/*******************   (C)   COPYRIGHT   2011   STMicroelectronics   *****END   OF   FILE****/\r
+/**
+  ******************************************************************************
+  * @file      startup_stm32f4xx.s
+  * @author    MCD Application Team
+  * @version   V1.0.0
+  * @date      30-September-2011
+  * @brief     STM32F4xx Devices vector table for Atollic TrueSTUDIO toolchain.
+  *            This module performs:
+  *                - Set the initial SP
+  *                - Set the initial PC == Reset_Handler,
+  *                - Set the vector table entries with the exceptions ISR address
+  *                - Configure the clock system and the external SRAM mounted on
+  *                  STM324xG-EVAL board to be used as data memory (optional,
+  *                  to be enabled by user)
+  *                - Branches to main in the C library (which eventually
+  *                  calls main()).
+  *            After Reset the Cortex-M4 processor is in Thread mode,
+  *            priority is Privileged, and the Stack is set to Main.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+
+  .syntax unified
+  .cpu cortex-m3
+  .fpu softvfp
+  .thumb
+
+.global  g_pfnVectors
+.global  Default_Handler
+
+/* start address for the initialization values of the .data section.
+defined in linker script */
+.word  _sidata
+/* start address for the .data section. defined in linker script */
+.word  _sdata
+/* end address for the .data section. defined in linker script */
+.word  _edata
+/* start address for the .bss section. defined in linker script */
+.word  _sbss
+/* end address for the .bss section. defined in linker script */
+.word  _ebss
+/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
+
+/**
+ * @brief  This is the code that gets called when the processor first
+ *          starts execution following a reset event. Only the absolutely
+ *          necessary set is performed, after which the application
+ *          supplied main() routine is called.
+ * @param  None
+ * @retval : None
+*/
+
+    .section  .text.Reset_Handler
+  .weak  Reset_Handler
+  .type  Reset_Handler, %function
+Reset_Handler:
+
+/* Copy the data segment initializers from flash to SRAM */
+  movs  r1, #0
+  b  LoopCopyDataInit
+
+CopyDataInit:
+  ldr  r3, =_sidata
+  ldr  r3, [r3, r1]
+  str  r3, [r0, r1]
+  adds  r1, r1, #4
+
+LoopCopyDataInit:
+  ldr  r0, =_sdata
+  ldr  r3, =_edata
+  adds  r2, r0, r1
+  cmp  r2, r3
+  bcc  CopyDataInit
+  ldr  r2, =_sbss
+  b  LoopFillZerobss
+/* Zero fill the bss segment. */
+FillZerobss:
+  movs  r3, #0
+  str  r3, [r2], #4
+
+LoopFillZerobss:
+  ldr  r3, = _ebss
+  cmp  r2, r3
+  bcc  FillZerobss
+
+/* Call the clock system intitialization function.*/
+  bl  SystemInit
+/* Call static constructors */
+    bl __libc_init_array
+/* Call the application's entry point.*/
+  bl  main
+  bx  lr
+.size  Reset_Handler, .-Reset_Handler
+
+/**
+ * @brief  This is the code that gets called when the processor receives an
+ *         unexpected interrupt.  This simply enters an infinite loop, preserving
+ *         the system state for examination by a debugger.
+ * @param  None
+ * @retval None
+*/
+    .section  .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+  b  Infinite_Loop
+  .size  Default_Handler, .-Default_Handler
+/******************************************************************************
+*
+* The minimal vector table for a Cortex M3. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+*
+*******************************************************************************/
+   .section  .isr_vector,"a",%progbits
+  .type  g_pfnVectors, %object
+  .size  g_pfnVectors, .-g_pfnVectors
+
+
+g_pfnVectors:
+  .word  _estack
+  .word  Reset_Handler
+  .word  NMI_Handler
+  .word  HardFault_Handler
+  .word  MemManage_Handler
+  .word  BusFault_Handler
+  .word  UsageFault_Handler
+  .word  0
+  .word  0
+  .word  0
+  .word  0
+  .word  SVC_Handler
+  .word  DebugMon_Handler
+  .word  0
+  .word  PendSV_Handler
+  .word  SysTick_Handler
+
+  /* External Interrupts */
+  .word     WWDG_IRQHandler                   /* Window WatchDog              */
+  .word     PVD_IRQHandler                    /* PVD through EXTI Line detection */
+  .word     TAMP_STAMP_IRQHandler             /* Tamper and TimeStamps through the EXTI line */
+  .word     RTC_WKUP_IRQHandler               /* RTC Wakeup through the EXTI line */
+  .word     FLASH_IRQHandler                  /* FLASH                        */
+  .word     RCC_IRQHandler                    /* RCC                          */
+  .word     EXTI0_IRQHandler                  /* EXTI Line0                   */
+  .word     EXTI1_IRQHandler                  /* EXTI Line1                   */
+  .word     EXTI2_IRQHandler                  /* EXTI Line2                   */
+  .word     EXTI3_IRQHandler                  /* EXTI Line3                   */
+  .word     EXTI4_IRQHandler                  /* EXTI Line4                   */
+  .word     DMA1_Stream0_IRQHandler           /* DMA1 Stream 0                */
+  .word     DMA1_Stream1_IRQHandler           /* DMA1 Stream 1                */
+  .word     DMA1_Stream2_IRQHandler           /* DMA1 Stream 2                */
+  .word     DMA1_Stream3_IRQHandler           /* DMA1 Stream 3                */
+  .word     DMA1_Stream4_IRQHandler           /* DMA1 Stream 4                */
+  .word     DMA1_Stream5_IRQHandler           /* DMA1 Stream 5                */
+  .word     DMA1_Stream6_IRQHandler           /* DMA1 Stream 6                */
+  .word     ADC_IRQHandler                    /* ADC1, ADC2 and ADC3s         */
+  .word     CAN1_TX_IRQHandler                /* CAN1 TX                      */
+  .word     CAN1_RX0_IRQHandler               /* CAN1 RX0                     */
+  .word     CAN1_RX1_IRQHandler               /* CAN1 RX1                     */
+  .word     CAN1_SCE_IRQHandler               /* CAN1 SCE                     */
+  .word     EXTI9_5_IRQHandler                /* External Line[9:5]s          */
+  .word     TIM1_BRK_TIM9_IRQHandler          /* TIM1 Break and TIM9          */
+  .word     TIM1_UP_TIM10_IRQHandler          /* TIM1 Update and TIM10        */
+  .word     TIM1_TRG_COM_TIM11_IRQHandler     /* TIM1 Trigger and Commutation and TIM11 */
+  .word     TIM1_CC_IRQHandler                /* TIM1 Capture Compare         */
+  .word     TIM2_IRQHandler                   /* TIM2                         */
+  .word     TIM3_IRQHandler                   /* TIM3                         */
+  .word     TIM4_IRQHandler                   /* TIM4                         */
+  .word     I2C1_EV_IRQHandler                /* I2C1 Event                   */
+  .word     I2C1_ER_IRQHandler                /* I2C1 Error                   */
+  .word     I2C2_EV_IRQHandler                /* I2C2 Event                   */
+  .word     I2C2_ER_IRQHandler                /* I2C2 Error                   */
+  .word     SPI1_IRQHandler                   /* SPI1                         */
+  .word     SPI2_IRQHandler                   /* SPI2                         */
+  .word     USART1_IRQHandler                 /* USART1                       */
+  .word     USART2_IRQHandler                 /* USART2                       */
+  .word     USART3_IRQHandler                 /* USART3                       */
+  .word     EXTI15_10_IRQHandler              /* External Line[15:10]s        */
+  .word     RTC_Alarm_IRQHandler              /* RTC Alarm (A and B) through EXTI Line */
+  .word     OTG_FS_WKUP_IRQHandler            /* USB OTG FS Wakeup through EXTI line */
+  .word     TIM8_BRK_TIM12_IRQHandler         /* TIM8 Break and TIM12         */
+  .word     TIM8_UP_TIM13_IRQHandler          /* TIM8 Update and TIM13        */
+  .word     TIM8_TRG_COM_TIM14_IRQHandler     /* TIM8 Trigger and Commutation and TIM14 */
+  .word     TIM8_CC_IRQHandler                /* TIM8 Capture Compare         */
+  .word     DMA1_Stream7_IRQHandler           /* DMA1 Stream7                 */
+  .word     FSMC_IRQHandler                   /* FSMC                         */
+  .word     SDIO_IRQHandler                   /* SDIO                         */
+  .word     TIM5_IRQHandler                   /* TIM5                         */
+  .word     SPI3_IRQHandler                   /* SPI3                         */
+  .word     UART4_IRQHandler                  /* UART4                        */
+  .word     UART5_IRQHandler                  /* UART5                        */
+  .word     TIM6_DAC_IRQHandler               /* TIM6 and DAC1&2 underrun errors */
+  .word     TIM7_IRQHandler                   /* TIM7                         */
+  .word     DMA2_Stream0_IRQHandler           /* DMA2 Stream 0                */
+  .word     DMA2_Stream1_IRQHandler           /* DMA2 Stream 1                */
+  .word     DMA2_Stream2_IRQHandler           /* DMA2 Stream 2                */
+  .word     DMA2_Stream3_IRQHandler           /* DMA2 Stream 3                */
+  .word     DMA2_Stream4_IRQHandler           /* DMA2 Stream 4                */
+  .word     ETH_IRQHandler                    /* Ethernet                     */
+  .word     ETH_WKUP_IRQHandler               /* Ethernet Wakeup through EXTI line */
+  .word     CAN2_TX_IRQHandler                /* CAN2 TX                      */
+  .word     CAN2_RX0_IRQHandler               /* CAN2 RX0                     */
+  .word     CAN2_RX1_IRQHandler               /* CAN2 RX1                     */
+  .word     CAN2_SCE_IRQHandler               /* CAN2 SCE                     */
+  .word     OTG_FS_IRQHandler                 /* USB OTG FS                   */
+  .word     DMA2_Stream5_IRQHandler           /* DMA2 Stream 5                */
+  .word     DMA2_Stream6_IRQHandler           /* DMA2 Stream 6                */
+  .word     DMA2_Stream7_IRQHandler           /* DMA2 Stream 7                */
+  .word     USART6_IRQHandler                 /* USART6                       */
+  .word     I2C3_EV_IRQHandler                /* I2C3 event                   */
+  .word     I2C3_ER_IRQHandler                /* I2C3 error                   */
+  .word     OTG_HS_EP1_OUT_IRQHandler         /* USB OTG HS End Point 1 Out   */
+  .word     OTG_HS_EP1_IN_IRQHandler          /* USB OTG HS End Point 1 In    */
+  .word     OTG_HS_WKUP_IRQHandler            /* USB OTG HS Wakeup through EXTI */
+  .word     OTG_HS_IRQHandler                 /* USB OTG HS                   */
+  .word     DCMI_IRQHandler                   /* DCMI                         */
+  .word     CRYP_IRQHandler                   /* CRYP crypto                  */
+  .word     HASH_RNG_IRQHandler               /* Hash and Rng                 */
+  .word     FPU_IRQHandler                    /* FPU                          */
+
+
+/*******************************************************************************
+*
+* Provide weak aliases for each Exception handler to the Default_Handler.
+* As they are weak aliases, any function with the same name will override
+* this definition.
+*
+*******************************************************************************/
+   .weak      NMI_Handler
+   .thumb_set NMI_Handler,Default_Handler
+
+   .weak      HardFault_Handler
+   .thumb_set HardFault_Handler,Default_Handler
+
+   .weak      MemManage_Handler
+   .thumb_set MemManage_Handler,Default_Handler
+
+   .weak      BusFault_Handler
+   .thumb_set BusFault_Handler,Default_Handler
+
+   .weak      UsageFault_Handler
+   .thumb_set UsageFault_Handler,Default_Handler
+
+   .weak      SVC_Handler
+   .thumb_set SVC_Handler,Default_Handler
+
+   .weak      DebugMon_Handler
+   .thumb_set DebugMon_Handler,Default_Handler
+
+   .weak      PendSV_Handler
+   .thumb_set PendSV_Handler,Default_Handler
+
+   .weak      SysTick_Handler
+   .thumb_set SysTick_Handler,Default_Handler
+
+   .weak      WWDG_IRQHandler
+   .thumb_set WWDG_IRQHandler,Default_Handler
+
+   .weak      PVD_IRQHandler
+   .thumb_set PVD_IRQHandler,Default_Handler
+
+   .weak      TAMP_STAMP_IRQHandler
+   .thumb_set TAMP_STAMP_IRQHandler,Default_Handler
+
+   .weak      RTC_WKUP_IRQHandler
+   .thumb_set RTC_WKUP_IRQHandler,Default_Handler
+
+   .weak      FLASH_IRQHandler
+   .thumb_set FLASH_IRQHandler,Default_Handler
+
+   .weak      RCC_IRQHandler
+   .thumb_set RCC_IRQHandler,Default_Handler
+
+   .weak      EXTI0_IRQHandler
+   .thumb_set EXTI0_IRQHandler,Default_Handler
+
+   .weak      EXTI1_IRQHandler
+   .thumb_set EXTI1_IRQHandler,Default_Handler
+
+   .weak      EXTI2_IRQHandler
+   .thumb_set EXTI2_IRQHandler,Default_Handler
+
+   .weak      EXTI3_IRQHandler
+   .thumb_set EXTI3_IRQHandler,Default_Handler
+
+   .weak      EXTI4_IRQHandler
+   .thumb_set EXTI4_IRQHandler,Default_Handler
+
+   .weak      DMA1_Stream0_IRQHandler
+   .thumb_set DMA1_Stream0_IRQHandler,Default_Handler
+
+   .weak      DMA1_Stream1_IRQHandler
+   .thumb_set DMA1_Stream1_IRQHandler,Default_Handler
+
+   .weak      DMA1_Stream2_IRQHandler
+   .thumb_set DMA1_Stream2_IRQHandler,Default_Handler
+
+   .weak      DMA1_Stream3_IRQHandler
+   .thumb_set DMA1_Stream3_IRQHandler,Default_Handler
+
+   .weak      DMA1_Stream4_IRQHandler
+   .thumb_set DMA1_Stream4_IRQHandler,Default_Handler
+
+   .weak      DMA1_Stream5_IRQHandler
+   .thumb_set DMA1_Stream5_IRQHandler,Default_Handler
+
+   .weak      DMA1_Stream6_IRQHandler
+   .thumb_set DMA1_Stream6_IRQHandler,Default_Handler
+
+   .weak      ADC_IRQHandler
+   .thumb_set ADC_IRQHandler,Default_Handler
+
+   .weak      CAN1_TX_IRQHandler
+   .thumb_set CAN1_TX_IRQHandler,Default_Handler
+
+   .weak      CAN1_RX0_IRQHandler
+   .thumb_set CAN1_RX0_IRQHandler,Default_Handler
+
+   .weak      CAN1_RX1_IRQHandler
+   .thumb_set CAN1_RX1_IRQHandler,Default_Handler
+
+   .weak      CAN1_SCE_IRQHandler
+   .thumb_set CAN1_SCE_IRQHandler,Default_Handler
+
+   .weak      EXTI9_5_IRQHandler
+   .thumb_set EXTI9_5_IRQHandler,Default_Handler
+
+   .weak      TIM1_BRK_TIM9_IRQHandler
+   .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
+
+   .weak      TIM1_UP_TIM10_IRQHandler
+   .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
+
+   .weak      TIM1_TRG_COM_TIM11_IRQHandler
+   .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
+
+   .weak      TIM1_CC_IRQHandler
+   .thumb_set TIM1_CC_IRQHandler,Default_Handler
+
+   .weak      TIM2_IRQHandler
+   .thumb_set TIM2_IRQHandler,Default_Handler
+
+   .weak      TIM3_IRQHandler
+   .thumb_set TIM3_IRQHandler,Default_Handler
+
+   .weak      TIM4_IRQHandler
+   .thumb_set TIM4_IRQHandler,Default_Handler
+
+   .weak      I2C1_EV_IRQHandler
+   .thumb_set I2C1_EV_IRQHandler,Default_Handler
+
+   .weak      I2C1_ER_IRQHandler
+   .thumb_set I2C1_ER_IRQHandler,Default_Handler
+
+   .weak      I2C2_EV_IRQHandler
+   .thumb_set I2C2_EV_IRQHandler,Default_Handler
+
+   .weak      I2C2_ER_IRQHandler
+   .thumb_set I2C2_ER_IRQHandler,Default_Handler
+
+   .weak      SPI1_IRQHandler
+   .thumb_set SPI1_IRQHandler,Default_Handler
+
+   .weak      SPI2_IRQHandler
+   .thumb_set SPI2_IRQHandler,Default_Handler
+
+   .weak      USART1_IRQHandler
+   .thumb_set USART1_IRQHandler,Default_Handler
+
+   .weak      USART2_IRQHandler
+   .thumb_set USART2_IRQHandler,Default_Handler
+
+   .weak      USART3_IRQHandler
+   .thumb_set USART3_IRQHandler,Default_Handler
+
+   .weak      EXTI15_10_IRQHandler
+   .thumb_set EXTI15_10_IRQHandler,Default_Handler
+
+   .weak      RTC_Alarm_IRQHandler
+   .thumb_set RTC_Alarm_IRQHandler,Default_Handler
+
+   .weak      OTG_FS_WKUP_IRQHandler
+   .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
+
+   .weak      TIM8_BRK_TIM12_IRQHandler
+   .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
+
+   .weak      TIM8_UP_TIM13_IRQHandler
+   .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
+
+   .weak      TIM8_TRG_COM_TIM14_IRQHandler
+   .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
+
+   .weak      TIM8_CC_IRQHandler
+   .thumb_set TIM8_CC_IRQHandler,Default_Handler
+
+   .weak      DMA1_Stream7_IRQHandler
+   .thumb_set DMA1_Stream7_IRQHandler,Default_Handler
+
+   .weak      FSMC_IRQHandler
+   .thumb_set FSMC_IRQHandler,Default_Handler
+
+   .weak      SDIO_IRQHandler
+   .thumb_set SDIO_IRQHandler,Default_Handler
+
+   .weak      TIM5_IRQHandler
+   .thumb_set TIM5_IRQHandler,Default_Handler
+
+   .weak      SPI3_IRQHandler
+   .thumb_set SPI3_IRQHandler,Default_Handler
+
+   .weak      UART4_IRQHandler
+   .thumb_set UART4_IRQHandler,Default_Handler
+
+   .weak      UART5_IRQHandler
+   .thumb_set UART5_IRQHandler,Default_Handler
+
+   .weak      TIM6_DAC_IRQHandler
+   .thumb_set TIM6_DAC_IRQHandler,Default_Handler
+
+   .weak      TIM7_IRQHandler
+   .thumb_set TIM7_IRQHandler,Default_Handler
+
+   .weak      DMA2_Stream0_IRQHandler
+   .thumb_set DMA2_Stream0_IRQHandler,Default_Handler
+
+   .weak      DMA2_Stream1_IRQHandler
+   .thumb_set DMA2_Stream1_IRQHandler,Default_Handler
+
+   .weak      DMA2_Stream2_IRQHandler
+   .thumb_set DMA2_Stream2_IRQHandler,Default_Handler
+
+   .weak      DMA2_Stream3_IRQHandler
+   .thumb_set DMA2_Stream3_IRQHandler,Default_Handler
+
+   .weak      DMA2_Stream4_IRQHandler
+   .thumb_set DMA2_Stream4_IRQHandler,Default_Handler
+
+   .weak      ETH_IRQHandler
+   .thumb_set ETH_IRQHandler,Default_Handler
+
+   .weak      ETH_WKUP_IRQHandler
+   .thumb_set ETH_WKUP_IRQHandler,Default_Handler
+
+   .weak      CAN2_TX_IRQHandler
+   .thumb_set CAN2_TX_IRQHandler,Default_Handler
+
+   .weak      CAN2_RX0_IRQHandler
+   .thumb_set CAN2_RX0_IRQHandler,Default_Handler
+
+   .weak      CAN2_RX1_IRQHandler
+   .thumb_set CAN2_RX1_IRQHandler,Default_Handler
+
+   .weak      CAN2_SCE_IRQHandler
+   .thumb_set CAN2_SCE_IRQHandler,Default_Handler
+
+   .weak      OTG_FS_IRQHandler
+   .thumb_set OTG_FS_IRQHandler,Default_Handler
+
+   .weak      DMA2_Stream5_IRQHandler
+   .thumb_set DMA2_Stream5_IRQHandler,Default_Handler
+
+   .weak      DMA2_Stream6_IRQHandler
+   .thumb_set DMA2_Stream6_IRQHandler,Default_Handler
+
+   .weak      DMA2_Stream7_IRQHandler
+   .thumb_set DMA2_Stream7_IRQHandler,Default_Handler
+
+   .weak      USART6_IRQHandler
+   .thumb_set USART6_IRQHandler,Default_Handler
+
+   .weak      I2C3_EV_IRQHandler
+   .thumb_set I2C3_EV_IRQHandler,Default_Handler
+
+   .weak      I2C3_ER_IRQHandler
+   .thumb_set I2C3_ER_IRQHandler,Default_Handler
+
+   .weak      OTG_HS_EP1_OUT_IRQHandler
+   .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
+
+   .weak      OTG_HS_EP1_IN_IRQHandler
+   .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
+
+   .weak      OTG_HS_WKUP_IRQHandler
+   .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
+
+   .weak      OTG_HS_IRQHandler
+   .thumb_set OTG_HS_IRQHandler,Default_Handler
+
+   .weak      DCMI_IRQHandler
+   .thumb_set DCMI_IRQHandler,Default_Handler
+
+   .weak      CRYP_IRQHandler
+   .thumb_set CRYP_IRQHandler,Default_Handler
+
+   .weak      HASH_RNG_IRQHandler
+   .thumb_set HASH_RNG_IRQHandler,Default_Handler
+
+   .weak      FPU_IRQHandler
+   .thumb_set FPU_IRQHandler,Default_Handler
+
+/*******************   (C)   COPYRIGHT   2011   STMicroelectronics   *****END   OF   FILE****/
index ef65a7f597110651909c4ad6059a9fba8af146ff..cba9ea7947b037dea391b52f30e6864ce0ec076b 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: stm32f4_dac.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 1 June 2013\r
-\r
-  DAC driver module for STM32F4. DAC1 is connected to pin PA4, DAC2\r
-  is connected to pin PA5.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2013 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include "stm32f4xx.h"\r
-#include "codec2_fifo.h"\r
-#include "stm32f4_dac.h"\r
-#include "debugblinky.h"\r
-\r
-/* write to these registers for 12 bit left aligned data, as per data sheet \r
-   make sure 4 least sig bits set to 0 */\r
-\r
-#define DAC_DHR12R1_ADDRESS    0x40007408\r
-#define DAC_DHR12R2_ADDRESS    0x40007414\r
-\r
-#define DAC_MAX      4096            /* maximum amplitude */\r
-\r
-/* y=mx+c mapping of samples16 bit shorts to DAC samples.  Table: 74\r
-   of data sheet indicates With DAC buffer on, DAC range is limited to\r
-   0x0E0 to 0xF1C at VREF+ = 3.6 V, we have Vref=3.3V which is close.\r
- */\r
-\r
-#define M ((3868.0-224.0)/65536.0)\r
-#define C 2047.0\r
-\r
-static struct FIFO *dac1_fifo;\r
-static struct FIFO *dac2_fifo;\r
-\r
-static unsigned short dac1_buf[DAC_BUF_SZ];\r
-static unsigned short dac2_buf[DAC_BUF_SZ];\r
-\r
-static void tim6_config(void);\r
-static void dac1_config(void);\r
-static void dac2_config(void);\r
-\r
-int dac_underflow;\r
-\r
-void dac_open(int fifo_size) {\r
-\r
-    memset(dac1_buf, 32768, sizeof(short)*DAC_BUF_SZ);\r
-    memset(dac2_buf, 32768, sizeof(short)*DAC_BUF_SZ);\r
-\r
-    /* Create fifos */\r
-\r
-    dac1_fifo = fifo_create(fifo_size);\r
-    dac2_fifo = fifo_create(fifo_size);\r
-    assert(dac1_fifo != NULL);\r
-    assert(dac2_fifo != NULL);\r
-\r
-    /* Turn on the clocks we need -----------------------------------------------*/\r
-\r
-    /* DMA1 clock enable */\r
-    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);\r
-    /* GPIOA clock enable (to be used with DAC) */\r
-    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                         \r
-    /* DAC Periph clock enable */\r
-    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);\r
-\r
-    /* GPIO Pin configuration DAC1->PA.4, DAC2->PA.5 configuration --------------*/\r
-\r
-    GPIO_InitTypeDef GPIO_InitStructure;\r
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;\r
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;\r
-    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;\r
-    GPIO_Init(GPIOA, &GPIO_InitStructure);\r
-\r
-    /* Timer and DAC 1 & 2 Configuration ----------------------------------------*/\r
-\r
-    tim6_config();  \r
-    dac1_config();\r
-    dac2_config();\r
-\r
-    init_debug_blinky();\r
-}\r
-\r
-/* Call these puppies to send samples to the DACs.  For your\r
-   convenience they accept signed 16 bit samples. */\r
-\r
-int dac1_write(short buf[], int n) {   \r
-    return fifo_write(dac1_fifo, buf, n);\r
-}\r
-\r
-int dac2_write(short buf[], int n) {   \r
-    return fifo_write(dac2_fifo, buf, n);\r
-}\r
-\r
-int dac1_free() {\r
-    return fifo_free(dac1_fifo);\r
-}\r
-\r
-int dac2_free() {\r
-    return fifo_free(dac2_fifo);\r
-}\r
-\r
-static void tim6_config(void)\r
-{\r
-  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;\r
-\r
-  /* TIM6 Periph clock enable */\r
-  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);\r
-  \r
-  /* --------------------------------------------------------\r
-  \r
-  TIM6 input clock (TIM6CLK) is set to 2 * APB1 clock (PCLK1), since\r
-  APB1 prescaler is different from 1 (see system_stm32f4xx.c and Fig\r
-  13 clock tree figure in DM0031020.pdf).\r
-\r
-     Sample rate Fs = 2*PCLK1/TIM_ClockDivision \r
-                    = (HCLK/2)/TIM_ClockDivision\r
-                    \r
-  ----------------------------------------------------------- */\r
-\r
-  /* Time base configuration */\r
-\r
-  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); \r
-  TIM_TimeBaseStructure.TIM_Period = 5250;          \r
-  TIM_TimeBaseStructure.TIM_Prescaler = 0;       \r
-  TIM_TimeBaseStructure.TIM_ClockDivision = 0;    \r
-  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  \r
-  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);\r
-\r
-  /* TIM6 TRGO selection */\r
-\r
-  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);\r
-  \r
-  /* TIM6 enable counter */\r
-\r
-  TIM_Cmd(TIM6, ENABLE);\r
-}\r
-\r
-static void dac1_config(void)\r
-{\r
-  DAC_InitTypeDef  DAC_InitStructure;\r
-  DMA_InitTypeDef  DMA_InitStructure;\r
-  NVIC_InitTypeDef NVIC_InitStructure;\r
-  \r
-  /* DAC channel 1 Configuration */\r
-\r
-  /* \r
-     This line fixed a bug that cost me 5 days, bad wave amplitude\r
-     value, and some STM32F4 periph library bugs caused triangle wave\r
-     geneartion to be enable resulting in a low level tone on the\r
-     SM1000, that we thought was caused by analog issues like layour\r
-     or power supply biasing\r
-  */\r
-  DAC_StructInit(&DAC_InitStructure); \r
-\r
-  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO; \r
-  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;\r
-  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;\r
-  DAC_Init(DAC_Channel_1, &DAC_InitStructure);\r
-\r
-  /* DMA1_Stream5 channel7 configuration **************************************/\r
-  /* Table 35 page 219 of the monster data sheet */\r
-\r
-  DMA_DeInit(DMA1_Stream5);\r
-  DMA_InitStructure.DMA_Channel = DMA_Channel_7;  \r
-  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R1_ADDRESS;\r
-  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac1_buf;\r
-  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;\r
-  DMA_InitStructure.DMA_BufferSize = DAC_BUF_SZ;\r
-  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;\r
-  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;\r
-  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;\r
-  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;\r
-  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;\r
-  DMA_InitStructure.DMA_Priority = DMA_Priority_High;\r
-  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         \r
-  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;\r
-  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;\r
-  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;\r
-  DMA_Init(DMA1_Stream5, &DMA_InitStructure);\r
-\r
-  /* Enable DMA Half & Complete interrupts */\r
-\r
-  DMA_ITConfig(DMA1_Stream5, DMA_IT_TC | DMA_IT_HT, ENABLE);\r
-\r
-  /* Enable the DMA Stream IRQ Channel */\r
-\r
-  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;\r
-  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;\r
-  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;\r
-  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;\r
-  NVIC_Init(&NVIC_InitStructure);     \r
-\r
-  /* Enable DMA1_Stream5 */\r
-\r
-  DMA_Cmd(DMA1_Stream5, ENABLE);\r
-\r
-  /* Enable DAC Channel 1 */\r
-\r
-  DAC_Cmd(DAC_Channel_1, ENABLE);\r
-\r
-  /* Enable DMA for DAC Channel 1 */\r
-\r
-  DAC_DMACmd(DAC_Channel_1, ENABLE);\r
-}\r
-\r
-static void dac2_config(void)\r
-{\r
-  DAC_InitTypeDef  DAC_InitStructure;\r
-  DMA_InitTypeDef DMA_InitStructure;\r
-  NVIC_InitTypeDef NVIC_InitStructure;\r
-  \r
-  /* DAC channel 2 Configuration (see notes in dac1_config() above) */\r
-\r
-  DAC_StructInit(&DAC_InitStructure);\r
-  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;\r
-  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;\r
-  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;\r
-  DAC_Init(DAC_Channel_2, &DAC_InitStructure);\r
-\r
-  /* DMA1_Stream6 channel7 configuration **************************************/\r
-\r
-  DMA_DeInit(DMA1_Stream6);\r
-  DMA_InitStructure.DMA_Channel = DMA_Channel_7;  \r
-  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R2_ADDRESS;\r
-  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac2_buf;\r
-  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;\r
-  DMA_InitStructure.DMA_BufferSize = DAC_BUF_SZ;\r
-  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;\r
-  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;\r
-  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;\r
-  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;\r
-  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;\r
-  DMA_InitStructure.DMA_Priority = DMA_Priority_High;\r
-  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         \r
-  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;\r
-  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;\r
-  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;\r
-  DMA_Init(DMA1_Stream6, &DMA_InitStructure);\r
-\r
-  /* Enable DMA Half & Complete interrupts */\r
-\r
-  DMA_ITConfig(DMA1_Stream6, DMA_IT_TC | DMA_IT_HT, ENABLE);\r
-\r
-  /* Enable the DMA Stream IRQ Channel */\r
-\r
-  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;\r
-  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;\r
-  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;\r
-  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;\r
-  NVIC_Init(&NVIC_InitStructure);     \r
-\r
-  /* Enable DMA1_Stream6 */\r
-\r
-  DMA_Cmd(DMA1_Stream6, ENABLE);\r
-\r
-  /* Enable DAC Channel 2 */\r
-\r
-  DAC_Cmd(DAC_Channel_2, ENABLE);\r
-\r
-  /* Enable DMA for DAC Channel 2 */\r
-\r
-  DAC_DMACmd(DAC_Channel_2, ENABLE);\r
-\r
-}\r
-\r
-/******************************************************************************/\r
-/*                 STM32F4xx Peripherals Interrupt Handlers                   */\r
-/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */\r
-/*  available peripheral interrupt handler's name please refer to the startup */\r
-/*  file (startup_stm32f40xx.s/startup_stm32f427x.s).                         */\r
-/******************************************************************************/\r
-\r
-/*\r
-  This function handles DMA1 Stream 5 interrupt request for DAC1.\r
-*/\r
-\r
-void DMA1_Stream5_IRQHandler(void) {\r
-    int i, j, sam;\r
-    short signed_buf[DAC_BUF_SZ/2];\r
-\r
-    GPIOE->ODR |= (1 << 1);\r
-\r
-    /* Transfer half empty interrupt - refill first half */\r
-\r
-    if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_HTIF5) != RESET) {\r
-        /* fill first half from fifo */\r
-\r
-        if (fifo_read(dac1_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {\r
-            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);\r
-            dac_underflow++;\r
-        }\r
-\r
-        /* convert to unsigned */\r
-\r
-        for(i=0; i<DAC_BUF_SZ/2; i++) {\r
-            sam = (int)(M*(float)signed_buf[i] + C);\r
-            dac1_buf[i] = (unsigned short)sam;\r
-        }\r
-\r
-        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
-        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_HTIF5);  \r
-    }\r
-\r
-    /* Transfer complete interrupt - refill 2nd half */\r
-\r
-    if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5) != RESET) {\r
-        /* fill second half from fifo */\r
-\r
-        if (fifo_read(dac1_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {\r
-            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);\r
-            dac_underflow++;\r
-        }\r
-\r
-        /* convert to unsigned */\r
-\r
-        for(i=0, j=DAC_BUF_SZ/2; i<DAC_BUF_SZ/2; i++,j++) {\r
-            sam = (int)(M*(float)signed_buf[i] + C);\r
-            dac1_buf[j] = (unsigned short)sam;\r
-        }\r
-\r
-        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
-        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);  \r
-    }\r
-\r
-    GPIOE->ODR &= ~(1 << 1);\r
-}\r
-\r
-/*\r
-  This function handles DMA1 Stream 6 interrupt request for DAC2.\r
-*/\r
-\r
-void DMA1_Stream6_IRQHandler(void) {\r
-    int i, j, sam;\r
-    short signed_buf[DAC_BUF_SZ/2];\r
-\r
-    GPIOE->ODR |= (1 << 2);\r
-\r
-    /* Transfer half empty interrupt - refill first half */\r
-\r
-    if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_HTIF6) != RESET) {\r
-        /* fill first half from fifo */\r
-\r
-        if (fifo_read(dac2_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {\r
-            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);\r
-            dac_underflow++;\r
-        }\r
-\r
-        /* convert to unsigned */\r
-\r
-        for(i=0; i<DAC_BUF_SZ/2; i++) {\r
-            sam = (int)(M*(float)signed_buf[i] + C);\r
-            dac2_buf[i] = (unsigned short)sam;\r
-        }\r
-\r
-        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
-        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_HTIF6);  \r
-    }\r
-\r
-    /* Transfer complete interrupt - refill 2nd half */\r
-\r
-    if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) != RESET) {\r
-        /* fill second half from fifo */\r
-\r
-        if (fifo_read(dac2_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {\r
-            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);\r
-            dac_underflow++;\r
-        }\r
-\r
-        /* convert to unsigned  */\r
-\r
-        for(i=0, j=DAC_BUF_SZ/2; i<DAC_BUF_SZ/2; i++,j++) {\r
-            sam = (int)(M*(float)signed_buf[i] + C);\r
-            dac2_buf[j] = (unsigned short)sam;\r
-        }\r
-\r
-        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
-        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);  \r
-    }\r
-\r
-    GPIOE->ODR &= ~(1 << 2);\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: stm32f4_dac.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 1 June 2013
+
+  DAC driver module for STM32F4. DAC1 is connected to pin PA4, DAC2
+  is connected to pin PA5.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2013 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "stm32f4xx.h"
+#include "codec2_fifo.h"
+#include "stm32f4_dac.h"
+#include "debugblinky.h"
+
+/* write to these registers for 12 bit left aligned data, as per data sheet 
+   make sure 4 least sig bits set to 0 */
+
+#define DAC_DHR12R1_ADDRESS    0x40007408
+#define DAC_DHR12R2_ADDRESS    0x40007414
+
+#define DAC_MAX      4096            /* maximum amplitude */
+
+/* y=mx+c mapping of samples16 bit shorts to DAC samples.  Table: 74
+   of data sheet indicates With DAC buffer on, DAC range is limited to
+   0x0E0 to 0xF1C at VREF+ = 3.6 V, we have Vref=3.3V which is close.
+ */
+
+#define M ((3868.0-224.0)/65536.0)
+#define C 2047.0
+
+static struct FIFO *dac1_fifo;
+static struct FIFO *dac2_fifo;
+
+static unsigned short dac1_buf[DAC_BUF_SZ];
+static unsigned short dac2_buf[DAC_BUF_SZ];
+
+static void tim6_config(void);
+static void dac1_config(void);
+static void dac2_config(void);
+
+int dac_underflow;
+
+void dac_open(int fifo_size) {
+
+    memset(dac1_buf, 32768, sizeof(short)*DAC_BUF_SZ);
+    memset(dac2_buf, 32768, sizeof(short)*DAC_BUF_SZ);
+
+    /* Create fifos */
+
+    dac1_fifo = fifo_create(fifo_size);
+    dac2_fifo = fifo_create(fifo_size);
+    assert(dac1_fifo != NULL);
+    assert(dac2_fifo != NULL);
+
+    /* Turn on the clocks we need -----------------------------------------------*/
+
+    /* DMA1 clock enable */
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
+    /* GPIOA clock enable (to be used with DAC) */
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                         
+    /* DAC Periph clock enable */
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
+
+    /* GPIO Pin configuration DAC1->PA.4, DAC2->PA.5 configuration --------------*/
+
+    GPIO_InitTypeDef GPIO_InitStructure;
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+    /* Timer and DAC 1 & 2 Configuration ----------------------------------------*/
+
+    tim6_config();  
+    dac1_config();
+    dac2_config();
+
+    init_debug_blinky();
+}
+
+/* Call these puppies to send samples to the DACs.  For your
+   convenience they accept signed 16 bit samples. */
+
+int dac1_write(short buf[], int n) {   
+    return fifo_write(dac1_fifo, buf, n);
+}
+
+int dac2_write(short buf[], int n) {   
+    return fifo_write(dac2_fifo, buf, n);
+}
+
+int dac1_free() {
+    return fifo_free(dac1_fifo);
+}
+
+int dac2_free() {
+    return fifo_free(dac2_fifo);
+}
+
+static void tim6_config(void)
+{
+  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
+
+  /* TIM6 Periph clock enable */
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
+  
+  /* --------------------------------------------------------
+  
+  TIM6 input clock (TIM6CLK) is set to 2 * APB1 clock (PCLK1), since
+  APB1 prescaler is different from 1 (see system_stm32f4xx.c and Fig
+  13 clock tree figure in DM0031020.pdf).
+
+     Sample rate Fs = 2*PCLK1/TIM_ClockDivision 
+                    = (HCLK/2)/TIM_ClockDivision
+                    
+  ----------------------------------------------------------- */
+
+  /* Time base configuration */
+
+  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
+  TIM_TimeBaseStructure.TIM_Period = 5250;          
+  TIM_TimeBaseStructure.TIM_Prescaler = 0;       
+  TIM_TimeBaseStructure.TIM_ClockDivision = 0;    
+  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
+  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
+
+  /* TIM6 TRGO selection */
+
+  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
+  
+  /* TIM6 enable counter */
+
+  TIM_Cmd(TIM6, ENABLE);
+}
+
+static void dac1_config(void)
+{
+  DAC_InitTypeDef  DAC_InitStructure;
+  DMA_InitTypeDef  DMA_InitStructure;
+  NVIC_InitTypeDef NVIC_InitStructure;
+  
+  /* DAC channel 1 Configuration */
+
+  /* 
+     This line fixed a bug that cost me 5 days, bad wave amplitude
+     value, and some STM32F4 periph library bugs caused triangle wave
+     geneartion to be enable resulting in a low level tone on the
+     SM1000, that we thought was caused by analog issues like layour
+     or power supply biasing
+  */
+  DAC_StructInit(&DAC_InitStructure); 
+
+  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO; 
+  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
+  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+  DAC_Init(DAC_Channel_1, &DAC_InitStructure);
+
+  /* DMA1_Stream5 channel7 configuration **************************************/
+  /* Table 35 page 219 of the monster data sheet */
+
+  DMA_DeInit(DMA1_Stream5);
+  DMA_InitStructure.DMA_Channel = DMA_Channel_7;  
+  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R1_ADDRESS;
+  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac1_buf;
+  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+  DMA_InitStructure.DMA_BufferSize = DAC_BUF_SZ;
+  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
+  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
+  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
+  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
+  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
+  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
+  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
+  DMA_Init(DMA1_Stream5, &DMA_InitStructure);
+
+  /* Enable DMA Half & Complete interrupts */
+
+  DMA_ITConfig(DMA1_Stream5, DMA_IT_TC | DMA_IT_HT, ENABLE);
+
+  /* Enable the DMA Stream IRQ Channel */
+
+  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&NVIC_InitStructure);     
+
+  /* Enable DMA1_Stream5 */
+
+  DMA_Cmd(DMA1_Stream5, ENABLE);
+
+  /* Enable DAC Channel 1 */
+
+  DAC_Cmd(DAC_Channel_1, ENABLE);
+
+  /* Enable DMA for DAC Channel 1 */
+
+  DAC_DMACmd(DAC_Channel_1, ENABLE);
+}
+
+static void dac2_config(void)
+{
+  DAC_InitTypeDef  DAC_InitStructure;
+  DMA_InitTypeDef DMA_InitStructure;
+  NVIC_InitTypeDef NVIC_InitStructure;
+  
+  /* DAC channel 2 Configuration (see notes in dac1_config() above) */
+
+  DAC_StructInit(&DAC_InitStructure);
+  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
+  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
+  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+  DAC_Init(DAC_Channel_2, &DAC_InitStructure);
+
+  /* DMA1_Stream6 channel7 configuration **************************************/
+
+  DMA_DeInit(DMA1_Stream6);
+  DMA_InitStructure.DMA_Channel = DMA_Channel_7;  
+  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R2_ADDRESS;
+  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac2_buf;
+  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+  DMA_InitStructure.DMA_BufferSize = DAC_BUF_SZ;
+  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
+  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
+  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
+  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
+  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
+  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
+  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
+  DMA_Init(DMA1_Stream6, &DMA_InitStructure);
+
+  /* Enable DMA Half & Complete interrupts */
+
+  DMA_ITConfig(DMA1_Stream6, DMA_IT_TC | DMA_IT_HT, ENABLE);
+
+  /* Enable the DMA Stream IRQ Channel */
+
+  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&NVIC_InitStructure);     
+
+  /* Enable DMA1_Stream6 */
+
+  DMA_Cmd(DMA1_Stream6, ENABLE);
+
+  /* Enable DAC Channel 2 */
+
+  DAC_Cmd(DAC_Channel_2, ENABLE);
+
+  /* Enable DMA for DAC Channel 2 */
+
+  DAC_DMACmd(DAC_Channel_2, ENABLE);
+
+}
+
+/******************************************************************************/
+/*                 STM32F4xx Peripherals Interrupt Handlers                   */
+/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
+/*  available peripheral interrupt handler's name please refer to the startup */
+/*  file (startup_stm32f40xx.s/startup_stm32f427x.s).                         */
+/******************************************************************************/
+
+/*
+  This function handles DMA1 Stream 5 interrupt request for DAC1.
+*/
+
+void DMA1_Stream5_IRQHandler(void) {
+    int i, j, sam;
+    short signed_buf[DAC_BUF_SZ/2];
+
+    GPIOE->ODR |= (1 << 1);
+
+    /* Transfer half empty interrupt - refill first half */
+
+    if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_HTIF5) != RESET) {
+        /* fill first half from fifo */
+
+        if (fifo_read(dac1_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {
+            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);
+            dac_underflow++;
+        }
+
+        /* convert to unsigned */
+
+        for(i=0; i<DAC_BUF_SZ/2; i++) {
+            sam = (int)(M*(float)signed_buf[i] + C);
+            dac1_buf[i] = (unsigned short)sam;
+        }
+
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */
+
+        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_HTIF5);  
+    }
+
+    /* Transfer complete interrupt - refill 2nd half */
+
+    if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5) != RESET) {
+        /* fill second half from fifo */
+
+        if (fifo_read(dac1_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {
+            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);
+            dac_underflow++;
+        }
+
+        /* convert to unsigned */
+
+        for(i=0, j=DAC_BUF_SZ/2; i<DAC_BUF_SZ/2; i++,j++) {
+            sam = (int)(M*(float)signed_buf[i] + C);
+            dac1_buf[j] = (unsigned short)sam;
+        }
+
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */
+
+        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);  
+    }
+
+    GPIOE->ODR &= ~(1 << 1);
+}
+
+/*
+  This function handles DMA1 Stream 6 interrupt request for DAC2.
+*/
+
+void DMA1_Stream6_IRQHandler(void) {
+    int i, j, sam;
+    short signed_buf[DAC_BUF_SZ/2];
+
+    GPIOE->ODR |= (1 << 2);
+
+    /* Transfer half empty interrupt - refill first half */
+
+    if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_HTIF6) != RESET) {
+        /* fill first half from fifo */
+
+        if (fifo_read(dac2_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {
+            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);
+            dac_underflow++;
+        }
+
+        /* convert to unsigned */
+
+        for(i=0; i<DAC_BUF_SZ/2; i++) {
+            sam = (int)(M*(float)signed_buf[i] + C);
+            dac2_buf[i] = (unsigned short)sam;
+        }
+
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */
+
+        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_HTIF6);  
+    }
+
+    /* Transfer complete interrupt - refill 2nd half */
+
+    if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) != RESET) {
+        /* fill second half from fifo */
+
+        if (fifo_read(dac2_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {
+            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);
+            dac_underflow++;
+        }
+
+        /* convert to unsigned  */
+
+        for(i=0, j=DAC_BUF_SZ/2; i<DAC_BUF_SZ/2; i++,j++) {
+            sam = (int)(M*(float)signed_buf[i] + C);
+            dac2_buf[j] = (unsigned short)sam;
+        }
+
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */
+
+        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);  
+    }
+
+    GPIOE->ODR &= ~(1 << 2);
+}
+
index ec683c37779b63be175ced438779cb7633319d4f..da2dc45996850c5fe2acf65f5348718d97a82832 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: stm32f4_dac.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 1 June 2013\r
-\r
-  DAC driver module for STM32F4. DAC1 if fixed at Fs of 2Mhz.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2013 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include "stm32f4xx.h"\r
-#include "codec2_fifo.h"\r
-#include "stm32f4_dacduc.h"\r
-#include "debugblinky.h"\r
\r
-/* write to these registers for 12 bit left aligned data, as per data sheet \r
-   make sure 4 least sig bits set to 0 */\r
-\r
-#define DAC_DHR12R1_ADDRESS    0x40007408\r
-#define DAC_DHR12R2_ADDRESS    0x40007414\r
-\r
-#define DAC_MAX      4096            /* maximum amplitude */\r
-\r
-/* y=mx+c mapping of samples16 bit shorts to DAC samples.  Table: 74\r
-   of data sheet indicates With DAC buffer on, DAC range is limited to\r
-   0x0E0 to 0xF1C at VREF+ = 3.6 V, we have Vref=3.3V which is close.\r
- */\r
-\r
-#define M ((3868.0-224.0)/65536.0)\r
-#define C 2047.0\r
-\r
-\r
-static struct FIFO *dac1_fifo;\r
-static struct FIFO *dac2_fifo;\r
-\r
-static unsigned short dac1_buf[DAC_DUC_BUF_SZ];\r
-static unsigned short dac2_buf[DAC_BUF_SZ];\r
-\r
-static void tim6_config(void);\r
-static void tim7_config(void);\r
-static void dac1_config(void);\r
-static void dac2_config(void);\r
-\r
-int dac_underflow;\r
-\r
-void fast_dac_open(int dac1_fifo_size,int dac2_fifo_size) {\r
-\r
-    memset(dac1_buf, 32768, sizeof(short)*DAC_DUC_BUF_SZ);\r
-    memset(dac2_buf, 32768, sizeof(short)*DAC_BUF_SZ);\r
-\r
-    /* Create fifos */\r
-\r
-    dac1_fifo = fifo_create(dac1_fifo_size);\r
-    dac2_fifo = fifo_create(dac2_fifo_size);\r
-    assert(dac1_fifo != NULL);\r
-    assert(dac2_fifo != NULL);\r
-\r
-    /* Turn on the clocks we need -----------------------------------------------*/\r
-\r
-    /* DMA1 clock enable */\r
-    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);\r
-    /* GPIOA clock enable (to be used with DAC) */\r
-    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                         \r
-    /* DAC Periph clock enable */\r
-    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);\r
-\r
-    /* GPIO Pin configuration DAC1->PA.4, DAC2->PA.5 configuration --------------*/\r
-\r
-    GPIO_InitTypeDef GPIO_InitStructure;\r
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;\r
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;\r
-    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;\r
-    GPIO_Init(GPIOA, &GPIO_InitStructure);\r
-\r
-    /* Timer and DAC 1 & 2 Configuration ----------------------------------------*/\r
-    tim7_config();\r
-    tim6_config();  \r
-    dac1_config();\r
-    dac2_config();\r
-\r
-    init_debug_blinky();\r
-}\r
-\r
-\r
-/* Call these puppies to send samples to the DACs.  For your\r
-   convenience they accept signed 16 bit samples. */\r
-\r
-int dac1_write(short buf[], int n) {   \r
-    return fifo_write(dac1_fifo, buf, n);\r
-}\r
-\r
-int dac2_write(short buf[], int n) {   \r
-    return fifo_write(dac2_fifo, buf, n);\r
-}\r
-\r
-static void tim6_config(void)\r
-{\r
-  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;\r
-\r
-  /* TIM6 Periph clock enable */\r
-  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);\r
-  \r
-  /* --------------------------------------------------------\r
-  \r
-  TIM6 input clock (TIM6CLK) is set to 2 * APB1 clock (PCLK1), since\r
-  APB1 prescaler is different from 1 (see system_stm32f4xx.c and Fig\r
-  13 clock tree figure in DM0031020.pdf).\r
-\r
-     Sample rate Fs = 2*PCLK1/TIM_ClockDivision \r
-                    = (HCLK/2)/TIM_ClockDivision\r
-                    \r
-  ----------------------------------------------------------- */\r
-\r
-  /* Time base configuration */\r
-\r
-  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); \r
-  TIM_TimeBaseStructure.TIM_Period = 5250;          \r
-  TIM_TimeBaseStructure.TIM_Prescaler = 0;       \r
-  TIM_TimeBaseStructure.TIM_ClockDivision = 0;    \r
-  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  \r
-  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);\r
-\r
-  /* TIM6 TRGO selection */\r
-\r
-  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);\r
-  \r
-  /* TIM6 enable counter */\r
-\r
-  TIM_Cmd(TIM6, ENABLE);\r
-}\r
-\r
-/* Sets up tim7 to run at a high sample rate */\r
-void tim7_config(void)\r
-{\r
-  /* Set up tim7 */\r
-\r
-\r
-  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;\r
-\r
-  /* TIM7 Periph clock enable */\r
-  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);\r
-  \r
-  /* --------------------------------------------------------\r
-\r
-  \r
-  TIM7 input clock (TIM7CLK) is set to 2 * APB1 clock (PCLK1), since\r
-  APB1 prescaler is different from 1 (see system_stm32f4xx.c and Fig\r
-  13 clock tree figure in DM0031020.pdf).\r
-\r
-     Sample rate Fs = 2*PCLK1/TIM_ClockDivision \r
-                    = (HCLK/2)/TIM_ClockDivision\r
-                    \r
-  ----------------------------------------------------------- */\r
-\r
-  /* Time base configuration */\r
-\r
-  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); \r
-  TIM_TimeBaseStructure.TIM_Period = 41;          \r
-  TIM_TimeBaseStructure.TIM_Prescaler = 0;       \r
-  TIM_TimeBaseStructure.TIM_ClockDivision = 0;    \r
-  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  \r
-  TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);\r
-\r
-  /* TIM7 TRGO selection */\r
-\r
-  TIM_SelectOutputTrigger(TIM7, TIM_TRGOSource_Update);\r
-  \r
-  /* TIM7 enable counter */\r
-\r
-  TIM_Cmd(TIM7, ENABLE);\r
-}\r
-\r
-static void dac1_config(void)\r
-{\r
-  DAC_InitTypeDef  DAC_InitStructure;\r
-  DMA_InitTypeDef  DMA_InitStructure;\r
-  NVIC_InitTypeDef NVIC_InitStructure;\r
-  \r
-  /* DAC channel 1 Configuration */\r
-\r
-  /* \r
-     This line fixed a bug that cost me 5 days, bad wave amplitude\r
-     value, and some STM32F4 periph library bugs caused triangle wave\r
-     geneartion to be enable resulting in a low level tone on the\r
-     SM1000, that we thought was caused by analog issues like layour\r
-     or power supply biasing\r
-  */\r
-  DAC_StructInit(&DAC_InitStructure); \r
-\r
-  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO; \r
-  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;\r
-\r
-  /*External buffering is needed to get nice square samples at Fs=2Mhz. See DM00129215.pdf */\r
-  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;\r
-  DAC_Init(DAC_Channel_1, &DAC_InitStructure);\r
-\r
-  /* DMA1_Stream5 channel7 configuration **************************************/\r
-  /* Table 35 page 219 of the monster data sheet */\r
-\r
-  DMA_DeInit(DMA1_Stream5);\r
-  DMA_InitStructure.DMA_Channel = DMA_Channel_7;  \r
-  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R1_ADDRESS;\r
-  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac1_buf;\r
-  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;\r
-  DMA_InitStructure.DMA_BufferSize = DAC_DUC_BUF_SZ;\r
-  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;\r
-  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;\r
-  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;\r
-  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;\r
-  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;\r
-  DMA_InitStructure.DMA_Priority = DMA_Priority_High;\r
-  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         \r
-  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;\r
-  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;\r
-  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;\r
-  DMA_Init(DMA1_Stream5, &DMA_InitStructure);\r
-\r
-  /* Enable DMA Half & Complete interrupts */\r
-\r
-  DMA_ITConfig(DMA1_Stream5, DMA_IT_TC | DMA_IT_HT, ENABLE);\r
-\r
-  /* Enable the DMA Stream IRQ Channel */\r
-\r
-  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;\r
-  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;\r
-  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;\r
-  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;\r
-  NVIC_Init(&NVIC_InitStructure);     \r
-\r
-  /* Enable DMA1_Stream5 */\r
-\r
-  DMA_Cmd(DMA1_Stream5, ENABLE);\r
-\r
-  /* Enable DAC Channel 1 */\r
-\r
-  DAC_Cmd(DAC_Channel_1, ENABLE);\r
-\r
-  /* Enable DMA for DAC Channel 1 */\r
-\r
-  DAC_DMACmd(DAC_Channel_1, ENABLE);\r
-}\r
-\r
-static void dac2_config(void)\r
-{\r
-  DAC_InitTypeDef  DAC_InitStructure;\r
-  DMA_InitTypeDef DMA_InitStructure;\r
-  NVIC_InitTypeDef NVIC_InitStructure;\r
-  \r
-  /* DAC channel 2 Configuration (see notes in dac1_config() above) */\r
-\r
-  DAC_StructInit(&DAC_InitStructure);\r
-  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;\r
-  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;\r
-  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;\r
-  DAC_Init(DAC_Channel_2, &DAC_InitStructure);\r
-\r
-  /* DMA1_Stream6 channel7 configuration **************************************/\r
-\r
-  DMA_DeInit(DMA1_Stream6);\r
-  DMA_InitStructure.DMA_Channel = DMA_Channel_7;  \r
-  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R2_ADDRESS;\r
-  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac2_buf;\r
-  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;\r
-  DMA_InitStructure.DMA_BufferSize = DAC_BUF_SZ;\r
-  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;\r
-  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;\r
-  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;\r
-  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;\r
-  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;\r
-  DMA_InitStructure.DMA_Priority = DMA_Priority_High;\r
-  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         \r
-  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;\r
-  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;\r
-  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;\r
-  DMA_Init(DMA1_Stream6, &DMA_InitStructure);\r
-\r
-  /* Enable DMA Half & Complete interrupts */\r
-\r
-  DMA_ITConfig(DMA1_Stream6, DMA_IT_TC | DMA_IT_HT, ENABLE);\r
-\r
-  /* Enable the DMA Stream IRQ Channel */\r
-\r
-  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;\r
-  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;\r
-  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;\r
-  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;\r
-  NVIC_Init(&NVIC_InitStructure);     \r
-\r
-  /* Enable DMA1_Stream6 */\r
-\r
-  DMA_Cmd(DMA1_Stream6, ENABLE);\r
-\r
-  /* Enable DAC Channel 2 */\r
-\r
-  DAC_Cmd(DAC_Channel_2, ENABLE);\r
-\r
-  /* Enable DMA for DAC Channel 2 */\r
-\r
-  DAC_DMACmd(DAC_Channel_2, ENABLE);\r
-\r
-}\r
-\r
-/******************************************************************************/\r
-/*                 STM32F4xx Peripherals Interrupt Handlers                   */\r
-/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */\r
-/*  available peripheral interrupt handler's name please refer to the startup */\r
-/*  file (startup_stm32f40xx.s/startup_stm32f427x.s).                         */\r
-/******************************************************************************/\r
-\r
-/*\r
-  This function handles DMA1 Stream 5 interrupt request for DAC1.\r
-*/\r
-\r
-void DMA1_Stream5_IRQHandler(void) {\r
-    GPIOE->ODR |= (1 << 1);\r
-\r
-    /* Transfer half empty interrupt - refill first half */\r
-\r
-    if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_HTIF5) != RESET) {\r
-        /* fill first half from fifo */\r
-       fifo_read(dac1_fifo, (short*)dac1_buf, DAC_DUC_BUF_SZ/2);\r
-\r
-        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_HTIF5);  \r
-    }\r
-\r
-    /* Transfer complete interrupt - refill 2nd half */\r
-\r
-    if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5) != RESET) {\r
-        /* fill second half from fifo */\r
-       fifo_read(dac1_fifo, (short*)(dac1_buf+DAC_DUC_BUF_SZ/2), DAC_DUC_BUF_SZ/2);\r
-\r
-        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);  \r
-    }\r
-\r
-    GPIOE->ODR &= ~(1 << 1);\r
-}\r
-\r
-/*\r
-  This function handles DMA1 Stream 6 interrupt request for DAC2.\r
-*/\r
-\r
-void DMA1_Stream6_IRQHandler(void) {\r
-    int i, j, sam;\r
-    short signed_buf[DAC_BUF_SZ/2];\r
-\r
-    GPIOE->ODR |= (1 << 2);\r
-\r
-    /* Transfer half empty interrupt - refill first half */\r
-\r
-    if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_HTIF6) != RESET) {\r
-        /* fill first half from fifo */\r
-\r
-        if (fifo_read(dac2_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {\r
-            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);\r
-            dac_underflow++;\r
-        }\r
-\r
-        /* convert to unsigned */\r
-\r
-        for(i=0; i<DAC_BUF_SZ/2; i++) {\r
-            sam = (int)(M*(float)signed_buf[i] + C);\r
-            dac2_buf[i] = (unsigned short)sam;\r
-        }\r
-\r
-        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
-        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_HTIF6);  \r
-    }\r
-\r
-    /* Transfer complete interrupt - refill 2nd half */\r
-\r
-    if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) != RESET) {\r
-        /* fill second half from fifo */\r
-\r
-        if (fifo_read(dac2_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {\r
-            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);\r
-            dac_underflow++;\r
-        }\r
-\r
-        /* convert to unsigned  */\r
-\r
-        for(i=0, j=DAC_BUF_SZ/2; i<DAC_BUF_SZ/2; i++,j++) {\r
-            sam = (int)(M*(float)signed_buf[i] + C);\r
-            dac2_buf[j] = (unsigned short)sam;\r
-        }\r
-\r
-        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
-        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);  \r
-    }\r
-\r
-    GPIOE->ODR &= ~(1 << 2);\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: stm32f4_dac.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 1 June 2013
+
+  DAC driver module for STM32F4. DAC1 if fixed at Fs of 2Mhz.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2013 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "stm32f4xx.h"
+#include "codec2_fifo.h"
+#include "stm32f4_dacduc.h"
+#include "debugblinky.h"
+/* write to these registers for 12 bit left aligned data, as per data sheet 
+   make sure 4 least sig bits set to 0 */
+
+#define DAC_DHR12R1_ADDRESS    0x40007408
+#define DAC_DHR12R2_ADDRESS    0x40007414
+
+#define DAC_MAX      4096            /* maximum amplitude */
+
+/* y=mx+c mapping of samples16 bit shorts to DAC samples.  Table: 74
+   of data sheet indicates With DAC buffer on, DAC range is limited to
+   0x0E0 to 0xF1C at VREF+ = 3.6 V, we have Vref=3.3V which is close.
+ */
+
+#define M ((3868.0-224.0)/65536.0)
+#define C 2047.0
+
+
+static struct FIFO *dac1_fifo;
+static struct FIFO *dac2_fifo;
+
+static unsigned short dac1_buf[DAC_DUC_BUF_SZ];
+static unsigned short dac2_buf[DAC_BUF_SZ];
+
+static void tim6_config(void);
+static void tim7_config(void);
+static void dac1_config(void);
+static void dac2_config(void);
+
+int dac_underflow;
+
+void fast_dac_open(int dac1_fifo_size,int dac2_fifo_size) {
+
+    memset(dac1_buf, 32768, sizeof(short)*DAC_DUC_BUF_SZ);
+    memset(dac2_buf, 32768, sizeof(short)*DAC_BUF_SZ);
+
+    /* Create fifos */
+
+    dac1_fifo = fifo_create(dac1_fifo_size);
+    dac2_fifo = fifo_create(dac2_fifo_size);
+    assert(dac1_fifo != NULL);
+    assert(dac2_fifo != NULL);
+
+    /* Turn on the clocks we need -----------------------------------------------*/
+
+    /* DMA1 clock enable */
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
+    /* GPIOA clock enable (to be used with DAC) */
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                         
+    /* DAC Periph clock enable */
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
+
+    /* GPIO Pin configuration DAC1->PA.4, DAC2->PA.5 configuration --------------*/
+
+    GPIO_InitTypeDef GPIO_InitStructure;
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+    /* Timer and DAC 1 & 2 Configuration ----------------------------------------*/
+    tim7_config();
+    tim6_config();  
+    dac1_config();
+    dac2_config();
+
+    init_debug_blinky();
+}
+
+
+/* Call these puppies to send samples to the DACs.  For your
+   convenience they accept signed 16 bit samples. */
+
+int dac1_write(short buf[], int n) {   
+    return fifo_write(dac1_fifo, buf, n);
+}
+
+int dac2_write(short buf[], int n) {   
+    return fifo_write(dac2_fifo, buf, n);
+}
+
+static void tim6_config(void)
+{
+  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
+
+  /* TIM6 Periph clock enable */
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
+  
+  /* --------------------------------------------------------
+  
+  TIM6 input clock (TIM6CLK) is set to 2 * APB1 clock (PCLK1), since
+  APB1 prescaler is different from 1 (see system_stm32f4xx.c and Fig
+  13 clock tree figure in DM0031020.pdf).
+
+     Sample rate Fs = 2*PCLK1/TIM_ClockDivision 
+                    = (HCLK/2)/TIM_ClockDivision
+                    
+  ----------------------------------------------------------- */
+
+  /* Time base configuration */
+
+  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
+  TIM_TimeBaseStructure.TIM_Period = 5250;          
+  TIM_TimeBaseStructure.TIM_Prescaler = 0;       
+  TIM_TimeBaseStructure.TIM_ClockDivision = 0;    
+  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
+  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
+
+  /* TIM6 TRGO selection */
+
+  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
+  
+  /* TIM6 enable counter */
+
+  TIM_Cmd(TIM6, ENABLE);
+}
+
+/* Sets up tim7 to run at a high sample rate */
+void tim7_config(void)
+{
+  /* Set up tim7 */
+
+
+  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
+
+  /* TIM7 Periph clock enable */
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
+  
+  /* --------------------------------------------------------
+
+  
+  TIM7 input clock (TIM7CLK) is set to 2 * APB1 clock (PCLK1), since
+  APB1 prescaler is different from 1 (see system_stm32f4xx.c and Fig
+  13 clock tree figure in DM0031020.pdf).
+
+     Sample rate Fs = 2*PCLK1/TIM_ClockDivision 
+                    = (HCLK/2)/TIM_ClockDivision
+                    
+  ----------------------------------------------------------- */
+
+  /* Time base configuration */
+
+  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
+  TIM_TimeBaseStructure.TIM_Period = 41;          
+  TIM_TimeBaseStructure.TIM_Prescaler = 0;       
+  TIM_TimeBaseStructure.TIM_ClockDivision = 0;    
+  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
+  TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
+
+  /* TIM7 TRGO selection */
+
+  TIM_SelectOutputTrigger(TIM7, TIM_TRGOSource_Update);
+  
+  /* TIM7 enable counter */
+
+  TIM_Cmd(TIM7, ENABLE);
+}
+
+static void dac1_config(void)
+{
+  DAC_InitTypeDef  DAC_InitStructure;
+  DMA_InitTypeDef  DMA_InitStructure;
+  NVIC_InitTypeDef NVIC_InitStructure;
+  
+  /* DAC channel 1 Configuration */
+
+  /* 
+     This line fixed a bug that cost me 5 days, bad wave amplitude
+     value, and some STM32F4 periph library bugs caused triangle wave
+     geneartion to be enable resulting in a low level tone on the
+     SM1000, that we thought was caused by analog issues like layour
+     or power supply biasing
+  */
+  DAC_StructInit(&DAC_InitStructure); 
+
+  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO; 
+  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
+
+  /*External buffering is needed to get nice square samples at Fs=2Mhz. See DM00129215.pdf */
+  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
+  DAC_Init(DAC_Channel_1, &DAC_InitStructure);
+
+  /* DMA1_Stream5 channel7 configuration **************************************/
+  /* Table 35 page 219 of the monster data sheet */
+
+  DMA_DeInit(DMA1_Stream5);
+  DMA_InitStructure.DMA_Channel = DMA_Channel_7;  
+  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R1_ADDRESS;
+  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac1_buf;
+  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+  DMA_InitStructure.DMA_BufferSize = DAC_DUC_BUF_SZ;
+  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
+  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
+  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
+  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
+  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
+  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
+  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
+  DMA_Init(DMA1_Stream5, &DMA_InitStructure);
+
+  /* Enable DMA Half & Complete interrupts */
+
+  DMA_ITConfig(DMA1_Stream5, DMA_IT_TC | DMA_IT_HT, ENABLE);
+
+  /* Enable the DMA Stream IRQ Channel */
+
+  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&NVIC_InitStructure);     
+
+  /* Enable DMA1_Stream5 */
+
+  DMA_Cmd(DMA1_Stream5, ENABLE);
+
+  /* Enable DAC Channel 1 */
+
+  DAC_Cmd(DAC_Channel_1, ENABLE);
+
+  /* Enable DMA for DAC Channel 1 */
+
+  DAC_DMACmd(DAC_Channel_1, ENABLE);
+}
+
+static void dac2_config(void)
+{
+  DAC_InitTypeDef  DAC_InitStructure;
+  DMA_InitTypeDef DMA_InitStructure;
+  NVIC_InitTypeDef NVIC_InitStructure;
+  
+  /* DAC channel 2 Configuration (see notes in dac1_config() above) */
+
+  DAC_StructInit(&DAC_InitStructure);
+  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
+  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
+  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+  DAC_Init(DAC_Channel_2, &DAC_InitStructure);
+
+  /* DMA1_Stream6 channel7 configuration **************************************/
+
+  DMA_DeInit(DMA1_Stream6);
+  DMA_InitStructure.DMA_Channel = DMA_Channel_7;  
+  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R2_ADDRESS;
+  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac2_buf;
+  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+  DMA_InitStructure.DMA_BufferSize = DAC_BUF_SZ;
+  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
+  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
+  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
+  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
+  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
+  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
+  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
+  DMA_Init(DMA1_Stream6, &DMA_InitStructure);
+
+  /* Enable DMA Half & Complete interrupts */
+
+  DMA_ITConfig(DMA1_Stream6, DMA_IT_TC | DMA_IT_HT, ENABLE);
+
+  /* Enable the DMA Stream IRQ Channel */
+
+  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&NVIC_InitStructure);     
+
+  /* Enable DMA1_Stream6 */
+
+  DMA_Cmd(DMA1_Stream6, ENABLE);
+
+  /* Enable DAC Channel 2 */
+
+  DAC_Cmd(DAC_Channel_2, ENABLE);
+
+  /* Enable DMA for DAC Channel 2 */
+
+  DAC_DMACmd(DAC_Channel_2, ENABLE);
+
+}
+
+/******************************************************************************/
+/*                 STM32F4xx Peripherals Interrupt Handlers                   */
+/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
+/*  available peripheral interrupt handler's name please refer to the startup */
+/*  file (startup_stm32f40xx.s/startup_stm32f427x.s).                         */
+/******************************************************************************/
+
+/*
+  This function handles DMA1 Stream 5 interrupt request for DAC1.
+*/
+
+void DMA1_Stream5_IRQHandler(void) {
+    GPIOE->ODR |= (1 << 1);
+
+    /* Transfer half empty interrupt - refill first half */
+
+    if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_HTIF5) != RESET) {
+        /* fill first half from fifo */
+       fifo_read(dac1_fifo, (short*)dac1_buf, DAC_DUC_BUF_SZ/2);
+
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */
+        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_HTIF5);  
+    }
+
+    /* Transfer complete interrupt - refill 2nd half */
+
+    if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5) != RESET) {
+        /* fill second half from fifo */
+       fifo_read(dac1_fifo, (short*)(dac1_buf+DAC_DUC_BUF_SZ/2), DAC_DUC_BUF_SZ/2);
+
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */
+        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);  
+    }
+
+    GPIOE->ODR &= ~(1 << 1);
+}
+
+/*
+  This function handles DMA1 Stream 6 interrupt request for DAC2.
+*/
+
+void DMA1_Stream6_IRQHandler(void) {
+    int i, j, sam;
+    short signed_buf[DAC_BUF_SZ/2];
+
+    GPIOE->ODR |= (1 << 2);
+
+    /* Transfer half empty interrupt - refill first half */
+
+    if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_HTIF6) != RESET) {
+        /* fill first half from fifo */
+
+        if (fifo_read(dac2_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {
+            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);
+            dac_underflow++;
+        }
+
+        /* convert to unsigned */
+
+        for(i=0; i<DAC_BUF_SZ/2; i++) {
+            sam = (int)(M*(float)signed_buf[i] + C);
+            dac2_buf[i] = (unsigned short)sam;
+        }
+
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */
+
+        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_HTIF6);  
+    }
+
+    /* Transfer complete interrupt - refill 2nd half */
+
+    if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) != RESET) {
+        /* fill second half from fifo */
+
+        if (fifo_read(dac2_fifo, signed_buf, DAC_BUF_SZ/2) == -1) {
+            memset(signed_buf, 0, sizeof(short)*DAC_BUF_SZ/2);
+            dac_underflow++;
+        }
+
+        /* convert to unsigned  */
+
+        for(i=0, j=DAC_BUF_SZ/2; i<DAC_BUF_SZ/2; i++,j++) {
+            sam = (int)(M*(float)signed_buf[i] + C);
+            dac2_buf[j] = (unsigned short)sam;
+        }
+
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */
+
+        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);  
+    }
+
+    GPIOE->ODR &= ~(1 << 2);
+}
+
index 86953137bc6e5fc6184a5e627dce47bd8c2a6005..08f36260ea43296277dff70cbe3bb6787f30ef65 100644 (file)
-/**\r
- ******************************************************************************\r
- * @file    system_stm32f4xx.c\r
- * @author  MCD Application Team\r
- * @version V1.0.1\r
- * @date    10-July-2012\r
- * @brief   CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.\r
- *          This file contains the system clock configuration for STM32F4xx devices,\r
- *          and is generated by the clock configuration tool\r
- *          stm32f4xx_Clock_Configuration_V1.0.1.xls\r
- *\r
- * 1.  This file provides two functions and one global variable to be called from\r
- *     user application:\r
- *      - SystemInit(): Setups the system clock (System clock source, PLL Multiplier\r
- *                      and Divider factors, AHB/APBx prescalers and Flash settings),\r
- *                      depending on the configuration made in the clock xls tool.\r
- *                      This function is called at startup just after reset and\r
- *                      before branch to main program. This call is made inside\r
- *                      the "startup_stm32f4xx.s" file.\r
- *\r
- *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used\r
- *                                  by the user application to setup the SysTick\r
- *                                  timer or configure other parameters.\r
- *\r
- *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must\r
- *                                 be called whenever the core clock is changed\r
- *                                 during program execution.\r
- *\r
- * 2. After each device reset the HSI (16 MHz) is used as system clock source.\r
- *    Then SystemInit() function is called, in "startup_stm32f4xx.s" file, to\r
- *    configure the system clock before to branch to main program.\r
- *\r
- * 3. If the system clock source selected by user fails to startup, the SystemInit()\r
- *    function will do nothing and HSI still used as system clock source. User can\r
- *    add some code to deal with this issue inside the SetSysClock() function.\r
- *\r
- * 4. The default value of HSE crystal is set to 25MHz, refer to "HSE_VALUE" define\r
- *    in "stm32f4xx.h" file. When HSE is used as system clock source, directly or\r
- *    through PLL, and you are using different crystal you have to adapt the HSE\r
- *    value to your own configuration.\r
- *\r
- * 5. This file configures the system clock as follows:\r
- *=============================================================================\r
- *=============================================================================\r
- *        Supported STM32F4xx device revision    | Rev A\r
- *-----------------------------------------------------------------------------\r
- *        System Clock source                    | PLL (HSE)\r
- *-----------------------------------------------------------------------------\r
- *        SYSCLK(Hz)                             | 168000000\r
- *-----------------------------------------------------------------------------\r
- *        HCLK(Hz)                               | 168000000\r
- *-----------------------------------------------------------------------------\r
- *        AHB Prescaler                          | 1\r
- *-----------------------------------------------------------------------------\r
- *        APB1 Prescaler                         | 4\r
- *-----------------------------------------------------------------------------\r
- *        APB2 Prescaler                         | 2\r
- *-----------------------------------------------------------------------------\r
- *        HSE Frequency(Hz)                      | 8000000\r
- *-----------------------------------------------------------------------------\r
- *        PLL_M                                  | 8\r
- *-----------------------------------------------------------------------------\r
- *        PLL_N                                  | 336\r
- *-----------------------------------------------------------------------------\r
- *        PLL_P                                  | 2\r
- *-----------------------------------------------------------------------------\r
- *        PLL_Q                                  | 7\r
- *-----------------------------------------------------------------------------\r
- *        PLLI2S_N                               | 352\r
- *-----------------------------------------------------------------------------\r
- *        PLLI2S_R                               | 2\r
- *-----------------------------------------------------------------------------\r
- *        I2S input clock(Hz)                    | 176000000\r
- *                                               |\r
- *        To achieve the following I2S config:   |\r
- *         - Master clock output (MCKO): OFF     |\r
- *         - Frame wide                : 16bit   |\r
- *         - Error %                   : 0,0000  |\r
- *         - Prescaler Odd factor (ODD): 1       |\r
- *         - Linear prescaler (DIV)    : 14      |\r
- *-----------------------------------------------------------------------------\r
- *        VDD(V)                                 | 3,3\r
- *-----------------------------------------------------------------------------\r
- *        Main regulator output voltage          | Scale1 mode\r
- *-----------------------------------------------------------------------------\r
- *        Flash Latency(WS)                      | 5\r
- *-----------------------------------------------------------------------------\r
- *        Prefetch Buffer                        | OFF\r
- *-----------------------------------------------------------------------------\r
- *        Instruction cache                      | ON\r
- *-----------------------------------------------------------------------------\r
- *        Data cache                             | ON\r
- *-----------------------------------------------------------------------------\r
- *        Require 48MHz for USB OTG FS,          | Enabled\r
- *        SDIO and RNG clock                     |\r
- *-----------------------------------------------------------------------------\r
- *=============================================================================\r
- ******************************************************************************\r
- * @attention\r
- *\r
- * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
- * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
- * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
- * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
- * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
- * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
- *\r
- * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>\r
- ******************************************************************************\r
- */\r
-\r
-/** @addtogroup CMSIS\r
- * @{\r
- */\r
-\r
-/** @addtogroup stm32f4xx_system\r
- * @{\r
- */\r
-\r
-/** @addtogroup STM32F4xx_System_Private_Includes\r
- * @{\r
- */\r
-\r
-#include "stm32f4xx.h"\r
-\r
-/**\r
- * @}\r
- */\r
-\r
-/** @addtogroup STM32F4xx_System_Private_TypesDefinitions\r
- * @{\r
- */\r
-\r
-/**\r
- * @}\r
- */\r
-\r
-/** @addtogroup STM32F4xx_System_Private_Defines\r
- * @{\r
- */\r
-\r
-/************************* Miscellaneous Configuration ************************/\r
-/*!< Uncomment the following line if you need to use external SRAM mounted\r
-     on STM324xG_EVAL board as data memory  */\r
-/* #define DATA_IN_ExtSRAM */\r
-\r
-/*!< Uncomment the following line if you need to relocate your vector Table in\r
-     Internal SRAM. */\r
-/* #define VECT_TAB_SRAM */\r
-#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field. \r
-                                   This value must be a multiple of 0x200. */\r
-/******************************************************************************/\r
-\r
-/************************* PLL Parameters *************************************/\r
-/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */\r
-#define PLL_M      8\r
-#define PLL_N      336\r
-\r
-/* SYSCLK = PLL_VCO / PLL_P */\r
-#define PLL_P      2\r
-\r
-/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */\r
-#define PLL_Q      7\r
-\r
-/* PLLI2S_VCO = (HSE_VALUE Or HSI_VALUE / PLL_M) * PLLI2S_N\r
-   I2SCLK = PLLI2S_VCO / PLLI2S_R */\r
-#define START_I2SCLOCK         0\r
-#define PLLI2S_N               352\r
-#define PLLI2S_R               2\r
-\r
-/******************************************************************************/\r
-\r
-/**\r
- * @}\r
- */\r
-\r
-/** @addtogroup STM32F4xx_System_Private_Macros\r
- * @{\r
- */\r
-\r
-/**\r
- * @}\r
- */\r
-\r
-/** @addtogroup STM32F4xx_System_Private_Variables\r
- * @{\r
- */\r
-\r
-uint32_t SystemCoreClock = 168000000;\r
-\r
-__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};\r
-\r
-/**\r
- * @}\r
- */\r
-\r
-/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes\r
- * @{\r
- */\r
-\r
-static void SetSysClock(void);\r
-#ifdef DATA_IN_ExtSRAM\r
-static void SystemInit_ExtMemCtl(void);\r
-#endif /* DATA_IN_ExtSRAM */\r
-\r
-/**\r
- * @}\r
- */\r
-\r
-/** @addtogroup STM32F4xx_System_Private_Functions\r
- * @{\r
- */\r
-\r
-/**\r
- * @brief  Setup the microcontroller system\r
- *         Initialize the Embedded Flash Interface, the PLL and update the\r
- *         SystemFrequency variable.\r
- * @param  None\r
- * @retval None\r
- */\r
-void SystemInit(void)\r
-{\r
-       /* FPU settings ------------------------------------------------------------*/\r
-#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)\r
-       SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */\r
-#endif\r
-       /* Reset the RCC clock configuration to the default reset state ------------*/\r
-       /* Set HSION bit */\r
-       RCC->CR |= (uint32_t)0x00000001;\r
-\r
-       /* Reset CFGR register */\r
-       RCC->CFGR = 0x00000000;\r
-\r
-       /* Reset HSEON, CSSON and PLLON bits */\r
-       RCC->CR &= (uint32_t)0xFEF6FFFF;\r
-\r
-       /* Reset PLLCFGR register */\r
-       RCC->PLLCFGR = 0x24003010;\r
-\r
-       /* Reset HSEBYP bit */\r
-       RCC->CR &= (uint32_t)0xFFFBFFFF;\r
-\r
-       /* Disable all interrupts */\r
-       RCC->CIR = 0x00000000;\r
-\r
-#ifdef DATA_IN_ExtSRAM\r
-       SystemInit_ExtMemCtl();\r
-#endif /* DATA_IN_ExtSRAM */\r
-\r
-       /* Configure the System clock source, PLL Multiplier and Divider factors,\r
-     AHB/APBx prescalers and Flash settings ----------------------------------*/\r
-       SetSysClock();\r
-\r
-       /* Configure the Vector Table location add offset address ------------------*/\r
-#ifdef VECT_TAB_SRAM\r
-       SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */\r
-#else\r
-       SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */\r
-#endif\r
-}\r
-\r
-/**\r
- * @brief  Update SystemCoreClock variable according to Clock Register Values.\r
- *         The SystemCoreClock variable contains the core clock (HCLK), it can\r
- *         be used by the user application to setup the SysTick timer or configure\r
- *         other parameters.\r
- *\r
- * @note   Each time the core clock (HCLK) changes, this function must be called\r
- *         to update SystemCoreClock variable value. Otherwise, any configuration\r
- *         based on this variable will be incorrect.\r
- *\r
- * @note   - The system frequency computed by this function is not the real\r
- *           frequency in the chip. It is calculated based on the predefined\r
- *           constant and the selected clock source:\r
- *\r
- *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)\r
- *\r
- *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)\r
- *\r
- *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)\r
- *             or HSI_VALUE(*) multiplied/divided by the PLL factors.\r
- *\r
- *         (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value\r
- *             16 MHz) but the real value may vary depending on the variations\r
- *             in voltage and temperature.\r
- *\r
- *         (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value\r
- *              25 MHz), user has to ensure that HSE_VALUE is same as the real\r
- *              frequency of the crystal used. Otherwise, this function may\r
- *              have wrong result.\r
- *\r
- *         - The result of this function could be not correct when using fractional\r
- *           value for HSE crystal.\r
- *\r
- * @param  None\r
- * @retval None\r
- */\r
-void SystemCoreClockUpdate(void)\r
-{\r
-       uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;\r
-\r
-       /* Get SYSCLK source -------------------------------------------------------*/\r
-       tmp = RCC->CFGR & RCC_CFGR_SWS;\r
-\r
-       switch (tmp)\r
-       {\r
-       case 0x00:  /* HSI used as system clock source */\r
-               SystemCoreClock = HSI_VALUE;\r
-               break;\r
-       case 0x04:  /* HSE used as system clock source */\r
-               SystemCoreClock = HSE_VALUE;\r
-               break;\r
-       case 0x08:  /* PLL used as system clock source */\r
-\r
-               /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N\r
-         SYSCLK = PLL_VCO / PLL_P\r
-                */\r
-               pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;\r
-               pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;\r
-\r
-               if (pllsource != 0)\r
-               {\r
-                       /* HSE used as PLL clock source */\r
-                       pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);\r
-               }\r
-               else\r
-               {\r
-                       /* HSI used as PLL clock source */\r
-                       pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);\r
-               }\r
-\r
-               pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;\r
-               SystemCoreClock = pllvco/pllp;\r
-               break;\r
-       default:\r
-               SystemCoreClock = HSI_VALUE;\r
-               break;\r
-       }\r
-       /* Compute HCLK frequency --------------------------------------------------*/\r
-       /* Get HCLK prescaler */\r
-       tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];\r
-       /* HCLK frequency */\r
-       SystemCoreClock >>= tmp;\r
-}\r
-\r
-/**\r
- * @brief  Configures the System clock source, PLL Multiplier and Divider factors,\r
- *         AHB/APBx prescalers and Flash settings\r
- * @Note   This function should be called only once the RCC clock configuration\r
- *         is reset to the default reset state (done in SystemInit() function).\r
- * @param  None\r
- * @retval None\r
- */\r
-static void SetSysClock(void)\r
-{\r
-       /******************************************************************************/\r
-       /*            PLL (clocked by HSE) used as System clock source                */\r
-       /******************************************************************************/\r
-       __IO uint32_t StartUpCounter = 0, HSEStatus = 0;\r
-\r
-       /* Enable HSE */\r
-       RCC->CR |= ((uint32_t)RCC_CR_HSEON);\r
-\r
-       /* Wait till HSE is ready and if Time out is reached exit */\r
-       do\r
-       {\r
-               HSEStatus = RCC->CR & RCC_CR_HSERDY;\r
-               StartUpCounter++;\r
-       } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));\r
-\r
-       if ((RCC->CR & RCC_CR_HSERDY) != RESET)\r
-       {\r
-               HSEStatus = (uint32_t)0x01;\r
-       }\r
-       else\r
-       {\r
-               HSEStatus = (uint32_t)0x00;\r
-       }\r
-\r
-       if (HSEStatus == (uint32_t)0x01)\r
-       {\r
-               /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */\r
-               RCC->APB1ENR |= RCC_APB1ENR_PWREN;\r
-               PWR->CR |= PWR_CR_VOS;\r
-\r
-               /* HCLK = SYSCLK / 1*/\r
-               RCC->CFGR |= RCC_CFGR_HPRE_DIV1;\r
-\r
-               /* PCLK2 = HCLK / 2*/\r
-               RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;\r
-\r
-               /* PCLK1 = HCLK / 4*/\r
-               RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;\r
-\r
-               /* Configure the main PLL */\r
-               RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |\r
-                               (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);\r
-\r
-               /* Enable the main PLL */\r
-               RCC->CR |= RCC_CR_PLLON;\r
-\r
-               /* Wait till the main PLL is ready */\r
-               while((RCC->CR & RCC_CR_PLLRDY) == 0)\r
-               {\r
-               }\r
-\r
-               /* Configure Flash prefetch, Instruction cache, Data cache and wait state */\r
-               FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;\r
-\r
-               /* Select the main PLL as system clock source */\r
-               RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));\r
-               RCC->CFGR |= RCC_CFGR_SW_PLL;\r
-\r
-               /* Wait till the main PLL is used as system clock source */\r
-               while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);\r
-               {\r
-               }\r
-       }\r
-       else\r
-       { /* If HSE fails to start-up, the application will have wrong clock\r
-         configuration. User can add here some code to deal with this error */\r
-       }\r
-\r
-\r
-       /******************************************************************************/\r
-       /*                          I2S clock configuration                           */\r
-       /******************************************************************************/\r
-\r
-#if START_I2SCLOCK\r
-       /* PLLI2S clock used as I2S clock source */\r
-       RCC->CFGR &= ~RCC_CFGR_I2SSRC;\r
-\r
-       /* Configure PLLI2S */\r
-       RCC->PLLI2SCFGR = (PLLI2S_N << 6) | (PLLI2S_R << 28);\r
-\r
-       /* Enable PLLI2S */\r
-       RCC->CR |= ((uint32_t)RCC_CR_PLLI2SON);\r
-\r
-       /* Wait till PLLI2S is ready */\r
-       while((RCC->CR & RCC_CR_PLLI2SRDY) == 0)\r
-       {\r
-       }\r
-#endif\r
-}\r
-\r
-/**\r
- * @brief  Setup the external memory controller. Called in startup_stm32f4xx.s\r
- *          before jump to __main\r
- * @param  None\r
- * @retval None\r
- */\r
-#ifdef DATA_IN_ExtSRAM\r
-/**\r
- * @brief  Setup the external memory controller.\r
- *         Called in startup_stm32f4xx.s before jump to main.\r
- *         This function configures the external SRAM mounted on STM324xG_EVAL board\r
- *         This SRAM will be used as program data memory (including heap and stack).\r
- * @param  None\r
- * @retval None\r
- */\r
-void SystemInit_ExtMemCtl(void)\r
-{\r
-       /*-- GPIOs Configuration -----------------------------------------------------*/\r
-       /*\r
- +-------------------+--------------------+------------------+------------------+\r
- +                       SRAM pins assignment                                   +\r
- +-------------------+--------------------+------------------+------------------+\r
- | PD0  <-> FSMC_D2  | PE0  <-> FSMC_NBL0 | PF0  <-> FSMC_A0 | PG0 <-> FSMC_A10 | \r
- | PD1  <-> FSMC_D3  | PE1  <-> FSMC_NBL1 | PF1  <-> FSMC_A1 | PG1 <-> FSMC_A11 | \r
- | PD4  <-> FSMC_NOE | PE3  <-> FSMC_A19  | PF2  <-> FSMC_A2 | PG2 <-> FSMC_A12 | \r
- | PD5  <-> FSMC_NWE | PE4  <-> FSMC_A20  | PF3  <-> FSMC_A3 | PG3 <-> FSMC_A13 | \r
- | PD8  <-> FSMC_D13 | PE7  <-> FSMC_D4   | PF4  <-> FSMC_A4 | PG4 <-> FSMC_A14 | \r
- | PD9  <-> FSMC_D14 | PE8  <-> FSMC_D5   | PF5  <-> FSMC_A5 | PG5 <-> FSMC_A15 | \r
- | PD10 <-> FSMC_D15 | PE9  <-> FSMC_D6   | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | \r
- | PD11 <-> FSMC_A16 | PE10 <-> FSMC_D7   | PF13 <-> FSMC_A7 |------------------+\r
- | PD12 <-> FSMC_A17 | PE11 <-> FSMC_D8   | PF14 <-> FSMC_A8 | \r
- | PD13 <-> FSMC_A18 | PE12 <-> FSMC_D9   | PF15 <-> FSMC_A9 | \r
- | PD14 <-> FSMC_D0  | PE13 <-> FSMC_D10  |------------------+\r
- | PD15 <-> FSMC_D1  | PE14 <-> FSMC_D11  |\r
- |                   | PE15 <-> FSMC_D12  |\r
- +-------------------+--------------------+\r
-        */\r
-       /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */\r
-       RCC->AHB1ENR   = 0x00000078;\r
-\r
-       /* Connect PDx pins to FSMC Alternate function */\r
-       GPIOD->AFR[0]  = 0x00cc00cc;\r
-       GPIOD->AFR[1]  = 0xcc0ccccc;\r
-       /* Configure PDx pins in Alternate function mode */\r
-       GPIOD->MODER   = 0xaaaa0a0a;\r
-       /* Configure PDx pins speed to 100 MHz */\r
-       GPIOD->OSPEEDR = 0xffff0f0f;\r
-       /* Configure PDx pins Output type to push-pull */\r
-       GPIOD->OTYPER  = 0x00000000;\r
-       /* No pull-up, pull-down for PDx pins */\r
-       GPIOD->PUPDR   = 0x00000000;\r
-\r
-       /* Connect PEx pins to FSMC Alternate function */\r
-       GPIOE->AFR[0]  = 0xc00cc0cc;\r
-       GPIOE->AFR[1]  = 0xcccccccc;\r
-       /* Configure PEx pins in Alternate function mode */\r
-       GPIOE->MODER   = 0xaaaa828a;\r
-       /* Configure PEx pins speed to 100 MHz */\r
-       GPIOE->OSPEEDR = 0xffffc3cf;\r
-       /* Configure PEx pins Output type to push-pull */\r
-       GPIOE->OTYPER  = 0x00000000;\r
-       /* No pull-up, pull-down for PEx pins */\r
-       GPIOE->PUPDR   = 0x00000000;\r
-\r
-       /* Connect PFx pins to FSMC Alternate function */\r
-       GPIOF->AFR[0]  = 0x00cccccc;\r
-       GPIOF->AFR[1]  = 0xcccc0000;\r
-       /* Configure PFx pins in Alternate function mode */\r
-       GPIOF->MODER   = 0xaa000aaa;\r
-       /* Configure PFx pins speed to 100 MHz */\r
-       GPIOF->OSPEEDR = 0xff000fff;\r
-       /* Configure PFx pins Output type to push-pull */\r
-       GPIOF->OTYPER  = 0x00000000;\r
-       /* No pull-up, pull-down for PFx pins */\r
-       GPIOF->PUPDR   = 0x00000000;\r
-\r
-       /* Connect PGx pins to FSMC Alternate function */\r
-       GPIOG->AFR[0]  = 0x00cccccc;\r
-       GPIOG->AFR[1]  = 0x000000c0;\r
-       /* Configure PGx pins in Alternate function mode */\r
-       GPIOG->MODER   = 0x00080aaa;\r
-       /* Configure PGx pins speed to 100 MHz */\r
-       GPIOG->OSPEEDR = 0x000c0fff;\r
-       /* Configure PGx pins Output type to push-pull */\r
-       GPIOG->OTYPER  = 0x00000000;\r
-       /* No pull-up, pull-down for PGx pins */\r
-       GPIOG->PUPDR   = 0x00000000;\r
-\r
-       /*-- FSMC Configuration ------------------------------------------------------*/\r
-       /* Enable the FSMC interface clock */\r
-       RCC->AHB3ENR         = 0x00000001;\r
-\r
-       /* Configure and enable Bank1_SRAM2 */\r
-       FSMC_Bank1->BTCR[2]  = 0x00001015;\r
-       FSMC_Bank1->BTCR[3]  = 0x00010603;\r
-       FSMC_Bank1E->BWTR[2] = 0x0fffffff;\r
-       /*\r
-  Bank1_SRAM2 is configured as follow:\r
-\r
-  p.FSMC_AddressSetupTime = 3;\r
-  p.FSMC_AddressHoldTime = 0;\r
-  p.FSMC_DataSetupTime = 6;\r
-  p.FSMC_BusTurnAroundDuration = 1;\r
-  p.FSMC_CLKDivision = 0;\r
-  p.FSMC_DataLatency = 0;\r
-  p.FSMC_AccessMode = FSMC_AccessMode_A;\r
-\r
-  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2;\r
-  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;\r
-  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM;\r
-  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;\r
-  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;\r
-  FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;  \r
-  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;\r
-  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;\r
-  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;\r
-  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;\r
-  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;\r
-  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;\r
-  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;\r
-  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;\r
-  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;\r
-        */\r
-}\r
-#endif /* DATA_IN_ExtSRAM */\r
-\r
-\r
-/**\r
- * @}\r
- */\r
-\r
-/**\r
- * @}\r
- */\r
-\r
-/**\r
- * @}\r
- */\r
-/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/\r
+/**
+ ******************************************************************************
+ * @file    system_stm32f4xx.c
+ * @author  MCD Application Team
+ * @version V1.0.1
+ * @date    10-July-2012
+ * @brief   CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
+ *          This file contains the system clock configuration for STM32F4xx devices,
+ *          and is generated by the clock configuration tool
+ *          stm32f4xx_Clock_Configuration_V1.0.1.xls
+ *
+ * 1.  This file provides two functions and one global variable to be called from
+ *     user application:
+ *      - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
+ *                      and Divider factors, AHB/APBx prescalers and Flash settings),
+ *                      depending on the configuration made in the clock xls tool.
+ *                      This function is called at startup just after reset and
+ *                      before branch to main program. This call is made inside
+ *                      the "startup_stm32f4xx.s" file.
+ *
+ *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
+ *                                  by the user application to setup the SysTick
+ *                                  timer or configure other parameters.
+ *
+ *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
+ *                                 be called whenever the core clock is changed
+ *                                 during program execution.
+ *
+ * 2. After each device reset the HSI (16 MHz) is used as system clock source.
+ *    Then SystemInit() function is called, in "startup_stm32f4xx.s" file, to
+ *    configure the system clock before to branch to main program.
+ *
+ * 3. If the system clock source selected by user fails to startup, the SystemInit()
+ *    function will do nothing and HSI still used as system clock source. User can
+ *    add some code to deal with this issue inside the SetSysClock() function.
+ *
+ * 4. The default value of HSE crystal is set to 25MHz, refer to "HSE_VALUE" define
+ *    in "stm32f4xx.h" file. When HSE is used as system clock source, directly or
+ *    through PLL, and you are using different crystal you have to adapt the HSE
+ *    value to your own configuration.
+ *
+ * 5. This file configures the system clock as follows:
+ *=============================================================================
+ *=============================================================================
+ *        Supported STM32F4xx device revision    | Rev A
+ *-----------------------------------------------------------------------------
+ *        System Clock source                    | PLL (HSE)
+ *-----------------------------------------------------------------------------
+ *        SYSCLK(Hz)                             | 168000000
+ *-----------------------------------------------------------------------------
+ *        HCLK(Hz)                               | 168000000
+ *-----------------------------------------------------------------------------
+ *        AHB Prescaler                          | 1
+ *-----------------------------------------------------------------------------
+ *        APB1 Prescaler                         | 4
+ *-----------------------------------------------------------------------------
+ *        APB2 Prescaler                         | 2
+ *-----------------------------------------------------------------------------
+ *        HSE Frequency(Hz)                      | 8000000
+ *-----------------------------------------------------------------------------
+ *        PLL_M                                  | 8
+ *-----------------------------------------------------------------------------
+ *        PLL_N                                  | 336
+ *-----------------------------------------------------------------------------
+ *        PLL_P                                  | 2
+ *-----------------------------------------------------------------------------
+ *        PLL_Q                                  | 7
+ *-----------------------------------------------------------------------------
+ *        PLLI2S_N                               | 352
+ *-----------------------------------------------------------------------------
+ *        PLLI2S_R                               | 2
+ *-----------------------------------------------------------------------------
+ *        I2S input clock(Hz)                    | 176000000
+ *                                               |
+ *        To achieve the following I2S config:   |
+ *         - Master clock output (MCKO): OFF     |
+ *         - Frame wide                : 16bit   |
+ *         - Error %                   : 0,0000  |
+ *         - Prescaler Odd factor (ODD): 1       |
+ *         - Linear prescaler (DIV)    : 14      |
+ *-----------------------------------------------------------------------------
+ *        VDD(V)                                 | 3,3
+ *-----------------------------------------------------------------------------
+ *        Main regulator output voltage          | Scale1 mode
+ *-----------------------------------------------------------------------------
+ *        Flash Latency(WS)                      | 5
+ *-----------------------------------------------------------------------------
+ *        Prefetch Buffer                        | OFF
+ *-----------------------------------------------------------------------------
+ *        Instruction cache                      | ON
+ *-----------------------------------------------------------------------------
+ *        Data cache                             | ON
+ *-----------------------------------------------------------------------------
+ *        Require 48MHz for USB OTG FS,          | Enabled
+ *        SDIO and RNG clock                     |
+ *-----------------------------------------------------------------------------
+ *=============================================================================
+ ******************************************************************************
+ * @attention
+ *
+ * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+ * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+ * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32f4xx_system
+ * @{
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Includes
+ * @{
+ */
+
+#include "stm32f4xx.h"
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Defines
+ * @{
+ */
+
+/************************* Miscellaneous Configuration ************************/
+/*!< Uncomment the following line if you need to use external SRAM mounted
+     on STM324xG_EVAL board as data memory  */
+/* #define DATA_IN_ExtSRAM */
+
+/*!< Uncomment the following line if you need to relocate your vector Table in
+     Internal SRAM. */
+/* #define VECT_TAB_SRAM */
+#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field. 
+                                   This value must be a multiple of 0x200. */
+/******************************************************************************/
+
+/************************* PLL Parameters *************************************/
+/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
+#define PLL_M      8
+#define PLL_N      336
+
+/* SYSCLK = PLL_VCO / PLL_P */
+#define PLL_P      2
+
+/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
+#define PLL_Q      7
+
+/* PLLI2S_VCO = (HSE_VALUE Or HSI_VALUE / PLL_M) * PLLI2S_N
+   I2SCLK = PLLI2S_VCO / PLLI2S_R */
+#define START_I2SCLOCK         0
+#define PLLI2S_N               352
+#define PLLI2S_R               2
+
+/******************************************************************************/
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Variables
+ * @{
+ */
+
+uint32_t SystemCoreClock = 168000000;
+
+__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
+ * @{
+ */
+
+static void SetSysClock(void);
+#ifdef DATA_IN_ExtSRAM
+static void SystemInit_ExtMemCtl(void);
+#endif /* DATA_IN_ExtSRAM */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief  Setup the microcontroller system
+ *         Initialize the Embedded Flash Interface, the PLL and update the
+ *         SystemFrequency variable.
+ * @param  None
+ * @retval None
+ */
+void SystemInit(void)
+{
+       /* FPU settings ------------------------------------------------------------*/
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+       SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
+#endif
+       /* Reset the RCC clock configuration to the default reset state ------------*/
+       /* Set HSION bit */
+       RCC->CR |= (uint32_t)0x00000001;
+
+       /* Reset CFGR register */
+       RCC->CFGR = 0x00000000;
+
+       /* Reset HSEON, CSSON and PLLON bits */
+       RCC->CR &= (uint32_t)0xFEF6FFFF;
+
+       /* Reset PLLCFGR register */
+       RCC->PLLCFGR = 0x24003010;
+
+       /* Reset HSEBYP bit */
+       RCC->CR &= (uint32_t)0xFFFBFFFF;
+
+       /* Disable all interrupts */
+       RCC->CIR = 0x00000000;
+
+#ifdef DATA_IN_ExtSRAM
+       SystemInit_ExtMemCtl();
+#endif /* DATA_IN_ExtSRAM */
+
+       /* Configure the System clock source, PLL Multiplier and Divider factors,
+     AHB/APBx prescalers and Flash settings ----------------------------------*/
+       SetSysClock();
+
+       /* Configure the Vector Table location add offset address ------------------*/
+#ifdef VECT_TAB_SRAM
+       SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
+#else
+       SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
+#endif
+}
+
+/**
+ * @brief  Update SystemCoreClock variable according to Clock Register Values.
+ *         The SystemCoreClock variable contains the core clock (HCLK), it can
+ *         be used by the user application to setup the SysTick timer or configure
+ *         other parameters.
+ *
+ * @note   Each time the core clock (HCLK) changes, this function must be called
+ *         to update SystemCoreClock variable value. Otherwise, any configuration
+ *         based on this variable will be incorrect.
+ *
+ * @note   - The system frequency computed by this function is not the real
+ *           frequency in the chip. It is calculated based on the predefined
+ *           constant and the selected clock source:
+ *
+ *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
+ *
+ *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
+ *
+ *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
+ *             or HSI_VALUE(*) multiplied/divided by the PLL factors.
+ *
+ *         (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value
+ *             16 MHz) but the real value may vary depending on the variations
+ *             in voltage and temperature.
+ *
+ *         (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value
+ *              25 MHz), user has to ensure that HSE_VALUE is same as the real
+ *              frequency of the crystal used. Otherwise, this function may
+ *              have wrong result.
+ *
+ *         - The result of this function could be not correct when using fractional
+ *           value for HSE crystal.
+ *
+ * @param  None
+ * @retval None
+ */
+void SystemCoreClockUpdate(void)
+{
+       uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
+
+       /* Get SYSCLK source -------------------------------------------------------*/
+       tmp = RCC->CFGR & RCC_CFGR_SWS;
+
+       switch (tmp)
+       {
+       case 0x00:  /* HSI used as system clock source */
+               SystemCoreClock = HSI_VALUE;
+               break;
+       case 0x04:  /* HSE used as system clock source */
+               SystemCoreClock = HSE_VALUE;
+               break;
+       case 0x08:  /* PLL used as system clock source */
+
+               /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
+         SYSCLK = PLL_VCO / PLL_P
+                */
+               pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
+               pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+
+               if (pllsource != 0)
+               {
+                       /* HSE used as PLL clock source */
+                       pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+               }
+               else
+               {
+                       /* HSI used as PLL clock source */
+                       pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+               }
+
+               pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
+               SystemCoreClock = pllvco/pllp;
+               break;
+       default:
+               SystemCoreClock = HSI_VALUE;
+               break;
+       }
+       /* Compute HCLK frequency --------------------------------------------------*/
+       /* Get HCLK prescaler */
+       tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
+       /* HCLK frequency */
+       SystemCoreClock >>= tmp;
+}
+
+/**
+ * @brief  Configures the System clock source, PLL Multiplier and Divider factors,
+ *         AHB/APBx prescalers and Flash settings
+ * @Note   This function should be called only once the RCC clock configuration
+ *         is reset to the default reset state (done in SystemInit() function).
+ * @param  None
+ * @retval None
+ */
+static void SetSysClock(void)
+{
+       /******************************************************************************/
+       /*            PLL (clocked by HSE) used as System clock source                */
+       /******************************************************************************/
+       __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+       /* Enable HSE */
+       RCC->CR |= ((uint32_t)RCC_CR_HSEON);
+
+       /* Wait till HSE is ready and if Time out is reached exit */
+       do
+       {
+               HSEStatus = RCC->CR & RCC_CR_HSERDY;
+               StartUpCounter++;
+       } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+       if ((RCC->CR & RCC_CR_HSERDY) != RESET)
+       {
+               HSEStatus = (uint32_t)0x01;
+       }
+       else
+       {
+               HSEStatus = (uint32_t)0x00;
+       }
+
+       if (HSEStatus == (uint32_t)0x01)
+       {
+               /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */
+               RCC->APB1ENR |= RCC_APB1ENR_PWREN;
+               PWR->CR |= PWR_CR_VOS;
+
+               /* HCLK = SYSCLK / 1*/
+               RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
+
+               /* PCLK2 = HCLK / 2*/
+               RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
+
+               /* PCLK1 = HCLK / 4*/
+               RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
+
+               /* Configure the main PLL */
+               RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
+                               (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
+
+               /* Enable the main PLL */
+               RCC->CR |= RCC_CR_PLLON;
+
+               /* Wait till the main PLL is ready */
+               while((RCC->CR & RCC_CR_PLLRDY) == 0)
+               {
+               }
+
+               /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
+               FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
+
+               /* Select the main PLL as system clock source */
+               RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
+               RCC->CFGR |= RCC_CFGR_SW_PLL;
+
+               /* Wait till the main PLL is used as system clock source */
+               while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
+               {
+               }
+       }
+       else
+       { /* If HSE fails to start-up, the application will have wrong clock
+         configuration. User can add here some code to deal with this error */
+       }
+
+
+       /******************************************************************************/
+       /*                          I2S clock configuration                           */
+       /******************************************************************************/
+
+#if START_I2SCLOCK
+       /* PLLI2S clock used as I2S clock source */
+       RCC->CFGR &= ~RCC_CFGR_I2SSRC;
+
+       /* Configure PLLI2S */
+       RCC->PLLI2SCFGR = (PLLI2S_N << 6) | (PLLI2S_R << 28);
+
+       /* Enable PLLI2S */
+       RCC->CR |= ((uint32_t)RCC_CR_PLLI2SON);
+
+       /* Wait till PLLI2S is ready */
+       while((RCC->CR & RCC_CR_PLLI2SRDY) == 0)
+       {
+       }
+#endif
+}
+
+/**
+ * @brief  Setup the external memory controller. Called in startup_stm32f4xx.s
+ *          before jump to __main
+ * @param  None
+ * @retval None
+ */
+#ifdef DATA_IN_ExtSRAM
+/**
+ * @brief  Setup the external memory controller.
+ *         Called in startup_stm32f4xx.s before jump to main.
+ *         This function configures the external SRAM mounted on STM324xG_EVAL board
+ *         This SRAM will be used as program data memory (including heap and stack).
+ * @param  None
+ * @retval None
+ */
+void SystemInit_ExtMemCtl(void)
+{
+       /*-- GPIOs Configuration -----------------------------------------------------*/
+       /*
+ +-------------------+--------------------+------------------+------------------+
+ +                       SRAM pins assignment                                   +
+ +-------------------+--------------------+------------------+------------------+
+ | PD0  <-> FSMC_D2  | PE0  <-> FSMC_NBL0 | PF0  <-> FSMC_A0 | PG0 <-> FSMC_A10 | 
+ | PD1  <-> FSMC_D3  | PE1  <-> FSMC_NBL1 | PF1  <-> FSMC_A1 | PG1 <-> FSMC_A11 | 
+ | PD4  <-> FSMC_NOE | PE3  <-> FSMC_A19  | PF2  <-> FSMC_A2 | PG2 <-> FSMC_A12 | 
+ | PD5  <-> FSMC_NWE | PE4  <-> FSMC_A20  | PF3  <-> FSMC_A3 | PG3 <-> FSMC_A13 | 
+ | PD8  <-> FSMC_D13 | PE7  <-> FSMC_D4   | PF4  <-> FSMC_A4 | PG4 <-> FSMC_A14 | 
+ | PD9  <-> FSMC_D14 | PE8  <-> FSMC_D5   | PF5  <-> FSMC_A5 | PG5 <-> FSMC_A15 | 
+ | PD10 <-> FSMC_D15 | PE9  <-> FSMC_D6   | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | 
+ | PD11 <-> FSMC_A16 | PE10 <-> FSMC_D7   | PF13 <-> FSMC_A7 |------------------+
+ | PD12 <-> FSMC_A17 | PE11 <-> FSMC_D8   | PF14 <-> FSMC_A8 | 
+ | PD13 <-> FSMC_A18 | PE12 <-> FSMC_D9   | PF15 <-> FSMC_A9 | 
+ | PD14 <-> FSMC_D0  | PE13 <-> FSMC_D10  |------------------+
+ | PD15 <-> FSMC_D1  | PE14 <-> FSMC_D11  |
+ |                   | PE15 <-> FSMC_D12  |
+ +-------------------+--------------------+
+        */
+       /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
+       RCC->AHB1ENR   = 0x00000078;
+
+       /* Connect PDx pins to FSMC Alternate function */
+       GPIOD->AFR[0]  = 0x00cc00cc;
+       GPIOD->AFR[1]  = 0xcc0ccccc;
+       /* Configure PDx pins in Alternate function mode */
+       GPIOD->MODER   = 0xaaaa0a0a;
+       /* Configure PDx pins speed to 100 MHz */
+       GPIOD->OSPEEDR = 0xffff0f0f;
+       /* Configure PDx pins Output type to push-pull */
+       GPIOD->OTYPER  = 0x00000000;
+       /* No pull-up, pull-down for PDx pins */
+       GPIOD->PUPDR   = 0x00000000;
+
+       /* Connect PEx pins to FSMC Alternate function */
+       GPIOE->AFR[0]  = 0xc00cc0cc;
+       GPIOE->AFR[1]  = 0xcccccccc;
+       /* Configure PEx pins in Alternate function mode */
+       GPIOE->MODER   = 0xaaaa828a;
+       /* Configure PEx pins speed to 100 MHz */
+       GPIOE->OSPEEDR = 0xffffc3cf;
+       /* Configure PEx pins Output type to push-pull */
+       GPIOE->OTYPER  = 0x00000000;
+       /* No pull-up, pull-down for PEx pins */
+       GPIOE->PUPDR   = 0x00000000;
+
+       /* Connect PFx pins to FSMC Alternate function */
+       GPIOF->AFR[0]  = 0x00cccccc;
+       GPIOF->AFR[1]  = 0xcccc0000;
+       /* Configure PFx pins in Alternate function mode */
+       GPIOF->MODER   = 0xaa000aaa;
+       /* Configure PFx pins speed to 100 MHz */
+       GPIOF->OSPEEDR = 0xff000fff;
+       /* Configure PFx pins Output type to push-pull */
+       GPIOF->OTYPER  = 0x00000000;
+       /* No pull-up, pull-down for PFx pins */
+       GPIOF->PUPDR   = 0x00000000;
+
+       /* Connect PGx pins to FSMC Alternate function */
+       GPIOG->AFR[0]  = 0x00cccccc;
+       GPIOG->AFR[1]  = 0x000000c0;
+       /* Configure PGx pins in Alternate function mode */
+       GPIOG->MODER   = 0x00080aaa;
+       /* Configure PGx pins speed to 100 MHz */
+       GPIOG->OSPEEDR = 0x000c0fff;
+       /* Configure PGx pins Output type to push-pull */
+       GPIOG->OTYPER  = 0x00000000;
+       /* No pull-up, pull-down for PGx pins */
+       GPIOG->PUPDR   = 0x00000000;
+
+       /*-- FSMC Configuration ------------------------------------------------------*/
+       /* Enable the FSMC interface clock */
+       RCC->AHB3ENR         = 0x00000001;
+
+       /* Configure and enable Bank1_SRAM2 */
+       FSMC_Bank1->BTCR[2]  = 0x00001015;
+       FSMC_Bank1->BTCR[3]  = 0x00010603;
+       FSMC_Bank1E->BWTR[2] = 0x0fffffff;
+       /*
+  Bank1_SRAM2 is configured as follow:
+
+  p.FSMC_AddressSetupTime = 3;
+  p.FSMC_AddressHoldTime = 0;
+  p.FSMC_DataSetupTime = 6;
+  p.FSMC_BusTurnAroundDuration = 1;
+  p.FSMC_CLKDivision = 0;
+  p.FSMC_DataLatency = 0;
+  p.FSMC_AccessMode = FSMC_AccessMode_A;
+
+  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2;
+  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
+  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM;
+  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
+  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
+  FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;  
+  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
+  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
+  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
+  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
+  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
+  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
+  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
+  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
+  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
+        */
+}
+#endif /* DATA_IN_ExtSRAM */
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
index ac5220003d205bde7a71117b64a97c266604e15f..0bd590d257661f62a509e66ce1f982a9f5edbd4b 100644 (file)
-/*---------------------------------------------------------------------------*\\r
-\r
-  FILE........: tuner_ut.c\r
-  AUTHOR......: David Rowe\r
-  DATE CREATED: 20 Feb 2015\r
-\r
-  Unit test for high speed ADC radio tuner, samples signal centred at\r
-  500kHz using Fs=2 MHz and uploads to host at Fs=10 kHz.\r
-\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
-  Copyright (C) 2015 David Rowe\r
-\r
-  All rights reserved.\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU Lesser General Public License version 2.1, as\r
-  published by the Free Software Foundation.  This program is\r
-  distributed in the hope that it will be useful, but WITHOUT ANY\r
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
-  License for more details.\r
-\r
-  You should have received a copy of the GNU Lesser General Public License\r
-  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#include <assert.h>\r
-#include <stdlib.h>\r
-#include "gdb_stdio.h"\r
-#include "stm32f4_dac.h"\r
-#include "stm32f4_adc_tuner.h"\r
-#include "iir_tuner.h"\r
-#include "sm1000_leds_switches.h"\r
-#include "../src/codec2_fm.h"\r
-#include "stm32f4xx.h"\r
-\r
-#define REC_TIME_SECS 10\r
-#define FS            50000\r
-#define N             5000\r
-\r
-extern int adc_overflow1;\r
-\r
-int main(void) {\r
-    float  tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+N/2];\r
-    float  fm_out[N/2];\r
-    //float  dec_10[(N/2)/5];\r
-    short  dec_10_short[(N/2)];\r
-    int    bufs, i, j, k, fifo_sz, bn;\r
-    FILE  *ftuner;\r
-    struct FM *fm;\r
-\r
-    ftuner = fopen("tuner.raw", "wb");\r
-    if (ftuner == NULL) {\r
-        printf("Error opening input file: tuner.raw\n\nTerminating....\n");\r
-        exit(1);\r
-    }\r
-    bufs = FS*REC_TIME_SECS/N;\r
-    fifo_sz = ((4*N/ADC_TUNER_N)+1)*ADC_TUNER_N;\r
-    printf("Starting! bufs: %d %d\n", bufs, fifo_sz);\r
\r
-    //dac_open(DAC_BUF_SZ);\r
-    adc_open(fifo_sz);\r
-    sm1000_leds_switches_init();\r
-\r
-    fm         = fm_create(N/2);\r
-    fm->Fs     = 44400.0;\r
-    fm->fm_max = 3000.0;\r
-    fm->fd     = 5000.0;\r
-    fm->fc     = fm->Fs/4;\r
-\r
-    i = 0; bn = 0;\r
-    while(1) {\r
-        /* wait for buffer of Fs=50kHz tuner output samples */\r
-\r
-        while(adc1_read((short *)&tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM], N) == -1);\r
-\r
-        /* The semi-hosting system can only handle Fs=16kHz and below so resample down\r
-           to Fs=10 kHz and convert to shorts */\r
-\r
-        #ifdef SSB\r
-        iir_tuner_dec_50_to_10(dec_10, &tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM], N/2);\r
-        for(j=0; j<IIR_TUNER_DEC_50_10_FILT_MEM; j++)\r
-            tuner_out[j] = tuner_out[j+N/2];\r
-        for(j=0; j<(N/2)/5; j++)\r
-            dec_10_short[j] = dec_10[j]/ADC_TUNER_M;\r
-        #else\r
-        GPIOE->ODR |= (1 << 3);\r
-        /*\r
-        for(j=0; j<N/2; j++)\r
-            tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j] = 0;\r
-        for(j=1; j<N/2; j+=4)\r
-            tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j] = 100;\r
-        for(j=3; j<N/2; j+=4)\r
-            tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j] = -100;\r
-        */\r
-        fm_demod(fm, fm_out, &tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM]);\r
-        GPIOE->ODR &= ~(1 << 3);\r
-\r
-        for(j=0,k=0; j<N/2; j+=5,k++)\r
-            dec_10_short[k+bn] = 16384*fm_out[j];\r
-        bn += (N/2)/5;\r
-        #endif\r
-\r
-        if ((bn == N/2) && (i < bufs)) {\r
-            //for(j=0; j<N/2; j++)\r
-            //    dec_10_short[j] = tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j];\r
-            fwrite(dec_10_short, sizeof(short), (N/2), ftuner);\r
-            bn = 0;\r
-            i += 5;\r
-            //fwrite(dec_10_short, sizeof(short), (N/2)/5, ftuner);\r
-            //printf("%d %d\n", i, adc_overflow1);\r
-        }\r
-        if (i == bufs) {\r
-            printf("finished! %d\n", adc_overflow1);\r
-            fclose(ftuner);\r
-            i++;\r
-        }\r
-    }\r
-}\r
-\r
+/*---------------------------------------------------------------------------*\
+
+  FILE........: tuner_ut.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 20 Feb 2015
+
+  Unit test for high speed ADC radio tuner, samples signal centred at
+  500kHz using Fs=2 MHz and uploads to host at Fs=10 kHz.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2015 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include "gdb_stdio.h"
+#include "stm32f4_dac.h"
+#include "stm32f4_adc_tuner.h"
+#include "iir_tuner.h"
+#include "sm1000_leds_switches.h"
+#include "../src/codec2_fm.h"
+#include "stm32f4xx.h"
+
+#define REC_TIME_SECS 10
+#define FS            50000
+#define N             5000
+
+extern int adc_overflow1;
+
+int main(void) {
+    float  tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+N/2];
+    float  fm_out[N/2];
+    //float  dec_10[(N/2)/5];
+    short  dec_10_short[(N/2)];
+    int    bufs, i, j, k, fifo_sz, bn;
+    FILE  *ftuner;
+    struct FM *fm;
+
+    ftuner = fopen("tuner.raw", "wb");
+    if (ftuner == NULL) {
+        printf("Error opening input file: tuner.raw\n\nTerminating....\n");
+        exit(1);
+    }
+    bufs = FS*REC_TIME_SECS/N;
+    fifo_sz = ((4*N/ADC_TUNER_N)+1)*ADC_TUNER_N;
+    printf("Starting! bufs: %d %d\n", bufs, fifo_sz);
+    //dac_open(DAC_BUF_SZ);
+    adc_open(fifo_sz);
+    sm1000_leds_switches_init();
+
+    fm         = fm_create(N/2);
+    fm->Fs     = 44400.0;
+    fm->fm_max = 3000.0;
+    fm->fd     = 5000.0;
+    fm->fc     = fm->Fs/4;
+
+    i = 0; bn = 0;
+    while(1) {
+        /* wait for buffer of Fs=50kHz tuner output samples */
+
+        while(adc1_read((short *)&tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM], N) == -1);
+
+        /* The semi-hosting system can only handle Fs=16kHz and below so resample down
+           to Fs=10 kHz and convert to shorts */
+
+        #ifdef SSB
+        iir_tuner_dec_50_to_10(dec_10, &tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM], N/2);
+        for(j=0; j<IIR_TUNER_DEC_50_10_FILT_MEM; j++)
+            tuner_out[j] = tuner_out[j+N/2];
+        for(j=0; j<(N/2)/5; j++)
+            dec_10_short[j] = dec_10[j]/ADC_TUNER_M;
+        #else
+        GPIOE->ODR |= (1 << 3);
+        /*
+        for(j=0; j<N/2; j++)
+            tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j] = 0;
+        for(j=1; j<N/2; j+=4)
+            tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j] = 100;
+        for(j=3; j<N/2; j+=4)
+            tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j] = -100;
+        */
+        fm_demod(fm, fm_out, &tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM]);
+        GPIOE->ODR &= ~(1 << 3);
+
+        for(j=0,k=0; j<N/2; j+=5,k++)
+            dec_10_short[k+bn] = 16384*fm_out[j];
+        bn += (N/2)/5;
+        #endif
+
+        if ((bn == N/2) && (i < bufs)) {
+            //for(j=0; j<N/2; j++)
+            //    dec_10_short[j] = tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j];
+            fwrite(dec_10_short, sizeof(short), (N/2), ftuner);
+            bn = 0;
+            i += 5;
+            //fwrite(dec_10_short, sizeof(short), (N/2)/5, ftuner);
+            //printf("%d %d\n", i, adc_overflow1);
+        }
+        if (i == bufs) {
+            printf("finished! %d\n", adc_overflow1);
+            fclose(ftuner);
+            i++;
+        }
+    }
+}
+
index 74cf2401ad9bed3b16b205929d07b6d9494add07..6f8745018332875d7c935310ba70d03345781282 100644 (file)
@@ -380,7 +380,7 @@ index f92fc05..e54d136 100644
                perror("listen");
                return 1;
        }
--\r
+-
 +
 +        /* init for file I/O */
 +