From f846c3cea626c1e1bd81fc10bc832a6a9d5d1a46 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Wed, 27 May 2015 07:57:46 +0000 Subject: [PATCH] reasonable results on fading channels for C version of modem, still testing git-svn-id: https://svn.code.sf.net/p/freetel/code@2153 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/tcohpsk.m | 44 +++++++-- codec2-dev/octave/test_cohpsk_ch.m | 21 +++++ codec2-dev/src/cohpsk.c | 4 +- codec2-dev/unittest/test_cohpsk_ch.c | 136 ++++++++++++++++++++++----- 4 files changed, 173 insertions(+), 32 deletions(-) create mode 100644 codec2-dev/octave/test_cohpsk_ch.m diff --git a/codec2-dev/octave/tcohpsk.m b/codec2-dev/octave/tcohpsk.m index ee6eb314..b0b4a1ea 100644 --- a/codec2-dev/octave/tcohpsk.m +++ b/codec2-dev/octave/tcohpsk.m @@ -56,9 +56,9 @@ randn('state',1); % select which test ---------------------------------------------------------- -test = 'compare to c'; +%test = 'compare to c'; %test = 'awgn'; -%test = 'fading'; +test = 'fading'; % some parameters that can be over ridden, e.g. to disable parts of modem @@ -84,27 +84,27 @@ 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; fading_en = 0; hf_delay_ms = 2; compare_with_c = 0; - sample_rate_ppm = -1500; + sample_rate_ppm = 0; end % Similar to AWGN - should be BER around 0.015 to 0.02 if strcmp(test, 'fading'); frames = 100; - foff = -53.1; + foff = 55; dfoff = 0.0/Fs; EsNodB = 12; fading_en = 1; hf_delay_ms = 2; compare_with_c = 0; - sample_rate_ppm = -100; + sample_rate_ppm = 0; end EsNo = 10^(EsNodB/10); @@ -228,6 +228,7 @@ ptx_bits_coh = 1; Nerrs = Tbits = 0; prev_tx_bits = prev_tx_bits2 = []; +error_positions_hist = zeros(1,framesize); phase_ch = 1; sync = initial_sync; @@ -482,6 +483,7 @@ for f=1:frames; Nerrs += sum(error_positions); nerr_log = [nerr_log sum(error_positions)]; Tbits += length(error_positions); + error_positions_hist += error_positions; end printf("\r [%d]", f); end @@ -659,8 +661,15 @@ else clf h = freqz(b,a,Fs/2); plot(20*log10(abs(h))) - axis([1 Fs/2 -50 0]) + axis([1 Fs/2 -20 0]) grid + title('SSB tx filter') + + figure(9) + clf + plot(error_positions_hist) + title('histogram of bit errors') + end @@ -686,3 +695,24 @@ function write_noise_file(uvnoise_log) fclose(f); endfunction + + +% function to write float fading samples for use by C programs + +function write_noise_file(raw_file_name, Fs, len_samples) + [spread spread_2ms hf_gain] = init_hf_model(Fs, len_samples); + hf_gain + % interleave real imag samples + + inter = zeros(1,len_samples*4); + inter(1:4) = hf_gain; + for i=1:len_samples + inter(i*4+1) = real(spread(i)); + inter(i*4+2) = imag(spread(i)); + inter(i*4+3) = real(spread_2ms(i)); + inter(i*4+4) = imag(spread_2ms(i)); + end + f = fopen(raw_file_name,"wb"); + fwrite(f, inter, "float32"); + fclose(f); +endfunction diff --git a/codec2-dev/octave/test_cohpsk_ch.m b/codec2-dev/octave/test_cohpsk_ch.m new file mode 100644 index 00000000..73446641 --- /dev/null +++ b/codec2-dev/octave/test_cohpsk_ch.m @@ -0,0 +1,21 @@ +% test_cohpsk_ch.m +% David Rowe May 2015 +% +% Plot outputs from test_coh_psk_ch.c + +Nc=7; Nd=2; + +load ../build_linux/unittest/test_cohpsk_ch_out.txt + +figure(3) +clf; + +% plot combined signals to show diversity gains + +combined = rx_symb_log_c(:,1:Nc); +for d=2:Nd + combined += rx_symb_log_c(:, (d-1)*Nc+1:d*Nc); +end +plot(combined*exp(j*pi/4)/sqrt(Nd),'+') +title('Scatter'); +axis([-2 2 -2 2]) diff --git a/codec2-dev/src/cohpsk.c b/codec2-dev/src/cohpsk.c index 8806e526..2c880f81 100644 --- a/codec2-dev/src/cohpsk.c +++ b/codec2-dev/src/cohpsk.c @@ -627,8 +627,8 @@ void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[]) for(r=0; rNc , tx_onesym, fdmdv->tx_filter_memory, - fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect); + tx_filter_and_upconvert_coh(&tx_fdm[r*COHPSK_M], COHPSK_NC*ND , tx_onesym, fdmdv->tx_filter_memory, + fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect); } } diff --git a/codec2-dev/unittest/test_cohpsk_ch.c b/codec2-dev/unittest/test_cohpsk_ch.c index cf4d6bbc..f304eaec 100644 --- a/codec2-dev/unittest/test_cohpsk_ch.c +++ b/codec2-dev/unittest/test_cohpsk_ch.c @@ -37,13 +37,18 @@ #include "octave.h" #include "comp_prim.h" #include "noise_samples.h" +#include "cohpsk_defs.h" +#include "cohpsk_internal.h" -#define FS 8000 #define FRAMES 100 -#define FOFF_HZ 10.5 -#define ES_NO_DB 8.0 +#define SYNC_FRAMES 12 /* sync state uses up extra log storage as we reprocess several times */ +#define FRAMESL (SYNC_FRAMES*FRAMES) /* worst case is every frame is out of sync */ + +#define FOFF_HZ 0.0 +#define ES_NO_DB 80.0 #define HF_DELAY_MS 2.0 -#define HF_GAIN 1.423599 + +#define CH_BUF_SZ (4*COHPSK_SAMPLES_PER_FRAME) #define FADING_FILE_NAME "../../raw/fading_samples.float" @@ -53,7 +58,11 @@ int main(int argc, char *argv[]) int tx_bits[COHPSK_BITS_PER_FRAME]; COMP tx_fdm[COHPSK_SAMPLES_PER_FRAME]; COMP ch_fdm[COHPSK_SAMPLES_PER_FRAME]; + COMP ch_buf[CH_BUF_SZ]; int rx_bits[COHPSK_BITS_PER_FRAME]; + float rx_amp_log[NSYMROW*FRAMES][COHPSK_NC*ND]; + float rx_phi_log[NSYMROW*FRAMES][COHPSK_NC*ND]; + COMP rx_symb_log[NSYMROW*FRAMES][COHPSK_NC*ND]; int f, r, i; int *ptest_bits_coh, *ptest_bits_coh_end, *ptest_bits_coh_rx; @@ -64,12 +73,21 @@ int main(int argc, char *argv[]) float EsNo, variance; COMP scaled_noise; float EsNodB, foff_hz; - int fading_en, nhfdelay, ret, nin; + int fading_en, nhfdelay, ret, nin_frame; + float hf_gain; COMP *ch_fdm_delay, aspread, aspread_2ms, delayed, direct; - FILE *ffading; + FILE *ffading, *fout; + 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; + + for(i=0; ich_symb_log_col_sz = COHPSK_NC*ND; + coh->ch_symb_log = (COMP *)malloc(sizeof(COMP)*NSYMROWPILOT*FRAMESL*coh->ch_symb_log_col_sz); + ptest_bits_coh = ptest_bits_coh_rx = (int*)test_bits_coh; ptest_bits_coh_end = (int*)test_bits_coh + sizeof(test_bits_coh)/sizeof(int); + phase_ch.real = 1.0; phase_ch.imag = 0.0; noise_r = 0; noise_end = sizeof(noise)/sizeof(COMP); - + ch_buf_n = 0; + + log_data_r = 0; + /* 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 */ @@ -101,19 +128,23 @@ int main(int argc, char *argv[]) printf("Can't find fading file: %s\n", FADING_FILE_NAME); exit(1); } - nhfdelay = floor(HF_DELAY_MS*FS/1000); + 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= ptest_bits_coh_end) { ptest_bits_coh = (int*)test_bits_coh; + //fprintf(stderr, " [%d] tx test bits wrap\n", f); } cohpsk_mod(coh, tx_fdm, tx_bits); + cohpsk_clip(tx_fdm); + + for(r=0; r noise_end) + if (noise_r > noise_end) { noise_r = 0; + //fprintf(stderr, " [%d] noise wrap\n", f); + } + } + /* buffer so we can let demod Fs offset code do it's thing */ + + memcpy(&ch_buf[ch_buf_n], ch_fdm, sizeof(COMP)*COHPSK_SAMPLES_PER_FRAME); + ch_buf_n += COHPSK_SAMPLES_PER_FRAME; + assert(ch_buf_n < CH_BUF_SZ); + + // add SAMPLES to end + // subtract nin from beginning /* --------------------------------------------------------*\ Demod \*---------------------------------------------------------*/ - cohpsk_demod(coh, rx_bits, &reliable_sync_bit, ch_fdm, &nin); + /* locks timing to avoid complications when we know there is + no Fs offset */ + tmp = nin_frame; + cohpsk_demod(coh, rx_bits, &reliable_sync_bit, ch_buf, &tmp); + ch_buf_n -= nin_frame; + assert(ch_buf_n >= 0); + if (ch_buf_n) + memcpy(ch_buf, &ch_buf[nin_frame], sizeof(COMP)*ch_buf_n); + nin_frame = tmp; + + //fprintf(stderr, " [%d] nin_frame: %d\n", f, nin_frame); errors = 0; for(i=0; i= ptest_bits_coh_end) { ptest_bits_coh_rx = (int*)test_bits_coh; + //fprintf(stderr, " [%d] rx test bits wrap\n", f); } - } + for(r=0; ramp_[r][c]; + rx_phi_log[log_data_r][c] = coh->phi_[r][c]; + rx_symb_log[log_data_r][c] = coh->rx_symb[r][c]; + } + } + } + state = next_state; } - + printf("%4.3f %d %d\n", (float)nerrors/nbits, nbits, nerrors); - + printf("tx var: %f noise var: %f rx var: %f\n", + tx_pwr/(FRAMES*COHPSK_SAMPLES_PER_FRAME), + noise_pwr/(FRAMES*COHPSK_SAMPLES_PER_FRAME), + rx_pwr/(FRAMES*COHPSK_SAMPLES_PER_FRAME) + ); if (fading_en) { free(ch_fdm_delay); fclose(ffading); } cohpsk_destroy(coh); + + //for(i=0; ich_symb_log, coh->ch_symb_log_r, COHPSK_NC*ND, COHPSK_NC*ND); + octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, log_data_r, COHPSK_NC*ND, COHPSK_NC*ND); + octave_save_float(fout, "rx_phi_log_c", (float*)rx_phi_log, log_data_r, COHPSK_NC*ND, COHPSK_NC*ND); + octave_save_complex(fout, "rx_symb_log_c", (COMP*)rx_symb_log, log_data_r, COHPSK_NC*ND, COHPSK_NC*ND); + fclose(fout); return 0; } -- 2.25.1