Fixed CLI for timing recovery, added max_dphase for Costas

This commit is contained in:
ha7ilm 2017-05-15 21:35:58 +02:00
parent fe46aba98d
commit 50528abd71
5 changed files with 587 additions and 63 deletions

31
csdr.c
View file

@ -127,7 +127,7 @@ char usage[]=
" rtty_baudot2ascii_u8_u8\n"
" serial_line_decoder_f_u8 <samples_per_bits> [databits [stopbits]]\n"
" octave_complex_c <samples_to_plot> <out_of_n_samples>\n"
" timing_recovery_cc <algorithm> <decimation> [mu [--add_q [--output_error | --output_indexes | --octave <debug_n>]]] \n"
" timing_recovery_cc <algorithm> <decimation> [mu [--add_q [--output_error | --output_indexes | --octave <show_every_nth> | --octave_save <show_every_nth> <directory> ]]] \n"
" psk31_varicode_encoder_u8_u8\n"
" psk31_varicode_decoder_u8_u8\n"
" differential_encoder_u8_u8\n"
@ -136,7 +136,7 @@ char usage[]=
" psk_modulator_u8_c <n_psk>\n"
" psk31_interpolate_sine_cc <interpolation>\n"
" duplicate_samples_ntimes_u8_u8 <sample_size_bytes> <ntimes>\n"
" bpsk_costas_loop_cc //<loop_bandwidth> <damping_factor> [--dd | --decision_directed] [--output_error | --output_dphase | --output_nco | --output_combined <error_file> <dphase_file> <nco_file>]\n"
" bpsk_costas_loop_cc <loop_bandwidth> <damping_factor> [--dd | --decision_directed] [--output_error | --output_dphase | --output_nco | --output_combined <error_file> <dphase_file> <nco_file>]\n"
" binary_slicer_f_u8\n"
" simple_agc_cc <rate> [reference [max_gain]]\n"
" firdes_peak_c <rate> <length> [window [--octave]]\n"
@ -2549,7 +2549,7 @@ int main(int argc, char *argv[])
}
}
if(!strcmp(argv[1],"timing_recovery_cc")) //<algorithm> <decimation> [loop_gain [max_error [--add_q] [--output_error | --output_indexes | --octave <debug_n>]]]
if(!strcmp(argv[1],"timing_recovery_cc")) //<algorithm> <decimation> [mu [max_error [--add_q [--output_error | --output_indexes | --octave <show_every_nth> | --octave_save <show_every_nth> <directory> ]]]] \n"
{
if(argc<=2) return badsyntax("need required parameter (algorithm)");
timing_recovery_algorithm_t algorithm = timing_recovery_get_algorithm_from_string(argv[2]);
@ -2568,11 +2568,22 @@ int main(int argc, char *argv[])
int add_q = !!(argc>=7 && !strcmp(argv[6], "--add_q"));
int debug_n = 0;
int debug_every_nth = -1;
int output_error = 0;
int output_indexes = 0;
if(argc+add_q>=8 && !strcmp(argv[6+add_q], "--octave")) debug_n = atoi(argv[7+add_q]);
if(debug_n<0) return badsyntax("debug_n should be >= 0");
int octave_save = 0;
char* octave_save_path = NULL;
if(argc>=8+add_q && (!strcmp(argv[6+add_q], "--octave") || (octave_save = !strcmp(argv[6+add_q], "--octave_save"))))
{
debug_every_nth = atoi(argv[7+add_q]);
if(debug_every_nth<0) return badsyntax("debug_every_nth should be >= 0");
}
if(octave_save)
{
if(argc>=9+add_q) octave_save_path = argv[8+add_q];
else octave_save_path = "figs";
}
if(debug_every_nth<0) { errhead(); fprintf(stderr, "--add_q mode on\n"); }
if(argc>=(8+add_q) && !strcmp(argv[7+add_q], "--output_error")) output_error = 1;
float* timing_error = NULL;
@ -2585,17 +2596,13 @@ int main(int argc, char *argv[])
if(!initialize_buffers()) return -2;
sendbufsize(the_bufsize/decimation);
timing_recovery_state_t state = timing_recovery_init(algorithm, decimation, add_q, loop_gain, max_error);
timing_recovery_state_t state = timing_recovery_init(algorithm, decimation, add_q, loop_gain, max_error, debug_every_nth, octave_save_path);
int debug_i=0;
state.debug_writefiles = 1;
state.debug_force = !!debug_n; //should remove that later
FREAD_C;
unsigned buffer_start_counter = 0;
for(;;)
{
FEOF_CHECK;
if(debug_n && ++debug_i%debug_n==0) timing_recovery_trigger_debug(&state, 3);
timing_recovery_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, timing_error, (int*)sampled_indexes, &state);
//fprintf(stderr, "trcc is=%d, os=%d, ip=%d\n",the_bufsize, state.output_size, state.input_processed);
if(timing_error) fwrite(timing_error, sizeof(float), state.output_size, stdout);
@ -2819,9 +2826,9 @@ int main(int argc, char *argv[])
FILE* file_output_error = NULL;
FILE* file_output_dphase = NULL;
FILE* file_output_nco = NULL;
if(!(argc>4+decision_directed+3)) { errhead(); return badsyntax("need required parameters after --output_combined: <error_file> <dphase_file> <nco_file>"); }
if(output_combined)
{
if(!(argc>4+decision_directed+3)) { return badsyntax("need required parameters after --output_combined: <error_file> <dphase_file> <nco_file>"); }
file_output_error = fopen(argv[4+decision_directed+1], "w");
file_output_dphase = fopen(argv[4+decision_directed+2], "w");
file_output_nco = fopen(argv[4+decision_directed+3], "w");

View file

@ -257,7 +257,7 @@
</param>
<param>
<key>commandline</key>
<value>csdr dsb_fc | csdr shift_addition_cc $(csdr =-2000./48e3) | csdr fir_decimate_cc 32 | csdr simple_agc_cc 0.0001 0.5</value>
<value>csdr dsb_fc | csdr shift_addition_cc $(csdr =-2000./48e3) | csdr fir_decimate_cc 32</value>
</param>
<param>
<key>comment</key>
@ -304,7 +304,7 @@
</param>
<param>
<key>commandline</key>
<value>csdr bpsk_costas_loop_cc 48</value>
<value>csdr bpsk_costas_loop_cc 0.05 0.707</value>
</param>
<param>
<key>comment</key>
@ -316,7 +316,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -363,7 +363,7 @@
</param>
<param>
<key>_enabled</key>
<value>1</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -390,6 +390,53 @@
<value>cc</value>
</param>
</block>
<block>
<key>ha5kfu_execproc_xx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>commandline</key>
<value>csdr bandpass_fir_fft_cc $(csdr '=-(31.25)/1.5e3') $(csdr '=(31.25)/1.5e3') $(csdr '=31.25/1.5e3') | csdr simple_agc_cc 0.0001 0.5 </value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(568, 643)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>ha5kfu_execproc_xx_0_1</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>type</key>
<value>cc</value>
</param>
</block>
<block>
<key>notebook</key>
<param>
@ -422,7 +469,7 @@
</param>
<param>
<key>labels</key>
<value>['tab1', 'tab2', 'tab3', 'tab4']</value>
<value>['tab1', 'channel', 'tab3', 'tab4','bpf']</value>
</param>
<param>
<key>notebook</key>
@ -667,7 +714,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>0</value>
</param>
<param>
<key>fft_size</key>
@ -742,6 +789,109 @@
<value>10</value>
</param>
</block>
<block>
<key>wxgui_fftsink2</key>
<param>
<key>avg_alpha</key>
<value>0</value>
</param>
<param>
<key>average</key>
<value>False</value>
</param>
<param>
<key>baseband_freq</key>
<value>0</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>1</value>
</param>
<param>
<key>fft_size</key>
<value>1024</value>
</param>
<param>
<key>freqvar</key>
<value>None</value>
</param>
<param>
<key>_coordinate</key>
<value>(832, 563)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>wxgui_fftsink2_0_1_0</value>
</param>
<param>
<key>notebook</key>
<value>nb, 4</value>
</param>
<param>
<key>peak_hold</key>
<value>False</value>
</param>
<param>
<key>ref_level</key>
<value>0</value>
</param>
<param>
<key>ref_scale</key>
<value>2.0</value>
</param>
<param>
<key>fft_rate</key>
<value>15</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate/32</value>
</param>
<param>
<key>title</key>
<value>FFT Plot</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>win_size</key>
<value></value>
</param>
<param>
<key>win</key>
<value>window.hamming</value>
</param>
<param>
<key>y_divs</key>
<value>10</value>
</param>
<param>
<key>y_per_div</key>
<value>10</value>
</param>
</block>
<block>
<key>wxgui_scopesink2</key>
<param>
@ -762,7 +912,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -849,7 +999,7 @@
</param>
<param>
<key>_enabled</key>
<value>1</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -916,6 +1066,283 @@
<value>Counts</value>
</param>
</block>
<block>
<key>wxgui_scopesink2</key>
<param>
<key>ac_couple</key>
<value>False</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(832, 787)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>wxgui_scopesink2_0_0_0</value>
</param>
<param>
<key>notebook</key>
<value>nb,4</value>
</param>
<param>
<key>num_inputs</key>
<value>1</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate/32</value>
</param>
<param>
<key>t_scale</key>
<value>0</value>
</param>
<param>
<key>title</key>
<value>Scope Plot</value>
</param>
<param>
<key>trig_mode</key>
<value>wxgui.TRIG_MODE_AUTO</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>v_offset</key>
<value>0</value>
</param>
<param>
<key>v_scale</key>
<value>0</value>
</param>
<param>
<key>win_size</key>
<value></value>
</param>
<param>
<key>xy_mode</key>
<value>False</value>
</param>
<param>
<key>y_axis_label</key>
<value>Counts</value>
</param>
</block>
<block>
<key>wxgui_waterfallsink2</key>
<param>
<key>avg_alpha</key>
<value>0</value>
</param>
<param>
<key>average</key>
<value>False</value>
</param>
<param>
<key>baseband_freq</key>
<value>0</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>dynamic_range</key>
<value>100</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fft_rate</key>
<value>15</value>
</param>
<param>
<key>fft_size</key>
<value>512</value>
</param>
<param>
<key>freqvar</key>
<value>None</value>
</param>
<param>
<key>_coordinate</key>
<value>(840, 907)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>wxgui_waterfallsink2_0</value>
</param>
<param>
<key>notebook</key>
<value>nb,4</value>
</param>
<param>
<key>ref_scale</key>
<value>2.0</value>
</param>
<param>
<key>ref_level</key>
<value>0</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate/32</value>
</param>
<param>
<key>title</key>
<value>Waterfall Plot</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>win_size</key>
<value></value>
</param>
<param>
<key>win</key>
<value>None</value>
</param>
</block>
<block>
<key>wxgui_waterfallsink2</key>
<param>
<key>avg_alpha</key>
<value>0</value>
</param>
<param>
<key>average</key>
<value>False</value>
</param>
<param>
<key>baseband_freq</key>
<value>0</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>dynamic_range</key>
<value>100</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fft_rate</key>
<value>15</value>
</param>
<param>
<key>fft_size</key>
<value>512</value>
</param>
<param>
<key>freqvar</key>
<value>None</value>
</param>
<param>
<key>_coordinate</key>
<value>(1120, 43)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>wxgui_waterfallsink2_0_0</value>
</param>
<param>
<key>notebook</key>
<value>nb,1</value>
</param>
<param>
<key>ref_scale</key>
<value>2.0</value>
</param>
<param>
<key>ref_level</key>
<value>0</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate/32</value>
</param>
<param>
<key>title</key>
<value>Waterfall Plot</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>win_size</key>
<value></value>
</param>
<param>
<key>win</key>
<value>None</value>
</param>
</block>
<connection>
<source_block_id>audio_source_0</source_block_id>
<sink_block_id>ha5kfu_execproc_xx_0</sink_block_id>
@ -946,12 +1373,24 @@
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>blocks_float_to_complex_0</source_block_id>
<sink_block_id>ha5kfu_execproc_xx_0_1</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>blocks_float_to_complex_0</source_block_id>
<sink_block_id>wxgui_fftsink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>blocks_float_to_complex_0</source_block_id>
<sink_block_id>wxgui_waterfallsink2_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>ha5kfu_execproc_xx_0</source_block_id>
<sink_block_id>blocks_deinterleave_0</sink_block_id>
@ -982,4 +1421,22 @@
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>ha5kfu_execproc_xx_0_1</source_block_id>
<sink_block_id>wxgui_fftsink2_0_1_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>ha5kfu_execproc_xx_0_1</source_block_id>
<sink_block_id>wxgui_scopesink2_0_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>ha5kfu_execproc_xx_0_1</source_block_id>
<sink_block_id>wxgui_waterfallsink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
</flow_graph>

View file

@ -293,7 +293,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -336,7 +336,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -399,7 +399,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -446,7 +446,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -489,7 +489,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
@ -575,6 +575,65 @@
<value>1</value>
</param>
</block>
<block>
<key>blocks_vector_source_x</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(32, 443)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>blocks_vector_source_x_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>repeat</key>
<value>True</value>
</param>
<param>
<key>tags</key>
<value>[]</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
<param>
<key>vector</key>
<value>(1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1)</value>
</param>
</block>
<block>
<key>digital_costas_loop_cc</key>
<param>
@ -650,7 +709,7 @@
</param>
<param>
<key>_enabled</key>
<value>True</value>
<value>1</value>
</param>
<param>
<key>_coordinate</key>
@ -693,7 +752,7 @@
</param>
<param>
<key>commandline</key>
<value>tee /s/costas_input | csdr bpsk_costas_loop_cc 0.1 0.707 --output_combined /s/costas_error /s/costas_dphase /s/costas_nco | tee /s/costas_output</value>
<value>tee /s/costas_input | CSDR_FIXED_BUFSIZE=1 csdr bpsk_costas_loop_cc 0.1 0.707 --dd --output_combined /s/costas_error /s/costas_dphase /s/costas_nco | tee /s/costas_output</value>
</param>
<param>
<key>comment</key>
@ -948,6 +1007,12 @@
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>blocks_vector_source_x_0</source_block_id>
<sink_block_id>freq_xlating_fir_filter_xxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>digital_costas_loop_cc_0</source_block_id>
<sink_block_id>wxgui_scopesink2_0_0_0</sink_block_id>

View file

@ -1894,7 +1894,7 @@ void pll_cc(pll_t* p, complexf* input, float* output_dphase, complexf* output_nc
}
}
void octave_plot_point_on_cplxsig(complexf* signal, int signal_size, float error, int index, int correction_offset, int writefiles, int points_size, ...)
void octave_plot_point_on_cplxsig(complexf* signal, int signal_size, float error, int index, int correction_offset, char* writefiles_path, int points_size, ...)
{
static int figure_output_counter = 0;
int* points_z = (int*)malloc(sizeof(int)*points_size);
@ -1906,7 +1906,7 @@ void octave_plot_point_on_cplxsig(complexf* signal, int signal_size, float error
points_z[i] = va_arg(vl, int);
points_color[i] = va_arg(vl, int);
}
if(writefiles && !figure_output_counter) fprintf(stderr, "cf=figure();\n");
if(writefiles_path && !figure_output_counter) fprintf(stderr, "cf=figure();\n");
fprintf(stderr, "N = %d;\nisig = [", signal_size);
for(int i=0;i<signal_size;i++) fprintf(stderr, "%f ", iof(signal,i));
fprintf(stderr, "];\nqsig = [");
@ -1931,13 +1931,13 @@ void octave_plot_point_on_cplxsig(complexf* signal, int signal_size, float error
(char)points_color[i]&0xff, (i<points_size-1)?',':' '
);
fprintf(stderr, ");\n");
if(writefiles) fprintf(stderr, "print(cf, \"figs/%05d.png\", \"-S1024,1024\");\n", figure_output_counter++);
if(writefiles_path) fprintf(stderr, "print(cf, \"%s/%05d.png\", \"-S1024,1024\");\n", writefiles_path, figure_output_counter++);
fflush(stderr);
free(points_z);
free(points_color);
}
timing_recovery_state_t timing_recovery_init(timing_recovery_algorithm_t algorithm, int decimation_rate, int use_q, float loop_gain, float max_error)
timing_recovery_state_t timing_recovery_init(timing_recovery_algorithm_t algorithm, int decimation_rate, int use_q, float loop_gain, float max_error, int debug_every_nth, char* debug_writefiles_path)
{
timing_recovery_state_t to_return;
to_return.algorithm = algorithm;
@ -1945,20 +1945,13 @@ timing_recovery_state_t timing_recovery_init(timing_recovery_algorithm_t algorit
to_return.loop_gain = loop_gain;
to_return.max_error = max_error;
to_return.use_q = use_q;
to_return.debug_phase = -1;
to_return.debug_count = 3;
to_return.debug_force = 0;
to_return.debug_writefiles = 0;
to_return.debug_phase = to_return.debug_every_nth = debug_every_nth; //debug is effective if it is >=0
to_return.last_correction_offset = 0;
to_return.earlylate_ratio = 0.25; //0..0.5
to_return.debug_writefiles_path = debug_writefiles_path;
return to_return;
}
void timing_recovery_trigger_debug(timing_recovery_state_t* state, int debug_phase)
{
state->debug_phase=debug_phase;
}
#define MTIMINGR_HDEBUG 0
void timing_recovery_cc(complexf* input, complexf* output, int input_size, float* timing_error, int* sampled_indexes, timing_recovery_state_t* state)
@ -1971,11 +1964,10 @@ void timing_recovery_cc(complexf* input, complexf* output, int input_size, float
int num_samples_halfbit = state->decimation_rate / 2;
int num_samples_quarterbit = state->decimation_rate / 4;
int num_samples_earlylate_wing = num_samples_bit * state->earlylate_ratio;
int debug_i = state->debug_count;
float error;
int el_point_left_index, el_point_right_index, el_point_mid_index;
int si = 0;
if(state->debug_force) fprintf(stderr, "disp(\"begin timing_recovery_cc\");\n");
if(state->debug_every_nth>=0) fprintf(stderr, "disp(\"begin timing_recovery_cc\");\n");
if(MTIMINGR_HDEBUG) fprintf(stderr, "timing_recovery_cc started, nsb = %d, nshb = %d, nsqb = %d\n", num_samples_bit, num_samples_halfbit, num_samples_quarterbit);
{
for(;;)
@ -2026,21 +2018,24 @@ void timing_recovery_cc(complexf* input, complexf* output, int input_size, float
if(error>state->max_error) error=state->max_error;
if(error<-state->max_error) error=-state->max_error;
if( state->debug_force || (state->debug_phase >= si && debug_i) )
if(state->debug_every_nth>=0)
{
debug_i--;
if(!debug_i) state->debug_phase = -1;
if(state->debug_every_nth==0 || state->debug_phase==0)
{
state->debug_phase = state->debug_every_nth;
octave_plot_point_on_cplxsig(input+current_bitstart_index, state->decimation_rate*2,
error,
current_bitstart_index,
correction_offset,
state->debug_writefiles,
state->debug_writefiles_path,
3,
el_point_left_index - current_bitstart_index, 'r',
el_point_right_index - current_bitstart_index, 'r',
el_point_mid_index - current_bitstart_index, 'r',
0);
}
else state->debug_phase--;
}
int error_sign = (state->algorithm == TIMING_RECOVERY_ALGORITHM_GARDNER) ? -1 : 1;
correction_offset = num_samples_halfbit * error_sign * error * state->loop_gain;
current_bitstart_index += num_samples_bit + correction_offset;
@ -2085,6 +2080,7 @@ void init_bpsk_costas_loop_cc(bpsk_costas_loop_state_t* s, int decision_directed
s->alpha = (4*damping_factor*bandwidth_omega)/denomiator;
s->beta = (4*bandwidth_omega*bandwidth_omega)/denomiator;
s->iir_temp = s->dphase = s->nco_phase = 0;
s->dphase_max=0.9*PI; //if it reached PI or -PI then it might actually hang and not come back
}
void bpsk_costas_loop_cc(complexf* input, complexf* output, int input_size, float* output_error, float* output_dphase, complexf* output_nco, bpsk_costas_loop_state_t* s)
@ -2111,8 +2107,8 @@ void bpsk_costas_loop_cc(complexf* input, complexf* output, int input_size, floa
if(output_error) output_error[i]=error;
s->dphase = error * s->alpha + s->iir_temp;
s->iir_temp += error * s->beta; //iir_temp could be named current_freq. See Tom Rondeau's article for better understanding.
if(s->dphase>PI) s->dphase=PI;
if(s->dphase<-PI) s->dphase=-PI;
if(s->dphase>s->dphase_max) s->dphase=s->dphase_max;
if(s->dphase<-s->dphase_max) s->dphase=-s->dphase_max;
if(output_dphase) output_dphase[i]=s->dphase;
//fprintf(stderr, " error = %f; dphase = %f; nco_phase = %f;\n", error, s->dphase, s->nco_phase);

View file

@ -327,21 +327,19 @@ typedef struct timing_recovery_state_s
int input_processed;
int use_q; //use both I and Q for calculating the error
int debug_phase;
int debug_count;
int debug_force;
int debug_writefiles;
int debug_every_nth;
char* debug_writefiles_path;
int last_correction_offset;
float earlylate_ratio;
float loop_gain;
float max_error;
} timing_recovery_state_t;
timing_recovery_state_t timing_recovery_init(timing_recovery_algorithm_t algorithm, int decimation_rate, int use_q, float loop_gain, float max_error);
timing_recovery_state_t timing_recovery_init(timing_recovery_algorithm_t algorithm, int decimation_rate, int use_q, float loop_gain, float max_error, int debug_every_nth, char* debug_writefiles_path);
void timing_recovery_cc(complexf* input, complexf* output, int input_size, float* timing_error, int* sampled_indexes, timing_recovery_state_t* state);
timing_recovery_algorithm_t timing_recovery_get_algorithm_from_string(char* input);
char* timing_recovery_get_string_from_algorithm(timing_recovery_algorithm_t algorithm);
void timing_recovery_trigger_debug(timing_recovery_state_t* state, int debug_phase);
void octave_plot_point_on_cplxsig(complexf* signal, int signal_size, float error, int index, int correction_offset, int writefiles, int points_size, ...);
void octave_plot_point_on_cplxsig(complexf* signal, int signal_size, float error, int index, int correction_offset, char* writefiles_path, int points_size, ...);
void psk_modulator_u8_c(unsigned char* input, complexf* output, int input_size, int n_psk);
void duplicate_samples_ntimes_u8_u8(unsigned char* input, unsigned char* output, int input_size_bytes, int sample_size_bytes, int ntimes);
complexf psk31_interpolate_sine_cc(complexf* input, complexf* output, int input_size, int interpolation, complexf last_input);
@ -372,6 +370,7 @@ typedef struct bpsk_costas_loop_state_s
float iir_temp;
float dphase;
float nco_phase;
float dphase_max;
} bpsk_costas_loop_state_t;
void plain_interpolate_cc(complexf* input, complexf* output, int input_size, int interpolation);