From: drowe67 Date: Thu, 26 Apr 2012 05:08:37 +0000 (+0000) Subject: freq state machine working X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=067ffec2964788b1dd2cf83bbdd7cb8af3887872;p=freetel-svn-tracking.git freq state machine working git-svn-id: https://svn.code.sf.net/p/freetel/code@382 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/README_fdmdv.txt b/codec2-dev/octave/README_fdmdv.txt index fb1b3eaf..a845678e 100644 --- a/codec2-dev/octave/README_fdmdv.txt +++ b/codec2-dev/octave/README_fdmdv.txt @@ -6,6 +6,11 @@ sox -r 8000 -s -2 mod_dqpsk.raw -s -2 mod_dqpsk_8008hz.raw rate -h 8008 TODO +[ ] consider moving this file to root + [ ] sep SVN repo, automake etc? +[ ] list each fdmdv.m script (ut, mod, demod) and Cprogram/src and what it does + [ ] example usage +[ ] repair fdmdv_ut and mod/demod after new statres exposed and var renames [X] Get file based mod and demod working again [ ] try interfering sine wave + maybe swept @@ -26,6 +31,7 @@ TODO [ ] mod in func with all vars [ ] check with ch impairments [ ] test with freq offsets + [ ] measure execution speed [ ] document use of fdmdv_ut and fdmdv_demod + PathSim [ ] block diagram [ ] maybe in ascii art diff --git a/codec2-dev/octave/fdmdv_ut.m b/codec2-dev/octave/fdmdv_ut.m index c99447af..248ffe3d 100644 --- a/codec2-dev/octave/fdmdv_ut.m +++ b/codec2-dev/octave/fdmdv_ut.m @@ -185,7 +185,7 @@ for f=1:frames else rx_symbols_log = [rx_symbols_log rx_symbols]; endif - [rx_bits sync ferr] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation); + [rx_bits sync foff_fine] = 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 0175f7a7..a1f8cf06 100644 --- a/codec2-dev/octave/tfdmdv.m +++ b/codec2-dev/octave/tfdmdv.m @@ -19,6 +19,9 @@ passes = fails = 0; frames = 25; prev_tx_symbols = ones(Nc+1,1); prev_rx_symbols = ones(Nc+1,1); +foff_phase_rect = 1; +track = 0; +fest_state = 0; % Octave outputs we want to collect for comparison to C version @@ -32,6 +35,8 @@ pilot_lpf1_log = []; pilot_lpf2_log = []; S1_log = []; S2_log = []; +foff_coarse_log = []; +foff_fine_log = []; foff_log = []; rx_baseband_log = []; rx_filt_log = []; @@ -39,8 +44,8 @@ env_log = []; rx_timing_log = []; rx_symbols_log = []; rx_bits_log = []; -ferr_log = []; sync_bit_log = []; +track_log = []; for f=1:frames @@ -62,8 +67,12 @@ for f=1:frames [pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, M); - [foff S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, M); + [foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, M); + if track == 0 + foff = foff_coarse; + end foff_log = [foff_log foff]; + foff_coarse_log = [foff_coarse_log foff_coarse]; pilot_baseband1_log = [pilot_baseband1_log pilot_baseband1]; pilot_baseband2_log = [pilot_baseband2_log pilot_baseband2]; @@ -72,7 +81,14 @@ for f=1:frames S1_log = [S1_log S1]; S2_log = [S2_log S2]; - rx_baseband = fdm_downconvert(rx_fdm, M); + foff_rect = exp(j*2*pi*foff/Fs); + + for i=1:M + foff_phase_rect *= foff_rect'; + rx_fdm_fcorr(i) = rx_fdm(i)*foff_phase_rect; + end + + rx_baseband = fdm_downconvert(rx_fdm_fcorr, M); rx_baseband_log = [rx_baseband_log rx_baseband]; rx_filt = rx_filter(rx_baseband, M); @@ -84,11 +100,16 @@ for f=1:frames 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'); + [rx_bits sync_bit foff_fine] = 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]; + foff_fine_log = [foff_fine_log foff_fine]; sync_bit_log = [sync_bit_log sync_bit]; + + % freq est state machine + + [track fest_state] = freq_state(sync_bit, fest_state); + track_log = [track_log track]; end % Compare to the output from the C version @@ -164,26 +185,29 @@ plot_sig_and_error(7, 212, imag(S1_log), imag(S1_log - S1_log_c), 'S1 imag' ) plot_sig_and_error(8, 211, real(S2_log), real(S2_log - S2_log_c), 'S2 real' ) 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' ) +plot_sig_and_error(9, 211, foff_coarse_log, foff_coarse_log - foff_coarse_log_c, 'Coarse Freq Offset' ) +plot_sig_and_error(9, 212, foff_fine_log, foff_fine_log - foff_fine_log_c, 'Fine Freq Offset' ) + +plot_sig_and_error(10, 211, foff_log, foff_log - foff_log_c, 'Freq Offset' ) +plot_sig_and_error(10, 212, track_log, track_log - track_log_c, 'Freq Track' ) 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' ) +plot_sig_and_error(11, 211, real(rx_baseband_log(c,:)), real(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband real' ) +plot_sig_and_error(11, 212, imag(rx_baseband_log(c,:)), imag(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband imag' ) -plot_sig_and_error(11, 211, real(rx_filt_log(c,:)), real(rx_filt_log(c,:) - rx_filt_log_c(c,:)), 'Rx filt real' ) -plot_sig_and_error(11, 212, imag(rx_filt_log(c,:)), imag(rx_filt_log(c,:) - rx_filt_log_c(c,:)), 'Rx filt imag' ) +plot_sig_and_error(12, 211, real(rx_filt_log(c,:)), real(rx_filt_log(c,:) - rx_filt_log_c(c,:)), 'Rx filt real' ) +plot_sig_and_error(12, 212, imag(rx_filt_log(c,:)), imag(rx_filt_log(c,:) - rx_filt_log_c(c,:)), 'Rx filt imag' ) -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' ) +plot_sig_and_error(13, 211, env_log, env_log - env_log_c, 'env' ) +plot_sig_and_error(13, 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' ) +plot_sig_and_error(14, 211, rx_timing_log, rx_timing_log - rx_timing_log_c, 'Rx Timing' ) 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]) +stem_sig_and_error(15, 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]) + % --------------------------------------------------------------------------------------- % AUTOMATED CHECKS ------------------------------------------ % --------------------------------------------------------------------------------------- @@ -198,8 +222,8 @@ function check(a, b, test_name) printf("."); end printf(": "); - - if sum(a - b)/n < 1E-3 + + if abs(sum(a - b))/n < 1E-3 printf("OK\n"); passes++; else @@ -208,23 +232,24 @@ function check(a, b, test_name) end endfunction -check(tx_bits_log, tx_bits_log_c, 'fdmdv_get_test_bits'); -check(tx_symbols_log, tx_symbols_log_c, 'bits_to_dqpsk_symbols'); -check(tx_baseband_log, tx_baseband_log_c, 'tx_filter'); +check(tx_bits_log, tx_bits_log_c, 'tx_bits'); +check(tx_symbols_log, tx_symbols_log_c, 'tx_symbols'); +check(tx_baseband_log, tx_baseband_log_c, 'tx_baseband'); check(tx_fdm_log, tx_fdm_log_c, 'tx_fdm'); check(pilot_lut, pilot_lut_c, 'pilot_lut'); check(pilot_baseband1_log, pilot_baseband1_log_c, 'pilot lpf1'); 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(foff_coarse_log, foff_coarse_log_c, 'foff_coarse'); +check(foff_fine_log, foff_fine_log_c, 'foff_fine'); +check(foff_log, foff_log_c, 'foff'); 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_timing_log, rx_timing_log_c, 'rx_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 a70ff11b..abf6b94a 100644 --- a/codec2-dev/src/fdmdv.c +++ b/codec2-dev/src/fdmdv.c @@ -222,6 +222,14 @@ struct FDMDV *fdmdv_create(void) f->pilot_lpf1[i].imag = f->pilot_lpf2[i].imag = 0.0; } + f->foff_rect.real = 1.0; + f->foff_rect.imag = 0.0; + f->foff_phase_rect.real = 1.0; + f->foff_phase_rect.imag = 0.0; + + f->fest_state = 0; + f->track = 0; + return f; } @@ -432,6 +440,31 @@ void fdm_upconvert(COMP tx_fdm[], COMP tx_baseband[NC+1][M], COMP phase_tx[], CO } +/*---------------------------------------------------------------------------*\ + + FUNCTION....: fdmdv_mod() + AUTHOR......: David Rowe + DATE CREATED: 26/4/2012 + + FDMDV modulator, take a frame of FDMDV_BITS_PER_FRAME bits and + generates a frame of FDMDV_SAMPLES_PER_FRAME modulated symbols. + Sync bit is returned to aid alignment of your next frame. + +\*---------------------------------------------------------------------------*/ + +void fdmdv_mod(struct FDMDV *fdmdv, COMP tx_fdm[], int tx_bits[], int *sync_bit) +{ + COMP tx_symbols[NC+1]; + COMP tx_baseband[NC+1][M]; + + bits_to_dqpsk_symbols(tx_symbols, fdmdv->prev_tx_symbols, tx_bits, &fdmdv->tx_pilot_bit); + memcpy(fdmdv->prev_tx_symbols, tx_symbols, sizeof(COMP)*(NC+1)); + tx_filter(tx_baseband, tx_symbols, fdmdv->tx_filter_memory); + fdm_upconvert(tx_fdm, tx_baseband, fdmdv->phase_tx, fdmdv->freq); + + *sync_bit = fdmdv->tx_pilot_bit; +} + /*---------------------------------------------------------------------------*\ FUNCTION....: generate_pilot_fdm() @@ -647,6 +680,29 @@ float rx_est_freq_offset(struct FDMDV *f, float rx_fdm[], int nin) return foff; } +/*---------------------------------------------------------------------------*\ + + FUNCTION....: freq_shift() + AUTHOR......: David Rowe + DATE CREATED: 26/4/2012 + + Frequency shift modem signal. + +\*---------------------------------------------------------------------------*/ + +void freq_shift(COMP rx_fdm_fcorr[], float rx_fdm[], float foff, COMP *foff_rect, COMP *foff_phase_rect, int nin) +{ + int i; + + foff_rect->real = cos(2.0*PI*foff/FS); + foff_rect->imag = sin(2.0*PI*foff/FS); + for(i=0; ifoff_rect, &fdmdv->foff_phase_rect, *nin); + + /* 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)); +} + diff --git a/codec2-dev/src/fdmdv.h b/codec2-dev/src/fdmdv.h index 755bc6a2..75700629 100644 --- a/codec2-dev/src/fdmdv.h +++ b/codec2-dev/src/fdmdv.h @@ -52,8 +52,8 @@ struct FDMDV_STATS { struct FDMDV *fdmdv_create(void); void fdmdv_destroy(struct FDMDV *fdmdv_state); -void fdmdv_mod(struct FDMDV *fdmdv_state, COMP tx_fdm[], int tx_bits[], int *sync); -void fdmdv_demod(struct FDMDV *fdmdv_state, int rx_bits[], int *sync, float rx_fdm[], int *nin); +void fdmdv_mod(struct FDMDV *fdmdv_state, COMP tx_fdm[], int tx_bits[], int *sync_bit); +void fdmdv_demod(struct FDMDV *fdmdv_state, int rx_bits[], int *sync_bit, float rx_fdm[], int *nin); void fdmdv_get_test_bits(struct FDMDV *fdmdv_state, int tx_bits[]); void fdmdv_put_test_bits(struct FDMDV *f, int *sync, int *bit_errors, int rx_bits[]); diff --git a/codec2-dev/src/fdmdv_internal.h b/codec2-dev/src/fdmdv_internal.h index 9fbedd90..7982ff6b 100644 --- a/codec2-dev/src/fdmdv_internal.h +++ b/codec2-dev/src/fdmdv_internal.h @@ -90,11 +90,17 @@ struct FDMDV { COMP S1[MPILOTFFT]; COMP S2[MPILOTFFT]; + COMP foff_rect; + COMP foff_phase_rect; + COMP phase_rx[NC+1]; 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]; + + int fest_state; + int track; }; /*---------------------------------------------------------------------------*\ @@ -110,6 +116,7 @@ void generate_pilot_fdm(COMP *pilot_fdm, int *bit, float *symbol, float *filter_ void generate_pilot_lut(COMP pilot_lut[], COMP *pilot_freq); float rx_est_freq_offset(struct FDMDV *f, float rx_fdm[], int nin); void lpf_peak_pick(float *foff, float *max, COMP pilot_baseband[], COMP pilot_lpf[], COMP S[], int nin); +void freq_shift(COMP rx_fdm_fcorr[], float rx_fdm[], float foff, COMP *foff_rect, COMP *foff_phase_rect, int nin); void fdm_downconvert(COMP rx_baseband[NC+1][M+M/P], COMP rx_fdm[], COMP phase_rx[], COMP freq[], int nin); void rx_filter(COMP rx_filt[NC+1][P+1], COMP rx_baseband[NC+1][M+M/P], COMP rx_filter_memory[NC+1][NFILTER], int nin); float rx_est_timing(COMP rx_symbols[], diff --git a/codec2-dev/unittest/tfdmdv.c b/codec2-dev/unittest/tfdmdv.c index a28a3990..3b8277e6 100644 --- a/codec2-dev/unittest/tfdmdv.c +++ b/codec2-dev/unittest/tfdmdv.c @@ -52,9 +52,8 @@ int main(int argc, char *argv[]) COMP tx_baseband[NC+1][M]; COMP tx_fdm[M]; float rx_fdm[M+M/P]; + float foff_coarse; float foff; - COMP foff_rect; - COMP foff_phase_rect; int nin; COMP rx_fdm_fcorr[M+M/P]; COMP rx_baseband[NC+1][M+M/P]; @@ -63,9 +62,10 @@ int main(int argc, char *argv[]) float env[NT*P]; COMP rx_symbols[NC+1]; int rx_bits[FDMDV_BITS_PER_FRAME]; - float ferr; + float foff_fine; int sync_bit; - + int fest_state; + int tx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES]; COMP tx_symbols_log[(NC+1)*FRAMES]; COMP tx_baseband_log[(NC+1)][M*FRAMES]; @@ -76,6 +76,7 @@ int main(int argc, char *argv[]) COMP pilot_lpf2_log[NPILOTLPF*FRAMES]; COMP S1_log[MPILOTFFT*FRAMES]; COMP S2_log[MPILOTFFT*FRAMES]; + float foff_coarse_log[FRAMES]; float foff_log[FRAMES]; COMP rx_baseband_log[(NC+1)][(M+M/P)*FRAMES]; int rx_baseband_log_col_index; @@ -85,14 +86,14 @@ int main(int argc, char *argv[]) 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]; + float foff_fine_log[FRAMES]; int sync_bit_log[FRAMES]; + int track_log[FRAMES]; FILE *fout; int f,c,i; fdmdv = fdmdv_create(); - foff_phase_rect.real = 0.0; foff_phase_rect.imag = 0.0; rx_baseband_log_col_index = 0; rx_filt_log_col_index = 0; @@ -119,7 +120,9 @@ int main(int argc, char *argv[]) /* freq offset estimation and correction */ - foff = rx_est_freq_offset(fdmdv, rx_fdm, nin); + foff_coarse = rx_est_freq_offset(fdmdv, rx_fdm, nin); + if (fdmdv->track == 0) + foff = foff_coarse; freq_shift(rx_fdm_fcorr, rx_fdm, foff, &fdmdv->foff_rect, &fdmdv->foff_phase_rect, nin); /* baseband processing */ @@ -127,9 +130,10 @@ int main(int argc, char *argv[]) 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); + foff_fine = qpsk_to_bits(rx_bits, &sync_bit, fdmdv->prev_rx_symbols, rx_symbols); memcpy(fdmdv->prev_rx_symbols, rx_symbols, sizeof(COMP)*(NC+1)); - + fdmdv->track = freq_state(sync_bit, &fdmdv->fest_state); + /* --------------------------------------------------------*\ Log each vector \*---------------------------------------------------------*/ @@ -149,6 +153,7 @@ int main(int argc, char *argv[]) memcpy(&pilot_lpf2_log[f*NPILOTLPF], fdmdv->pilot_lpf2, sizeof(COMP)*NPILOTLPF); memcpy(&S1_log[f*MPILOTFFT], fdmdv->S1, sizeof(COMP)*MPILOTFFT); memcpy(&S2_log[f*MPILOTFFT], fdmdv->S2, sizeof(COMP)*MPILOTFFT); + foff_coarse_log[f] = foff_coarse; foff_log[f] = foff; /* rx down conversion */ @@ -177,8 +182,10 @@ int main(int argc, char *argv[]) /* qpsk_to_bits() */ memcpy(&rx_bits_log[FDMDV_BITS_PER_FRAME*f], rx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME); - ferr_log[f] = ferr; + foff_fine_log[f] = foff_fine; sync_bit_log[f] = sync_bit; + + track_log[f] = fdmdv->track; } @@ -202,14 +209,16 @@ int main(int argc, char *argv[]) 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_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_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, "ferr_log_c", ferr_log, 1, FRAMES); + octave_save_float(fout, "foff_fine_log_c", foff_fine_log, 1, FRAMES); octave_save_int(fout, "sync_bit_log_c", sync_bit_log, 1, FRAMES); + octave_save_int(fout, "track_log_c", track_log, 1, FRAMES); fclose(fout); codec2_destroy(fdmdv);