2
0

fdmdv_demod.m 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. % fdmdv_demod.m
  2. %
  3. % Demodulator function for FDMDV modem (Octave version). Requires
  4. % 8kHz sample rate raw files as input
  5. %
  6. % Copyright David Rowe 2012
  7. % This program is distributed under the terms of the GNU General Public License
  8. % Version 2
  9. %
  10. function fdmdv_demod(rawfilename, nbits, pngname)
  11. fdmdv; % include modem code
  12. modulation = 'dqpsk';
  13. fin = fopen(rawfilename, "rb");
  14. gain = 1000;
  15. frames = nbits/(Nc*Nb);
  16. prev_rx_symbols = ones(Nc+1,1);
  17. foff_phase = 1;
  18. % BER stats
  19. total_bit_errors = 0;
  20. total_bits = 0;
  21. bit_errors_log = [];
  22. sync_log = [];
  23. test_frame_sync_log = [];
  24. test_frame_sync_state = 0;
  25. % SNR states
  26. sig_est = zeros(Nc+1,1);
  27. noise_est = zeros(Nc+1,1);
  28. % logs of various states for plotting
  29. rx_symbols_log = [];
  30. rx_timing_log = [];
  31. foff_log = [];
  32. rx_fdm_log = [];
  33. snr_est_log = [];
  34. % misc states
  35. nin = M; % timing correction for sample rate differences
  36. foff = 0;
  37. track_log = [];
  38. track = 0;
  39. fest_state = 0;
  40. % Main loop ----------------------------------------------------
  41. for f=1:frames
  42. % obtain nin samples of the test input signal
  43. for i=1:nin
  44. rx_fdm(i) = fread(fin, 1, "short")/gain;
  45. end
  46. rx_fdm_log = [rx_fdm_log rx_fdm(1:nin)];
  47. % frequency offset estimation and correction
  48. [pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, nin);
  49. [foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, nin);
  50. if track == 0
  51. foff = foff_coarse;
  52. end
  53. foff_log = [ foff_log foff ];
  54. foff_rect = exp(j*2*pi*foff/Fs);
  55. for i=1:nin
  56. foff_phase *= foff_rect';
  57. rx_fdm(i) = rx_fdm(i)*foff_phase;
  58. end
  59. % baseband processing
  60. rx_baseband = fdm_downconvert(rx_fdm, nin);
  61. rx_filt = rx_filter(rx_baseband, nin);
  62. [rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, nin);
  63. rx_timing_log = [rx_timing_log rx_timing];
  64. nin = M;
  65. if rx_timing > 2*M/P
  66. nin += M/P;
  67. end
  68. if rx_timing < 0;
  69. nin -= M/P;
  70. end
  71. if strcmp(modulation,'dqpsk')
  72. rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)];
  73. else
  74. rx_symbols_log = [rx_symbols_log rx_symbols];
  75. endif
  76. [rx_bits sync f_err pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
  77. [sig_est noise_est] = snr_update(sig_est, noise_est, pd);
  78. snr_est = calc_snr(sig_est, noise_est);
  79. snr_est_log = [snr_est_log snr_est];
  80. foff -= 0.5*f_err;
  81. prev_rx_symbols = rx_symbols;
  82. sync_log = [sync_log sync];
  83. % freq est state machine
  84. [track fest_state] = freq_state(sync, fest_state);
  85. track_log = [track_log track];
  86. % count bit errors if we find a test frame
  87. [test_frame_sync bit_errors] = put_test_bits(rx_bits);
  88. if (test_frame_sync == 1)
  89. total_bit_errors = total_bit_errors + bit_errors;
  90. total_bits = total_bits + Ntest_bits;
  91. bit_errors_log = [bit_errors_log bit_errors/Ntest_bits];
  92. else
  93. bit_errors_log = [bit_errors_log 0];
  94. end
  95. % test frame sync state machine, just for more informative plots
  96. next_test_frame_sync_state = test_frame_sync_state;
  97. if (test_frame_sync_state == 0)
  98. if (test_frame_sync == 1)
  99. next_test_frame_sync_state = 1;
  100. test_frame_count = 0;
  101. end
  102. end
  103. if (test_frame_sync_state == 1)
  104. % we only expect another test_frame_sync pulse every 4 symbols
  105. test_frame_count++;
  106. if (test_frame_count == 4)
  107. test_frame_count = 0;
  108. if ((test_frame_sync == 0))
  109. next_test_frame_sync_state = 0;
  110. end
  111. end
  112. end
  113. test_frame_sync_state = next_test_frame_sync_state;
  114. test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
  115. end
  116. % ---------------------------------------------------------------------
  117. % Print Stats
  118. % ---------------------------------------------------------------------
  119. ber = total_bit_errors / total_bits;
  120. printf("%d bits %d errors BER: %1.4f\n",total_bits, total_bit_errors, ber);
  121. % ---------------------------------------------------------------------
  122. % Plots
  123. % ---------------------------------------------------------------------
  124. xt = (1:frames)/Rs;
  125. secs = frames/Rs;
  126. figure(1)
  127. clf;
  128. [n m] = size(rx_symbols_log);
  129. plot(real(rx_symbols_log(1:Nc+1,15:m)),imag(rx_symbols_log(1:Nc+1,15:m)),'+')
  130. axis([-2 2 -2 2]);
  131. title('Scatter Diagram');
  132. figure(2)
  133. clf;
  134. subplot(211)
  135. plot(xt, rx_timing_log)
  136. title('timing offset (samples)');
  137. subplot(212)
  138. plot(xt, foff_log, '-;freq offset;')
  139. hold on;
  140. plot(xt, track_log*75, 'r;course-fine;');
  141. hold off;
  142. title('Freq offset (Hz)');
  143. grid
  144. figure(3)
  145. clf;
  146. subplot(211)
  147. [a b] = size(rx_fdm_log);
  148. xt1 = (1:b)/Fs;
  149. plot(xt1, rx_fdm_log);
  150. title('Rx FDM Signal');
  151. subplot(212)
  152. spec(rx_fdm_log,8000);
  153. title('FDM Rx Spectrogram');
  154. figure(4)
  155. clf;
  156. subplot(311)
  157. stem(xt, sync_log)
  158. axis([0 secs 0 1.5]);
  159. title('BPSK Sync')
  160. subplot(312)
  161. stem(xt, bit_errors_log);
  162. title('Bit Errors for test frames')
  163. subplot(313)
  164. plot(xt, test_frame_sync_log);
  165. axis([0 secs 0 1.5]);
  166. title('Test Frame Sync')
  167. figure(5)
  168. clf;
  169. plot(xt, snr_est_log);
  170. title('SNR Estimates')
  171. endfunction