Added normalized_timing_variance_u32_f, ??, etc.

This commit is contained in:
ha7ilm 2017-04-29 18:10:53 +02:00
parent a9dc49c8d9
commit 80ee1645ec
4 changed files with 133 additions and 10 deletions

View file

@ -855,6 +855,32 @@ It outputs white noise within the range [-1.0, 1.0].
---- ----
### [pack_bits_8to1_u8_u8](#pack_bits_8to1_u8_u8)
Syntax:
csdr pack_bits_8to1_u8_u8
It serializes the bytes on the input: it outputs each bit of the input byte as a single byte valued 0x00 or 0x01, starting from the lowest bit and going to the highest bit.
The output is 8 times as large in size as the input.
For example, the input byte 0x43 will result in eight bytes at the output:
```
01 01 00 00 00 00 01 00
```
For consequtive 0x02, 0x03, 0xff bytes on the input, the output will be:
```
00 01 00 00 00 00 00 00
01 01 00 00 00 00 00 00
01 01 01 01 01 01 01 01
```
----
### [awgn_cc](#awgn_cc) ### [awgn_cc](#awgn_cc)
Syntax: Syntax:
@ -867,6 +893,16 @@ If the `--snrshow` switch is given, it also shows the actual SNR based on the ca
---- ----
### [add_n_zero_samples_at_beginning_f](#add_n_zero_samples_at_beginning_f)
Syntax:
csdr add_n_zero_samples_at_beginning_f <n_zero_samples>
When the function is executed, it furst writes `<n_zero_samples>` 32-bit floating point zeros at the output, after that it just clones the input at the output.
----
### [?](#search_the_function_list) ### [?](#search_the_function_list)
Syntax: Syntax:

76
csdr.c
View file

@ -75,7 +75,6 @@ char usage[]=
" yes_f <to_repeat> [buf_times]\n" " yes_f <to_repeat> [buf_times]\n"
" detect_nan_ff\n" " detect_nan_ff\n"
" dump_f\n" " dump_f\n"
" flowcontrol <data_rate> <reads_per_second> [prebuffer_sec] [thrust]\n"
" shift_math_cc <rate>\n" " shift_math_cc <rate>\n"
" shift_math_cc --fifo <fifo_path>\n" " shift_math_cc --fifo <fifo_path>\n"
" shift_addition_cc <rate>\n" " shift_addition_cc <rate>\n"
@ -125,7 +124,7 @@ char usage[]=
" rtty_baudot2ascii_u8_u8\n" " rtty_baudot2ascii_u8_u8\n"
" serial_line_decoder_u8_u8\n" " serial_line_decoder_u8_u8\n"
" octave_complex_c <samples_to_plot> <out_of_n_samples>\n" " octave_complex_c <samples_to_plot> <out_of_n_samples>\n"
" timing_recovery_cc <algorithm> <decimation> [--add_q] [--octave <debug_n>]\n" " timing_recovery_cc <algorithm> <decimation> [--add_q [--output_error | --output_indexes | --octave <debug_n>]] \n"
" psk31_varicode_encoder_u8_u8\n" " psk31_varicode_encoder_u8_u8\n"
" psk31_varicode_decoder_u8_u8\n" " psk31_varicode_decoder_u8_u8\n"
" differential_encoder_u8_u8\n" " differential_encoder_u8_u8\n"
@ -142,6 +141,8 @@ char usage[]=
" repeat_u8 <data_bytes × N>\n" " repeat_u8 <data_bytes × N>\n"
" noise_f\n" " noise_f\n"
" awgn_cc <snr_db> [--snrshow]\n" " awgn_cc <snr_db> [--snrshow]\n"
" pack_bits_8to1_u8_u8\n"
" add_n_zero_samples_at_beginning_f <n_zero_samples>\n"
" ?<search_the_function_list>\n" " ?<search_the_function_list>\n"
" =<evaluate_python_expression>\n" " =<evaluate_python_expression>\n"
" \n" " \n"
@ -2519,7 +2520,7 @@ int main(int argc, char *argv[])
} }
} }
if(!strcmp(argv[1],"timing_recovery_cc")) //<algorithm> <decimation> [--add_q [--output_error | --octave <debug_n>]] if(!strcmp(argv[1],"timing_recovery_cc")) //<algorithm> <decimation> [--add_q [--output_error | --output_indexes | --octave <debug_n>]]
{ {
if(argc<=2) return badsyntax("need required parameter (algorithm)"); if(argc<=2) return badsyntax("need required parameter (algorithm)");
timing_recovery_algorithm_t algorithm = timing_recovery_get_algorithm_from_string(argv[2]); timing_recovery_algorithm_t algorithm = timing_recovery_get_algorithm_from_string(argv[2]);
@ -2534,12 +2535,18 @@ int main(int argc, char *argv[])
int debug_n = 0; int debug_n = 0;
int output_error = 0; int output_error = 0;
int output_indexes = 0;
if(argc>=7 && !strcmp(argv[5], "--octave")) debug_n = atoi(argv[6]); if(argc>=7 && !strcmp(argv[5], "--octave")) debug_n = atoi(argv[6]);
if(debug_n<0) badsyntax("debug_n should be >= 0"); if(debug_n<0) badsyntax("debug_n should be >= 0");
if(argc>=6 && !strcmp(argv[5], "--output_error")) output_error = 1;
if(argc>=6 && !strcmp(argv[5], "--output_error")) output_error = 1;
float* timing_error = NULL; float* timing_error = NULL;
if(output_error) timing_error = (float*)malloc(sizeof(float)*the_bufsize); if(output_error) timing_error = (float*)malloc(sizeof(float)*the_bufsize);
if(argc>=6 && !strcmp(argv[5], "--output_indexes")) output_indexes = 1;
unsigned* sampled_indexes = NULL;
if(output_indexes) sampled_indexes = (unsigned*)malloc(sizeof(float)*the_bufsize);
if(!initialize_buffers()) return -2; if(!initialize_buffers()) return -2;
sendbufsize(the_bufsize/decimation); sendbufsize(the_bufsize/decimation);
@ -2549,16 +2556,23 @@ int main(int argc, char *argv[])
state.debug_writefiles = 1; state.debug_writefiles = 1;
state.debug_force = !!debug_n; //should remove that later state.debug_force = !!debug_n; //should remove that later
FREAD_C; FREAD_C;
unsigned buffer_start_counter = 0;
for(;;) for(;;)
{ {
FEOF_CHECK; FEOF_CHECK;
if(debug_n && ++debug_i%debug_n==0) timing_recovery_trigger_debug(&state, 3); 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, &state); 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); //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); if(timing_error) fwrite(timing_error, sizeof(float), state.output_size, stdout);
else if(sampled_indexes)
{
for(int i=0;i<state.output_size;i++) sampled_indexes[i]+=buffer_start_counter;
fwrite(sampled_indexes, sizeof(unsigned), state.output_size, stdout);
}
else fwrite(output_buffer, sizeof(complexf), state.output_size, stdout); else fwrite(output_buffer, sizeof(complexf), state.output_size, stdout);
TRY_YIELD; TRY_YIELD;
//fprintf(stderr, "state.input_processed = %d\n", state.input_processed); //fprintf(stderr, "state.input_processed = %d\n", state.input_processed);
buffer_start_counter+=state.input_processed;
memmove((complexf*)input_buffer,((complexf*)input_buffer)+state.input_processed,(the_bufsize-state.input_processed)*sizeof(complexf)); //memmove lets the source and destination overlap memmove((complexf*)input_buffer,((complexf*)input_buffer)+state.input_processed,(the_bufsize-state.input_processed)*sizeof(complexf)); //memmove lets the source and destination overlap
fread(((complexf*)input_buffer)+(the_bufsize-state.input_processed), sizeof(complexf), state.input_processed, stdin); fread(((complexf*)input_buffer)+(the_bufsize-state.input_processed), sizeof(complexf), state.input_processed, stdin);
//fprintf(stderr,"iskip=%d state.output_size=%d start=%x target=%x skipcount=%x \n",state.input_processed,state.output_size,input_buffer, ((complexf*)input_buffer)+(BIG_BUFSIZE-state.input_processed),(BIG_BUFSIZE-state.input_processed)); //fprintf(stderr,"iskip=%d state.output_size=%d start=%x target=%x skipcount=%x \n",state.input_processed,state.output_size,input_buffer, ((complexf*)input_buffer)+(BIG_BUFSIZE-state.input_processed),(BIG_BUFSIZE-state.input_processed));
@ -2945,18 +2959,64 @@ int main(int argc, char *argv[])
get_random_samples_f(output_buffer, the_bufsize, urandom); get_random_samples_f(output_buffer, the_bufsize, urandom);
FWRITE_R; FWRITE_R;
TRY_YIELD; TRY_YIELD;
} }
} }
if(!strcmp(argv[1], "normalized_timing_variance_u32_f")) //<samples_per_symbol> <initial_sample_offset>
{
int samples_per_symbol = 0;
if(argc<=2) badsyntax("required parameter <samples_per_symbol> is missing.");
sscanf(argv[2],"%d",&samples_per_symbol);
int initial_sample_offset = 0;
if(argc<=3) badsyntax("required parameter <initial_sample_offset> is missing.");
sscanf(argv[3],"%d",&initial_sample_offset);
if(!initialize_buffers()) return -2;
sendbufsize(the_bufsize);
float* temp_buffer = (float*)malloc(sizeof(float)*the_bufsize);
for(;;)
{
FEOF_CHECK;
FREAD_R; //doesn't count, reads 4 bytes per sample anyway
float nv = normalized_timing_variance_u32_f((unsigned*)input_buffer, temp_buffer, the_bufsize, samples_per_symbol, initial_sample_offset);
fwrite(&nv, sizeof(float), 1, stdout);
fprintf(stderr, "csdr normalized_timing_variance_u32_f: normalized variance = %f\n", nv);
FWRITE_R;
TRY_YIELD;
}
}
if(!strcmp(argv[1], "add_n_zero_samples_at_beginning_f")) //<n_zero_samples>
{
int n_zero_samples = 0;
if(argc<=2) badsyntax("required parameter <n_zero_samples> is missing.");
sscanf(argv[2],"%d",&n_zero_samples);
if(!sendbufsize(initialize_buffers())) return -2;
float* zeros=(float*)calloc(sizeof(float),n_zero_samples);
fwrite(zeros, sizeof(float), n_zero_samples, stdout);
clone_(the_bufsize);
}
if(!strcmp(argv[1],"none")) if(!strcmp(argv[1],"none"))
{ {
return 0; return 0;
} }
if(argv[1][0]=='?' && argv[1][1]=='?')
{
char buffer[1000];
snprintf(buffer, 1000-1, "xdg-open https://github.com/simonyiszk/csdr/blob/master/README.md#$(csdr ?%s | head -n1 | awk '{print $1;}')", argv[1]+2);
fprintf(stderr, "csdr ??: %s\n", buffer);
system(buffer);
return 0;
}
if(argv[1][0]=='?') if(argv[1][0]=='?')
{ {
char buffer[100]; char buffer[1000];
snprintf(buffer, 100-1, "csdr 2>&1 | grep %s", argv[1]+1); snprintf(buffer, 1000-1, "csdr 2>&1 | grep %s", argv[1]+1);
fprintf(stderr, "csdr ?: %s\n", buffer); fprintf(stderr, "csdr ?: %s\n", buffer);
system(buffer); system(buffer);
return 0; return 0;

View file

@ -1925,7 +1925,7 @@ void timing_recovery_trigger_debug(timing_recovery_state_t* state, int debug_pha
#define MTIMINGR_HDEBUG 0 #define MTIMINGR_HDEBUG 0
void timing_recovery_cc(complexf* input, complexf* output, int input_size, float* timing_error, timing_recovery_state_t* state) void timing_recovery_cc(complexf* input, complexf* output, int input_size, float* timing_error, int* sampled_indexes, timing_recovery_state_t* state)
{ {
//We always assume that the input starts at center of the first symbol cross before the first symbol. //We always assume that the input starts at center of the first symbol cross before the first symbol.
//Last time we consumed that much from the input samples that it is there. //Last time we consumed that much from the input samples that it is there.
@ -1963,6 +1963,7 @@ void timing_recovery_cc(complexf* input, complexf* output, int input_size, float
el_point_right_index = current_bitstart_index + num_samples_earlylate_wing * 3; el_point_right_index = current_bitstart_index + num_samples_earlylate_wing * 3;
el_point_left_index = current_bitstart_index + num_samples_earlylate_wing * 1 - correction_offset; el_point_left_index = current_bitstart_index + num_samples_earlylate_wing * 1 - correction_offset;
el_point_mid_index = current_bitstart_index + num_samples_halfbit; el_point_mid_index = current_bitstart_index + num_samples_halfbit;
if(sampled_indexes) sampled_indexes[si]=el_point_mid_index;
output[si++] = input[el_point_mid_index]; output[si++] = input[el_point_mid_index];
} }
else if(state->algorithm == TIMING_RECOVERY_ALGORITHM_GARDNER) else if(state->algorithm == TIMING_RECOVERY_ALGORITHM_GARDNER)
@ -1971,6 +1972,7 @@ void timing_recovery_cc(complexf* input, complexf* output, int input_size, float
el_point_right_index = current_bitstart_index + num_samples_halfbit * 3; el_point_right_index = current_bitstart_index + num_samples_halfbit * 3;
el_point_left_index = current_bitstart_index + num_samples_halfbit * 1; el_point_left_index = current_bitstart_index + num_samples_halfbit * 1;
el_point_mid_index = current_bitstart_index + num_samples_halfbit * 2; el_point_mid_index = current_bitstart_index + num_samples_halfbit * 2;
if(sampled_indexes) sampled_indexes[si]=el_point_left_index;
output[si++] = input[el_point_left_index]; output[si++] = input[el_point_left_index];
} }
else break; else break;
@ -2167,7 +2169,31 @@ int apply_fir_cc(complexf* input, complexf* output, int input_size, complexf* ta
return i; return i;
} }
float normalized_timing_variance_u32_f(unsigned* input, float* temp, int input_size, int samples_per_symbol, int initial_sample_offset)
{
float *ndiff_rad = temp;
float ndiff_rad_mean = 0;
for(int i=0;i<input_size;i++)
{
//find out which real sample index this input sample index is the nearest to.
unsigned sinearest = (input[i]-initial_sample_offset) / samples_per_symbol;
unsigned sinearest_remain = (input[i]-initial_sample_offset) % samples_per_symbol;
if(sinearest_remain>samples_per_symbol/2) sinearest++;
unsigned sicorrect = initial_sample_offset+(sinearest*samples_per_symbol); //the sample offset which input[i] should have been, in order to sample at the maximum effect point
int sidiff = abs(sicorrect-input[i]);
float ndiff = sidiff/samples_per_symbol;
fprintf(stderr, "ndiff = %f\n", ndiff);
ndiff_rad[i] = ndiff*PI;
ndiff_rad_mean = ndiff_rad_mean*(((float)i-1)/i)+(ndiff_rad[i]/i);
}
fprintf(stderr, "ndiff_rad_mean = %f\n", ndiff_rad_mean);
float result = 0;
for(int i=0;i<input_size;i++) result+=(powf(ndiff_rad[i]-ndiff_rad_mean,2))/(input_size-1);
fprintf(stderr, "nv = %f\n", result);
return result;
}
/* /*
_____ _ _ _____ _ _

View file

@ -334,7 +334,7 @@ typedef struct timing_recovery_state_s
} timing_recovery_state_t; } timing_recovery_state_t;
timing_recovery_state_t timing_recovery_init(timing_recovery_algorithm_t algorithm, int decimation_rate, int use_q); timing_recovery_state_t timing_recovery_init(timing_recovery_algorithm_t algorithm, int decimation_rate, int use_q);
void timing_recovery_cc(complexf* input, complexf* output, int input_size, float* timing_error, timing_recovery_state_t* state); 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); timing_recovery_algorithm_t timing_recovery_get_algorithm_from_string(char* input);
char* timing_recovery_get_string_from_algorithm(timing_recovery_algorithm_t algorithm); 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 timing_recovery_trigger_debug(timing_recovery_state_t* state, int debug_phase);
@ -369,3 +369,4 @@ void get_random_gaussian_samples_c(complexf* output, int output_size, FILE* stat
int deinit_get_random_samples_f(FILE* status); int deinit_get_random_samples_f(FILE* status);
float* add_ff(float* input1, float* input2, float* output, int input_size); float* add_ff(float* input1, float* input2, float* output, int input_size);
float total_logpower_cf(complexf* input, int input_size); float total_logpower_cf(complexf* input, int input_size);
float normalized_timing_variance_u32_f(unsigned* input, float* temp, int input_size, int samples_per_symbol, int initial_sample_offset);