From: drowe67 Date: Wed, 25 Apr 2012 02:16:09 +0000 (+0000) Subject: rx bits working OK X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=a5112661fcd74a86ec2092f74785bb7fad8538f8;p=freetel-svn-tracking.git rx bits working OK git-svn-id: https://svn.code.sf.net/p/freetel/code@379 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/README_fdmdv.txt b/codec2-dev/octave/README_fdmdv.txt index d0a011dc..fb1b3eaf 100644 --- a/codec2-dev/octave/README_fdmdv.txt +++ b/codec2-dev/octave/README_fdmdv.txt @@ -15,13 +15,22 @@ TODO [ ] test rx level sensitivity, i.e. 0 to 20dB attenuation [ ] try to run from shell script [ ] arb bit stream input to Octave mod and demod +[ ] make fine freq indep of amplitude + + use angle rather than imag corrd [ ] C port and UT framework - [ ] doumnent how to use + [ ] document how to use + [ ] demo modem C test program + [ ] freq corr in func, state vars in struct + [ ] fine freq est in func, statevars + [ ] demod in func with all vars + [ ] mod in func with all vars + [ ] check with ch impairments + [ ] test with freq offsets [ ] document use of fdmdv_ut and fdmdv_demod + PathSim [ ] block diagram + [ ] maybe in ascii art [ ] blog posts(s) [ ] Codec 2 web page update -[ ] demo modem C test program Tests diff --git a/codec2-dev/octave/fdmdv.m b/codec2-dev/octave/fdmdv.m index 6ce43b71..f7d44dae 100644 --- a/codec2-dev/octave/fdmdv.m +++ b/codec2-dev/octave/fdmdv.m @@ -637,7 +637,7 @@ endfunction % freq offset state machine. Moves between acquire and track states based % on BPSK pilot sequence. Freq offset estimator occasionally makes mistakes -% when used continuously. So we use it unit we have acquired the BPSK pilot, +% when used continuously. So we use it until we have acquired the BPSK pilot, % then switch to a more robust tracking algorithm. If we lose sync we switch % back to acquire mode for fast-requisition. diff --git a/codec2-dev/octave/fdmdv_ut.m b/codec2-dev/octave/fdmdv_ut.m index 0a20a42b..c99447af 100644 --- a/codec2-dev/octave/fdmdv_ut.m +++ b/codec2-dev/octave/fdmdv_ut.m @@ -30,7 +30,7 @@ rx_baseband_log = []; rx_bits_offset = zeros(Nc*Nb*2); prev_tx_symbols = ones(Nc+1,1); prev_rx_symbols = ones(Nc+1,1); -f_err = 0; +ferr = 0; foff = 0; foff_log = []; tx_baseband_log = []; @@ -185,8 +185,8 @@ for f=1:frames else rx_symbols_log = [rx_symbols_log rx_symbols]; endif - [rx_bits sync f_err] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation); - foff -= 0.5*f_err; + [rx_bits sync ferr] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation); + foff -= 0.5*ferr; prev_rx_symbols = rx_symbols; sync_log = [sync_log sync]; diff --git a/codec2-dev/octave/tfdmdv.m b/codec2-dev/octave/tfdmdv.m index 776bcc4a..0175f7a7 100644 --- a/codec2-dev/octave/tfdmdv.m +++ b/codec2-dev/octave/tfdmdv.m @@ -18,6 +18,7 @@ global fails; passes = fails = 0; frames = 25; prev_tx_symbols = ones(Nc+1,1); +prev_rx_symbols = ones(Nc+1,1); % Octave outputs we want to collect for comparison to C version @@ -37,6 +38,9 @@ rx_filt_log = []; env_log = []; rx_timing_log = []; rx_symbols_log = []; +rx_bits_log = []; +ferr_log = []; +sync_bit_log = []; for f=1:frames @@ -70,12 +74,21 @@ for f=1:frames rx_baseband = fdm_downconvert(rx_fdm, M); rx_baseband_log = [rx_baseband_log rx_baseband]; + rx_filt = rx_filter(rx_baseband, M); rx_filt_log = [rx_filt_log rx_filt]; + [rx_symbols rx_timing env] = rx_est_timing(rx_filt, rx_baseband, M); env_log = [env_log env]; + rx_timing_log = [rx_timing_log rx_timing]; rx_symbols_log = [rx_symbols_log rx_symbols]; + + [rx_bits sync_bit ferr] = qpsk_to_bits(prev_rx_symbols, rx_symbols, 'dqpsk'); + prev_rx_symbols = rx_symbols; + rx_bits_log = [rx_bits_log rx_bits]; + ferr_log = [ferr_log ferr]; + sync_bit_log = [sync_bit_log sync_bit]; end % Compare to the output from the C version @@ -154,7 +167,7 @@ plot_sig_and_error(8, 212, imag(S2_log), imag(S2_log - S2_log_c), 'S2 imag' ) plot_sig_and_error(9, 211, real(foff_log), real(foff_log - foff_log_c), 'Freq Offset' ) plot_sig_and_error(9, 212, rx_timing_log, rx_timing_log - rx_timing_log_c, 'Rx Timing' ) -c=10; +c=15; plot_sig_and_error(10, 211, real(rx_baseband_log(c,:)), real(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband real' ) plot_sig_and_error(10, 212, imag(rx_baseband_log(c,:)), imag(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband imag' ) @@ -164,6 +177,13 @@ plot_sig_and_error(11, 212, imag(rx_filt_log(c,:)), imag(rx_filt_log(c,:) - rx_f plot_sig_and_error(12, 211, env_log, env_log - env_log_c, 'env' ) plot_sig_and_error(12, 212, real(rx_symbols_log(c,:)), real(rx_symbols_log(c,:) - rx_symbols_log_c(c,:)), 'rx symbols' ) +st=10*28; +en = 12*28; +stem_sig_and_error(13, 211, rx_bits_log_c(st:en), rx_bits_log(st:en) - rx_bits_log_c(st:en), 'RX bits', [1 en-st -1.5 1.5]) + +plot_sig_and_error(14, 211, ferr_log, ferr_log - ferr_log_c, 'Fine freq error' ) +stem_sig_and_error(14, 212, sync_bit_log_c, sync_bit_log - sync_bit_log_c, 'Sync bit', [1 n -1.5 1.5]) + % --------------------------------------------------------------------------------------- % AUTOMATED CHECKS ------------------------------------------ % --------------------------------------------------------------------------------------- @@ -198,10 +218,13 @@ check(pilot_baseband2_log, pilot_baseband2_log_c, 'pilot lpf2'); check(S1_log, S1_log_c, 'S1'); check(S2_log, S2_log_c, 'S2'); check(foff_log, foff_log_c, 'rx_est_freq_offset'); -check(rx_baseband_log, rx_baseband_log_c, 'fdm_downconvert'); -check(rx_filt_log, rx_filt_log_c, 'fdm_downconvert'); +check(rx_baseband_log, rx_baseband_log_c, 'rx baseband'); +check(rx_filt_log, rx_filt_log_c, 'rx filt'); check(env_log, env_log_c, 'env'); check(rx_timing_log, rx_timing_log_c, 'rx_est_timing'); check(rx_symbols_log, rx_symbols_log_c, 'rx_symbols'); +check(rx_bits_log, rx_bits_log_c, 'rx bits'); +check(ferr_log, ferr_log_c, 'fine freq error'); +check(sync_bit_log, sync_bit_log_c, 'sync bit'); printf("\npasses: %d fails: %d\n", passes, fails); diff --git a/codec2-dev/src/fdmdv.c b/codec2-dev/src/fdmdv.c index 4525a114..a70ff11b 100644 --- a/codec2-dev/src/fdmdv.c +++ b/codec2-dev/src/fdmdv.c @@ -149,10 +149,17 @@ struct FDMDV *fdmdv_create(void) return NULL; f->current_test_bit = 0; + for(i=0; irx_test_bits_mem[i] = 0; + f->tx_pilot_bit = 0; + for(c=0; cprev_tx_symbols[c].real = 1.0; f->prev_tx_symbols[c].imag = 0.0; + f->prev_rx_symbols[c].real = 1.0; + f->prev_rx_symbols[c].imag = 0.0; + for(k=0; ktx_filter_memory[c][k].real = 0.0; f->tx_filter_memory[c][k].imag = 0.0; @@ -201,7 +208,7 @@ struct FDMDV *fdmdv_create(void) generate_pilot_lut(f->pilot_lut, &f->freq[NC]); - /* Freq Offset estimation */ + /* freq Offset estimation states */ for(i=0; ipilot_baseband1[i].real = f->pilot_baseband2[i].real = 0.0; @@ -834,7 +841,193 @@ float rx_est_timing(COMP rx_symbols[], for(k=s,j=0; k= 0) && (d.imag >= 0)) { + msb = 0; lsb = 0; + } + if ((d.real < 0) && (d.imag >= 0)) { + msb = 0; lsb = 1; + } + if ((d.real < 0) && (d.imag < 0)) { + msb = 1; lsb = 0; + } + if ((d.real >= 0) && (d.imag < 0)) { + msb = 1; lsb = 1; + } + rx_bits[2*c] = msb; + rx_bits[2*c+1] = lsb; + } + + /* Extract DBPSK encoded Sync bit */ + + phase_difference[NC] = cmult(rx_symbols[NC], cconj(prev_rx_symbols[NC])); + if (phase_difference[NC].real < 0) { + *sync_bit = 0; + ferr = phase_difference[NC].imag; + } + else { + *sync_bit = 1; + ferr = -phase_difference[NC].imag; + } + + return ferr; +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: fdmdv_put_test_bits() + AUTHOR......: David Rowe + DATE CREATED: 24/4/2012 + + Accepts nbits from rx and attempts to sync with test_bits sequence. + If sync OK measures bit errors. + +\*---------------------------------------------------------------------------*/ + +void fdmdv_put_test_bits(struct FDMDV *f, int *sync, int *bit_errors, int rx_bits[]) +{ + int i,j; + float ber; + + /* Append to our memory */ + + for(i=0,j=FDMDV_BITS_PER_FRAME; irx_test_bits_mem[i] = f->rx_test_bits_mem[j]; + for(i=NTEST_BITS-FDMDV_BITS_PER_FRAME,j=0; irx_test_bits_mem[i] = rx_bits[j]; + + /* see how many bit errors we get when checked against test sequence */ + + *bit_errors = 0; + for(i=0; irx_test_bits_mem[i]; + + /* if less than a thresh we are aligned and in sync with test sequence */ + + ber = *bit_errors/NTEST_BITS; + + *sync = 0; + if (ber < 0.2) + *sync = 1; +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: freq_state(() + AUTHOR......: David Rowe + DATE CREATED: 24/4/2012 + + Freq offset state machine. Moves between acquire and track states based + on BPSK pilot sequence. Freq offset estimator occasionally makes mistakes + when used continuously. So we use it until we have acquired the BPSK pilot, + then switch to a more robust tracking algorithm. If we lose sync we switch + back to acquire mode for fast-requisition. + +\*---------------------------------------------------------------------------*/ + +int freq_state(int sync_bit, int *state) +{ + int next_state, track; + + /* acquire state, look for 6 symbol 010101 sequence from sync bit */ + + next_state = *state; + switch(*state) { + case 0: + if (sync_bit == 0) + next_state = 1; + break; + case 1: + if (sync_bit == 1) + next_state = 2; + else + next_state = 0; + break; + case 2: + if (sync_bit == 0) + next_state = 3; + else + next_state = 0; + break; + case 3: + if (sync_bit == 1) + next_state = 4; + else + next_state = 0; + break; + case 4: + if (sync_bit == 0) + next_state = 5; + else + next_state = 0; + break; + case 5: + if (sync_bit == 1) + next_state = 6; + else + next_state = 0; + break; + + /* states 6 and above are track mode, make sure we keep + getting 0101 sync bit sequence */ + + case 6: + if (sync_bit == 0) + next_state = 7; + else + next_state = 0; + + break; + case 7: + if (sync_bit == 1) + next_state = 6; + else + next_state = 0; + break; + } + + *state = next_state; + if (*state >= 6) + track = 1; + else + track = 0; + + return track; +} diff --git a/codec2-dev/src/fdmdv.h b/codec2-dev/src/fdmdv.h index 702dfc6f..755bc6a2 100644 --- a/codec2-dev/src/fdmdv.h +++ b/codec2-dev/src/fdmdv.h @@ -56,7 +56,7 @@ void fdmdv_mod(struct FDMDV *fdmdv_state, COMP tx_fdm[], int tx_bits[], void fdmdv_demod(struct FDMDV *fdmdv_state, int rx_bits[], int *sync, float rx_fdm[], int *nin); void fdmdv_get_test_bits(struct FDMDV *fdmdv_state, int tx_bits[]); -void fdmdv_put_test_bits(struct FDMDV *fdmdv_state, int rx_bits[]); +void fdmdv_put_test_bits(struct FDMDV *f, int *sync, int *bit_errors, int rx_bits[]); float fdmdv_get_demod_stats(struct FDMDV *fdmdv_state, struct FDMDV_STATS *fdmdv_stats); void fdmdv_get_waterfall_line(struct FDMDV *fdmdv_state, float magnitudes[], int *magnitude_points); diff --git a/codec2-dev/src/fdmdv_internal.h b/codec2-dev/src/fdmdv_internal.h index eec78de0..9fbedd90 100644 --- a/codec2-dev/src/fdmdv_internal.h +++ b/codec2-dev/src/fdmdv_internal.h @@ -71,6 +71,7 @@ struct FDMDV { int current_test_bit; + int rx_test_bits_mem[NTEST_BITS]; int tx_pilot_bit; COMP prev_tx_symbols[NC+1]; @@ -93,6 +94,7 @@ struct FDMDV { COMP rx_filter_memory[NC+1][NFILTER]; COMP rx_filter_mem_timing[NC+1][NT*P]; COMP rx_baseband_mem_timing[NC+1][NFILTERTIMING]; + COMP prev_rx_symbols[NC+1]; }; /*---------------------------------------------------------------------------*\ @@ -117,5 +119,7 @@ float rx_est_timing(COMP rx_symbols[], float env[], COMP rx_baseband_mem_timing[NC+1][NFILTERTIMING], int nin); +float qpsk_to_bits(int rx_bits[], int *sync_bit, COMP prev_rx_symbols[], COMP rx_symbols[]); +int freq_state(int sync_bit, int *state); #endif diff --git a/codec2-dev/unittest/tfdmdv.c b/codec2-dev/unittest/tfdmdv.c index b7405f15..5141de3a 100644 --- a/codec2-dev/unittest/tfdmdv.c +++ b/codec2-dev/unittest/tfdmdv.c @@ -61,7 +61,10 @@ int main(int argc, char *argv[]) float rx_timing; float env[NT*P]; COMP rx_symbols[NC+1]; - + int rx_bits[FDMDV_BITS_PER_FRAME]; + float ferr; + int sync_bit; + int tx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES]; COMP tx_symbols_log[(NC+1)*FRAMES]; COMP tx_baseband_log[(NC+1)][M*FRAMES]; @@ -80,7 +83,10 @@ int main(int argc, char *argv[]) float env_log[NT*P*FRAMES]; float rx_timing_log[FRAMES]; COMP rx_symbols_log[NC+1][FRAMES]; - + int rx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES]; + float ferr_log[FRAMES]; + int sync_bit_log[FRAMES]; + FILE *fout; int f,c,i; @@ -106,7 +112,7 @@ int main(int argc, char *argv[]) /* demodulator ----------------------------------------*/ - /* Freq offset estimation and correction */ + /* freq offset estimation and correction */ foff = rx_est_freq_offset(fdmdv, rx_fdm, nin); @@ -121,10 +127,14 @@ int main(int argc, char *argv[]) rx_fdm_fcorr[i].imag = 0.0; } + /* baseband processing */ + fdm_downconvert(rx_baseband, rx_fdm_fcorr, fdmdv->phase_rx, fdmdv->freq, nin); rx_filter(rx_filt, rx_baseband, fdmdv->rx_filter_memory, nin); rx_timing = rx_est_timing(rx_symbols, rx_filt, rx_baseband, fdmdv->rx_filter_mem_timing, env, fdmdv->rx_baseband_mem_timing, nin); - + ferr = qpsk_to_bits(rx_bits, &sync_bit, fdmdv->prev_rx_symbols, rx_symbols); + memcpy(fdmdv->prev_rx_symbols, rx_symbols, sizeof(COMP)*(NC+1)); + /* save log of outputs ------------------------------------------------------*/ memcpy(&tx_bits_log[FDMDV_BITS_PER_FRAME*f], tx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME); @@ -166,9 +176,16 @@ int main(int argc, char *argv[]) rx_timing_log[f] = rx_timing; for(c=0; c