123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- % fdmdv_demod.m
- %
- % Demodulator function for FDMDV modem (Octave version). Requires
- % 8kHz sample rate raw files as input
- %
- % Copyright David Rowe 2012
- % This program is distributed under the terms of the GNU General Public License
- % Version 2
- %
- function fdmdv_demod(rawfilename, nbits, pngname)
- fdmdv; % include modem code
- modulation = 'dqpsk';
- fin = fopen(rawfilename, "rb");
- gain = 1000;
- frames = nbits/(Nc*Nb);
- prev_rx_symbols = ones(Nc+1,1);
- foff_phase = 1;
- % BER stats
- total_bit_errors = 0;
- total_bits = 0;
- bit_errors_log = [];
- sync_log = [];
- test_frame_sync_log = [];
- test_frame_sync_state = 0;
- % SNR states
- sig_est = zeros(Nc+1,1);
- noise_est = zeros(Nc+1,1);
- % logs of various states for plotting
- rx_symbols_log = [];
- rx_timing_log = [];
- foff_log = [];
- rx_fdm_log = [];
- snr_est_log = [];
- % misc states
- nin = M; % timing correction for sample rate differences
- foff = 0;
- track_log = [];
- track = 0;
- fest_state = 0;
- % Main loop ----------------------------------------------------
- for f=1:frames
-
- % obtain nin samples of the test input signal
-
- for i=1:nin
- rx_fdm(i) = fread(fin, 1, "short")/gain;
- end
-
- rx_fdm_log = [rx_fdm_log rx_fdm(1:nin)];
- % frequency offset estimation and correction
- [pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, nin);
- [foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, nin);
-
- if track == 0
- foff = foff_coarse;
- end
- foff_log = [ foff_log foff ];
- foff_rect = exp(j*2*pi*foff/Fs);
- for i=1:nin
- foff_phase *= foff_rect';
- rx_fdm(i) = rx_fdm(i)*foff_phase;
- end
- % baseband processing
- rx_baseband = fdm_downconvert(rx_fdm, nin);
- rx_filt = rx_filter(rx_baseband, nin);
- [rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, nin);
-
- rx_timing_log = [rx_timing_log rx_timing];
- nin = M;
- if rx_timing > 2*M/P
- nin += M/P;
- end
- if rx_timing < 0;
- nin -= M/P;
- end
- if strcmp(modulation,'dqpsk')
- rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)];
- else
- rx_symbols_log = [rx_symbols_log rx_symbols];
- endif
- [rx_bits sync f_err pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
- [sig_est noise_est] = snr_update(sig_est, noise_est, pd);
- snr_est = calc_snr(sig_est, noise_est);
- snr_est_log = [snr_est_log snr_est];
- foff -= 0.5*f_err;
- prev_rx_symbols = rx_symbols;
- sync_log = [sync_log sync];
- % freq est state machine
- [track fest_state] = freq_state(sync, fest_state);
- track_log = [track_log track];
- % count bit errors if we find a test frame
- [test_frame_sync bit_errors] = put_test_bits(rx_bits);
- if (test_frame_sync == 1)
- total_bit_errors = total_bit_errors + bit_errors;
- total_bits = total_bits + Ntest_bits;
- bit_errors_log = [bit_errors_log bit_errors/Ntest_bits];
- else
- bit_errors_log = [bit_errors_log 0];
- end
- % test frame sync state machine, just for more informative plots
-
- next_test_frame_sync_state = test_frame_sync_state;
- if (test_frame_sync_state == 0)
- if (test_frame_sync == 1)
- next_test_frame_sync_state = 1;
- test_frame_count = 0;
- end
- end
- if (test_frame_sync_state == 1)
- % we only expect another test_frame_sync pulse every 4 symbols
- test_frame_count++;
- if (test_frame_count == 4)
- test_frame_count = 0;
- if ((test_frame_sync == 0))
- next_test_frame_sync_state = 0;
- end
- end
- end
- test_frame_sync_state = next_test_frame_sync_state;
- test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
- end
-
- % ---------------------------------------------------------------------
- % Print Stats
- % ---------------------------------------------------------------------
- ber = total_bit_errors / total_bits;
- printf("%d bits %d errors BER: %1.4f\n",total_bits, total_bit_errors, ber);
- % ---------------------------------------------------------------------
- % Plots
- % ---------------------------------------------------------------------
- xt = (1:frames)/Rs;
- secs = frames/Rs;
- figure(1)
- clf;
- [n m] = size(rx_symbols_log);
- plot(real(rx_symbols_log(1:Nc+1,15:m)),imag(rx_symbols_log(1:Nc+1,15:m)),'+')
- axis([-2 2 -2 2]);
- title('Scatter Diagram');
- figure(2)
- clf;
- subplot(211)
- plot(xt, rx_timing_log)
- title('timing offset (samples)');
- subplot(212)
- plot(xt, foff_log, '-;freq offset;')
- hold on;
- plot(xt, track_log*75, 'r;course-fine;');
- hold off;
- title('Freq offset (Hz)');
- grid
- figure(3)
- clf;
- subplot(211)
- [a b] = size(rx_fdm_log);
- xt1 = (1:b)/Fs;
- plot(xt1, rx_fdm_log);
- title('Rx FDM Signal');
- subplot(212)
- spec(rx_fdm_log,8000);
- title('FDM Rx Spectrogram');
- figure(4)
- clf;
- subplot(311)
- stem(xt, sync_log)
- axis([0 secs 0 1.5]);
- title('BPSK Sync')
- subplot(312)
- stem(xt, bit_errors_log);
- title('Bit Errors for test frames')
- subplot(313)
- plot(xt, test_frame_sync_log);
- axis([0 secs 0 1.5]);
- title('Test Frame Sync')
- figure(5)
- clf;
- plot(xt, snr_est_log);
- title('SNR Estimates')
-
- endfunction
|