plot(xt, rx_timing_log)
title('timing offset (samples)');
subplot(212)
- plot(xt, foff_log)
+ plot(xt, foff_log, '-;freq offset;')
hold on;
- plot(xt, track_log*75, 'r');
+ plot(xt, track_log*75, 'r;course-fine;');
hold off;
title('Freq offset (Hz)');
grid
plot(xt1, rx_fdm_log);
title('Rx FDM Signal');
subplot(212)
- Nfft=Fs;
- S=fft(rx_fdm_log,Nfft);
- SdB=20*log10(abs(S));
- plot(SdB(1:Fs/4))
- title('FDM Rx Spectrum');
+ spec(rx_fdm_log,8000);
+ title('FDM Rx Spectrogram');
figure(4)
clf;
function fdmdv_demod_c(dumpfilename, bits)
fdmdv; % include modem code
+
frames = bits/(Nc*Nb);
load(dumpfilename);
+ % BER stats
+
+ total_bit_errors = 0;
+ total_bits = 0;
+ bit_errors_log = [];
+ sync_log = [];
+ test_frame_sync_log = [];
+ test_frame_sync_state = 0;
+
+ % Run thru received bits to look for test pattern
+
+ bits_per_frame = Nc*Nb;
+
+ for f=1:frames
+
+ rx_bits = rx_bits_log_c((f-1)*bits_per_frame+1:f*bits_per_frame);
+
+ % 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
+
% ---------------------------------------------------------------------
% Plots
% ---------------------------------------------------------------------
plot(xt, rx_timing_log_c(1:frames))
title('timing offset (samples)');
subplot(212)
- plot(xt, foff_log_c(1:frames))
+ plot(xt, foff_log_c(1:frames), '-;freq offset;')
hold on;
- plot(xt, coarse_fine_log_c(1:frames)*75, 'r');
+ plot(xt, coarse_fine_log_c(1:frames)*75, 'r;course-fine;');
hold off;
title('Freq offset (Hz)');
grid
+ figure(3)
+ clf;
+ subplot(211)
+ b = M*frames;
+ xt1 = (1:b)/Fs;
+ plot(xt1, rx_fdm_log_c(1:b));
+ title('Rx FDM Signal');
+ subplot(212)
+ spec(rx_fdm_log_c(1:b),8000);
+ title('FDM Rx Spectrogram');
+
+ figure(4)
+ clf;
+ subplot(311)
+ stem(xt, sync_bit_log_c(1:frames))
+ 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')
+
+
endfunction
outputs a file of bits. The output file is assumed to be arranged
as codec frames of 56 bits (7 bytes) which are received as two 28
bit modem frames.
+
+ Demod states can be optionally logged to an Octave file for display
+ using the Octave script fdmdv_demod_c.m. This is useful for
+ checking demod performance.
\*---------------------------------------------------------------------------*/
int sync_bit;
int state, next_state;
- int frames;
+ int f;
FILE *foct = NULL;
struct FDMDV_STATS stats;
+ float rx_fdm_log[FDMDV_MAX_SAMPLES_PER_FRAME*MAX_FRAMES];
+ int rx_fdm_log_col_index;
COMP rx_symbols_log[FDMDV_NSYM][MAX_FRAMES];
int coarse_fine_log[MAX_FRAMES];
float rx_timing_log[MAX_FRAMES];
float foff_log[MAX_FRAMES];
+ int sync_bit_log[MAX_FRAMES];
+ int rx_bits_log[FDMDV_BITS_PER_FRAME*MAX_FRAMES];
if (argc < 3) {
printf("usage: %s InputModemRawFile OutputBitFile [OctaveDumpFile]\n", argv[0]);
}
fdmdv = fdmdv_create();
- frames = 0;
+ f = 0;
state = 0;
nin = FDMDV_NOM_SAMPLES_PER_FRAME;
+ rx_fdm_log_col_index = 0;
while(fread(rx_fdm_scaled, sizeof(short), nin, fin) == nin)
{
/* log data for optional Octave dump */
- if (frames < MAX_FRAMES) {
+ if (f < MAX_FRAMES) {
fdmdv_get_demod_stats(fdmdv, &stats);
+
+ /* log modem states for later dumping to Octave log file */
+
+ memcpy(&rx_fdm_log[rx_fdm_log_col_index], rx_fdm, sizeof(float)*nin);
+ rx_fdm_log_col_index += nin;
+
for(c=0; c<FDMDV_NSYM; c++)
- rx_symbols_log[c][frames] = stats.rx_symbols[c];
- foff_log[frames] = stats.foff;
- rx_timing_log[frames] = stats.rx_timing;
- coarse_fine_log[frames] = stats.fest_coarse_fine;
- frames++;
+ rx_symbols_log[c][f] = stats.rx_symbols[c];
+ foff_log[f] = stats.foff;
+ rx_timing_log[f] = stats.rx_timing;
+ coarse_fine_log[f] = stats.fest_coarse_fine;
+ sync_bit_log[f] = sync_bit;
+ memcpy(&rx_bits_log[FDMDV_BITS_PER_FRAME*f], rx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME);
+
+ f++;
}
else
printf("MAX_FRAMES exceed in Octave log, log truncated\n");
argv[3], strerror(errno));
exit(1);
}
- octave_save_complex(foct, "rx_symbols_log_c", (COMP*)rx_symbols_log, FDMDV_NSYM, MAX_FRAMES, MAX_FRAMES);
- octave_save_float(foct, "foff_log_c", foff_log, 1, MAX_FRAMES);
- octave_save_float(foct, "rx_timing_log_c", rx_timing_log, 1, MAX_FRAMES);
- octave_save_int(foct, "coarse_fine_log_c", coarse_fine_log, 1, MAX_FRAMES);
+ octave_save_float(foct, "rx_fdm_log_c", rx_fdm_log, 1, rx_fdm_log_col_index, FDMDV_MAX_SAMPLES_PER_FRAME);
+ octave_save_complex(foct, "rx_symbols_log_c", (COMP*)rx_symbols_log, FDMDV_NSYM, f, MAX_FRAMES);
+ octave_save_float(foct, "foff_log_c", foff_log, 1, f, MAX_FRAMES);
+ octave_save_float(foct, "rx_timing_log_c", rx_timing_log, 1, f, MAX_FRAMES);
+ octave_save_int(foct, "coarse_fine_log_c", coarse_fine_log, 1, f);
+ octave_save_int(foct, "rx_bits_log_c", rx_bits_log, 1, FDMDV_BITS_PER_FRAME*f);
+ octave_save_int(foct, "sync_bit_log_c", sync_bit_log, 1, f);
fclose(foct);
}
}
AUTHOR......: David Rowe
DATE CREATED: April 28 2012
- Functions to save C arrays in Octave matrix format. the output text
- file can be directly read into octave using "load filename".
+ Functions to save C arrays in GNU Octave matrix format. The output text
+ file can be directly read into Octave using "load filename".
\*---------------------------------------------------------------------------*/
fprintf(f, "\n\n");
}
-void octave_save_float(FILE *f, char name[], float data[], int rows, int cols)
+void octave_save_float(FILE *f, char name[], float data[], int rows, int cols, int col_len)
{
int r,c;
for(r=0; r<rows; r++) {
for(c=0; c<cols; c++)
- fprintf(f, " %f", data[r*cols+c]);
+ fprintf(f, " %f", data[r*col_len+c]);
fprintf(f, "\n");
}
#include "comp.h"
void octave_save_int(FILE *f, char name[], int data[], int rows, int cols);
-void octave_save_float(FILE *f, char name[], float data[], int rows, int cols);
+void octave_save_float(FILE *f, char name[], float data[], int rows, int cols, int col_len);
void octave_save_complex(FILE *f, char name[], COMP data[], int rows, int cols, int col_len);
#endif
octave_save_complex(fout, "pilot_lpf2_log_c", pilot_lpf2_log, 1, NPILOTLPF*FRAMES, NPILOTLPF*FRAMES);
octave_save_complex(fout, "S1_log_c", S1_log, 1, MPILOTFFT*FRAMES, MPILOTFFT*FRAMES);
octave_save_complex(fout, "S2_log_c", S2_log, 1, MPILOTFFT*FRAMES, MPILOTFFT*FRAMES);
- octave_save_float(fout, "foff_log_c", foff_log, 1, FRAMES);
- octave_save_float(fout, "foff_coarse_log_c", foff_coarse_log, 1, FRAMES);
+ octave_save_float(fout, "foff_log_c", foff_log, 1, FRAMES, FRAMES);
+ octave_save_float(fout, "foff_coarse_log_c", foff_coarse_log, 1, FRAMES, FRAMES);
octave_save_complex(fout, "rx_baseband_log_c", (COMP*)rx_baseband_log, (NC+1), rx_baseband_log_col_index, (M+M/P)*FRAMES);
octave_save_complex(fout, "rx_filt_log_c", (COMP*)rx_filt_log, (NC+1), rx_filt_log_col_index, (P+1)*FRAMES);
- octave_save_float(fout, "env_log_c", env_log, 1, NT*P*FRAMES);
- octave_save_float(fout, "rx_timing_log_c", rx_timing_log, 1, FRAMES);
+ octave_save_float(fout, "env_log_c", env_log, 1, NT*P*FRAMES, NT*P*FRAMES);
+ octave_save_float(fout, "rx_timing_log_c", rx_timing_log, 1, FRAMES, FRAMES);
octave_save_complex(fout, "rx_symbols_log_c", (COMP*)rx_symbols_log, (NC+1), FRAMES, FRAMES);
octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, FDMDV_BITS_PER_FRAME*FRAMES);
- octave_save_float(fout, "foff_fine_log_c", foff_fine_log, 1, FRAMES);
+ octave_save_float(fout, "foff_fine_log_c", foff_fine_log, 1, FRAMES, FRAMES);
octave_save_int(fout, "sync_bit_log_c", sync_bit_log, 1, FRAMES);
octave_save_int(fout, "coarse_fine_log_c", coarse_fine_log, 1, FRAMES);
octave_save_int(fout, "nin_log_c", nin_log, 1, FRAMES);