From: drowe67 Date: Thu, 28 May 2015 09:16:22 +0000 (+0000) Subject: cohpsk_ch cmd line channel simulator partially written and working as expected with... X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=c5dda472f8c9e80b7bcd2a878219220cbb4d343d;p=freetel-svn-tracking.git cohpsk_ch cmd line channel simulator partially written and working as expected with awgn and fading channels, next step is to interface codec git-svn-id: https://svn.code.sf.net/p/freetel/code@2158 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/make_hilb.m b/codec2-dev/octave/make_hilb.m new file mode 100644 index 00000000..35d4e55e --- /dev/null +++ b/codec2-dev/octave/make_hilb.m @@ -0,0 +1,51 @@ +% make_hilb.m +% David Rowe May 2015 +% +% creates Hilber Transformer FIR coeffs + +graphics_toolkit ("gnuplot"); + +ht_n = 100; +imp = [1 zeros(1,ht_n-1)]; +ht_coeff = fftshift(hilbert(imp)) .* hanning(ht_n)'; + +figure(1) +subplot(211) +plot(real(ht_coeff)) +subplot(212) +plot(imag(ht_coeff)) + +figure(2) +plot(20*log10(abs(fft(ht_coeff)))) + +% test it + +n=1:8000; +w = 2*pi/4; +x = cos(n*w); +figure(3) +y = filter(ht_coeff,1,x); +figure(3) +subplot(211) +plot(y(800:8000)) +subplot(212) +plot(20*log10(abs(fft(y(800:8000))))) + +% save coeffs to a C header file + +f=fopen("../src/ht_coeff.h","wt"); +fprintf(f,"/* Hilbert Transform FIR filter coeffs */\n"); +fprintf(f,"/* Generated by make_hilb Octave script */\n"); + +fprintf(f,"\n#define HT_N %d\n\n", ht_n); + +fprintf(f,"COMP ht_coeff[]={\n"); +for r=1:ht_n + if r < ht_n + fprintf(f, " {%f,%f},\n", real(ht_coeff(r)), imag(ht_coeff(r))); + else + fprintf(f, " {%f,%f}\n};", real(ht_coeff(r)), imag(ht_coeff(r))); + end +end + +fclose(f); diff --git a/codec2-dev/octave/tcohpsk.m b/codec2-dev/octave/tcohpsk.m index 5da70d68..9f565a56 100644 --- a/codec2-dev/octave/tcohpsk.m +++ b/codec2-dev/octave/tcohpsk.m @@ -42,7 +42,14 @@ % + however other filters may have other effects, should test this, % e.g. scatter plots, some sort of BER metric? % [ ] pilot based EsNo estimation +% [ ] filter reqd with compression? +% + make sure not too much noise passed into noise floor % [ ] different diversity combination +% [ ] histogram of bit errors +% + lot of data +% + ssb filter +% + compression +% + make sure it's flat with many errors graphics_toolkit ("gnuplot"); more off; @@ -57,14 +64,14 @@ randn('state',1); % select which test ---------------------------------------------------------- %test = 'compare to c'; -%test = 'awgn'; -test = 'fading'; +test = 'awgn'; +%test = 'fading'; % some parameters that can be over ridden, e.g. to disable parts of modem initial_sync = 0; % setting this to 1 put us straight into sync w/o freq offset est ftrack_en = 1; % set to 1 to enable freq tracking -ssb_tx_filt = 1; % set to 1 to to simulate SSB tx filter with passband ripple +ssb_tx_filt = 0; % set to 1 to to simulate SSB tx filter with passband ripple Fs = 7500; % predefined tests .... @@ -84,10 +91,10 @@ end % should be BER around 0.015 to 0.02 if strcmp(test, 'awgn') - frames = 100; + frames = 10; foff = 0; dfoff = -0/Fs; - EsNodB = 8; + EsNodB = 80; fading_en = 0; hf_delay_ms = 2; compare_with_c = 0; @@ -350,6 +357,8 @@ while tin < length(ch_fdm_frame_log) end ch_fdm_frame_log = ch_fdm_frame_log_out(1:tout-1); +%ch_fdm_frame_log = real(ch_fdm_frame_log); + % Now run demod ---------------------------------------------------------------- ch_fdm_frame_log_index = 1; diff --git a/codec2-dev/src/CMakeLists.txt b/codec2-dev/src/CMakeLists.txt index 30b26513..fbf7e3e6 100644 --- a/codec2-dev/src/CMakeLists.txt +++ b/codec2-dev/src/CMakeLists.txt @@ -287,6 +287,9 @@ target_link_libraries(cohpsk_get_test_bits ${CMAKE_REQUIRED_LIBRARIES} codec2) add_executable(cohpsk_put_test_bits cohpsk_put_test_bits.c) target_link_libraries(cohpsk_put_test_bits ${CMAKE_REQUIRED_LIBRARIES} codec2) +add_executable(cohpsk_ch cohpsk_ch.c) +target_link_libraries(cohpsk_ch ${CMAKE_REQUIRED_LIBRARIES} codec2) + install(TARGETS codec2 EXPORT codec2-config LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/codec2-dev/src/codec2_cohpsk.h b/codec2-dev/src/codec2_cohpsk.h index aa1ccbb2..387e75a6 100644 --- a/codec2-dev/src/codec2_cohpsk.h +++ b/codec2-dev/src/codec2_cohpsk.h @@ -35,7 +35,6 @@ #define COHPSK_FS 7500 /* note this is a wierd value to get an integer oversampling rate */ #include "comp.h" -#include "codec2_fdmdv.h" struct COHPSK; diff --git a/codec2-dev/src/cohpsk_ch.c b/codec2-dev/src/cohpsk_ch.c new file mode 100644 index 00000000..78f36c1c --- /dev/null +++ b/codec2-dev/src/cohpsk_ch.c @@ -0,0 +1,283 @@ +/*---------------------------------------------------------------------------*\ + + FILE........: cohpsk_ch.c + AUTHOR......: David Rowe + DATE CREATED: May 2015 + + Channel impairment program for testing command line versions of + cohpsk modem. + + TODO: + [ ] measure and prints pwrs to check, prints warning + [ ] SNR in 3000Hz input + [ ] example operation with sox for sample rate change + [ ] way to calibrate for different input pwrs + [ ] HT to do real->complex + [ ] check no BER hit just through HT + [ ] unit test HT + [ ] clipping detect + +\*---------------------------------------------------------------------------*/ + +/* + 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, 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 . +*/ + +#include +#include +#include +#include +#include +#include + +#include "codec2_cohpsk.h" +#include "comp_prim.h" +#include "../unittest/noise_samples.h" +#include "ht_coeff.h" +#include "codec2_fdmdv.h" + +#define BUF_N 160 +#define HF_DELAY_MS 2.0 + +/* This file gets generated using the function write_noise_file in tcohpsk.m. You have to run + tcohpsk first (any variant) to load the function into Octave, e.g.: + + octave:17> tcohpsk + octave:18> write_noise_file("../raw/fading_samples.float", 7500, 7500*60) +*/ + +#define FADING_FILE_NAME "../../raw/fading_samples.float" + +int main(int argc, char *argv[]) +{ + FILE *fin, *ffading, *fout; + float EsNodB, foff_hz; + int fading_en, nhfdelay; + + short buf[BUF_N]; + float htbuf[HT_N+BUF_N]; + COMP ch_in[BUF_N]; + COMP ch_fdm[BUF_N]; + + COMP phase_ch; + int noise_r, noise_end; + float EsNo, variance; + COMP scaled_noise; + float hf_gain; + COMP *ch_fdm_delay, aspread, aspread_2ms, delayed, direct; + float tx_pwr, rx_pwr, noise_pwr; + int frames, i, j, k, ret; + float sam; + + if (argc == 6) { + if (strcmp(argv[1], "-") == 0) fin = stdin; + else if ( (fin = fopen(argv[1],"rb")) == NULL ) { + fprintf(stderr, "Error opening input modem raw file: %s: %s.\n", + argv[1], strerror(errno)); + exit(1); + } + + if (strcmp(argv[2], "-") == 0) fout = stdout; + else if ( (fout = fopen(argv[2],"wb")) == NULL ) { + fprintf(stderr, "Error opening output modem raw file: %s: %s.\n", + argv[2], strerror(errno)); + exit(1); + } + + EsNodB = atof(argv[3]); + foff_hz = atof(argv[4]); + fading_en = atoi(argv[5]); + } + else { + fprintf(stderr, "usage: %s InputRealModemRawFileFs7500Hz OutputRealModemRawFileFs7500Hz SNR3000Hz FoffHz FadingEn\n", argv[0]); + exit(1); + } + fprintf(stderr, "EsNodB: %4.2f foff: %4.2f Hz fading: %d\n", EsNodB, foff_hz, fading_en); + + phase_ch.real = 1.0; phase_ch.imag = 0.0; + noise_r = 0; + noise_end = sizeof(noise)/sizeof(COMP); + + /* 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) */ + + EsNo = pow(10.0, EsNodB/10.0); + variance = 2.0*COHPSK_FS/(COHPSK_RS*EsNo); + + tx_pwr = rx_pwr = noise_pwr = 0.0; + + /* init HF fading model */ + + if (fading_en) { + ffading = fopen(FADING_FILE_NAME, "rb"); + if (ffading == NULL) { + printf("Can't find fading file: %s\n", FADING_FILE_NAME); + exit(1); + } + nhfdelay = floor(HF_DELAY_MS*COHPSK_FS/1000); + ch_fdm_delay = (COMP*)malloc((nhfdelay+COHPSK_SAMPLES_PER_FRAME)*sizeof(COMP)); + assert(ch_fdm_delay != NULL); + for(i=0; i noise_end) { + noise_r = 0; + //fprintf(stderr, " [%d] noise wrap\n", f); + } + + } + + /* scale and save to disk as shorts */ + + for(i=0; i 32767.0) + fprintf(stderr,"clipping: %f\n", sam); + buf[i] = sam; + } + + fwrite(buf, sizeof(short), BUF_N, fout); + + /* if this is in a pipeline, we probably don't want the usual + buffering to occur */ + + if (fout == stdout) fflush(stdout); + if (fin == stdin) fflush(stdin); + } + + fclose(fin); + fclose(fout); + + fprintf(stderr, "tx var: %f noise var: %f rx var: %f\n", + tx_pwr/(frames*BUF_N), + noise_pwr/(frames*BUF_N), + rx_pwr/(frames*BUF_N) + ); + + return 0; +} + diff --git a/codec2-dev/src/cohpsk_demod.c b/codec2-dev/src/cohpsk_demod.c index b4bbed3f..fdac1a94 100644 --- a/codec2-dev/src/cohpsk_demod.c +++ b/codec2-dev/src/cohpsk_demod.c @@ -34,6 +34,7 @@ #include #include "codec2_cohpsk.h" +#include "codec2_fdmdv.h" int main(int argc, char *argv[]) { @@ -42,7 +43,7 @@ int main(int argc, char *argv[]) int rx_bits[COHPSK_BITS_PER_FRAME]; COMP rx_fdm[COHPSK_SAMPLES_PER_FRAME]; short rx_fdm_scaled[COHPSK_SAMPLES_PER_FRAME]; - int frames, reliable_sync_bit; + int frames, reliable_sync_bit, nin_frame; int i; if (argc < 3) { @@ -68,19 +69,21 @@ int main(int argc, char *argv[]) frames = 0; - while(fread(rx_fdm_scaled, sizeof(short), COHPSK_SAMPLES_PER_FRAME, fin) == COHPSK_SAMPLES_PER_FRAME) { + nin_frame = COHPSK_SAMPLES_PER_FRAME; + while(fread(rx_fdm_scaled, sizeof(short), nin_frame, fin) == nin_frame) { frames++; /* scale and demod */ - for(i=0; i #include "codec2_cohpsk.h" +#include "codec2_fdmdv.h" int main(int argc, char *argv[]) { @@ -73,6 +74,7 @@ int main(int argc, char *argv[]) frames++; cohpsk_mod(cohpsk, tx_fdm, tx_bits); + cohpsk_clip(tx_fdm); /* scale and save to disk as shorts */ diff --git a/codec2-dev/src/cohpsk_put_test_bits.c b/codec2-dev/src/cohpsk_put_test_bits.c index 7b369e89..3a2d85e0 100644 --- a/codec2-dev/src/cohpsk_put_test_bits.c +++ b/codec2-dev/src/cohpsk_put_test_bits.c @@ -42,8 +42,11 @@ int main(int argc, char *argv[]) FILE *fin; int rx_bits[COHPSK_BITS_PER_FRAME]; int *ptest_bits_coh, *ptest_bits_coh_end; - int state, next_state, i, nbits, nerrors; - float corr; + int state, next_state, i, nbits, errors, nerrors; + int error_positions_hist[COHPSK_BITS_PER_FRAME]; + + for(i=0; i= ptest_bits_coh_end) { @@ -96,7 +102,7 @@ int main(int argc, char *argv[]) } fclose(fin); - printf("BER: %3.2f Nbits: %d Nerrors: %d\n", (float)nerrors/nbits, nbits, nerrors); + printf("BER: %4.3f Nbits: %d Nerrors: %d\n", (float)nerrors/nbits, nbits, nerrors); return 0; } diff --git a/codec2-dev/src/ht_coeff.h b/codec2-dev/src/ht_coeff.h new file mode 100644 index 00000000..98c5c6ea --- /dev/null +++ b/codec2-dev/src/ht_coeff.h @@ -0,0 +1,107 @@ +/* Hilbert Transform FIR filter coeffs */ +/* Generated by make_hilb Octave script */ + +#define HT_N 100 + +COMP ht_coeff[]={ + {0.000000,0.000000}, + {-0.000000,-0.000001}, + {0.000000,0.000000}, + {-0.000000,-0.000017}, + {0.000000,0.000000}, + {0.000000,-0.000079}, + {0.000000,0.000000}, + {0.000000,-0.000217}, + {0.000000,0.000000}, + {0.000000,-0.000461}, + {0.000000,0.000000}, + {-0.000000,-0.000842}, + {0.000000,0.000000}, + {-0.000000,-0.001391}, + {0.000000,0.000000}, + {-0.000000,-0.002140}, + {0.000000,0.000000}, + {-0.000000,-0.003121}, + {0.000000,0.000000}, + {0.000000,-0.004371}, + {0.000000,0.000000}, + {0.000000,-0.005928}, + {0.000000,0.000000}, + {-0.000000,-0.007839}, + {0.000000,0.000000}, + {-0.000000,-0.010159}, + {0.000000,0.000000}, + {-0.000000,-0.012957}, + {0.000000,0.000000}, + {-0.000000,-0.016327}, + {0.000000,0.000000}, + {0.000000,-0.020399}, + {0.000000,0.000000}, + {-0.000000,-0.025364}, + {0.000000,0.000000}, + {0.000000,-0.031512}, + {0.000000,0.000000}, + {0.000000,-0.039319}, + {0.000000,0.000000}, + {0.000000,-0.049610}, + {0.000000,0.000000}, + {-0.000000,-0.063952}, + {0.000000,0.000000}, + {-0.000000,-0.085722}, + {0.000000,0.000000}, + {0.000000,-0.123718}, + {0.000000,0.000000}, + {0.000000,-0.210249}, + {0.000000,0.000000}, + {-0.000000,-0.636250}, + {0.999748,0.000000}, + {0.000000,0.634969}, + {0.000000,0.000000}, + {0.000000,0.208979}, + {0.000000,0.000000}, + {0.000000,0.122467}, + {0.000000,0.000000}, + {-0.000000,0.084502}, + {0.000000,0.000000}, + {0.000000,0.062771}, + {0.000000,0.000000}, + {0.000000,0.048477}, + {0.000000,0.000000}, + {0.000000,0.038242}, + {0.000000,0.000000}, + {-0.000000,0.030497}, + {0.000000,0.000000}, + {0.000000,0.024418}, + {0.000000,0.000000}, + {0.000000,0.019527}, + {0.000000,0.000000}, + {-0.000000,0.015532}, + {0.000000,0.000000}, + {0.000000,0.012242}, + {0.000000,0.000000}, + {-0.000000,0.009524}, + {0.000000,0.000000}, + {-0.000000,0.007285}, + {0.000000,0.000000}, + {-0.000000,0.005454}, + {0.000000,0.000000}, + {-0.000000,0.003973}, + {0.000000,0.000000}, + {0.000000,0.002796}, + {0.000000,0.000000}, + {-0.000000,0.001882}, + {0.000000,0.000000}, + {-0.000000,0.001196}, + {0.000000,0.000000}, + {-0.000000,0.000701}, + {0.000000,0.000000}, + {0.000000,0.000367}, + {0.000000,0.000000}, + {0.000000,0.000160}, + {0.000000,0.000000}, + {0.000000,0.000051}, + {0.000000,0.000000}, + {-0.000000,0.000008}, + {0.000000,0.000000}, + {0.000000,0.000000} +}; \ No newline at end of file diff --git a/codec2-dev/unittest/test_cohpsk_ch.c b/codec2-dev/unittest/test_cohpsk_ch.c index 6f9ae139..82530265 100644 --- a/codec2-dev/unittest/test_cohpsk_ch.c +++ b/codec2-dev/unittest/test_cohpsk_ch.c @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) int ch_buf_n; float tx_pwr, rx_pwr, noise_pwr; int error_positions_hist[COHPSK_BITS_PER_FRAME]; - int log_data_r, c, j, tmp; + int log_data_r, c, j, tmp, ret; for(i=0; i