/ csdr.c
csdr.c
1 /* 2 This software is part of libcsdr, a set of simple DSP routines for 3 Software Defined Radio. 4 5 Copyright (c) 2014, Andras Retzler <randras@sdr.hu> 6 All rights reserved. 7 8 Redistribution and use in source and binary forms, with or without 9 modification, are permitted provided that the following conditions are met: 10 * Redistributions of source code must retain the above copyright 11 notice, this list of conditions and the following disclaimer. 12 * Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 * Neither the name of the copyright holder nor the 16 names of its contributors may be used to endorse or promote products 17 derived from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 DISCLAIMED. IN NO EVENT SHALL ANDRAS RETZLER BE LIABLE FOR ANY 23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #define _POSIX_C_SOURCE 199309L 32 #define _BSD_SOURCE 33 #define _GNU_SOURCE 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <limits.h> 38 #include <sys/time.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <fcntl.h> 42 #include <sys/ioctl.h> 43 #include <unistd.h> 44 #include <time.h> 45 #include <stdarg.h> 46 #include "libcsdr.h" 47 #include "libcsdr_gpl.h" 48 #include "ima_adpcm.h" 49 #include <sched.h> 50 #include <math.h> 51 #include <strings.h> 52 #include <errno.h> 53 #include "fastddc.h" 54 #include <assert.h> 55 56 char usage[]= 57 "csdr - a simple commandline tool for Software Defined Radio receiver DSP.\n\n" 58 "usage: \n\n" 59 " csdr function_name <function_param1> <function_param2> [optional_param] ...\n\n" 60 "list of functions:\n\n" 61 " convert_u8_f\n" 62 " convert_f_u8\n" 63 " convert_s8_f\n" 64 " convert_f_s8\n" 65 " convert_f_s16\n" 66 " convert_s16_f\n" 67 " convert_f_s24 [--bigendian]\n" 68 " convert_s24_f [--bigendian]\n" 69 " realpart_cf\n" 70 " clipdetect_ff\n" 71 " limit_ff [max_amplitude]\n" 72 " gain_ff <gain>\n" 73 " clone\n" 74 " none\n" 75 " yes_f <to_repeat> [buf_times]\n" 76 " detect_nan_ff\n" 77 " dump_f\n" 78 " shift_math_cc <rate>\n" 79 " shift_math_cc --fifo <fifo_path>\n" 80 " shift_addition_cc <rate>\n" 81 " shift_addition_cc --fifo <fifo_path>\n" 82 " shift_addition_cc_test\n" 83 " shift_table_cc <rate> [table_size]\n" 84 " shift_addition_fc <rate>\n" 85 " shift_addition_fc --fifo <fifo_path>\n" 86 " decimating_shift_addition_cc <rate> [decimation]\n" 87 " dcblock_ff\n" 88 " fastdcblock_ff\n" 89 " fmdemod_atan_cf\n" 90 " fmdemod_quadri_cf\n" 91 " fmdemod_quadri_novect_cf\n" 92 " deemphasis_wfm_ff <sample_rate> <tau>\n" 93 " deemphasis_nfm_ff <one_of_the_predefined_sample_rates>\n" 94 " amdemod_cf\n" 95 " amdemod_estimator_cf\n" 96 " fir_decimate_cc <decimation_factor> [transition_bw [window]]\n" 97 " fir_interpolate_cc <interpolation_factor> [transition_bw [window]]\n" 98 " firdes_lowpass_f <cutoff_rate> <length> [window [--octave]]\n" 99 " firdes_bandpass_c <low_cut> <high_cut> <length> [window [--octave]]\n" 100 " agc_ff [hang_time [reference [attack_rate [decay_rate [max_gain [attack_wait [filter_alpha]]]]]]]\n" 101 " fastagc_ff [block_size [reference]]\n" 102 " rational_resampler_ff <interpolation> <decimation> [transition_bw [window]]\n" 103 " old_fractional_decimator_ff <decimation_rate> [transition_bw [window]]\n" 104 " fractional_decimator_ff <decimation_rate> [num_poly_points ( [transition_bw [window]] | --prefilter )]\n" 105 " fft_cc <fft_size> <out_of_every_n_samples> [window [--octave] [--benchmark]]\n" 106 " fft_fc <fft_size> <out_of_every_n_samples> [window [--benchmark]]\n" 107 " logpower_cf [add_db]\n" 108 " fft_benchmark <fft_size> <fft_cycles> [--benchmark]\n" 109 " bandpass_fir_fft_cc <low_cut> <high_cut> <transition_bw> [window]\n" 110 " bandpass_fir_fft_cc --fifo <fifo_path> <transition_bw> [window]\n" 111 " encode_ima_adpcm_s16_u8\n" 112 " decode_ima_adpcm_u8_s16\n" 113 " compress_fft_adpcm_f_u8 <fft_size>\n" 114 " flowcontrol <data_rate> <reads_per_second>\n" 115 " through\n" 116 " dsb_fc [q_value]\n" 117 " convert_f_samperf <wait_for_this_sample> \n" 118 " fmmod_fc\n" 119 " fixed_amplitude_cc <new_amplitude>\n" 120 " mono2stereo_s16\n" 121 " setbuf <buffer_size>\n" 122 " fft_exchange_sides_ff <fft_size>\n" 123 " squelch_and_smeter_cc --fifo <squelch_fifo> --outfifo <smeter_fifo> <use_every_nth> <report_every_nth>\n" 124 " fifo <buffer_size> <number_of_buffers>\n" 125 " invert_u8_u8\n" 126 " rtty_line_decoder_u8_u8\n" 127 " rtty_baudot2ascii_u8_u8\n" 128 " serial_line_decoder_f_u8 <samples_per_bits> [databits [stopbits]]\n" 129 " octave_complex_c <samples_to_plot> <out_of_n_samples> [--2d]\n" 130 " 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" 131 " psk31_varicode_encoder_u8_u8\n" 132 " psk31_varicode_decoder_u8_u8\n" 133 " differential_encoder_u8_u8\n" 134 " differential_decoder_u8_u8\n" 135 " dump_u8\n" 136 " psk_modulator_u8_c <n_psk>\n" 137 " psk31_interpolate_sine_cc <interpolation>\n" 138 " duplicate_samples_ntimes_u8_u8 <sample_size_bytes> <ntimes>\n" 139 " 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" 140 " binary_slicer_f_u8\n" 141 " simple_agc_cc <rate> [reference [max_gain]]\n" 142 " firdes_peak_c <rate> <length> [window [--octave]]\n" 143 " peaks_fir_cc <taps_length> [peak_rate × N]\n" 144 " repeat_u8 <data_bytes × N>\n" 145 " uniform_noise_f\n" 146 " gaussian_noise_c\n" 147 " awgn_cc <snr_db> [--awgnfile <file>] [--snrshow]\n" 148 " pack_bits_8to1_u8_u8\n" 149 " pack_bits_1to8_u8_u8\n" 150 " firdes_pulse_shaping_filter_f (RRC <samples_per_symbol> <num_taps> <beta> | COSINE <samples_per_symbol>)\n" 151 " pulse_shaping_filter_cc (RRC <samples_per_symbol> <num_taps> <beta> | COSINE <samples_per_symbol>)\n" 152 " add_n_zero_samples_at_beginning_f <n_zero_samples>\n" 153 " generic_slicer_f_u8 <n_symbols>\n" 154 " plain_interpolate_cc <interpolation>\n" 155 " add_const_cc <i> <q>\n" 156 " tee <path> [buffers]\n" 157 " pll_cc (1 [alpha] |2 [bandwidth [damping_factor [ko [kd]]]])\n" 158 " pattern_search_u8_u8 <values_after> <pattern_values × N>\n" 159 " dbpsk_decoder_c_u8\n" 160 " bfsk_demod_cf <spacing> <filter_length>\n" 161 " normalized_timing_variance_u32_f <samples_per_symbol> <initial_sample_offset> [--debug]\n" 162 " ?<search_the_function_list>\n" 163 " ??<jump_to_function_docs_on_github>\n" 164 " =<evaluate_python_expression>\n" 165 " shift_addfast_cc <rate> #only if system supports NEON \n" 166 " shift_unroll_cc <rate>\n" 167 " logaveragepower_cf <add_db> <fft_size> <avgnumber>\n" 168 " fft_one_side_ff <fft_size>\n" 169 " convert_f_samplerf <wait_for_this_sample>\n" 170 " add_dcoffset_cc\n" 171 " fastddc_fwd_cc <decimation> [transition_bw [window]]\n" 172 " fastddc_inv_cc <shift_rate> <decimation> [transition_bw [window]]\n" 173 " _fft2octave <fft_size>\n" 174 " convert_f_i16 #deprecated, use instead: convert_f_s16\n" 175 " convert_i16_f #deprecated, use instead: convert_s16_f\n" 176 " floatdump_f #deprecated, use instead: dump_f\n" 177 " mono2stereo_i16 #deprecated, use instead: mono2stereo_s16\n" 178 " decode_ima_adpcm_u8_i16 #deprecated, use instead: decode_ima_adpcm_u8_s16\n" 179 " encode_ima_adpcm_i16_u8 #deprecated, use instead: encode_ima_adpcm_i16_u8\n" 180 " \n" 181 ; 182 183 //change on 2015-08-29: we rather dynamically determine the bufsize 184 //#define BUFSIZE (1024) 185 //#define BIG_BUFSIZE (1024*16) 186 //should be multiple of 16! (size of double complex) 187 //also, keep in mind that shift_addition_cc works better the smaller this buffer is. 188 189 int env_csdr_fixed_bufsize = 1024; 190 int env_csdr_fixed_big_bufsize = 1024*16; 191 int env_csdr_dynamic_bufsize_on = 0; 192 int env_csdr_print_bufsizes = 0; 193 int bigbufs = 0; 194 195 //change on on 2015-08-29: we don't yield at all. fread() will do it if it blocks 196 #define YIELD_EVERY_N_TIMES 3 197 //#define TRY_YIELD if(++yield_counter%YIELD_EVERY_N_TIMES==0) sched_yield() 198 #define TRY_YIELD fflush(stdout);sched_yield() 199 //unsigned yield_counter=0; 200 201 char **argv_global; 202 int argc_global; 203 204 int errhead() 205 { 206 fprintf(stderr, "%s%s%s: ", argv_global[0], ((argc_global>=2)?" ":""), ((argc_global>=2)?argv_global[1]:"")); 207 } 208 209 int badsyntax(char* why) 210 { 211 if(why==0) fprintf(stderr, "%s", usage); 212 else 213 { 214 errhead(); 215 fprintf(stderr, "%s\n", why); 216 } 217 return -1; 218 } 219 220 int clipdetect_ff(float* input, int input_size) 221 { 222 for(int i=0;i<input_size;i++) 223 { 224 if(input[i]<-1.0) { errhead(); fprintf(stderr, "Signal value below -1.0!\n"); return -1; } 225 if(input[i]>1.0) { errhead(); fprintf(stderr, "Signal value above 1.0!\n"); return 1; } 226 } 227 return 0; 228 } 229 230 int clone_(int bufsize_param) 231 { 232 unsigned char* clone_buffer; 233 clone_buffer = (unsigned char*)malloc(bufsize_param*sizeof(unsigned char)); 234 for(;;) 235 { 236 fread(clone_buffer, sizeof(unsigned char), bufsize_param, stdin); 237 fwrite(clone_buffer, sizeof(unsigned char), bufsize_param, stdout); 238 TRY_YIELD; 239 } 240 } 241 242 #define FREAD_U8 fread (input_buffer, sizeof(unsigned char), the_bufsize, stdin) 243 #define FWRITE_U8 fwrite (output_buffer, sizeof(unsigned char), the_bufsize, stdout) 244 #define FREAD_R fread (input_buffer, sizeof(float), the_bufsize, stdin) 245 #define FREAD_C fread (input_buffer, sizeof(float)*2, the_bufsize, stdin) 246 #define FWRITE_R fwrite (output_buffer, sizeof(float), the_bufsize, stdout) 247 #define FWRITE_C fwrite (output_buffer, sizeof(float)*2, the_bufsize, stdout) 248 #define FEOF_CHECK if(feof(stdin)) return 0 249 //#define BIG_FREAD_C fread(input_buffer, sizeof(float)*2, BIG_BUFSIZE, stdin) 250 //#define BIG_FWRITE_C fwrite(output_buffer, sizeof(float)*2, BIG_BUFSIZE, stdout) 251 252 int init_fifo(int argc, char *argv[]) 253 { 254 if(argc>=4) 255 { 256 if(!strcmp(argv[2],"--fifo")) 257 { 258 errhead(); fprintf(stderr,"fifo control mode on\n"); 259 int fd = open(argv[3], O_RDONLY); 260 int flags = fcntl(fd, F_GETFL, 0); 261 fcntl(fd, F_SETFL, flags | O_NONBLOCK); 262 return fd; 263 } 264 else if(!strcmp(argv[2],"--fd")) 265 { 266 //to use this: 267 //1. Create a pipe(pipedesc) in your process. 268 //2. fork() and execl() your process to run csdr, and give pipedesc[0] as parameter after --fd 269 // Note: when forking, the child process will get a copy of the file descriptor table! That's why this 270 // works at all, as file descriptor indexes are normally not transferable between processes, except for a *NIX socket way which is quite complicated... 271 //3. From your parent process, write into pipedesc[1]. 272 //This is implemented in ddcd, check there to see how to do it! 273 int fd; 274 if(sscanf(argv[3], "%d",&fd)<=0) return 0; 275 errhead(); 276 fprintf(stderr,"fd control mode on, fd=%d\n", fd); 277 int flags = fcntl(fd, F_GETFL, 0); 278 fcntl(fd, F_SETFL, flags | O_NONBLOCK); 279 return fd; 280 } 281 } 282 return 0; 283 } 284 285 286 287 #define RFCTL_BUFSIZE 1024 288 289 int read_fifo_ctl(int fd, char* format, ...) 290 { 291 if(!fd) return 0; 292 static char buffer[RFCTL_BUFSIZE]; 293 static int buffer_index=0; 294 int bytes_read=read(fd,buffer+buffer_index,(RFCTL_BUFSIZE-buffer_index)*sizeof(char)); 295 if(bytes_read<=0) return 0; 296 297 int prev_newline_at=0; 298 int last_newline_at=0; 299 for(int i=0;i<buffer_index+bytes_read;i++) 300 { 301 if(buffer[i]=='\n') 302 { 303 prev_newline_at=last_newline_at; 304 last_newline_at=i+1; 305 } 306 } 307 if(last_newline_at) 308 { 309 //fprintf(stderr,"pna=%d lna=%d\n",prev_newline_at,last_newline_at); 310 va_list vl; 311 va_start(vl,format); 312 vsscanf(buffer+prev_newline_at,format,vl); 313 va_end(vl); 314 memmove(buffer,buffer+last_newline_at,buffer_index+bytes_read-last_newline_at); 315 buffer_index=bytes_read-last_newline_at; 316 return 1; 317 } 318 else 319 { 320 buffer_index+=bytes_read; 321 return 0; 322 } 323 } 324 325 #define SETBUF_PREAMBLE "csdr" 326 #define SETBUF_DEFAULT_BUFSIZE 1024 327 #define STRINGIFY_VALUE(x) STRINGIFY_NAME(x) 328 #define STRINGIFY_NAME(x) #x 329 330 int getbufsize() 331 { 332 if(!env_csdr_dynamic_bufsize_on) return (bigbufs) ? env_csdr_fixed_big_bufsize : env_csdr_fixed_bufsize; 333 int recv_first[2]; 334 fread(recv_first, sizeof(int), 2, stdin); 335 if(memcmp(recv_first, SETBUF_PREAMBLE, sizeof(char)*4)!=0) 336 { badsyntax("warning! Did not match preamble on the beginning of the stream. You should put \"csdr setbuf <buffer size>\" at the beginning of the chain! Falling back to default buffer size: " STRINGIFY_VALUE(SETBUF_DEFAULT_BUFSIZE)); return SETBUF_DEFAULT_BUFSIZE; } 337 if(recv_first[1]<=0) { badsyntax("warning! Invalid buffer size." ); return 0; } 338 return recv_first[1]; 339 } 340 341 342 float* input_buffer; 343 unsigned char* buffer_u8; 344 float *output_buffer; 345 short *buffer_i16; 346 float *temp_f; 347 int the_bufsize = 0; 348 349 350 351 #define UNITROUND_UNIT 4 352 353 int unitround(int what) 354 { 355 if(what<=0) return UNITROUND_UNIT; 356 return ((what-1)&~(UNITROUND_UNIT-1))+UNITROUND_UNIT; 357 } 358 359 int initialize_buffers() 360 { 361 if(!(the_bufsize=getbufsize())) return 0; 362 the_bufsize=unitround(the_bufsize); 363 if(env_csdr_print_bufsizes) { errhead(); fprintf(stderr,"buffer size set to %d\n", the_bufsize); } 364 input_buffer = (float*) malloc(the_bufsize*sizeof(float) * 2); //need the 2× because we might also put complex floats into it 365 output_buffer = (float*) malloc(the_bufsize*sizeof(float) * 2); 366 buffer_u8 = (unsigned char*)malloc(the_bufsize*sizeof(unsigned char)); 367 buffer_i16 = (short*) malloc(the_bufsize*sizeof(short)); 368 temp_f = (float*) malloc(the_bufsize*sizeof(float) * 4); 369 if(the_bufsize<=4096) //this is hacky, should be done correctly 370 { 371 fcntl(STDIN_FILENO, F_SETPIPE_SZ, 4096); 372 fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 4096); 373 } 374 return the_bufsize; 375 } 376 377 int sendbufsize(int size) 378 { 379 if(size<=4096) 380 { 381 fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 4096); 382 } 383 //The first word is a preamble, "csdr". 384 //If the next csdr process detects it, sets the buffer size according to the second word 385 if(!env_csdr_dynamic_bufsize_on) return env_csdr_fixed_bufsize; 386 if(env_csdr_print_bufsizes) { errhead(); fprintf(stderr,"next process proposed input buffer size is %d\n", size); } 387 int send_first[2]; 388 memcpy((char*)send_first, SETBUF_PREAMBLE, 4*sizeof(char)); 389 send_first[1] = size; 390 fwrite(send_first, sizeof(int), 2, stdout); 391 return size; 392 } 393 394 int parse_env() 395 { 396 char* envtmp; 397 envtmp=getenv("CSDR_DYNAMIC_BUFSIZE_ON"); 398 //fprintf(stderr, "envtmp: %s\n",envtmp); 399 if(envtmp) 400 { 401 env_csdr_dynamic_bufsize_on = !!atoi(envtmp); 402 env_csdr_fixed_bufsize = 0; 403 } 404 else 405 { 406 envtmp=getenv("CSDR_FIXED_BUFSIZE"); 407 if(envtmp) 408 { 409 env_csdr_fixed_big_bufsize = env_csdr_fixed_bufsize = atoi(envtmp); 410 } 411 } 412 envtmp=getenv("CSDR_PRINT_BUFSIZES"); 413 if(envtmp) 414 { 415 env_csdr_print_bufsizes = atoi(envtmp); 416 } 417 } 418 419 int main(int argc, char *argv[]) 420 { 421 parse_env(); 422 argv_global=argv; 423 argc_global=argc; 424 if(argc<=1) return badsyntax(0); 425 if(!strcmp(argv[1],"--help")) return badsyntax(0); 426 427 fcntl(STDIN_FILENO, F_SETPIPE_SZ, 65536*32); 428 fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 65536*32); 429 //fprintf(stderr, "csdr: F_SETPIPE_SZ\n"); 430 431 if(!strcmp(argv[1],"setbuf")) 432 { 433 if(argc<=2) return badsyntax("need required parameter (buffer size)"); 434 sscanf(argv[2],"%d",&the_bufsize); 435 if(the_bufsize<=0) return badsyntax("buffer size <= 0 is invalid"); 436 sendbufsize(the_bufsize); 437 clone_(the_bufsize); //After sending the buffer size out, just copy stdin to stdout 438 } 439 440 if(!strcmp(argv[1],"clone") || !strcmp(argv[1],"REM")) 441 { 442 if(!sendbufsize(initialize_buffers())) return -2; 443 clone_(the_bufsize); 444 } 445 #define SET_NONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) 446 447 if(!strcmp(argv[1],"fifo")) 448 { 449 if(!sendbufsize(initialize_buffers())) return -2; 450 451 int fifo_buffer_size; 452 if(argc<=2) return badsyntax("need required parameter (buffer_size)"); 453 sscanf(argv[2],"%d",&fifo_buffer_size); 454 int fifo_num_buffers; 455 if(argc<=3) return badsyntax("need required parameter (number of buffers)"); 456 sscanf(argv[3],"%d",&fifo_num_buffers); 457 458 char** fifo_buffers = (char**)malloc(sizeof(char*)*fifo_num_buffers); 459 for(int i=0;i<fifo_num_buffers;i++) fifo_buffers[i]=(char*)malloc(sizeof(char)*fifo_buffer_size); 460 461 SET_NONBLOCK(STDIN_FILENO); 462 SET_NONBLOCK(STDOUT_FILENO); 463 464 fd_set read_fds; 465 FD_ZERO(&read_fds); 466 FD_SET(STDIN_FILENO, &read_fds); 467 fd_set write_fds; 468 FD_ZERO(&write_fds); 469 FD_SET(STDOUT_FILENO, &write_fds); 470 471 int highfd = ((STDOUT_FILENO > STDIN_FILENO) ? STDOUT_FILENO : STDIN_FILENO) + 1; 472 473 int fifo_actual_buffer_wr = fifo_num_buffers - 1; 474 int fifo_actual_buffer_rd = 0; 475 int fifo_actual_buffer_wr_pos = 0; 476 int fifo_actual_buffer_rd_pos = 0; 477 int fifo_error = 0; 478 int fifo_overrun_shown = 0; 479 480 for(;;) 481 { 482 select(highfd, &read_fds, NULL, NULL, NULL); 483 484 //try to read until buffer is full 485 if(FD_ISSET(STDIN_FILENO, &read_fds)) for(;;) 486 { 487 int read_bytes=read(STDIN_FILENO, fifo_buffers[fifo_actual_buffer_rd]+fifo_actual_buffer_rd_pos, fifo_buffer_size-fifo_actual_buffer_rd_pos); 488 //fprintf(stderr, "r %d %d | %d %d\n", read_bytes, fifo_buffer_size-fifo_actual_buffer_rd_pos, fifo_actual_buffer_rd, fifo_actual_buffer_rd_pos); 489 if(!read_bytes || ((read_bytes<0)&&(fifo_error=read_bytes)) ) break; 490 fifo_actual_buffer_rd_pos+=read_bytes; 491 if(!((fifo_actual_buffer_rd==fifo_actual_buffer_wr-1)||(fifo_actual_buffer_wr==0&&fifo_actual_buffer_rd==fifo_num_buffers-1))) 492 { 493 if(fifo_actual_buffer_rd_pos==fifo_buffer_size) 494 { 495 fifo_overrun_shown = 0; 496 fifo_actual_buffer_rd++; 497 fifo_actual_buffer_rd_pos = 0; 498 if(fifo_actual_buffer_rd>=fifo_num_buffers) fifo_actual_buffer_rd=0; 499 } 500 } 501 else 502 { 503 if(fifo_actual_buffer_rd_pos==fifo_buffer_size) 504 { 505 fifo_actual_buffer_rd_pos = 0; //rewrite same buffer 506 if(!fifo_overrun_shown) { fifo_overrun_shown=1; errhead(); fprintf(stderr, "circular buffer full, dropping samples\n"); } 507 } 508 } 509 } 510 //try to write until buffer is empty 511 if(FD_ISSET(STDOUT_FILENO, &write_fds)) for(;;) 512 { 513 if(fifo_actual_buffer_wr == fifo_actual_buffer_rd) break; 514 int written_bytes=write(STDOUT_FILENO, fifo_buffers[fifo_actual_buffer_wr]+fifo_actual_buffer_wr_pos, fifo_buffer_size-fifo_actual_buffer_wr_pos); 515 //fprintf(stderr, "w %d %d | %d %d\n", written_bytes, fifo_buffer_size-fifo_actual_buffer_wr_pos, fifo_actual_buffer_wr, fifo_actual_buffer_wr_pos); 516 if(!written_bytes || ((written_bytes<0)&&(fifo_error=written_bytes)) ) break; 517 fifo_actual_buffer_wr_pos+=written_bytes; 518 if(fifo_actual_buffer_wr_pos==fifo_buffer_size) 519 { 520 fifo_actual_buffer_wr++; 521 fifo_actual_buffer_wr_pos = 0; 522 if(fifo_actual_buffer_wr>=fifo_num_buffers) fifo_actual_buffer_wr=0; 523 } 524 525 } 526 if(fifo_error&&errno!=11) { errhead(); fprintf(stderr,"fifo_error (%d)", errno); return -1; } 527 } 528 529 return -1; 530 531 } 532 533 534 if(!strcmp(argv[1],"convert_u8_f")) 535 { 536 if(!sendbufsize(initialize_buffers())) return -2; 537 for(;;) 538 { 539 FEOF_CHECK; 540 fread(buffer_u8, sizeof(unsigned char), the_bufsize, stdin); 541 convert_u8_f(buffer_u8, output_buffer, the_bufsize); 542 FWRITE_R; 543 TRY_YIELD; 544 } 545 } 546 if(!strcmp(argv[1],"convert_f_u8")) //not tested 547 { 548 if(!sendbufsize(initialize_buffers())) return -2; 549 for(;;) 550 { 551 FEOF_CHECK; 552 FREAD_R; 553 convert_f_u8(input_buffer, buffer_u8, the_bufsize); 554 fwrite(buffer_u8, sizeof(unsigned char), the_bufsize, stdout); 555 TRY_YIELD; 556 } 557 } 558 if(!strcmp(argv[1],"convert_s8_f")) 559 { 560 if(!sendbufsize(initialize_buffers())) return -2; 561 for(;;) 562 { 563 FEOF_CHECK; 564 fread((signed char*)buffer_u8, sizeof(signed char), the_bufsize, stdin); 565 convert_s8_f((signed char*)buffer_u8, output_buffer, the_bufsize); 566 FWRITE_R; 567 TRY_YIELD; 568 } 569 } 570 if(!strcmp(argv[1],"convert_f_s8")) //not tested 571 { 572 if(!sendbufsize(initialize_buffers())) return -2; 573 for(;;) 574 { 575 FEOF_CHECK; 576 FREAD_R; 577 convert_f_s8(input_buffer, (signed char*)buffer_u8, the_bufsize); 578 fwrite((signed char*)buffer_u8, sizeof(signed char), the_bufsize, stdout); 579 TRY_YIELD; 580 } 581 } 582 if((!strcmp(argv[1],"convert_f_i16")) || (!strcmp(argv[1],"convert_f_s16"))) 583 { 584 if(!sendbufsize(initialize_buffers())) return -2; 585 for(;;) 586 { 587 FEOF_CHECK; 588 FREAD_R; 589 convert_f_i16(input_buffer, buffer_i16, the_bufsize); 590 fwrite(buffer_i16, sizeof(short), the_bufsize, stdout); 591 TRY_YIELD; 592 } 593 } 594 if((!strcmp(argv[1],"convert_i16_f")) || (!strcmp(argv[1],"convert_s16_f"))) 595 { 596 if(!sendbufsize(initialize_buffers())) return -2; 597 for(;;) 598 { 599 FEOF_CHECK; 600 fread(buffer_i16, sizeof(short), the_bufsize, stdin); 601 convert_i16_f(buffer_i16, output_buffer, the_bufsize); 602 FWRITE_R; 603 TRY_YIELD; 604 } 605 } 606 if(!strcmp(argv[1],"convert_f_s24")) 607 { 608 int bigendian = (argc>2) && (!strcmp(argv[2],"--bigendian")); 609 unsigned char* s24buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*3); 610 if(!sendbufsize(initialize_buffers())) return -2; 611 for(;;) 612 { 613 FEOF_CHECK; 614 FREAD_R; 615 convert_f_s24(input_buffer, s24buffer, the_bufsize, bigendian); 616 fwrite(s24buffer, sizeof(unsigned char)*3, the_bufsize, stdout); 617 TRY_YIELD; 618 } 619 } 620 if(!strcmp(argv[1],"convert_s24_f")) 621 { 622 int bigendian = (argc>2) && (!strcmp(argv[2],"--bigendian")); 623 unsigned char* s24buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*3); 624 if(!sendbufsize(initialize_buffers())) return -2; 625 for(;;) 626 { 627 FEOF_CHECK; 628 fread(s24buffer, sizeof(unsigned char)*3, the_bufsize, stdin); 629 convert_s24_f(s24buffer, output_buffer, the_bufsize, bigendian); 630 FWRITE_R; 631 TRY_YIELD; 632 } 633 } 634 if(!strcmp(argv[1],"realpart_cf")) 635 { 636 if(!sendbufsize(initialize_buffers())) return -2; 637 for(;;) 638 { 639 FEOF_CHECK; 640 FREAD_C; 641 for(int i=0;i<the_bufsize;i++) output_buffer[i]=iof(input_buffer,i); 642 FWRITE_R; 643 TRY_YIELD; 644 } 645 } 646 if(!strcmp(argv[1],"clipdetect_ff")) 647 { 648 if(!sendbufsize(initialize_buffers())) return -2; 649 for(;;) 650 { 651 FEOF_CHECK; 652 FREAD_R; 653 clipdetect_ff(input_buffer, the_bufsize); 654 fwrite(input_buffer, sizeof(float), the_bufsize, stdout); 655 TRY_YIELD; 656 } 657 } 658 if(!strcmp(argv[1],"gain_ff")) 659 { 660 if(argc<=2) return badsyntax("need required parameter (gain)"); 661 float gain; 662 sscanf(argv[2],"%g",&gain); 663 if(!sendbufsize(initialize_buffers())) return -2; 664 for(;;) 665 { 666 FEOF_CHECK; 667 FREAD_R; 668 gain_ff(input_buffer, output_buffer, the_bufsize, gain); 669 FWRITE_R; 670 TRY_YIELD; 671 } 672 } 673 if(!strcmp(argv[1],"limit_ff")) 674 { 675 float max_amplitude=1.0; 676 if(argc>=3) sscanf(argv[2],"%g",&max_amplitude); 677 if(!sendbufsize(initialize_buffers())) return -2; 678 for(;;) 679 { 680 FEOF_CHECK; 681 FREAD_R; 682 limit_ff(input_buffer, output_buffer, the_bufsize, max_amplitude); 683 FWRITE_R; 684 TRY_YIELD; 685 } 686 } 687 if(!strcmp(argv[1],"yes_f")) 688 { 689 if(argc<=2) return badsyntax("need required parameter (to_repeat)"); 690 float to_repeat; 691 sscanf(argv[2],"%g",&to_repeat); 692 int buf_times = 0; 693 if(argc>=4) sscanf(argv[3],"%d",&buf_times); 694 if(!sendbufsize(initialize_buffers())) return -2; 695 for(int i=0;i<the_bufsize;i++) output_buffer[i]=to_repeat; 696 for(int i=0;(!buf_times)||i<buf_times;i++) 697 { 698 fwrite(output_buffer, sizeof(float), the_bufsize, stdout); 699 TRY_YIELD; 700 } 701 return 0; 702 } 703 if(!strcmp(argv[1],"shift_math_cc")) 704 { 705 if(argc<=2) return badsyntax("need required parameter (rate)"); 706 float starting_phase=0; 707 float rate; 708 sscanf(argv[2],"%g",&rate); 709 if(!sendbufsize(initialize_buffers())) return -2; 710 for(;;) 711 { 712 FEOF_CHECK; 713 if(!FREAD_C) break; 714 starting_phase=shift_math_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, starting_phase); 715 FWRITE_C; 716 TRY_YIELD; 717 } 718 return 0; 719 } 720 //speed tests: 721 //csdr yes_f 1 1000000 | time csdr shift_math_cc 0.2 >/dev/null 722 //csdr yes_f 1 1000000 | time csdr shift_addition_cc 0.2 >/dev/null 723 //csdr yes_f 1 1000000 | time csdr shift_table_cc 0.2 >/dev/null 724 725 if(!strcmp(argv[1],"shift_table_cc")) 726 { 727 bigbufs=1; 728 if(argc<=2) return badsyntax("need required parameter (rate)"); 729 float starting_phase=0; 730 float rate; 731 int table_size=65536; 732 sscanf(argv[2],"%g",&rate); 733 if(argc>3) sscanf(argv[3],"%d",&table_size); 734 if(!sendbufsize(initialize_buffers())) return -2; 735 shift_table_data_t table_data=shift_table_init(table_size); 736 errhead(); 737 fprintf(stderr,"LUT initialized\n"); 738 for(;;) 739 { 740 FEOF_CHECK; 741 if(!FREAD_C) break; 742 starting_phase=shift_table_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, table_data, starting_phase); 743 FWRITE_C; 744 TRY_YIELD; 745 } 746 return 0; 747 } 748 749 if(!strcmp(argv[1],"shift_addfast_cc")) 750 { 751 bigbufs=1; 752 753 float starting_phase=0; 754 float rate; 755 756 int fd; 757 if(fd=init_fifo(argc,argv)) 758 { 759 while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); 760 } 761 else 762 { 763 if(argc<=2) return badsyntax("need required parameter (rate)"); 764 sscanf(argv[2],"%g",&rate); 765 } 766 767 if(!sendbufsize(initialize_buffers())) return -2; 768 for(;;) 769 { 770 shift_addfast_data_t data=shift_addfast_init(rate); 771 errhead(); 772 fprintf(stderr,"reinitialized to %g\n",rate); 773 int remain, current_size; 774 float* ibufptr; 775 float* obufptr; 776 for(;;) 777 { 778 FEOF_CHECK; 779 if(!FREAD_C) break; 780 remain=the_bufsize; 781 ibufptr=input_buffer; 782 obufptr=output_buffer; 783 while(remain) 784 { 785 current_size=(remain>1024)?1024:remain; 786 starting_phase=shift_addfast_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase); 787 ibufptr+=current_size*2; 788 obufptr+=current_size*2; 789 remain-=current_size; 790 } 791 FWRITE_C; 792 if(read_fifo_ctl(fd,"%g\n",&rate)) break; 793 TRY_YIELD; 794 } 795 } 796 return 0; 797 } 798 799 800 if(!strcmp(argv[1],"shift_unroll_cc")) 801 { 802 bigbufs=1; 803 804 float starting_phase=0; 805 float rate; 806 807 int fd; 808 if(fd=init_fifo(argc,argv)) 809 { 810 while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); 811 } 812 else 813 { 814 if(argc<=2) return badsyntax("need required parameter (rate)"); 815 sscanf(argv[2],"%g",&rate); 816 } 817 818 if(!sendbufsize(initialize_buffers())) return -2; 819 for(;;) 820 { 821 shift_unroll_data_t data=shift_unroll_init(rate, 1024); 822 errhead(); 823 fprintf(stderr,"reinitialized to %g\n",rate); 824 int remain, current_size; 825 float* ibufptr; 826 float* obufptr; 827 for(;;) 828 { 829 FEOF_CHECK; 830 if(!FREAD_C) break; 831 remain=the_bufsize; 832 ibufptr=input_buffer; 833 obufptr=output_buffer; 834 while(remain) 835 { 836 current_size=(remain>1024)?1024:remain; 837 starting_phase=shift_unroll_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase); 838 ibufptr+=current_size*2; 839 obufptr+=current_size*2; 840 remain-=current_size; 841 } 842 FWRITE_C; 843 if(read_fifo_ctl(fd,"%g\n",&rate)) break; 844 TRY_YIELD; 845 } 846 } 847 return 0; 848 } 849 850 #ifdef LIBCSDR_GPL 851 if(!strcmp(argv[1],"decimating_shift_addition_cc")) 852 { 853 bigbufs=1; 854 if(argc<=2) return badsyntax("need required parameter (rate)"); 855 float starting_phase=0; 856 float rate; 857 int decimation=1; 858 sscanf(argv[2],"%g",&rate); 859 if(argc>3) sscanf(argv[3],"%d",&decimation); 860 if(!initialize_buffers()) return -2; 861 sendbufsize(the_bufsize/decimation); 862 shift_addition_data_t d=decimating_shift_addition_init(rate, decimation); 863 decimating_shift_addition_status_t s; 864 s.decimation_remain=0; 865 s.starting_phase=0; 866 for(;;) 867 { 868 FEOF_CHECK; 869 if(!FREAD_C) break; 870 s=decimating_shift_addition_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, d, decimation, s); 871 fwrite(output_buffer, sizeof(float)*2, s.output_size, stdout); 872 TRY_YIELD; 873 } 874 return 0; 875 } 876 877 if(!strcmp(argv[1],"shift_addition_cc")) 878 { 879 bigbufs=1; 880 881 float starting_phase=0; 882 float rate; 883 884 int fd; 885 if(fd=init_fifo(argc,argv)) 886 { 887 while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); 888 } 889 else 890 { 891 if(argc<=2) return badsyntax("need required parameter (rate)"); 892 sscanf(argv[2],"%g",&rate); 893 } 894 895 if(!sendbufsize(initialize_buffers())) return -2; 896 for(;;) 897 { 898 shift_addition_data_t data=shift_addition_init(rate); 899 errhead(); 900 fprintf(stderr,"reinitialized to %g\n",rate); 901 int remain, current_size; 902 float* ibufptr; 903 float* obufptr; 904 for(;;) 905 { 906 FEOF_CHECK; 907 if(!FREAD_C) break; 908 remain=the_bufsize; 909 ibufptr=input_buffer; 910 obufptr=output_buffer; 911 while(remain) 912 { 913 current_size=(remain>1024)?1024:remain; 914 starting_phase=shift_addition_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, data, starting_phase); 915 ibufptr+=current_size*2; 916 obufptr+=current_size*2; 917 remain-=current_size; 918 } 919 FWRITE_C; 920 if(read_fifo_ctl(fd,"%g\n",&rate)) break; 921 TRY_YIELD; 922 } 923 } 924 return 0; 925 } 926 927 if(!strcmp(argv[1],"shift_addition_cc_test")) 928 { 929 if(argc<=2) return badsyntax("need required parameter (rate)"); 930 float rate; 931 sscanf(argv[2],"%g",&rate); 932 //if(initialize_buffers()) return -2; //most likely we don't need this here 933 shift_addition_data_t data=shift_addition_init(rate); 934 shift_addition_cc_test(data); 935 return 0; 936 } 937 #endif 938 if(!strcmp(argv[1],"dcblock_ff")) 939 { 940 static dcblock_preserve_t dcp; //will be 0 as .bss is set to 0 941 if(!sendbufsize(initialize_buffers())) return -2; 942 for(;;) 943 { 944 FEOF_CHECK; 945 FREAD_R; 946 dcp=dcblock_ff(input_buffer, output_buffer, the_bufsize, 0, dcp); 947 FWRITE_R; 948 TRY_YIELD; 949 } 950 } 951 952 if(!strcmp(argv[1],"fastdcblock_ff")) 953 { 954 int dcblock_bufsize=SETBUF_DEFAULT_BUFSIZE; 955 if(argc>=3) sscanf(argv[2],"%d",&dcblock_bufsize); 956 float* dcblock_buffer=(float*)malloc(sizeof(float)*dcblock_bufsize); 957 static float last_dc_level=0.0; 958 getbufsize(); //it is just dummy 959 sendbufsize(dcblock_bufsize); 960 for(;;) 961 { 962 FEOF_CHECK; 963 fread(dcblock_buffer, sizeof(float), dcblock_bufsize, stdin); 964 last_dc_level=fastdcblock_ff(dcblock_buffer, dcblock_buffer, dcblock_bufsize, last_dc_level); 965 fwrite(dcblock_buffer, sizeof(float), dcblock_bufsize, stdout); 966 TRY_YIELD; 967 } 968 } 969 970 if(!strcmp(argv[1],"fmdemod_atan_cf")) 971 { 972 if(!sendbufsize(initialize_buffers())) return -2; 973 float last_phase=0; 974 for(;;) 975 { 976 FEOF_CHECK; 977 FREAD_C; 978 if(feof(stdin)) return 0; 979 last_phase=fmdemod_atan_cf((complexf*)input_buffer, output_buffer, the_bufsize, last_phase); 980 FWRITE_R; 981 TRY_YIELD; 982 } 983 } 984 if(!strcmp(argv[1],"fmdemod_quadri_cf")) 985 { 986 if(!sendbufsize(initialize_buffers())) return -2; 987 complexf last_sample; 988 last_sample.i=0.; 989 last_sample.q=0.; 990 for(;;) 991 { 992 FEOF_CHECK; 993 FREAD_C; 994 last_sample=fmdemod_quadri_cf((complexf*)input_buffer, output_buffer, the_bufsize, temp_f, last_sample); 995 FWRITE_R; 996 TRY_YIELD; 997 } 998 } 999 if(!strcmp(argv[1],"fmdemod_quadri_novect_cf")) 1000 { 1001 if(!sendbufsize(initialize_buffers())) return -2; 1002 complexf last_sample; 1003 last_sample.i=0.; 1004 last_sample.q=0.; 1005 for(;;) 1006 { 1007 FEOF_CHECK; 1008 FREAD_C; 1009 last_sample=fmdemod_quadri_novect_cf((complexf*)input_buffer, output_buffer, the_bufsize, last_sample); 1010 FWRITE_R; 1011 TRY_YIELD; 1012 } 1013 } 1014 if(!strcmp(argv[1],"deemphasis_wfm_ff")) 1015 { 1016 if(argc<=3) return badsyntax("need required parameters (sample rate, tau)"); 1017 if(!sendbufsize(initialize_buffers())) return -2; 1018 int sample_rate; 1019 sscanf(argv[2],"%d",&sample_rate); 1020 float tau; 1021 sscanf(argv[3],"%g",&tau); 1022 errhead(); fprintf(stderr,"tau = %g, sample_rate = %d\n",tau,sample_rate); 1023 float last_output=0; 1024 for(;;) 1025 { 1026 FEOF_CHECK; 1027 FREAD_R; 1028 last_output=deemphasis_wfm_ff(input_buffer, output_buffer, the_bufsize, tau, sample_rate, last_output); 1029 FWRITE_R; 1030 TRY_YIELD; 1031 } 1032 } 1033 1034 if(!strcmp(argv[1],"detect_nan_ff")) 1035 { 1036 if(!sendbufsize(initialize_buffers())) return -2; 1037 for(;;) 1038 { 1039 FEOF_CHECK; 1040 FREAD_R; 1041 int nan_detect=0; 1042 for(int i=0; i<the_bufsize;i++) 1043 { 1044 if(is_nan(input_buffer[i])) 1045 { 1046 nan_detect=1; 1047 break; 1048 } 1049 } 1050 if(nan_detect) { errhead(); fprintf(stderr, "NaN detected!\n"); } 1051 fwrite(input_buffer, sizeof(float), the_bufsize, stdout); 1052 TRY_YIELD; 1053 } 1054 } 1055 1056 if(!strcmp(argv[1],"floatdump_f") || !strcmp(argv[1],"dump_f")) 1057 { 1058 if(!sendbufsize(initialize_buffers())) return -2; 1059 for(;;) 1060 { 1061 FEOF_CHECK; 1062 FREAD_R; 1063 for(int i=0; i<the_bufsize;i++) printf("%g ",input_buffer[i]); 1064 TRY_YIELD; 1065 } 1066 1067 } 1068 if(!strcmp(argv[1],"deemphasis_nfm_ff")) 1069 { 1070 if(argc<=2) return badsyntax("need required parameter (sample rate)"); 1071 int sample_rate; 1072 sscanf(argv[2],"%d",&sample_rate); 1073 1074 if(!sendbufsize(initialize_buffers())) return -2; //maybe we should take a /2 of bufsize over here 1075 1076 int processed=0; 1077 for(;;) 1078 { 1079 FEOF_CHECK; 1080 fread(input_buffer+the_bufsize-processed, sizeof(float), processed, stdin); 1081 processed=deemphasis_nfm_ff(input_buffer, output_buffer, the_bufsize, sample_rate); 1082 if(!processed) return badsyntax("deemphasis_nfm_ff: invalid sample rate (this function works only with specific sample rates)."); 1083 memmove(input_buffer,input_buffer+processed,(the_bufsize-processed)*sizeof(float)); //memmove lets the source and destination overlap 1084 fwrite(output_buffer, sizeof(float), processed, stdout); 1085 TRY_YIELD; 1086 } 1087 } 1088 if(!strcmp(argv[1],"amdemod_cf")) 1089 { 1090 if(!sendbufsize(initialize_buffers())) return -2; 1091 1092 for(;;) 1093 { 1094 FEOF_CHECK; 1095 FREAD_C; 1096 amdemod_cf((complexf*)input_buffer, output_buffer, the_bufsize); 1097 FWRITE_R; 1098 TRY_YIELD; 1099 } 1100 } 1101 if(!strcmp(argv[1],"amdemod_estimator_cf")) 1102 { 1103 if(!sendbufsize(initialize_buffers())) return -2; 1104 for(;;) 1105 { 1106 FEOF_CHECK; 1107 FREAD_C; 1108 amdemod_estimator_cf((complexf*)input_buffer, output_buffer, the_bufsize, 0., 0.); 1109 FWRITE_R; 1110 TRY_YIELD; 1111 } 1112 } 1113 1114 if(!strcmp(argv[1],"fir_decimate_cc")) 1115 { 1116 bigbufs=1; 1117 1118 if(argc<=2) return badsyntax("need required parameter (decimation factor)"); 1119 1120 int factor; 1121 sscanf(argv[2],"%d",&factor); 1122 1123 float transition_bw = 0.05; 1124 if(argc>=4) sscanf(argv[3],"%g",&transition_bw); 1125 1126 window_t window = WINDOW_DEFAULT; 1127 if(argc>=5) 1128 { 1129 window=firdes_get_window_from_string(argv[4]); 1130 } 1131 else fprintf(stderr,"fir_decimate_cc: window = %s\n",firdes_get_string_from_window(window)); 1132 1133 int taps_length=firdes_filter_len(transition_bw); 1134 fprintf(stderr,"fir_decimate_cc: taps_length = %d\n",taps_length); 1135 1136 while (env_csdr_fixed_big_bufsize < taps_length*2) env_csdr_fixed_big_bufsize*=2; //temporary fix for buffer size if [transition_bw] is low 1137 //fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize); 1138 1139 if(!initialize_buffers()) return -2; 1140 sendbufsize(the_bufsize/factor); 1141 1142 1143 int padded_taps_length = taps_length; 1144 float *taps; 1145 #define NEON_ALIGNMENT (4*4*2) 1146 #ifdef NEON_OPTS 1147 errhead(); fprintf(stderr,"taps_length = %d\n", taps_length); 1148 padded_taps_length = taps_length+(NEON_ALIGNMENT/4)-1 - ((taps_length+(NEON_ALIGNMENT/4)-1)%(NEON_ALIGNMENT/4)); 1149 errhead(); fprintf(stderr,"padded_taps_length = %d\n", padded_taps_length); 1150 1151 taps = (float*) (float*)malloc((padded_taps_length+NEON_ALIGNMENT)*sizeof(float)); 1152 errhead(); fprintf(stderr,"taps = %x\n", taps); 1153 taps = (float*)((((unsigned)taps)+NEON_ALIGNMENT-1) & ~(NEON_ALIGNMENT-1)); 1154 errhead(); fprintf(stderr,"NEON aligned taps = %x\n", taps); 1155 for(int i=0;i<padded_taps_length-taps_length;i++) taps[taps_length+i]=0; 1156 #else 1157 taps=(float*)malloc(taps_length*sizeof(float)); 1158 #endif 1159 1160 firdes_lowpass_f(taps,taps_length,0.5/(float)factor,window); 1161 1162 int input_skip=0; 1163 int output_size=0; 1164 FREAD_C; 1165 for(;;) 1166 { 1167 FEOF_CHECK; 1168 output_size=fir_decimate_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, factor, taps, padded_taps_length); 1169 //fprintf(stderr, "os %d\n",output_size); 1170 fwrite(output_buffer, sizeof(complexf), output_size, stdout); 1171 TRY_YIELD; 1172 input_skip=factor*output_size; 1173 memmove((complexf*)input_buffer,((complexf*)input_buffer)+input_skip,(the_bufsize-input_skip)*sizeof(complexf)); //memmove lets the source and destination overlap 1174 fread(((complexf*)input_buffer)+(the_bufsize-input_skip), sizeof(complexf), input_skip, stdin); 1175 //fprintf(stderr,"iskip=%d output_size=%d start=%x target=%x skipcount=%x \n",input_skip,output_size,input_buffer, ((complexf*)input_buffer)+(BIG_BUFSIZE-input_skip),(BIG_BUFSIZE-input_skip)); 1176 } 1177 } 1178 1179 if(!strcmp(argv[1],"fir_interpolate_cc")) 1180 { 1181 bigbufs=1; 1182 1183 if(argc<=2) return badsyntax("need required parameter (interpolation factor)"); 1184 1185 int factor; 1186 sscanf(argv[2],"%d",&factor); 1187 assert(factor >= 1); 1188 1189 float transition_bw = 0.05; 1190 if(argc>=4) sscanf(argv[3],"%g",&transition_bw); 1191 assert(transition_bw >= 0 && transition_bw < 1.); 1192 1193 window_t window = WINDOW_DEFAULT; 1194 if(argc>=5) 1195 { 1196 window=firdes_get_window_from_string(argv[4]); 1197 } 1198 else {errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window));} 1199 1200 int taps_length=firdes_filter_len(transition_bw); 1201 errhead(); fprintf(stderr,"taps_length = %d\n",taps_length); 1202 assert(taps_length > 0); 1203 1204 while (env_csdr_fixed_big_bufsize < taps_length*2) env_csdr_fixed_big_bufsize*=2; //temporary fix for buffer size if [transition_bw] is low 1205 //fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize); 1206 1207 if(!initialize_buffers()) return -2; 1208 sendbufsize(the_bufsize*factor); 1209 assert(the_bufsize > 0); 1210 1211 float *taps; 1212 taps=(float*)malloc(taps_length*sizeof(float)); 1213 assert(taps); 1214 1215 firdes_lowpass_f(taps,taps_length,0.5/(float)factor,window); 1216 1217 int input_skip=0; 1218 int output_size=0; 1219 float* interp_output_buffer = (float*)malloc(sizeof(float)*2*the_bufsize*factor); 1220 for(;;) 1221 { 1222 FEOF_CHECK; 1223 output_size=fir_interpolate_cc((complexf*)input_buffer, (complexf*)interp_output_buffer, the_bufsize, factor, taps, taps_length); 1224 //fprintf(stderr, "os %d\n",output_size); 1225 fwrite(interp_output_buffer, sizeof(complexf), output_size, stdout); 1226 TRY_YIELD; 1227 input_skip=output_size/factor; 1228 memmove((complexf*)input_buffer,((complexf*)input_buffer)+input_skip,(the_bufsize-input_skip)*sizeof(complexf)); //memmove lets the source and destination overlap 1229 fread(((complexf*)input_buffer)+(the_bufsize-input_skip), sizeof(complexf), input_skip, stdin); 1230 //fprintf(stderr,"iskip=%d output_size=%d start=%x target=%x skipcount=%x \n",input_skip,output_size,input_buffer, ((complexf*)input_buffer)+(BIG_BUFSIZE-input_skip),(BIG_BUFSIZE-input_skip)); 1231 } 1232 } 1233 1234 1235 1236 1237 /*if(!strcmp(argv[1],"ejw_test")) 1238 { 1239 printf("ejqd=["); 1240 complexf ejw; 1241 float phase=0; 1242 for(int i=0;i<63;i++) 1243 { 1244 e_powj(&ejw,phase); 1245 phase+=PI*0.3; 1246 printf("%g+(%g)*i ",iof(&ejw,0),qof(&ejw,0)); 1247 } 1248 printf("];"); 1249 return 0; 1250 }*/ 1251 if(!strcmp(argv[1],"firdes_lowpass_f")) 1252 { 1253 //Process the params 1254 if(argc<=3) return badsyntax("need required parameters (cutoff_rate, length)"); 1255 1256 float cutoff_rate; 1257 sscanf(argv[2],"%g",&cutoff_rate); 1258 1259 int length; 1260 sscanf(argv[3],"%d",&length); 1261 if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd"); 1262 1263 window_t window = WINDOW_DEFAULT; 1264 if(argc>=5) 1265 { 1266 window=firdes_get_window_from_string(argv[4]); 1267 } 1268 else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); } 1269 1270 int octave=(argc>=6 && !strcmp("--octave",argv[5])); 1271 1272 float* taps=(float*)malloc(sizeof(float)*length); 1273 1274 //Make the filter 1275 firdes_lowpass_f(taps,length,cutoff_rate,window); 1276 1277 //Do the output 1278 if(octave) printf("taps=["); 1279 for(int i=0;i<length;i++) printf("%g ",taps[i]); 1280 if(octave) printf("];plot(taps);figure(2);freqz(taps);\n"); 1281 1282 1283 //Wait forever, so that octave won't close just after popping up the window. 1284 //You can close it with ^C. 1285 if(octave) { fflush(stdout); getchar(); } 1286 return 0; 1287 } 1288 if(!strcmp(argv[1],"firdes_bandpass_c")) 1289 { 1290 //Process the params 1291 if(argc<=4) return badsyntax("need required parameters (low_cut, high_cut, length)"); 1292 1293 float low_cut; 1294 sscanf(argv[2],"%g",&low_cut); 1295 float high_cut; 1296 sscanf(argv[3],"%g",&high_cut); 1297 1298 int length; 1299 sscanf(argv[4],"%d",&length); 1300 if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd"); 1301 1302 window_t window = WINDOW_DEFAULT; 1303 if(argc>=6) 1304 { 1305 window=firdes_get_window_from_string(argv[5]); 1306 } 1307 else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window));} 1308 1309 int octave=(argc>=7 && !strcmp("--octave",argv[6])); 1310 1311 complexf* taps=(complexf*)malloc(sizeof(complexf)*length); 1312 1313 //Make the filter 1314 firdes_bandpass_c(taps, length, low_cut, high_cut, window); 1315 1316 //Do the output 1317 if(octave) printf("taps=["); 1318 for(int i=0;i<length;i++) printf("(%g)+(%g)*i ",iof(taps,i),qof(taps,i)); 1319 int fft_length=1024; 1320 while(fft_length<length) fft_length*=2; 1321 //if(octave) printf("];\n"); 1322 if(octave) printf( 1323 "];figure(\"Position\",[0 0 1000 1000]);fser=fft([taps,zeros(1,%d)]);ampl=abs(fser).^2;halfindex=floor(1+size(ampl)(2)/2);\n" 1324 "amplrev=[ampl(halfindex:end),ampl(1:halfindex)];\n" //we have to swap the output of FFT 1325 "subplot(2,1,1);plot(amplrev);\n" 1326 "subplot(2,1,2);plot(arg(fser));\n" 1327 "#figure(2);freqz(taps);\n" 1328 "#figur(3);plot3(taps);\n",fft_length-length); 1329 1330 //Wait forever, so that octave won't close just after popping up the window. 1331 //You can close it with ^C. 1332 if(octave) { fflush(stdout); getchar(); } 1333 return 0; 1334 } 1335 1336 #ifdef LIBCSDR_GPL 1337 if(!strcmp(argv[1],"agc_ff")) 1338 { 1339 //Process the params 1340 //Explanation of what these actually do is in the DSP source. 1341 //These good default values are for SSB sampled at 48000 kHz. 1342 short hang_time=200; 1343 if(argc>=3) sscanf(argv[2],"%hd",&hang_time); 1344 1345 float reference=0.2; 1346 if(argc>=4) sscanf(argv[3],"%g",&reference); 1347 1348 float attack_rate=0.01; 1349 if(argc>=5) sscanf(argv[4],"%g",&attack_rate); 1350 1351 float decay_rate=0.0001; 1352 if(argc>=6) sscanf(argv[5],"%g",&decay_rate); 1353 1354 float max_gain=65536; 1355 if(argc>=7) sscanf(argv[6],"%g",&max_gain); 1356 1357 short attack_wait=0; 1358 if(argc>=8) sscanf(argv[7],"%hd",&attack_wait); 1359 1360 float filter_alpha=0.999;//0.001; 1361 if(argc>=9) sscanf(argv[8],"%g",&filter_alpha); 1362 1363 if(!sendbufsize(initialize_buffers())) return -2; 1364 1365 float last_gain=1.0; 1366 for(;;) 1367 { 1368 FEOF_CHECK; 1369 FREAD_R; 1370 last_gain=agc_ff(input_buffer, output_buffer, the_bufsize, reference, attack_rate, decay_rate, max_gain, hang_time, attack_wait, filter_alpha, last_gain); 1371 FWRITE_R; 1372 TRY_YIELD; 1373 } 1374 } 1375 #endif 1376 1377 if(!strcmp(argv[1],"fastagc_ff")) 1378 { 1379 1380 static fastagc_ff_t input; //is in .bss and gets cleared to zero before main() 1381 1382 input.input_size=1024; 1383 if(argc>=3) sscanf(argv[2],"%d",&input.input_size); 1384 1385 getbufsize(); //dummy 1386 sendbufsize(input.input_size); 1387 1388 input.reference=1.0; 1389 if(argc>=4) sscanf(argv[3],"%g",&input.reference); 1390 1391 //input.max_peak_ratio=12.0; 1392 //if(argc>=5) sscanf(argv[3],"%g",&input.max_peak_ratio); 1393 1394 input.buffer_1=(float*)calloc(input.input_size,sizeof(float)); 1395 input.buffer_2=(float*)calloc(input.input_size,sizeof(float)); 1396 input.buffer_input=(float*)malloc(sizeof(float)*input.input_size); 1397 float* agc_output_buffer=(float*)malloc(sizeof(float)*input.input_size); 1398 for(;;) 1399 { 1400 FEOF_CHECK; 1401 fread(input.buffer_input, sizeof(float), input.input_size, stdin); 1402 fastagc_ff(&input, agc_output_buffer); 1403 fwrite(agc_output_buffer, sizeof(float), input.input_size, stdout); 1404 TRY_YIELD; 1405 } 1406 } 1407 1408 int suboptimal; 1409 if( (suboptimal=!strcmp(argv[1],"suboptimal_rational_resampler_ff"))||(!strcmp(argv[1],"rational_resampler_ff")) ) 1410 { 1411 1412 //last@2014-11-06: ./docompile; ./csdr yes_f 1.0 | ./csdr suboptimal_rational_resampler_ff 5 2 1413 1414 //Process the params 1415 if(argc<=3) return badsyntax("need required parameters (interpolation, decimation)"); 1416 int interpolation; 1417 sscanf(argv[2],"%d",&interpolation); 1418 int decimation; 1419 sscanf(argv[3],"%d",&decimation); 1420 1421 float transition_bw=0.05; 1422 if(argc>=5) sscanf(argv[4],"%g",&transition_bw); 1423 1424 window_t window = WINDOW_DEFAULT; 1425 if(argc>=6) 1426 { 1427 window=firdes_get_window_from_string(argv[5]); 1428 } 1429 else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); } 1430 1431 if(suboptimal) { errhead(); fprintf(stderr,"note: suboptimal rational resampler chosen.\n"); } 1432 1433 if(!initialize_buffers()) return -2; 1434 1435 if(decimation==1&&interpolation==1) { sendbufsize(the_bufsize); clone_(the_bufsize); } //copy input to output in this special case (and stick in this function). 1436 1437 //Alloc output buffer 1438 int resampler_output_buffer_size=(the_bufsize*interpolation)/decimation; 1439 sendbufsize(resampler_output_buffer_size); 1440 float* resampler_output_buffer=(float*)malloc(sizeof(float)*resampler_output_buffer_size); 1441 float* suboptimal_resampler_temp_buffer = (suboptimal)?(float*)malloc(sizeof(float)*the_bufsize*interpolation):NULL; 1442 1443 //Generate filter taps 1444 int taps_length = firdes_filter_len(transition_bw); 1445 float* taps = (float*)malloc(sizeof(float)*taps_length); 1446 rational_resampler_get_lowpass_f(taps, taps_length, interpolation, decimation, window); 1447 1448 static rational_resampler_ff_t d; //in .bss => initialized to zero 1449 1450 for(;;) 1451 { 1452 FEOF_CHECK; 1453 if(d.input_processed==0) d.input_processed=the_bufsize; 1454 else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed)); 1455 fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin); 1456 //if(suboptimal) d=suboptimal_rational_resampler_ff(input_buffer, resampler_output_buffer, the_bufsize, interpolation, decimation, taps, taps_length, suboptimal_resampler_temp_buffer); else 1457 d=rational_resampler_ff(input_buffer, resampler_output_buffer, the_bufsize, interpolation, decimation, taps, taps_length, d.last_taps_delay); 1458 //fprintf(stderr,"resampled %d %d, %d\n",d.output_size, d.input_processed, d.input_processed); 1459 fwrite(resampler_output_buffer, sizeof(float), d.output_size, stdout); 1460 TRY_YIELD; 1461 } 1462 } 1463 1464 1465 if(!strcmp(argv[1],"fractional_decimator_ff")) 1466 { 1467 //Process the params 1468 if(argc<=2) return badsyntax("need required parameters (rate)"); 1469 float rate; 1470 sscanf(argv[2],"%g",&rate); 1471 1472 int num_poly_points = 12; 1473 if(argc>=4) sscanf(argv[3],"%d",&num_poly_points); 1474 if(num_poly_points&1) return badsyntax("num_poly_points should be even"); 1475 if(num_poly_points<2) return badsyntax("num_poly_points should be >= 2"); 1476 1477 int use_prefilter = 0; 1478 float transition_bw=0.03; 1479 window_t window = WINDOW_DEFAULT; 1480 if(argc>=5) 1481 { 1482 if(!strcmp(argv[4], "--prefilter")) 1483 { 1484 errhead(); fprintf(stderr, "using prefilter with default values\n"); 1485 use_prefilter = 1; 1486 } 1487 else 1488 { 1489 sscanf(argv[4],"%g",&transition_bw); 1490 if(argc>=6) window = firdes_get_window_from_string(argv[5]); 1491 } 1492 } 1493 errhead(); fprintf(stderr,"use_prefilter = %d, num_poly_points = %d, transition_bw = %g, window = %s\n", 1494 use_prefilter, num_poly_points, transition_bw, firdes_get_string_from_window(window)); 1495 1496 if(!initialize_buffers()) return -2; 1497 sendbufsize(the_bufsize / rate); 1498 1499 if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function). 1500 1501 //Generate filter taps 1502 int taps_length = 0; 1503 float* taps = NULL; 1504 if(use_prefilter) 1505 { 1506 taps_length = firdes_filter_len(transition_bw); 1507 errhead(); fprintf(stderr,"taps_length = %d\n",taps_length); 1508 taps = (float*)malloc(sizeof(float)*taps_length); 1509 firdes_lowpass_f(taps, taps_length, 0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff 1510 //for(int=0;i<taps_length; i++) fprintf(stderr,"%g ",taps[i]); 1511 } 1512 else { errhead(); fprintf(stderr,"not using taps\n"); } 1513 fractional_decimator_ff_t d = fractional_decimator_ff_init(rate, num_poly_points, taps, taps_length); 1514 for(;;) 1515 { 1516 FEOF_CHECK; 1517 if(d.input_processed==0) d.input_processed=the_bufsize; 1518 else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed)); 1519 fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin); 1520 fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, &d); 1521 fwrite(output_buffer, sizeof(float), d.output_size, stdout); 1522 //fprintf(stderr, "os = %d, ip = %d\n", d.output_size, d.input_processed); 1523 TRY_YIELD; 1524 } 1525 } 1526 1527 if(!strcmp(argv[1],"old_fractional_decimator_ff")) 1528 { 1529 //Process the params 1530 if(argc<=2) return badsyntax("need required parameters (rate)"); 1531 float rate; 1532 sscanf(argv[2],"%g",&rate); 1533 1534 float transition_bw=0.03; 1535 if(argc>=4) sscanf(argv[3],"%g",&transition_bw); 1536 1537 window_t window = WINDOW_DEFAULT; 1538 if(argc>=5) 1539 { 1540 window = firdes_get_window_from_string(argv[4]); 1541 } 1542 else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); } 1543 1544 if(!initialize_buffers()) return -2; 1545 sendbufsize(the_bufsize / rate); 1546 1547 if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function). 1548 1549 //Generate filter taps 1550 int taps_length = firdes_filter_len(transition_bw); 1551 errhead(); fprintf(stderr,"taps_length = %d\n",taps_length); 1552 float* taps = (float*)malloc(sizeof(float)*taps_length); 1553 firdes_lowpass_f(taps, taps_length, 0.59*0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff 1554 //for(int=0;i<taps_length; i++) fprintf(stderr,"%g ",taps[i]); 1555 1556 static old_fractional_decimator_ff_t d; //in .bss => initialized to zero 1557 for(;;) 1558 { 1559 FEOF_CHECK; 1560 if(d.input_processed==0) d.input_processed=the_bufsize; 1561 else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed)); 1562 fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin); 1563 d = old_fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, rate, taps, taps_length, d); 1564 fwrite(output_buffer, sizeof(float), d.output_size, stdout); 1565 TRY_YIELD; 1566 } 1567 } 1568 1569 if(!strcmp(argv[1],"fft_cc")) 1570 { 1571 if(argc<=3) return badsyntax("need required parameters (fft_size, out_of_every_n_samples)"); 1572 int fft_size; 1573 sscanf(argv[2],"%d",&fft_size); 1574 if(log2n(fft_size)==-1) return badsyntax("fft_size should be power of 2"); 1575 int every_n_samples; 1576 sscanf(argv[3],"%d",&every_n_samples); 1577 int benchmark=0; 1578 int octave=0; 1579 window_t window = WINDOW_DEFAULT; 1580 if(argc>=5) 1581 { 1582 window=firdes_get_window_from_string(argv[4]); 1583 } 1584 if(argc>=6) 1585 { 1586 benchmark|=!strcmp("--benchmark",argv[5]); 1587 octave|=!strcmp("--octave",argv[5]); 1588 } 1589 if(argc>=7) 1590 { 1591 benchmark|=!strcmp("--benchmark",argv[6]); 1592 octave|=!strcmp("--octave",argv[6]); 1593 } 1594 1595 if(!initialize_buffers()) return -2; 1596 sendbufsize(fft_size); 1597 1598 //make FFT plan 1599 complexf* input=(complexf*)fft_malloc(sizeof(complexf)*fft_size); 1600 complexf* windowed=(complexf*)fft_malloc(sizeof(complexf)*fft_size); 1601 complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_size); 1602 if(benchmark) { errhead(); fprintf(stderr,"benchmarking..."); } 1603 FFT_PLAN_T* plan=make_fft_c2c(fft_size, windowed, output, 1, benchmark); 1604 if(benchmark) fprintf(stderr," done\n"); 1605 if(octave) printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); 1606 float *windowt; 1607 windowt = precalculate_window(fft_size, window); 1608 for(;;) 1609 { 1610 FEOF_CHECK; 1611 if(every_n_samples>fft_size) 1612 { 1613 fread(input, sizeof(complexf), fft_size, stdin); 1614 //skipping samples before next FFT (but fseek doesn't work for pipes) 1615 for(int seek_remain=every_n_samples-fft_size;seek_remain>0;seek_remain-=the_bufsize) 1616 { 1617 fread(temp_f, sizeof(complexf), MIN_M(the_bufsize,seek_remain), stdin); 1618 } 1619 } 1620 else 1621 { 1622 //overlapped FFT 1623 for(int i=0;i<fft_size-every_n_samples;i++) input[i]=input[i+every_n_samples]; 1624 fread(input+fft_size-every_n_samples, sizeof(complexf), every_n_samples, stdin); 1625 } 1626 //apply_window_c(input,windowed,fft_size,window); 1627 apply_precalculated_window_c(input,windowed,fft_size,windowt); 1628 fft_execute(plan); 1629 if(octave) 1630 { 1631 printf("fftdata=["); 1632 //we have to swap the two parts of the array to get a valid spectrum 1633 for(int i=fft_size/2;i<fft_size;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i)); 1634 for(int i=0;i<fft_size/2;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i)); 1635 printf( 1636 "];\n" 1637 "y=abs(fftdata);\n" 1638 "refreshdata;\n" 1639 ); 1640 } 1641 else fwrite(output, sizeof(complexf), fft_size, stdout); 1642 TRY_YIELD; 1643 } 1644 } 1645 #define LOGPOWERCF_BUFSIZE 64 1646 if(!strcmp(argv[1],"logpower_cf")) 1647 { 1648 float add_db=0; 1649 if(argc>=3) sscanf(argv[2],"%g",&add_db); 1650 1651 if(!sendbufsize(initialize_buffers())) return -2; 1652 1653 for(;;) 1654 { 1655 FEOF_CHECK; 1656 fread(input_buffer, sizeof(complexf), the_bufsize, stdin); 1657 logpower_cf((complexf*)input_buffer,output_buffer, the_bufsize, add_db); 1658 fwrite(output_buffer, sizeof(float), the_bufsize, stdout); 1659 TRY_YIELD; 1660 } 1661 } 1662 1663 if(!strcmp(argv[1],"logaveragepower_cf")) 1664 { 1665 bigbufs=1; 1666 if(argc<=4) return badsyntax("need required parameters (add_db, fft_size, avgnumber)"); 1667 float add_db=0; 1668 int avgnumber=0; 1669 int fft_size=0; 1670 1671 sscanf(argv[2],"%g",&add_db); 1672 sscanf(argv[3],"%d",&fft_size); 1673 sscanf(argv[4],"%d",&avgnumber); 1674 1675 float *input = malloc(sizeof(float)*2 * fft_size); 1676 float *output = malloc(sizeof(float) * fft_size); 1677 1678 add_db -= 10.0*log10(avgnumber); 1679 for(;;) 1680 { 1681 int i,n; 1682 for(i = 0; i < fft_size; i++) { 1683 output[i] = 0; 1684 } 1685 FEOF_CHECK; 1686 for(n = 0; n < avgnumber; n++) { 1687 fread (input, sizeof(float)*2, fft_size, stdin); 1688 accumulate_power_cf((complexf*)input, output, fft_size); 1689 } 1690 log_ff(output, output, fft_size, add_db); 1691 fwrite (output, sizeof(float), fft_size, stdout); 1692 TRY_YIELD; 1693 } 1694 return 0; 1695 } 1696 1697 if(!strcmp(argv[1],"fft_exchange_sides_ff")) 1698 { 1699 if(argc<=2) return badsyntax("need required parameters (fft_size)"); 1700 int fft_size; 1701 sscanf(argv[2],"%d",&fft_size); 1702 if(!getbufsize()) return -2; //dummy 1703 sendbufsize(fft_size); 1704 float* input_buffer_s1 = (float*)malloc(sizeof(float)*fft_size/2); 1705 float* input_buffer_s2 = (float*)malloc(sizeof(float)*fft_size/2); 1706 for(;;) 1707 { 1708 FEOF_CHECK; 1709 fread(input_buffer_s1, sizeof(float), fft_size/2, stdin); 1710 fread(input_buffer_s2, sizeof(float), fft_size/2, stdin); 1711 fwrite(input_buffer_s2, sizeof(float), fft_size/2, stdout); 1712 fwrite(input_buffer_s1, sizeof(float), fft_size/2, stdout); 1713 TRY_YIELD; 1714 } 1715 } 1716 1717 if(!strcmp(argv[1],"fft_one_side_ff")) 1718 { 1719 if(argc<=2) return badsyntax("need required parameters (fft_size)"); 1720 int fft_size; 1721 sscanf(argv[2],"%d",&fft_size); 1722 if(!getbufsize()) return -2; 1723 sendbufsize(fft_size); 1724 float* input_buffer_s1 = (float*)malloc(sizeof(float)*fft_size/2); 1725 float* input_buffer_s2 = (float*)malloc(sizeof(float)*fft_size/2); 1726 for(;;) 1727 { 1728 FEOF_CHECK; 1729 fread(input_buffer_s1, sizeof(float), fft_size/2, stdin); 1730 fread(input_buffer_s2, sizeof(float), fft_size/2, stdin); 1731 fwrite(input_buffer_s1, sizeof(float), fft_size/2, stdout); 1732 TRY_YIELD; 1733 } 1734 } 1735 1736 1737 #ifdef USE_IMA_ADPCM 1738 1739 #define COMPRESS_FFT_PAD_N 10 1740 //We will pad the FFT at the beginning, with the first value of the input data, COMPRESS_FFT_PAD_N times. 1741 //No, this is not advanced DSP, just the ADPCM codec produces some gabarge samples at the beginning, 1742 //so we just add data to become garbage and get skipped. 1743 //COMPRESS_FFT_PAD_N should be even. 1744 1745 if(!strcmp(argv[1],"compress_fft_adpcm_f_u8")) 1746 { 1747 if(argc<=2) return badsyntax("need required parameters (fft_size)"); 1748 int fft_size; 1749 sscanf(argv[2],"%d",&fft_size); 1750 int real_data_size=fft_size+COMPRESS_FFT_PAD_N; 1751 if(!getbufsize()) return -2; //dummy 1752 sendbufsize(real_data_size); 1753 float* input_buffer_cwa = (float*)malloc(sizeof(float)*real_data_size); 1754 short* temp_buffer_cwa = (short*)malloc(sizeof(short)*real_data_size); 1755 unsigned char* output_buffer_cwa = (unsigned char*)malloc(sizeof(unsigned char)*(real_data_size/2)); 1756 ima_adpcm_state_t d; 1757 d.index=d.previousValue=0; 1758 for(;;) 1759 { 1760 FEOF_CHECK; 1761 fread(input_buffer_cwa+COMPRESS_FFT_PAD_N, sizeof(float), fft_size, stdin); 1762 for(int i=0;i<COMPRESS_FFT_PAD_N;i++) input_buffer_cwa[i]=input_buffer_cwa[COMPRESS_FFT_PAD_N]; //do padding 1763 for(int i=0;i<real_data_size;i++) temp_buffer_cwa[i]=input_buffer_cwa[i]*100; //convert float dB values to short 1764 encode_ima_adpcm_i16_u8(temp_buffer_cwa, output_buffer_cwa, real_data_size, d); //we always return to original d at any new buffer 1765 fwrite(output_buffer_cwa, sizeof(unsigned char), real_data_size/2, stdout); 1766 TRY_YIELD; 1767 } 1768 } 1769 #endif 1770 1771 if(!strcmp(argv[1],"fft_benchmark")) 1772 { 1773 if(argc<=3) return badsyntax("need required parameters (fft_size, fft_cycles)"); 1774 int fft_size; 1775 sscanf(argv[2],"%d",&fft_size); 1776 int fft_cycles; 1777 sscanf(argv[3],"%d",&fft_cycles); 1778 1779 int benchmark=(argc>=5)&&!strcmp(argv[4],"--benchmark"); 1780 errhead(); fprintf(stderr,"FFT library used: %s\n",FFT_LIBRARY_USED); 1781 1782 complexf* input=(complexf*)fft_malloc(sizeof(complexf)*fft_size); 1783 complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_size); 1784 1785 //fill input with random data 1786 srand(time(NULL)); 1787 for(int i=0;i<fft_size;i++) 1788 { 1789 iof(input,i)=rand()/(float)INT_MAX; 1790 qof(input,i)=rand()/(float)INT_MAX; 1791 } 1792 1793 //initialize FFT library, and measure time 1794 errhead(); fprintf(stderr,"initializing... "); 1795 struct timespec start_time, end_time; 1796 clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); 1797 FFT_PLAN_T* plan=make_fft_c2c(fft_size,input,output,1,benchmark); 1798 clock_gettime(CLOCK_MONOTONIC_RAW, &end_time); 1799 fprintf(stderr,"done in %g seconds.\n",TIME_TAKEN(start_time,end_time)); 1800 1801 //do the actual measurement about the FFT 1802 clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); 1803 for(int i=0;i<fft_cycles;i++) fft_execute(plan); 1804 clock_gettime(CLOCK_MONOTONIC_RAW, &end_time); 1805 float time_taken_fft = TIME_TAKEN(start_time,end_time); 1806 errhead(); fprintf(stderr,"%d transforms of %d processed in %g seconds, %g seconds each.\n",fft_cycles,fft_size,time_taken_fft,time_taken_fft/fft_cycles); 1807 return 0; 1808 } 1809 1810 if(!strcmp(argv[1],"bandpass_fir_fft_cc")) //this command does not exist as a separate function 1811 { 1812 float low_cut; 1813 float high_cut; 1814 float transition_bw; 1815 window_t window = WINDOW_DEFAULT; 1816 int fd; 1817 if(fd=init_fifo(argc,argv)) 1818 { 1819 while(!read_fifo_ctl(fd,"%g %g\n",&low_cut,&high_cut)) usleep(10000); 1820 if(argc<=4) return badsyntax("need more required parameters (transition_bw)"); 1821 } 1822 else 1823 { 1824 if(argc<=4) return badsyntax("need required parameters (low_cut, high_cut, transition_bw)"); 1825 sscanf(argv[2],"%g",&low_cut); 1826 sscanf(argv[3],"%g",&high_cut); 1827 } 1828 sscanf(argv[4],"%g",&transition_bw); 1829 if(argc>=6) window=firdes_get_window_from_string(argv[5]); 1830 else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); } 1831 1832 //calculate the FFT size and the other length parameters 1833 int taps_length=firdes_filter_len(transition_bw); //the number of non-zero taps 1834 int fft_size=next_pow2(taps_length); //we will have to pad the taps with zeros until the next power of 2 for FFT 1835 //the number of padding zeros is the number of output samples we will be able to take away after every processing step, and it looks sane to check if it is large enough. 1836 if (fft_size-taps_length<200) fft_size<<=1; 1837 int input_size = fft_size - taps_length + 1; 1838 int overlap_length = taps_length - 1; 1839 errhead(); fprintf(stderr,"(fft_size = %d) = (taps_length = %d) + (input_size = %d) - 1\n(overlap_length = %d) = taps_length - 1\n", fft_size, taps_length, input_size, overlap_length ); 1840 if (fft_size<=2) return badsyntax("FFT size error."); 1841 1842 if(!sendbufsize(getbufsize())) return -2; 1843 1844 //prepare making the filter and doing FFT on it 1845 complexf* taps=(complexf*)calloc(sizeof(complexf),fft_size); //initialize to zero 1846 complexf* taps_fft=(complexf*)malloc(sizeof(complexf)*fft_size); 1847 FFT_PLAN_T* plan_taps = make_fft_c2c(fft_size, taps, taps_fft, 1, 0); //forward, don't benchmark (we need this only once) 1848 1849 //make FFT plans for continously processing the input 1850 complexf* input = fft_malloc(fft_size*sizeof(complexf)); 1851 complexf* input_fourier = fft_malloc(fft_size*sizeof(complexf)); 1852 FFT_PLAN_T* plan_forward = make_fft_c2c(fft_size, input, input_fourier, 1, 1); //forward, do benchmark 1853 1854 complexf* output_fourier = fft_malloc(fft_size*sizeof(complexf)); 1855 complexf* output_1 = fft_malloc(fft_size*sizeof(complexf)); 1856 complexf* output_2 = fft_malloc(fft_size*sizeof(complexf)); 1857 //we create 2x output buffers so that one will preserve the previous overlap: 1858 FFT_PLAN_T* plan_inverse_1 = make_fft_c2c(fft_size, output_fourier, output_1, 0, 1); //inverse, do benchmark 1859 FFT_PLAN_T* plan_inverse_2 = make_fft_c2c(fft_size, output_fourier, output_2, 0, 1); 1860 //we initialize this buffer to 0 as it will be taken as the overlap source for the first time: 1861 for(int i=0;i<fft_size;i++) iof(plan_inverse_2->output,i)=qof(plan_inverse_2->output,i)=0; 1862 1863 for(int i=input_size;i<fft_size;i++) iof(input,i)=qof(input,i)=0; //we pre-pad the input buffer with zeros 1864 1865 for(;;) 1866 { 1867 //make the filter 1868 errhead(); fprintf(stderr,"filter initialized, low_cut = %g, high_cut = %g\n",low_cut,high_cut); 1869 firdes_bandpass_c(taps, taps_length, low_cut, high_cut, window); 1870 fft_execute(plan_taps); 1871 1872 for(int odd=0;;odd=!odd) //the processing loop 1873 { 1874 FEOF_CHECK; 1875 fread(input, sizeof(complexf), input_size, stdin); 1876 FFT_PLAN_T* plan_inverse = (odd)?plan_inverse_2:plan_inverse_1; 1877 FFT_PLAN_T* plan_contains_last_overlap = (odd)?plan_inverse_1:plan_inverse_2; //the other 1878 complexf* last_overlap = (complexf*)plan_contains_last_overlap->output + input_size; //+ fft_size - overlap_length; 1879 apply_fir_fft_cc (plan_forward, plan_inverse, taps_fft, last_overlap, overlap_length); 1880 int returned=fwrite(plan_inverse->output, sizeof(complexf), input_size, stdout); 1881 if(read_fifo_ctl(fd,"%g %g\n",&low_cut,&high_cut)) break; 1882 TRY_YIELD; 1883 } 1884 } 1885 1886 } 1887 1888 #ifdef USE_IMA_ADPCM 1889 #define IMA_ADPCM_BUFSIZE BUFSIZE 1890 1891 if( (!strcmp(argv[1],"encode_ima_adpcm_i16_u8"))||(!strcmp(argv[1],"encode_ima_adpcm_s16_u8")) ) 1892 { 1893 if(!sendbufsize(initialize_buffers()/2)) return -2; 1894 ima_adpcm_state_t d; 1895 d.index=d.previousValue=0; 1896 for(;;) 1897 { 1898 FEOF_CHECK; 1899 fread(buffer_i16, sizeof(short), the_bufsize, stdin); 1900 d=encode_ima_adpcm_i16_u8(buffer_i16, buffer_u8, the_bufsize, d); 1901 fwrite(buffer_u8, sizeof(unsigned char), the_bufsize/2, stdout); 1902 TRY_YIELD; 1903 } 1904 } 1905 1906 if( (!strcmp(argv[1],"decode_ima_adpcm_u8_i16"))||(!strcmp(argv[1],"decode_ima_adpcm_u8_s16")) ) 1907 { 1908 ima_adpcm_state_t d; 1909 d.index=d.previousValue=0; 1910 if(!sendbufsize(initialize_buffers()*2)) return -2; 1911 for(;;) 1912 { 1913 FEOF_CHECK; 1914 fread(buffer_u8, sizeof(unsigned char), the_bufsize, stdin); 1915 d=decode_ima_adpcm_u8_i16(buffer_u8, buffer_i16, the_bufsize, d); 1916 fwrite(buffer_i16, sizeof(short), the_bufsize*2, stdout); 1917 TRY_YIELD; 1918 } 1919 } 1920 #endif 1921 1922 if(!strcmp(argv[1],"flowcontrol")) 1923 { 1924 if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)"); 1925 int data_rate; 1926 sscanf(argv[2],"%d",&data_rate); 1927 int reads_per_second; 1928 sscanf(argv[3],"%d",&reads_per_second); 1929 int flowcontrol_bufsize=ceil(1.*(double)data_rate/reads_per_second); 1930 if(!getbufsize()) return -2; 1931 sendbufsize(flowcontrol_bufsize); 1932 unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize); 1933 int flowcontrol_sleep=floor(1000000./reads_per_second); 1934 errhead(); fprintf(stderr, "flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_bufsize, flowcontrol_sleep); 1935 for(;;) 1936 { 1937 FEOF_CHECK; 1938 fread(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdin); 1939 fwrite(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdout); 1940 usleep(flowcontrol_sleep); 1941 TRY_YIELD; 1942 } 1943 } 1944 1945 #if 0 1946 if(!strcmp(argv[1],"flowcontrol")) 1947 { 1948 if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)"); 1949 1950 int data_rate; 1951 sscanf(argv[2],"%d",&data_rate); 1952 1953 int reads_per_second=0; 1954 if(strcmp(argv[3],"auto")) sscanf(argv[3],"%d",&reads_per_second); 1955 1956 float prebuffer=2; 1957 if(argc>4) sscanf(argv[4],"%g",&prebuffer); 1958 1959 int thrust=10; 1960 if(argc>5) sscanf(argv[5],"%d",&thrust); 1961 1962 int flowcontrol_readsize, flowcontrol_bufsize, got_bufsize; 1963 1964 if(!(got_bufsize=getbufsize())) return -2; 1965 1966 if(reads_per_second) 1967 { 1968 flowcontrol_readsize=ceil(1.*(double)data_rate/reads_per_second); 1969 } 1970 else 1971 { 1972 flowcontrol_readsize=got_bufsize; 1973 reads_per_second=data_rate/flowcontrol_readsize; 1974 } 1975 flowcontrol_bufsize=flowcontrol_readsize*floor(reads_per_second*prebuffer); 1976 1977 int flowcontrol_bufindex=0; 1978 unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize); 1979 int flowcontrol_sleep=floor(1000000./reads_per_second); 1980 1981 fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK); 1982 1983 sendbufsize(flowcontrol_readsize); 1984 fflush(stdout); 1985 1986 int flowcontrol_is_buffering = 1; 1987 int read_return; 1988 1989 struct timespec start_time, end_time; 1990 1991 unsigned long long int all_bytes_written=0; 1992 int test=0; 1993 1994 fprintf(stderr, "flowcontrol: flowcontrol_readsize = %d, flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_readsize, flowcontrol_bufsize, flowcontrol_sleep); 1995 for (; ;) //my friend has told me that this is like two smileys ;) 1996 { 1997 FEOF_CHECK; 1998 fprintf(stderr, "r"); 1999 read_return=read(STDIN_FILENO, flowcontrol_buffer+flowcontrol_bufindex, sizeof(unsigned char) * (flowcontrol_bufsize-flowcontrol_bufindex) ); 2000 fprintf(stderr, "t"); 2001 if(read_return>0) flowcontrol_bufindex+=read_return; 2002 2003 2004 if(flowcontrol_is_buffering) 2005 { 2006 fprintf(stderr, "flowcontrol: buffering, flowcontrol_bufindex = %d\n", flowcontrol_bufindex); 2007 if(flowcontrol_bufindex==flowcontrol_bufsize) { flowcontrol_is_buffering = 0; clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); } 2008 else if(read_return<=0) continue; 2009 } 2010 else { 2011 clock_gettime(CLOCK_MONOTONIC_RAW, &end_time); 2012 int thrust_added=0; 2013 while( (all_bytes_written+thrust*flowcontrol_readsize) / TIME_TAKEN(start_time,end_time) < data_rate ) 2014 { 2015 thrust_added |= thrust++; 2016 } 2017 //if(!(test++%10)) fprintf(stderr, "abw=%g\n", all_bytes_written / TIME_TAKEN(start_time,end_time)); 2018 /*if(!thrust_added && TIME_TAKEN(start_time,end_time)>50) 2019 { 2020 clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); 2021 all_bytes_written=0; 2022 }*/ 2023 while(all_bytes_written>data_rate && TIME_TAKEN(start_time,end_time)>1) 2024 { 2025 all_bytes_written-=data_rate; 2026 start_time.tv_sec++; 2027 } 2028 do 2029 { 2030 //if(thrust) fprintf(stderr, "flowcontrol: %d .. thrust\n", thrust); 2031 write(STDOUT_FILENO, flowcontrol_buffer, flowcontrol_readsize); 2032 fflush(stdout); 2033 //fsync(STDOUT_FILENO); 2034 memmove(flowcontrol_buffer, flowcontrol_buffer+flowcontrol_readsize, flowcontrol_bufindex-flowcontrol_readsize); 2035 flowcontrol_bufindex -= flowcontrol_readsize; 2036 all_bytes_written += flowcontrol_readsize; 2037 } while(thrust && thrust-- && flowcontrol_bufindex>=flowcontrol_readsize); 2038 } 2039 2040 usleep(flowcontrol_sleep); 2041 TRY_YIELD; 2042 } 2043 } 2044 #endif 2045 2046 if(!strcmp(argv[1],"through")) 2047 { 2048 struct timespec start_time, end_time; 2049 if(!sendbufsize(initialize_buffers())) return -2; 2050 2051 int time_now_sec=0; 2052 int buffer_count=0; 2053 2054 unsigned char* through_buffer; 2055 through_buffer = (unsigned char*)malloc(the_bufsize*sizeof(float)); 2056 2057 2058 for(;;) 2059 { 2060 FEOF_CHECK; 2061 fread(through_buffer, sizeof(float), the_bufsize, stdin); 2062 2063 if(!time_now_sec) 2064 { 2065 time_now_sec=1; 2066 clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); 2067 } 2068 else 2069 { 2070 clock_gettime(CLOCK_MONOTONIC_RAW, &end_time); 2071 float timetaken; 2072 if(time_now_sec<(timetaken=TIME_TAKEN(start_time,end_time))) 2073 { 2074 fprintf( stderr, "through: %lu bytes/s, buffer #%d\n", (unsigned long)floor((float)buffer_count*the_bufsize*sizeof(float)/timetaken), buffer_count ); 2075 time_now_sec=ceil(timetaken); 2076 } 2077 } 2078 fwrite(through_buffer, sizeof(float), the_bufsize, stdout); 2079 buffer_count++; 2080 TRY_YIELD; 2081 } 2082 } 2083 2084 if(!strcmp(argv[1],"dsb_fc")) 2085 { 2086 float q_value = 0; 2087 if(argc>=3) sscanf(argv[2],"%g",&q_value); 2088 2089 if(!sendbufsize(initialize_buffers())) return -2; 2090 for(;;) 2091 { 2092 FEOF_CHECK; 2093 FREAD_R; 2094 for(int i=0;i<the_bufsize;i++) 2095 { 2096 iof(output_buffer,i)=input_buffer[i]; 2097 qof(output_buffer,i)=q_value; 2098 } 2099 FWRITE_C; 2100 TRY_YIELD; 2101 } 2102 } 2103 2104 if(!strcmp(argv[1],"convert_f_samplerf")) 2105 { 2106 if(argc<=2) return badsyntax("need required parameter (wait_for_this_sample)"); 2107 2108 unsigned wait_for_this_sample; 2109 sscanf(argv[2],"%u",&wait_for_this_sample); 2110 2111 if(!sendbufsize(initialize_buffers())) return -2; 2112 unsigned char* samplerf_buf = (unsigned char*) malloc(16*the_bufsize); 2113 for(;;) 2114 { 2115 FEOF_CHECK; 2116 FREAD_R; 2117 for(int i=0;i<the_bufsize;i++) 2118 { 2119 *((double*)(&samplerf_buf[16*i])) = input_buffer[i]; 2120 *((unsigned*)(&samplerf_buf[16*i+8])) = wait_for_this_sample; 2121 *((unsigned*)(&samplerf_buf[16*i+12])) = 0; 2122 2123 } 2124 fwrite(samplerf_buf, 16, the_bufsize, stdout); 2125 TRY_YIELD; 2126 } 2127 } 2128 2129 if(!strcmp(argv[1],"add_dcoffset_cc")) 2130 { 2131 if(!sendbufsize(initialize_buffers())) return -2; 2132 for(;;) 2133 { 2134 FEOF_CHECK; 2135 FREAD_C; 2136 add_dcoffset_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize); 2137 FWRITE_C; 2138 TRY_YIELD; 2139 } 2140 } 2141 2142 if(!strcmp(argv[1],"fmmod_fc")) 2143 { 2144 if(!sendbufsize(initialize_buffers())) return -2; 2145 float last_phase = 0; 2146 for(;;) 2147 { 2148 FEOF_CHECK; 2149 FREAD_R; 2150 last_phase = fmmod_fc(input_buffer, (complexf*)output_buffer, the_bufsize, last_phase); 2151 FWRITE_C; 2152 TRY_YIELD; 2153 } 2154 } 2155 2156 if(!strcmp(argv[1],"fixed_amplitude_cc")) 2157 { 2158 if(argc<=2) return badsyntax("need required parameter (new_amplitude)"); 2159 2160 float new_amplitude; 2161 sscanf(argv[2],"%g",&new_amplitude); 2162 2163 if(!sendbufsize(initialize_buffers())) return -2; 2164 for(;;) 2165 { 2166 FEOF_CHECK; 2167 FREAD_C; 2168 fixed_amplitude_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, new_amplitude); 2169 FWRITE_C; 2170 TRY_YIELD; 2171 } 2172 } 2173 2174 if((!strcmp(argv[1],"mono2stereo_i16"))||(!strcmp(argv[1],"mono2stereo_s16"))) 2175 { 2176 if(!sendbufsize(initialize_buffers())) return -2; 2177 float last_phase = 0; 2178 for(;;) 2179 { 2180 FEOF_CHECK; 2181 fread (input_buffer, sizeof(short), the_bufsize, stdin); 2182 for(int i=0;i<the_bufsize;i++) 2183 { 2184 *(((short*)output_buffer)+2*i)=*(((short*)input_buffer)+i); 2185 *(((short*)output_buffer)+2*i+1)=*(((short*)input_buffer)+i); 2186 } 2187 fwrite (output_buffer, sizeof(short)*2, the_bufsize, stdout); 2188 TRY_YIELD; 2189 } 2190 } 2191 2192 if(!strcmp(argv[1],"squelch_and_smeter_cc")) 2193 { 2194 if(!sendbufsize(initialize_buffers())) return -2; 2195 float power; 2196 float squelch_level; 2197 int decimation; 2198 int report_every_nth; 2199 int fd; 2200 char power_value_buf[101]; 2201 int power_value_buf_size; 2202 int report_cntr=0; 2203 complexf* zerobuf = (complexf*)malloc(sizeof(complexf)*the_bufsize); 2204 for(int i=0;i<the_bufsize*2;i++) *(((float*)zerobuf)+i)=0; 2205 if(fd=init_fifo(argc,argv)) while(!read_fifo_ctl(fd,"%g\n",&squelch_level)) usleep(10000); 2206 else return badsyntax("need required parameter (--fifo <fifo>)"); 2207 errhead(); fprintf(stderr, "initial squelch level is %g\n", squelch_level); 2208 if((argc<=5)||((argc>5)&&(strcmp(argv[4],"--outfifo")))) return badsyntax("need required parameter (--outfifo <fifo>)"); 2209 int fd2 = open(argv[5], O_WRONLY); 2210 if(fd2==-1) return badsyntax("error while opening --outfifo"); 2211 int flags = fcntl(fd2, F_GETFL, 0); 2212 fcntl(fd2, F_SETFL, flags | O_NONBLOCK); 2213 if(argc<=6) return badsyntax("need required parameter (use_every_nth)"); 2214 sscanf(argv[6],"%d",&decimation); 2215 if(decimation<=0) return badsyntax("use_every_nth <= 0 is invalid"); 2216 if(argc<=7) return badsyntax("need required parameter (report_every_nth)"); 2217 sscanf(argv[7],"%d",&report_every_nth); 2218 if(report_every_nth<=0) return badsyntax("report_every_nth <= 0 is invalid"); 2219 for(;;) 2220 { 2221 FEOF_CHECK; 2222 FREAD_C; //read input data 2223 power = get_power_c((complexf*)input_buffer, the_bufsize, decimation); 2224 if(report_cntr++>report_every_nth) 2225 { 2226 report_cntr=0; 2227 power_value_buf_size=snprintf(power_value_buf,100,"%g\n",power); 2228 write(fd2,power_value_buf,power_value_buf_size*sizeof(char)); 2229 } 2230 if(squelch_level==0||power>=squelch_level) 2231 { 2232 //fprintf(stderr,"P"); 2233 fwrite(input_buffer, sizeof(complexf), the_bufsize, stdout); 2234 } 2235 else 2236 { 2237 //fprintf(stderr,"S"); 2238 fwrite(zerobuf, sizeof(complexf), the_bufsize, stdout); 2239 } 2240 if(read_fifo_ctl(fd,"%g\n",&squelch_level)) { errhead(); fprintf(stderr, "new squelch level is %g\n", squelch_level); } 2241 TRY_YIELD; 2242 } 2243 } 2244 2245 /* 2246 ______ _ _____ _____ _____ 2247 | ____| | | | __ \| __ \ / ____| 2248 | |__ __ _ ___| |_| | | | | | | | 2249 | __/ _` / __| __| | | | | | | | 2250 | | | (_| \__ \ |_| |__| | |__| | |____ 2251 |_| \__,_|___/\__|_____/|_____/ \_____| 2252 2253 */ 2254 2255 if( !strcmp(argv[1],"fastddc_fwd_cc") ) //<decimation> [transition_bw [window]] 2256 { 2257 2258 int decimation; 2259 if(argc<=2) return badsyntax("need required parameter (decimation)"); 2260 sscanf(argv[2],"%d",&decimation); 2261 2262 float transition_bw = 0.05; 2263 if(argc>3) sscanf(argv[3],"%g",&transition_bw); 2264 2265 window_t window = WINDOW_DEFAULT; 2266 if(argc>4) window=firdes_get_window_from_string(argv[4]); 2267 else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); } 2268 2269 fastddc_t ddc; 2270 if(fastddc_init(&ddc, transition_bw, decimation, 0)) { badsyntax("error in fastddc_init()"); return 1; } 2271 fastddc_print(&ddc,"fastddc_fwd_cc"); 2272 2273 if(!initialize_buffers()) return -2; 2274 sendbufsize(ddc.fft_size); 2275 2276 //make FFT plan 2277 complexf* input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); 2278 complexf* windowed = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); 2279 complexf* output = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); 2280 2281 for(int i=0;i<ddc.fft_size;i++) iof(input,i)=qof(input,i)=0; //null the input buffer 2282 2283 int benchmark = 1; 2284 if(benchmark) { errhead(); fprintf(stderr,"benchmarking FFT..."); } 2285 FFT_PLAN_T* plan=make_fft_c2c(ddc.fft_size, windowed, output, 1, benchmark); 2286 if(benchmark) fprintf(stderr," done\n"); 2287 2288 for(;;) 2289 { 2290 FEOF_CHECK; 2291 //overlapped FFT 2292 for(int i=0;i<ddc.overlap_length;i++) input[i]=input[i+ddc.input_size]; 2293 fread(input+ddc.overlap_length, sizeof(complexf), ddc.input_size, stdin); 2294 //apply_window_c(input,windowed,ddc.fft_size,window); 2295 memcpy(windowed, input, ddc.fft_size*sizeof(complexf)); //we can switch off windows; TODO: it is likely that we shouldn't apply a window to both the FFT and the filter. 2296 fft_execute(plan); 2297 fwrite(output, sizeof(complexf), ddc.fft_size, stdout); 2298 TRY_YIELD; 2299 } 2300 } 2301 2302 if( !strcmp(argv[1],"fastddc_inv_cc") ) //<shift_rate> <decimation> [transition_bw [window]] 2303 { 2304 float shift_rate; 2305 int plusarg=0; 2306 2307 int fd; 2308 if(fd=init_fifo(argc,argv)) 2309 { 2310 while(!read_fifo_ctl(fd,"%g\n",&shift_rate)) usleep(10000); 2311 plusarg=1; 2312 } 2313 else 2314 { 2315 if(argc<=2) return badsyntax("need required parameter (rate)"); 2316 sscanf(argv[2],"%g",&shift_rate); 2317 } 2318 2319 int decimation; 2320 if(argc<=3+plusarg) return badsyntax("need required parameter (decimation)"); 2321 sscanf(argv[3+plusarg],"%d",&decimation); 2322 //fprintf(stderr, "dec=%d %d\n", decimation); 2323 2324 float transition_bw = 0.05; 2325 if(argc>4+plusarg) sscanf(argv[4+plusarg],"%g",&transition_bw); 2326 2327 window_t window = WINDOW_DEFAULT; 2328 if(argc>5+plusarg) window=firdes_get_window_from_string(argv[5+plusarg]); 2329 else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); } 2330 2331 for(;;) 2332 { 2333 2334 fastddc_t ddc; 2335 if(fastddc_init(&ddc, transition_bw, decimation, shift_rate)) { badsyntax("error in fastddc_init()"); return 1; } 2336 fastddc_print(&ddc,"fastddc_inv_cc"); 2337 2338 if(!initialize_buffers()) return -2; 2339 sendbufsize(ddc.post_input_size/ddc.post_decimation); //TODO not exactly correct 2340 2341 //prepare making the filter and doing FFT on it 2342 complexf* taps=(complexf*)calloc(sizeof(complexf),ddc.fft_size); //initialize to zero 2343 complexf* taps_fft=(complexf*)malloc(sizeof(complexf)*ddc.fft_size); 2344 FFT_PLAN_T* plan_taps = make_fft_c2c(ddc.fft_size, taps, taps_fft, 1, 0); //forward, don't benchmark (we need this only once) 2345 2346 //make the filter 2347 float filter_half_bw = 0.5/decimation; 2348 errhead(); fprintf(stderr, "preparing a bandpass filter of [%g, %g] cutoff rates. Real transition bandwidth is: %g\n", (-shift_rate)-filter_half_bw, (-shift_rate)+filter_half_bw, 4.0/ddc.taps_length); 2349 firdes_bandpass_c(taps, ddc.taps_length, (-shift_rate)-filter_half_bw, (-shift_rate)+filter_half_bw, window); 2350 fft_execute(plan_taps); 2351 fft_swap_sides(taps_fft,ddc.fft_size); 2352 2353 //make FFT plan 2354 complexf* inv_input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_inv_size); 2355 complexf* inv_output = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_inv_size); 2356 errhead(); fprintf(stderr,"benchmarking FFT..."); 2357 FFT_PLAN_T* plan_inverse = make_fft_c2c(ddc.fft_inv_size, inv_input, inv_output, 0, 1); //inverse, do benchmark 2358 fprintf(stderr," done\n"); 2359 2360 //alloc. buffers 2361 complexf* input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); 2362 complexf* output = (complexf*)fft_malloc(sizeof(complexf)*ddc.post_input_size); 2363 2364 decimating_shift_addition_status_t shift_stat; 2365 bzero(&shift_stat, sizeof(shift_stat)); 2366 for(;;) 2367 { 2368 FEOF_CHECK; 2369 fread(input, sizeof(complexf), ddc.fft_size, stdin); 2370 shift_stat = fastddc_inv_cc(input, output, &ddc, plan_inverse, taps_fft, shift_stat); 2371 fwrite(output, sizeof(complexf), shift_stat.output_size, stdout); 2372 //fprintf(stderr, "ss os = %d\n", shift_stat.output_size); 2373 TRY_YIELD; 2374 if(read_fifo_ctl(fd,"%g\n",&shift_rate)) break; 2375 } 2376 2377 } 2378 } 2379 2380 if( !strcmp(argv[1], "_fft2octave") ) 2381 { 2382 int fft_size; 2383 if(argc<=2) return badsyntax("need required parameter (fft_size)"); 2384 sscanf(argv[2],"%d",&fft_size); 2385 2386 complexf* fft_input=(complexf*)malloc(sizeof(complexf)*fft_size); 2387 initialize_buffers(); 2388 if(!sendbufsize(fft_size)) return -2; 2389 2390 printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); 2391 for(;;) 2392 { 2393 FEOF_CHECK; 2394 fread(fft_input, sizeof(complexf), fft_size, stdin); 2395 printf("fftdata=["); 2396 //we have to swap the two parts of the array to get a valid spectrum 2397 for(int i=fft_size/2;i<fft_size;i++) printf("(%g)+(%g)*i ",iof(fft_input,i),qof(fft_input,i)); 2398 for(int i=0;i<fft_size/2;i++) printf("(%g)+(%g)*i ",iof(fft_input,i),qof(fft_input,i)); 2399 printf( 2400 "];\n" 2401 "y=abs(fftdata);\n" 2402 "refreshdata;\n" 2403 ); 2404 } 2405 } 2406 2407 /* 2408 _____ _ _ _ _ _ 2409 | __ \(_) (_) | | | | | 2410 | | | |_ __ _ _| |_ __ _| | _ __ ___ ___ __| | ___ ___ 2411 | | | | |/ _` | | __/ _` | | | '_ ` _ \ / _ \ / _` |/ _ \/ __| 2412 | |__| | | (_| | | || (_| | | | | | | | | (_) | (_| | __/\__ \ 2413 |_____/|_|\__, |_|\__\__,_|_| |_| |_| |_|\___/ \__,_|\___||___/ 2414 __/ | 2415 |___/ 2416 */ 2417 2418 if(!strcmp(argv[1],"psk31_varicode_decoder_u8_u8")) 2419 { 2420 unsigned long long status_shr = 0; 2421 unsigned char output; 2422 if(!sendbufsize(initialize_buffers())) return -2; 2423 unsigned char i=0; 2424 for(;;) 2425 { 2426 if((output=psk31_varicode_decoder_push(&status_shr, getchar()))) { putchar(output); fflush(stdout); } 2427 if(i++) continue; //do the following at every 256th execution of the loop body: 2428 FEOF_CHECK; 2429 TRY_YIELD; 2430 } 2431 } 2432 2433 if(!strcmp(argv[1],"invert_u8_u8")) 2434 { 2435 if(!sendbufsize(initialize_buffers())) return -2; 2436 unsigned char i=0; 2437 for(;;) 2438 { 2439 putchar(!getchar()); 2440 if(i++) continue; //do the following at every 256th execution of the loop body: 2441 FEOF_CHECK; 2442 TRY_YIELD; 2443 } 2444 } 2445 2446 if(!strcmp(argv[1],"rtty_line_decoder_u8_u8")) 2447 { 2448 static rtty_baudot_decoder_t status_baudot; //created on .bss -> initialized to 0 2449 unsigned char output; 2450 if(!sendbufsize(initialize_buffers())) return -2; 2451 unsigned char i=0; 2452 for(;;) 2453 { 2454 if((output=rtty_baudot_decoder_push(&status_baudot, getchar()))) { putchar(output); fflush(stdout); } 2455 if(i++) continue; //do the following at every 256th execution of the loop body: 2456 FEOF_CHECK; 2457 TRY_YIELD; 2458 } 2459 } 2460 2461 if(!strcmp(argv[1],"rtty_baudot2ascii_u8_u8")) 2462 { 2463 unsigned char fig_mode = 0; 2464 unsigned char output; 2465 if(!sendbufsize(initialize_buffers())) return -2; 2466 unsigned char i=0; 2467 for(;;) 2468 { 2469 if((output=rtty_baudot_decoder_lookup(&fig_mode, getchar()))) { putchar(output); fflush(stdout); } 2470 if(i++) continue; //do the following at every 256th execution of the loop body: 2471 FEOF_CHECK; 2472 TRY_YIELD; 2473 } 2474 } 2475 2476 if(!strcmp(argv[1],"binary_slicer_f_u8")) 2477 { 2478 if(!sendbufsize(initialize_buffers())) return -2; 2479 for(;;) 2480 { 2481 FEOF_CHECK; 2482 if(!FREAD_R) break; 2483 binary_slicer_f_u8(input_buffer, (unsigned char*)output_buffer, the_bufsize); 2484 FWRITE_U8; 2485 TRY_YIELD; 2486 } 2487 return 0; 2488 } 2489 2490 if(!strcmp(argv[1],"serial_line_decoder_f_u8")) //<samples_per_bits> [databits [stopbits]] 2491 { 2492 bigbufs=1; 2493 2494 serial_line_t serial; 2495 2496 if(argc<=2) return badsyntax("need required parameter (samples_per_bits)"); 2497 sscanf(argv[2],"%f",&serial.samples_per_bits); 2498 if(serial.samples_per_bits<1) return badsyntax("samples_per_bits should be at least 1."); 2499 if(serial.samples_per_bits<5) fprintf(stderr, "%s: warning: this algorithm does not work well if samples_per_bits is too low. It should be at least 5.\n", argv[1]); 2500 2501 serial.databits=8; 2502 if(argc>3) sscanf(argv[3],"%d",&serial.databits); 2503 if(serial.databits>8 || serial.databits<1) return badsyntax("databits should be between 1 and 8."); 2504 2505 serial.stopbits=1; 2506 if(argc>4) sscanf(argv[4],"%f",&serial.stopbits); 2507 if(serial.stopbits<1) return badsyntax("stopbits should be equal or above 1."); 2508 2509 serial.bit_sampling_width_ratio = 0.4; 2510 serial.input_used=0; 2511 2512 if(!sendbufsize(initialize_buffers())) return -2; 2513 2514 for(;;) 2515 { 2516 FEOF_CHECK; 2517 if(serial.input_used) 2518 { 2519 memmove(input_buffer, input_buffer+serial.input_used, sizeof(float)*(the_bufsize-serial.input_used)); 2520 fread(input_buffer+(the_bufsize-serial.input_used), sizeof(float), serial.input_used, stdin); 2521 } 2522 else fread(input_buffer, sizeof(float), the_bufsize, stdin); //should happen only on the first run 2523 serial_line_decoder_f_u8(&serial,input_buffer, (unsigned char*)output_buffer, the_bufsize); 2524 //printf("now in | "); 2525 if(serial.input_used==0) { errhead(); fprintf(stderr, "error: serial_line_decoder_f_u8() got stuck.\n"); return -3; } 2526 //printf("now out %d | ", serial.output_size); 2527 fwrite(output_buffer, sizeof(unsigned char), serial.output_size, stdout); 2528 TRY_YIELD; 2529 } 2530 } 2531 2532 if(!strcmp(argv[1],"pll_cc")) 2533 { 2534 pll_t pll; 2535 2536 if(argc<=2) return badsyntax("need required parameter (pll_type)"); 2537 sscanf(argv[2],"%d",(int*)&pll.pll_type); 2538 if(pll.pll_type == PLL_P_CONTROLLER) 2539 { 2540 float alpha = 0.01; 2541 if(argc>3) sscanf(argv[3],"%f",&alpha); 2542 pll_cc_init_p_controller(&pll, alpha); 2543 } 2544 else if(pll.pll_type == PLL_PI_CONTROLLER) 2545 { 2546 float bandwidth = 0.01, ko = 10, kd=0.1, damping_factor = 0.707; 2547 if(argc>3) sscanf(argv[3],"%f",&bandwidth); 2548 if(argc>4) sscanf(argv[4],"%f",&damping_factor); 2549 if(argc>5) sscanf(argv[5],"%f",&ko); 2550 if(argc>6) sscanf(argv[6],"%f",&kd); 2551 pll_cc_init_pi_controller(&pll, bandwidth, ko, kd, damping_factor); 2552 errhead(); fprintf(stderr, "bw=%f damping=%f ko=%f kd=%f alpha=%f beta=%f\n", bandwidth, damping_factor, ko, kd, pll.alpha, pll.beta); 2553 // pll.filter_taps_a[0], pll.filter_taps_a[1], pll.filter_taps_a[2], pll.filter_taps_b[0], pll.filter_taps_b[1], pll.filter_taps_b[2]); 2554 } 2555 else return badsyntax("invalid pll_type. Valid values are:\n\t1: PLL_P_CONTROLLER\n\t2: PLL_PI_CONTROLLER"); 2556 2557 if(!sendbufsize(initialize_buffers())) return -2; 2558 2559 for(;;) 2560 { 2561 FEOF_CHECK; 2562 FREAD_C; 2563 //fprintf(stderr, "| i"); 2564 // pll_cc(&pll, (complexf*)input_buffer, output_buffer, NULL, the_bufsize); 2565 // fwrite(output_buffer, sizeof(float), the_bufsize, stdout); 2566 pll_cc(&pll, (complexf*)input_buffer, NULL, (complexf*)output_buffer, the_bufsize); 2567 fwrite(output_buffer, sizeof(complexf), the_bufsize, stdout); 2568 //fprintf(stderr, "| o"); 2569 TRY_YIELD; 2570 } 2571 } 2572 2573 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" 2574 { 2575 if(argc<=2) return badsyntax("need required parameter (algorithm)"); 2576 timing_recovery_algorithm_t algorithm = timing_recovery_get_algorithm_from_string(argv[2]); 2577 //if(algorithm == TIMING_RECOVERY_ALGORITHM_DEFAULT) 2578 // fprintf(stderr,"#timing_recovery_cc: algorithm = %s\n",timing_recovery_get_string_from_algorithm(algorithm)); 2579 if(argc<=3) return badsyntax("need required parameter (decimation factor)"); 2580 int decimation; 2581 sscanf(argv[3],"%d",&decimation); 2582 if(decimation<=4 || decimation&3) return badsyntax("decimation factor should be a positive integer divisible by 4"); 2583 2584 float loop_gain = 0.5; 2585 if(argc>4) sscanf(argv[4],"%f",&loop_gain); 2586 2587 float max_error = 2; 2588 if(argc>5) sscanf(argv[5],"%f",&max_error); 2589 2590 int add_q = !!(argc>=7 && !strcmp(argv[6], "--add_q")); 2591 2592 int debug_every_nth = -1; 2593 int output_error = 0; 2594 int output_indexes = 0; 2595 int octave_save = 0; 2596 char* octave_save_path = NULL; 2597 if(argc>=8+add_q && (!strcmp(argv[6+add_q], "--octave") || (octave_save = !strcmp(argv[6+add_q], "--octave_save")))) 2598 { 2599 debug_every_nth = atoi(argv[7+add_q]); 2600 if(debug_every_nth<0) return badsyntax("debug_every_nth should be >= 0"); 2601 } 2602 if(octave_save) 2603 { 2604 if(argc>=9+add_q) octave_save_path = argv[8+add_q]; 2605 else octave_save_path = "figs"; 2606 } 2607 if(debug_every_nth<0) { errhead(); fprintf(stderr, "--add_q mode on\n"); } 2608 2609 if(argc>=(7+add_q) && !strcmp(argv[6+add_q], "--output_error")) output_error = 1; 2610 float* timing_error = NULL; 2611 if(output_error) timing_error = (float*)malloc(sizeof(float)*the_bufsize); 2612 if(output_error) { errhead(); fprintf(stderr, "--output_error mode\n"); } 2613 2614 if(argc>=(7+add_q) && !strcmp(argv[6+add_q], "--output_indexes")) output_indexes = 1; 2615 unsigned* sampled_indexes = NULL; 2616 if(output_indexes) sampled_indexes = (unsigned*)malloc(sizeof(float)*the_bufsize); 2617 if(output_indexes) { errhead(); fprintf(stderr, "--output_indexes mode\n"); } 2618 2619 if(!initialize_buffers()) return -2; 2620 sendbufsize(the_bufsize/decimation); 2621 2622 timing_recovery_state_t state = timing_recovery_init(algorithm, decimation, add_q, loop_gain, max_error, debug_every_nth, octave_save_path); 2623 2624 FREAD_C; 2625 unsigned buffer_start_counter = 0; 2626 for(;;) 2627 { 2628 FEOF_CHECK; 2629 timing_recovery_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, timing_error, (int*)sampled_indexes, &state); 2630 //fprintf(stderr, "trcc is=%d, os=%d, ip=%d\n",the_bufsize, state.output_size, state.input_processed); 2631 if(timing_error) fwrite(timing_error, sizeof(float), state.output_size, stdout); 2632 else if(sampled_indexes) 2633 { 2634 for(int i=0;i<state.output_size;i++) sampled_indexes[i]+=buffer_start_counter; 2635 fwrite(sampled_indexes, sizeof(unsigned), state.output_size, stdout); 2636 } 2637 else fwrite(output_buffer, sizeof(complexf), state.output_size, stdout); 2638 TRY_YIELD; 2639 //fprintf(stderr, "state.input_processed = %d\n", state.input_processed); 2640 buffer_start_counter+=state.input_processed; 2641 memmove((complexf*)input_buffer,((complexf*)input_buffer)+state.input_processed,(the_bufsize-state.input_processed)*sizeof(complexf)); //memmove lets the source and destination overlap 2642 fread(((complexf*)input_buffer)+(the_bufsize-state.input_processed), sizeof(complexf), state.input_processed, stdin); 2643 //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)); 2644 } 2645 } 2646 2647 if(!strcmp(argv[1],"octave_complex_c")) 2648 { 2649 if(argc<=2) return badsyntax("need required parameter (samples_to_plot)"); 2650 int samples_to_plot = 0; 2651 sscanf(argv[2], "%d", &samples_to_plot); 2652 if(samples_to_plot<=0) return badsyntax("Number of samples to plot should be > 0"); 2653 if(argc<=3) return badsyntax("need required parameter (out_of_n_samples)"); 2654 int out_of_n_samples = 0; 2655 sscanf(argv[3], "%d", &out_of_n_samples); 2656 if(out_of_n_samples<samples_to_plot) return badsyntax("out_of_n_samples should be < samples_to_plot"); 2657 int mode2d = 0; 2658 if(argc>4) mode2d = !strcmp(argv[4], "--2d"); 2659 complexf* read_buf = (complexf*)malloc(sizeof(complexf)*the_bufsize); 2660 2661 if(!sendbufsize(initialize_buffers())) return -2; 2662 for(;;) 2663 { 2664 fread(read_buf, sizeof(complexf), samples_to_plot, stdin); 2665 printf("N = %d;\nisig = [", samples_to_plot); 2666 for(int i=0;i<samples_to_plot;i++) printf("%f ", iof(read_buf, i)); 2667 printf("];\nqsig = ["); 2668 for(int i=0;i<samples_to_plot;i++) printf("%f ", qof(read_buf, i)); 2669 printf("];\nzsig = [0:N-1];\n"); 2670 if(mode2d) printf("subplot(2,1,1);\nplot(zsig,isig);\nsubplot(2,1,2);\nplot(zsig,qsig);\n"); 2671 else printf("plot3(isig,zsig,qsig);\n"); 2672 //printf("xlim([-1 1]);\nzlim([-1 1]);\n"); 2673 fflush(stdout); 2674 //if(fseek(stdin, (out_of_n_samples - samples_to_plot)*sizeof(complexf), SEEK_CUR)<0) { perror("fseek error"); return -3; } //this cannot be used on stdin 2675 for(int seek_remain=out_of_n_samples-samples_to_plot;seek_remain>0;seek_remain-=samples_to_plot) 2676 { 2677 fread(read_buf, sizeof(complexf), MIN_M(samples_to_plot,seek_remain), stdin); 2678 } 2679 FEOF_CHECK; 2680 TRY_YIELD; 2681 } 2682 } 2683 2684 if(!strcmp(argv[1],"psk_modulator_u8_c")) //<n_psk> 2685 { 2686 int n_psk; 2687 if(argc<=2) return badsyntax("need required parameter (n_psk)"); 2688 sscanf(argv[2],"%d",&n_psk); 2689 if(n_psk<=0 || n_psk>256) return badsyntax("n_psk should be between 1 and 256"); 2690 2691 if(!initialize_buffers()) return -2; 2692 sendbufsize(the_bufsize); 2693 2694 for(;;) 2695 { 2696 FEOF_CHECK; 2697 fread((unsigned char*)input_buffer, sizeof(unsigned char), the_bufsize, stdin); 2698 psk_modulator_u8_c((unsigned char*)input_buffer, (complexf*)output_buffer, the_bufsize, n_psk); 2699 FWRITE_C; 2700 TRY_YIELD; 2701 } 2702 } 2703 2704 if(!strcmp(argv[1],"duplicate_samples_ntimes_u8_u8")) //<sample_size_bytes> <ntimes> 2705 { 2706 int sample_size_bytes = 0, ntimes = 0; 2707 if(argc<=2) return badsyntax("need required parameter (sample_size_bytes)"); 2708 sscanf(argv[2],"%d",&sample_size_bytes); 2709 if(sample_size_bytes<=0) return badsyntax("sample_size_bytes should be >0"); 2710 if(argc<=3) return badsyntax("need required parameter (ntimes)"); 2711 sscanf(argv[3],"%d",&ntimes); 2712 if(ntimes<=0) return badsyntax("ntimes should be >0"); 2713 if(!initialize_buffers()) return -2; 2714 sendbufsize(the_bufsize*ntimes); 2715 unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*sample_size_bytes); 2716 unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*sample_size_bytes*ntimes); 2717 for(;;) 2718 { 2719 FEOF_CHECK; 2720 fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize*sample_size_bytes, stdin); 2721 duplicate_samples_ntimes_u8_u8(local_input_buffer, local_output_buffer, the_bufsize*sample_size_bytes, sample_size_bytes, ntimes); 2722 fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize*sample_size_bytes*ntimes, stdout); 2723 TRY_YIELD; 2724 } 2725 } 2726 2727 if(!strcmp(argv[1],"psk31_interpolate_sine_cc")) //<interpolation> 2728 { 2729 int interpolation; 2730 if(argc<=2) return badsyntax("need required parameter (interpolation)"); 2731 sscanf(argv[2],"%d",&interpolation); 2732 if(interpolation<=0) return badsyntax("interpolation should be >0"); 2733 if(!initialize_buffers()) return -2; 2734 sendbufsize(the_bufsize*interpolation); 2735 complexf* local_output_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize*interpolation); 2736 complexf last_input; 2737 iof(&last_input,0) = 0; 2738 qof(&last_input,0) = 0; 2739 for(;;) 2740 { 2741 FEOF_CHECK; 2742 FREAD_C; 2743 last_input = psk31_interpolate_sine_cc((complexf*)input_buffer, local_output_buffer, the_bufsize, interpolation, last_input); 2744 fwrite((void*)local_output_buffer, sizeof(complexf), the_bufsize*interpolation, stdout); 2745 TRY_YIELD; 2746 } 2747 } 2748 2749 if(!strcmp(argv[1],"pack_bits_1to8_u8_u8")) 2750 { 2751 if(!initialize_buffers()) return -2; 2752 sendbufsize(the_bufsize*8); 2753 unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); 2754 unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*8); 2755 for(;;) 2756 { 2757 FEOF_CHECK; 2758 fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); 2759 pack_bits_1to8_u8_u8(local_input_buffer, local_output_buffer, the_bufsize); 2760 fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize*8, stdout); 2761 TRY_YIELD; 2762 } 2763 } 2764 2765 if(!strcmp(argv[1],"pack_bits_8to1_u8_u8")) 2766 { 2767 if(!initialize_buffers()) return -2; 2768 sendbufsize(1); 2769 char local_input_buffer[8]; 2770 for(;;) 2771 { 2772 FEOF_CHECK; 2773 fread((void*)local_input_buffer, sizeof(unsigned char), 8, stdin); 2774 unsigned char c = pack_bits_8to1_u8_u8(local_input_buffer); 2775 fwrite(&c, sizeof(unsigned char), 1, stdout); 2776 TRY_YIELD; 2777 } 2778 } 2779 2780 if(!strcmp(argv[1],"psk31_varicode_encoder_u8_u8")) 2781 { 2782 if(!initialize_buffers()) return -2; 2783 sendbufsize(the_bufsize*8); 2784 int output_max_size=the_bufsize*30; 2785 int output_size; 2786 int input_processed; 2787 unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); 2788 unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*output_max_size); 2789 fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); 2790 for(;;) 2791 { 2792 psk31_varicode_encoder_u8_u8(local_input_buffer, local_output_buffer, the_bufsize, output_max_size, &input_processed, &output_size); 2793 //fprintf(stderr, "os = %d\n", output_size); 2794 fwrite((void*)local_output_buffer, sizeof(unsigned char), output_size, stdout); 2795 FEOF_CHECK; 2796 memmove(local_input_buffer, local_input_buffer+input_processed, the_bufsize-input_processed); 2797 fread(input_buffer+the_bufsize-input_processed, sizeof(unsigned char), input_processed, stdin); 2798 TRY_YIELD; 2799 } 2800 } 2801 2802 if(!strcmp(argv[1],"dump_u8")) 2803 { 2804 if(!initialize_buffers()) return -2; 2805 sendbufsize(the_bufsize*3); 2806 unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); 2807 for(;;) 2808 { 2809 FEOF_CHECK; 2810 fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); 2811 for(int i=0;i<the_bufsize;i++) printf("%02x ", local_input_buffer[i]); 2812 TRY_YIELD; 2813 } 2814 } 2815 2816 int differential_codec_encode = 0; 2817 if( (differential_codec_encode = !strcmp(argv[1],"differential_encoder_u8_u8")) || (!strcmp(argv[1],"differential_decoder_u8_u8")) ) 2818 { 2819 if(!initialize_buffers()) return -2; 2820 sendbufsize(the_bufsize); 2821 unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); 2822 unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); 2823 unsigned char state = 0; 2824 for(;;) 2825 { 2826 FEOF_CHECK; 2827 fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); 2828 state = differential_codec(local_input_buffer, local_output_buffer, the_bufsize, differential_codec_encode, state); 2829 fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize, stdout); 2830 TRY_YIELD; 2831 } 2832 } 2833 2834 if(!strcmp(argv[1],"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>] 2835 { 2836 float loop_bandwidth; 2837 if(argc<=2) return badsyntax("need required parameter (loop_bandwidth)"); 2838 sscanf(argv[2],"%f",&loop_bandwidth); 2839 2840 float damping_factor; 2841 if(argc<=3) return badsyntax("need required parameter (damping_factor)"); 2842 sscanf(argv[3],"%f",&damping_factor); 2843 2844 int decision_directed = !!(argc>4 && (!strcmp(argv[4], "--dd") || !strcmp(argv[5], "--decision_directed"))); 2845 if(decision_directed) { errhead(); fprintf(stderr, "decision directed mode\n"); } 2846 2847 int output_error = !!(argc>4+decision_directed && (!strcmp(argv[4+decision_directed], "--output_error"))); 2848 int output_dphase = !output_error & !!(argc>4+decision_directed && (!strcmp(argv[4+decision_directed], "--output_dphase"))); 2849 int output_nco = !output_dphase & !!(argc>4+decision_directed && (!strcmp(argv[4+decision_directed], "--output_nco"))); 2850 int output_combined = !output_nco & !!(argc>4+decision_directed && (!strcmp(argv[4+decision_directed], "--output_combined"))); 2851 2852 2853 bpsk_costas_loop_state_t state; 2854 init_bpsk_costas_loop_cc(&state, decision_directed, damping_factor, loop_bandwidth); 2855 errhead(); fprintf(stderr, "alpha = %f, beta = %f\n", state.alpha, state.beta); 2856 2857 if(!initialize_buffers()) return -2; 2858 sendbufsize(the_bufsize); 2859 2860 float* buffer_output_error = (!(output_combined || output_error)) ? NULL : (float*)malloc(sizeof(float)*the_bufsize); 2861 float* buffer_output_dphase = (!(output_combined || output_dphase)) ? NULL : (float*)malloc(sizeof(float)*the_bufsize); 2862 complexf* buffer_output_nco = (!(output_combined || output_nco)) ? NULL : (complexf*)malloc(sizeof(complexf)*the_bufsize); 2863 2864 FILE* file_output_error = NULL; 2865 FILE* file_output_dphase = NULL; 2866 FILE* file_output_nco = NULL; 2867 if(output_combined) 2868 { 2869 if(!(argc>4+decision_directed+3)) { return badsyntax("need required parameters after --output_combined: <error_file> <dphase_file> <nco_file>"); } 2870 file_output_error = fopen(argv[4+decision_directed+1], "w"); 2871 file_output_dphase = fopen(argv[4+decision_directed+2], "w"); 2872 file_output_nco = fopen(argv[4+decision_directed+3], "w"); 2873 } 2874 2875 for(;;) 2876 { 2877 FEOF_CHECK; 2878 FREAD_C; 2879 bpsk_costas_loop_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, 2880 buffer_output_error, buffer_output_dphase, buffer_output_nco, 2881 &state); 2882 if(output_error) fwrite(buffer_output_error, sizeof(float), the_bufsize, stdout); 2883 else if(output_dphase) fwrite(buffer_output_dphase, sizeof(float), the_bufsize, stdout); 2884 else if(output_nco) fwrite(buffer_output_nco, sizeof(complexf), the_bufsize, stdout); 2885 else 2886 { 2887 if(output_combined) 2888 { 2889 fwrite(buffer_output_error, sizeof(float), the_bufsize, file_output_error); 2890 fwrite(buffer_output_dphase, sizeof(float), the_bufsize, file_output_dphase); 2891 fwrite(buffer_output_nco, sizeof(complexf), the_bufsize, file_output_nco); 2892 } 2893 FWRITE_C; 2894 } 2895 TRY_YIELD; 2896 } 2897 fclose(file_output_error); 2898 fclose(file_output_dphase); 2899 fclose(file_output_nco); 2900 } 2901 2902 if(!strcmp(argv[1],"simple_agc_cc")) //<rate> [reference [max_gain]] 2903 { 2904 float rate; 2905 if(argc<=2) return badsyntax("need required parameter (rate)"); 2906 sscanf(argv[2],"%f",&rate); 2907 if(rate<=0) return badsyntax("rate should be > 0"); 2908 2909 float reference = 1.; 2910 if(argc>3) sscanf(argv[3],"%f",&reference); 2911 if(reference<=0) return badsyntax("reference should be > 0"); 2912 2913 float max_gain = 65535.; 2914 if(argc>4) sscanf(argv[4],"%f",&max_gain); 2915 if(max_gain<=0) return badsyntax("max_gain should be > 0"); 2916 2917 float current_gain = 1.; 2918 2919 if(!initialize_buffers()) return -2; 2920 sendbufsize(the_bufsize); 2921 2922 for(;;) 2923 { 2924 FEOF_CHECK; 2925 FREAD_C; 2926 simple_agc_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, reference, max_gain, ¤t_gain); 2927 FWRITE_C; 2928 TRY_YIELD; 2929 } 2930 } 2931 2932 if(!strcmp(argv[1],"firdes_peak_c")) //<rate> <length> [window [--octave]] 2933 { 2934 //Process the params 2935 if(argc<=3) return badsyntax("need required parameters (rate, length)"); 2936 2937 float rate; 2938 sscanf(argv[2],"%g",&rate); 2939 int length; 2940 sscanf(argv[3],"%d",&length); 2941 if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd"); 2942 2943 window_t window = WINDOW_DEFAULT; 2944 if(argc>=5) 2945 { 2946 window=firdes_get_window_from_string(argv[4]); 2947 } 2948 else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); } 2949 2950 int octave=(argc>=6 && !strcmp("--octave",argv[5])); 2951 2952 complexf* taps=(complexf*)malloc(sizeof(complexf)*length); 2953 2954 //Make the filter 2955 firdes_add_peak_c(taps, length, rate, window, 0, 1); 2956 2957 //Do the output 2958 if(octave) printf("taps=["); 2959 for(int i=0;i<length;i++) printf("(%g)+(%g)*i ",iof(taps,i),qof(taps,i)); 2960 int fft_length=1024; 2961 while(fft_length<length) fft_length*=2; 2962 //if(octave) printf("];\n"); 2963 if(octave) printf( 2964 "];figure(\"Position\",[0 0 1000 1000]);fser=fft([taps,zeros(1,%d)]);ampl=abs(fser).^2;halfindex=floor(1+size(ampl)(2)/2);\n" 2965 "amplrev=[ampl(halfindex:end),ampl(1:halfindex)];\n" //we have to swap the output of FFT 2966 "subplot(2,1,1);plot(amplrev);\n" 2967 "subplot(2,1,2);plot(arg(fser));\n",fft_length-length); 2968 2969 //Wait forever, so that octave won't close just after popping up the window. 2970 //You can close it with ^C. 2971 if(octave) { fflush(stdout); getchar(); } 2972 return 0; 2973 } 2974 2975 if(!strcmp(argv[1],"peaks_fir_cc")) //<taps_length> <peak_rate × N> 2976 { 2977 //rule of thumb: bw = 2/taps_length, which does not equal to transition_bw 2978 2979 if(argc<=2) return badsyntax("need required parameter (taps_length)"); 2980 int taps_length; 2981 sscanf(argv[2],"%d",&taps_length); 2982 2983 int num_peaks = argc-3; 2984 float* peak_rate = (float*)malloc(sizeof(float)*num_peaks); 2985 for(int i=0;i<num_peaks;i++) 2986 sscanf(argv[3+i], "%f", peak_rate+i); 2987 if(num_peaks<=0) return badsyntax("need required parameter (peak_rate) once or multiple times"); 2988 //for(int i=0;i<num_peaks;i++) fprintf(stderr, "%f\n", peak_rate[i]); 2989 fflush(stderr); 2990 2991 window_t window = WINDOW_DEFAULT; 2992 2993 if(!initialize_buffers()) return -2; 2994 sendbufsize(the_bufsize); 2995 if(the_bufsize - taps_length <= 0 ) return badsyntax("taps_length is below buffer size, decrease taps_length"); 2996 2997 complexf* taps = (complexf*)calloc(sizeof(complexf),taps_length); 2998 for(int i=0; i<num_peaks; i++) 2999 { 3000 //fprintf(stderr, "nr = %d\n", i==num_peaks-1); 3001 firdes_add_peak_c(taps, taps_length, peak_rate[i], window, 1, i==num_peaks-1); 3002 } 3003 3004 int output_size=0; 3005 FREAD_C; 3006 for(;;) 3007 { 3008 FEOF_CHECK; 3009 output_size = apply_fir_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, taps, taps_length); 3010 fwrite(output_buffer, sizeof(complexf), output_size, stdout); 3011 //fprintf(stderr, "os = %d, is = %d\n", output_size, the_bufsize); 3012 TRY_YIELD; 3013 memmove((complexf*)input_buffer,((complexf*)input_buffer)+output_size,(the_bufsize-output_size)*sizeof(complexf)); 3014 fread(((complexf*)input_buffer)+(the_bufsize-output_size), sizeof(complexf), output_size, stdin); 3015 } 3016 } 3017 3018 if(!strcmp(argv[1], "repeat_u8")) 3019 { 3020 if(argc<=2) return badsyntax("no data to repeat"); 3021 unsigned char* repeat_buffer = (unsigned char*)malloc(sizeof(unsigned char)*(argc-2)); 3022 if(!initialize_buffers()) return -2; 3023 sendbufsize(the_bufsize); //this is really (c-2) but this is a very fast source block so it makes no sense to send out a small number here 3024 for(int i=0;i<argc-2;i++) 3025 { 3026 FEOF_CHECK; 3027 int current_val; 3028 sscanf(argv[i+2], "%d", ¤t_val); 3029 repeat_buffer[i]=current_val; 3030 TRY_YIELD; 3031 } 3032 for(;;) fwrite(repeat_buffer, sizeof(unsigned char), argc-2, stdout); 3033 } 3034 3035 if(!strcmp(argv[1], "awgn_cc")) 3036 { 3037 FILE* urandom = init_get_random_samples_f(); 3038 if(argc<=2) return badsyntax("required parameter <snr_db> is missing."); 3039 float snr_db = 0; 3040 sscanf(argv[2],"%f",&snr_db); 3041 FILE* awgnfile = NULL; 3042 if(argc>=5 && !strcmp(argv[3],"--awgnfile")) 3043 { 3044 awgnfile=fopen(argv[4], "r"); 3045 if(!awgnfile) return badsyntax("failed to open the --awgnfile"); 3046 } 3047 int parnumadd=2*(!!awgnfile); 3048 int snrshow = 0; 3049 if(argc>=4+parnumadd && !strcmp(argv[3+parnumadd],"--snrshow")) snrshow = 1; 3050 float signal_amplitude_per_noise = pow(10,snr_db/20); 3051 float a_signal=signal_amplitude_per_noise/(signal_amplitude_per_noise+1.0); 3052 float a_noise=1.0/(signal_amplitude_per_noise+1.0); 3053 errhead(); fprintf(stderr, "a_signal = %f, a_noise = %f\n", a_signal, a_noise); 3054 if(!initialize_buffers()) return -2; 3055 sendbufsize(the_bufsize); 3056 complexf* awgn_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize); 3057 for(;;) 3058 { 3059 FEOF_CHECK; 3060 FREAD_C; 3061 //get_awgn_samples_f((float*)awgn_buffer, the_bufsize*2, urandom); 3062 if(!awgnfile) get_random_gaussian_samples_c(awgn_buffer, the_bufsize, urandom); 3063 else 3064 { 3065 for(;;) 3066 { 3067 int items_read=fread(awgn_buffer, sizeof(complexf), the_bufsize, awgnfile); 3068 if(items_read<the_bufsize) rewind(awgnfile); 3069 else break; 3070 } 3071 } 3072 /*if(snrshow) 3073 { 3074 float power_signal = total_logpower_cf((complexf*)input_buffer, the_bufsize); 3075 float power_noise = total_logpower_cf(awgn_buffer, the_bufsize); 3076 fprintf(stderr, "csdr awgn_cc: at the beginning, power_signal = %f dB, power_noise = %f dB\n", power_signal, power_noise); 3077 }*/ 3078 gain_ff(input_buffer, input_buffer, the_bufsize*2, a_signal); 3079 gain_ff((float*)awgn_buffer, (float*)awgn_buffer, the_bufsize*2, a_noise*0.707); 3080 if(snrshow) 3081 { 3082 float power_signal = total_logpower_cf((complexf*)input_buffer, the_bufsize); 3083 float power_noise = total_logpower_cf(awgn_buffer, the_bufsize); 3084 //fprintf(stderr, "csdr awgn_cc: after gain_ff, power_signal = %f dB, power_noise = %f dB\n", power_signal, power_noise); 3085 errhead(); fprintf(stderr, "SNR = %f dB\n", power_signal - power_noise); 3086 } 3087 add_ff(input_buffer, (float*)awgn_buffer, (float*)output_buffer, the_bufsize*2); 3088 FWRITE_C; 3089 TRY_YIELD; 3090 } 3091 } 3092 3093 if(!strcmp(argv[1], "uniform_noise_f")) 3094 { 3095 FILE* urandom = init_get_random_samples_f(); 3096 if(!initialize_buffers()) return -2; 3097 sendbufsize(the_bufsize); 3098 for(;;) 3099 { 3100 FEOF_CHECK; 3101 get_random_samples_f(output_buffer, the_bufsize, urandom); 3102 FWRITE_R; 3103 TRY_YIELD; 3104 } 3105 } 3106 3107 if(!strcmp(argv[1], "gaussian_noise_c")) 3108 { 3109 FILE* urandom = init_get_random_samples_f(); 3110 if(!initialize_buffers()) return -2; 3111 sendbufsize(the_bufsize); 3112 for(;;) 3113 { 3114 FEOF_CHECK; 3115 get_random_gaussian_samples_c((complexf*)output_buffer, the_bufsize, urandom); 3116 FWRITE_C; 3117 TRY_YIELD; 3118 } 3119 } 3120 3121 if(!strcmp(argv[1], "normalized_timing_variance_u32_f")) //<samples_per_symbol> <initial_sample_offset> [--debug] 3122 { 3123 int samples_per_symbol = 0; 3124 if(argc<=2) return badsyntax("required parameter <samples_per_symbol> is missing."); 3125 sscanf(argv[2],"%d",&samples_per_symbol); 3126 3127 int initial_sample_offset = 0; 3128 if(argc<=3) return badsyntax("required parameter <initial_sample_offset> is missing."); 3129 sscanf(argv[3],"%d",&initial_sample_offset); 3130 3131 int debug_print = 0; 3132 if(argc>4 && !strcmp(argv[4],"--debug")) debug_print = 1; 3133 3134 if(!initialize_buffers()) return -2; 3135 sendbufsize(the_bufsize); 3136 float* temp_buffer = (float*)malloc(sizeof(float)*the_bufsize); 3137 for(;;) 3138 { 3139 FEOF_CHECK; 3140 FREAD_R; //doesn't count, reads 4 bytes per sample anyway 3141 float nv = normalized_timing_variance_u32_f((unsigned*)input_buffer, temp_buffer, the_bufsize, samples_per_symbol, initial_sample_offset, debug_print); 3142 fwrite(&nv, sizeof(float), 1, stdout); 3143 errhead(); fprintf(stderr, "normalized variance = %f\n", nv); 3144 TRY_YIELD; 3145 } 3146 } 3147 3148 if(!strcmp(argv[1], "add_n_zero_samples_at_beginning_f")) //<n_zero_samples> 3149 { 3150 int n_zero_samples = 0; 3151 if(argc<=2) return badsyntax("required parameter <n_zero_samples> is missing."); 3152 sscanf(argv[2],"%d",&n_zero_samples); 3153 if(!sendbufsize(initialize_buffers())) return -2; 3154 float* zeros=(float*)calloc(sizeof(float),n_zero_samples); 3155 fwrite(zeros, sizeof(float), n_zero_samples, stdout); 3156 clone_(the_bufsize); 3157 } 3158 3159 int pulse_shaping_filter_which = 0; 3160 if( 3161 (!strcmp(argv[1], "firdes_pulse_shaping_filter_f") && (pulse_shaping_filter_which = 1)) || 3162 (!strcmp(argv[1], "pulse_shaping_filter_cc") && (pulse_shaping_filter_which = 2)) 3163 ) //(RRC <samples_per_symbol> <num_taps> <beta> | COSINE <samples_per_symbol>) 3164 { 3165 if(argc<=2) return badsyntax("required parameter <pulse_shaping_filter_type> is missing."); 3166 matched_filter_type_t type = matched_filter_get_type_from_string(argv[2]); 3167 3168 int samples_per_symbol = 0; 3169 if(argc<=3) return badsyntax("required parameter <samples_per_symbol> is missing."); 3170 sscanf(argv[3],"%d",&samples_per_symbol); 3171 3172 int num_taps = 0; 3173 if(type!=MATCHED_FILTER_COSINE) 3174 { 3175 if(argc<=4) return badsyntax("required parameter <num_taps> is missing."); 3176 sscanf(argv[4],"%d",&num_taps); 3177 } 3178 else num_taps = (2*samples_per_symbol)+1; 3179 3180 float beta = 0; 3181 if(type==MATCHED_FILTER_RRC) 3182 { 3183 if(argc<=5) return badsyntax("required parameter <beta> is missing."); 3184 sscanf(argv[5],"%f",&beta); 3185 } 3186 3187 float* taps = (float*)malloc(sizeof(float)*num_taps); 3188 switch(type) 3189 { 3190 case MATCHED_FILTER_RRC: 3191 firdes_rrc_f(taps, num_taps, samples_per_symbol, beta); 3192 break; 3193 case MATCHED_FILTER_COSINE: 3194 firdes_cosine_f(taps, num_taps, samples_per_symbol); 3195 break; 3196 } 3197 //fprintf(stderr, "beta = %f, num_taps = %d, samples_per_symbol = %d\n", beta, num_taps, samples_per_symbol); 3198 3199 if(!sendbufsize(initialize_buffers())) return -2; 3200 3201 if(pulse_shaping_filter_which==1) 3202 { 3203 for(int i=0;i<num_taps;i++) printf("%f ", taps[i]); 3204 return 0; 3205 } 3206 3207 int output_size=0; 3208 FREAD_C; 3209 for(;;) 3210 { 3211 FEOF_CHECK; 3212 output_size = apply_real_fir_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, taps, num_taps); 3213 fwrite(output_buffer, sizeof(complexf), output_size, stdout); 3214 //fprintf(stderr, "os = %d, is = %d, num_taps = %d\n", output_size, the_bufsize, num_taps); 3215 TRY_YIELD; 3216 memmove((complexf*)input_buffer,((complexf*)input_buffer)+output_size,(the_bufsize-output_size)*sizeof(complexf)); 3217 fread(((complexf*)input_buffer)+(the_bufsize-output_size), sizeof(complexf), output_size, stdin); 3218 } 3219 } 3220 3221 if(!strcmp(argv[1], "generic_slicer_f_u8")) //<n_symbols> 3222 { 3223 int n_symbols = 0; 3224 if(argc<=2) return badsyntax("required parameter <n_symbols> is missing."); 3225 sscanf(argv[2],"%d",&n_symbols); 3226 if(!sendbufsize(initialize_buffers())) return -2; 3227 for(;;) 3228 { 3229 FEOF_CHECK; 3230 if(!FREAD_R) break; 3231 generic_slicer_f_u8(input_buffer, (unsigned char*)output_buffer, the_bufsize, n_symbols); 3232 FWRITE_U8; 3233 TRY_YIELD; 3234 } 3235 return 0; 3236 } 3237 3238 if(!strcmp(argv[1], "plain_interpolate_cc")) //<interpolation> 3239 { 3240 int interpolation = 0; 3241 if(argc<=2) return badsyntax("required parameter <interpolation> is missing."); 3242 sscanf(argv[2],"%d",&interpolation); 3243 if(!sendbufsize(interpolation*initialize_buffers())) return -2; 3244 complexf* plainint_output_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize*interpolation); 3245 for(;;) 3246 { 3247 FEOF_CHECK; 3248 FREAD_C; 3249 plain_interpolate_cc((complexf*)input_buffer, plainint_output_buffer, the_bufsize, interpolation); 3250 fwrite(plainint_output_buffer, sizeof(float)*2, the_bufsize*interpolation, stdout); 3251 TRY_YIELD; 3252 } 3253 return 0; 3254 } 3255 3256 if(!strcmp(argv[1], "dbpsk_decoder_c_u8")) 3257 { 3258 if(!sendbufsize(initialize_buffers())) return -2; 3259 unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); 3260 for(;;) 3261 { 3262 FEOF_CHECK; 3263 FREAD_C; 3264 dbpsk_decoder_c_u8((complexf*)input_buffer, local_output_buffer, the_bufsize); 3265 fwrite(local_output_buffer, sizeof(unsigned char), the_bufsize, stdout); 3266 TRY_YIELD; 3267 } 3268 return 0; 3269 } 3270 3271 if(!strcmp(argv[1], "bfsk_demod_cf")) //<spacing> <filter_length> 3272 { 3273 float frequency_shift = 0; 3274 if(argc<=2) return badsyntax("required parameter <frequency_shift> is missing."); 3275 sscanf(argv[2],"%f",&frequency_shift); 3276 3277 int filter_length = 0; 3278 if(argc<=3) return badsyntax("required parameter <filter_length> is missing."); 3279 sscanf(argv[3],"%d",&filter_length); 3280 3281 complexf* mark_filter = (complexf*)malloc(sizeof(complexf)*filter_length); 3282 complexf* space_filter = (complexf*)malloc(sizeof(complexf)*filter_length); 3283 firdes_add_peak_c(mark_filter, filter_length, frequency_shift/2, WINDOW_DEFAULT, 0, 1); 3284 firdes_add_peak_c(space_filter, filter_length, -frequency_shift/2, WINDOW_DEFAULT, 0, 1); 3285 3286 if(!sendbufsize(initialize_buffers())) return -2; 3287 3288 int input_skip=0; 3289 int output_size=0; 3290 FREAD_C; 3291 for(;;) 3292 { 3293 FEOF_CHECK; 3294 output_size=bfsk_demod_cf((complexf*)input_buffer, output_buffer, the_bufsize, mark_filter, space_filter, filter_length); 3295 fwrite(output_buffer, sizeof(float), output_size, stdout); 3296 TRY_YIELD; 3297 memmove((complexf*)input_buffer,((complexf*)input_buffer)+output_size,(the_bufsize-output_size)*sizeof(complexf)); 3298 fread(((complexf*)input_buffer)+(the_bufsize-output_size), sizeof(complexf), output_size, stdin); 3299 } 3300 return 0; 3301 } 3302 3303 if(!strcmp(argv[1], "add_const_cc")) //<i> <q> 3304 { 3305 complexf x; 3306 if(argc<=2) return badsyntax("required parameter <add_i> is missing."); 3307 sscanf(argv[2],"%f",&iofv(x)); 3308 if(argc<=2) return badsyntax("required parameter <add_q> is missing."); 3309 sscanf(argv[2],"%f",&qofv(x)); 3310 3311 if(!sendbufsize(initialize_buffers())) return -2; 3312 for(;;) 3313 { 3314 FEOF_CHECK; 3315 FREAD_C; 3316 add_const_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, x); 3317 FWRITE_C; 3318 TRY_YIELD; 3319 } 3320 return 0; 3321 } 3322 3323 if(!strcmp(argv[1], "tee")) //<path> [buffers] 3324 { 3325 if(argc<=2) return badsyntax("required parameter <path> is missing."); 3326 FILE* teefile = fopen(argv[2],"w"); 3327 if(!teefile) return badsyntax("<path> cannot be opened!"); 3328 errhead(); fprintf(stderr, "file opened: %s\n", argv[2]); 3329 int num_buffers=100; 3330 if(argc>3) sscanf(argv[3], "%d", &num_buffers); 3331 if(num_buffers<=0) return badsyntax("num_buffers should be > 0"); 3332 SET_NONBLOCK(fileno(teefile)); 3333 if(!sendbufsize(initialize_buffers())) return -2; 3334 unsigned char* async_tee_buffers = malloc(sizeof(unsigned char)*the_bufsize*num_buffers); 3335 int current_buffer_read_cntr = 0; 3336 int current_buffer_write_cntr = 0; 3337 int current_byte_write_cntr = 0; 3338 for(;;) 3339 { 3340 FEOF_CHECK; 3341 fread(async_tee_buffers+(the_bufsize*current_buffer_read_cntr), sizeof(unsigned char), the_bufsize, stdin); 3342 fwrite(async_tee_buffers+(the_bufsize*current_buffer_read_cntr++), sizeof(unsigned char), the_bufsize, stdout); 3343 if(current_buffer_read_cntr>=num_buffers) current_buffer_read_cntr = 0; 3344 if(current_buffer_read_cntr==current_buffer_write_cntr) { errhead(); fprintf(stderr, "circular buffer overflow (read pointer gone past write pointer)\n"); } 3345 //errhead(); fprintf(stderr, "new fwrites\n"); 3346 while(current_buffer_write_cntr!=current_buffer_read_cntr) 3347 { 3348 int result = fwrite(async_tee_buffers+(the_bufsize*current_buffer_write_cntr)+current_byte_write_cntr, sizeof(unsigned char), the_bufsize-current_byte_write_cntr, teefile); 3349 if(!result) { errhead(); fprintf(stderr, "\t fwrite tee zero, next turn\n"); break; } 3350 current_byte_write_cntr += result; 3351 //errhead(); fprintf(stderr, "\tfwrite tee, current_byte_write_cntr = %d, current_buffer_write_cntr = %d, current_buffer_read_cntr = %d\n", 3352 // current_byte_write_cntr, current_buffer_write_cntr, current_buffer_read_cntr); 3353 if(current_byte_write_cntr >= the_bufsize) 3354 { 3355 current_byte_write_cntr = 0; 3356 current_buffer_write_cntr++; 3357 if(current_buffer_write_cntr>=num_buffers) current_buffer_write_cntr = 0; 3358 } 3359 } 3360 TRY_YIELD; 3361 } 3362 return 0; 3363 } 3364 3365 if(!strcmp(argv[1],"shift_addition_fc")) 3366 { 3367 bigbufs=1; 3368 3369 float starting_phase=0; 3370 float rate; 3371 3372 int fd; 3373 if(fd=init_fifo(argc,argv)) 3374 { 3375 while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); 3376 } 3377 else 3378 { 3379 if(argc<=2) return badsyntax("need required parameter (rate)"); 3380 sscanf(argv[2],"%g",&rate); 3381 } 3382 3383 if(!sendbufsize(initialize_buffers())) return -2; 3384 for(;;) 3385 { 3386 shift_addition_data_t data=shift_addition_init(rate); 3387 errhead(); fprintf(stderr,"reinitialized to %g\n",rate); 3388 int remain, current_size; 3389 float* ibufptr; 3390 float* obufptr; 3391 for(;;) 3392 { 3393 FEOF_CHECK; 3394 if(!FREAD_R) break; 3395 remain=the_bufsize; 3396 ibufptr=input_buffer; 3397 obufptr=output_buffer; 3398 while(remain) 3399 { 3400 current_size=(remain>1024)?1024:remain; 3401 starting_phase=shift_addition_fc(ibufptr, (complexf*)obufptr, current_size, data, starting_phase); 3402 ibufptr+=current_size; 3403 obufptr+=current_size*2; 3404 remain-=current_size; 3405 } 3406 FWRITE_C; 3407 if(read_fifo_ctl(fd,"%g\n",&rate)) break; 3408 TRY_YIELD; 3409 } 3410 } 3411 return 0; 3412 } 3413 3414 if(!strcmp(argv[1],"fft_fc")) 3415 { 3416 /* 3417 For real FFT, the parameter is the number of output complex bins 3418 instead of the actual FFT size. 3419 Number of input samples used for each FFT is twice the given parameter. 3420 This makes it easier to replace fft_cc by fft_fc in some applications. */ 3421 if(argc<=3) return badsyntax("need required parameters (fft_out_size, out_of_every_n_samples)"); 3422 int fft_in_size=0, fft_out_size=0; 3423 sscanf(argv[2],"%d",&fft_out_size); 3424 if(log2n(fft_out_size)==-1) return badsyntax("fft_out_size should be power of 2"); 3425 fft_in_size = 2*fft_out_size; 3426 int every_n_samples; 3427 sscanf(argv[3],"%d",&every_n_samples); 3428 int benchmark=0; 3429 int octave=0; 3430 window_t window = WINDOW_DEFAULT; 3431 if(argc>=5) 3432 { 3433 window=firdes_get_window_from_string(argv[4]); 3434 } 3435 if(argc>=6) 3436 { 3437 benchmark|=!strcmp("--benchmark",argv[5]); 3438 octave|=!strcmp("--octave",argv[5]); 3439 } 3440 if(argc>=7) 3441 { 3442 benchmark|=!strcmp("--benchmark",argv[6]); 3443 octave|=!strcmp("--octave",argv[6]); 3444 } 3445 3446 if(!initialize_buffers()) return -2; 3447 sendbufsize(fft_out_size); 3448 3449 //make FFT plan 3450 float* input=(float*)fft_malloc(sizeof(float)*fft_in_size); 3451 float* windowed=(float*)fft_malloc(sizeof(float)*fft_in_size); 3452 complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_out_size); 3453 if(benchmark) { errhead(); fprintf(stderr,"benchmarking..."); } 3454 FFT_PLAN_T* plan=make_fft_r2c(fft_in_size, windowed, output, benchmark); 3455 if(benchmark) fprintf(stderr," done\n"); 3456 //if(octave) printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); // TODO 3457 float *windowt; 3458 windowt = precalculate_window(fft_in_size, window); 3459 for(;;) 3460 { 3461 FEOF_CHECK; 3462 if(every_n_samples>fft_in_size) 3463 { 3464 fread(input, sizeof(float), fft_in_size, stdin); 3465 //skipping samples before next FFT (but fseek doesn't work for pipes) 3466 for(int seek_remain=every_n_samples-fft_in_size;seek_remain>0;seek_remain-=the_bufsize) 3467 { 3468 fread(temp_f, sizeof(complexf), MIN_M(the_bufsize,seek_remain), stdin); 3469 } 3470 } 3471 else 3472 { 3473 //overlapped FFT 3474 for(int i=0;i<fft_in_size-every_n_samples;i++) input[i]=input[i+every_n_samples]; 3475 fread(input+fft_in_size-every_n_samples, sizeof(float), every_n_samples, stdin); 3476 } 3477 //apply_window_c(input,windowed,fft_size,window); 3478 apply_precalculated_window_f(input,windowed,fft_in_size,windowt); 3479 fft_execute(plan); 3480 if(octave) 3481 { 3482 #if 0 3483 // TODO 3484 printf("fftdata=["); 3485 //we have to swap the two parts of the array to get a valid spectrum 3486 for(int i=fft_size/2;i<fft_size;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i)); 3487 for(int i=0;i<fft_size/2;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i)); 3488 printf( 3489 "];\n" 3490 "y=abs(fftdata);\n" 3491 "refreshdata;\n" 3492 ); 3493 #endif 3494 } 3495 else fwrite(output, sizeof(complexf), fft_out_size, stdout); 3496 TRY_YIELD; 3497 } 3498 } 3499 /* 3500 if(!strcmp(argv[1],"syncword_search")) 3501 { 3502 if(argc<3) return badsyntax("need required parameter (syncword)"); 3503 unsigned long syncword=0UL; 3504 int syncword_length=strlen(argv[2]); 3505 for(int i=0; i<sycword_len;i++) 3506 { 3507 syncword<<=4; 3508 char c=argv[2][i]; 3509 unsigned char cval = 0; 3510 if(c<='9'&&c>='0') cval = c-'0'; 3511 if(c<='f'&&c>='a') cval = c-'a'+10; 3512 syncword|=cval; 3513 } 3514 errhead(); fprintf("syncword = 0x%0x, syncword_length=%d\n", syncword, syncword_length); 3515 if(argc<4) return badsyntax("need required parameter (bits_after)"); 3516 int bits_after = 0; 3517 sscanf(argv[3], &bits_after); 3518 if(bits_after<0) return badsyntax("bits_after should be >0"); 3519 unsigned char* syncword_bits = malloc(sizeof(unsigned char)*syncword_length*4); 3520 int k=0; 3521 for(int i=0;i<syncword_length;i++) 3522 { 3523 for(int j=7;j;j--) 3524 { 3525 syncword_bits[k++]=syncword[i]>>j 3526 } 3527 } 3528 malloc 3529 3530 } 3531 */ 3532 if(!strcmp(argv[1],"pattern_search_u8_u8")) //<values_after> <pattern_values × N> 3533 { 3534 if(argc<3) return badsyntax("need required parameter (values_after)"); 3535 int values_after = 0; 3536 sscanf(argv[2], "%d", &values_after); 3537 if(argc<4) return badsyntax("need required parameter (pattern_values × N)"); 3538 int pattern_values_length = argc-3; 3539 unsigned* pattern_values = (unsigned*)malloc(sizeof(unsigned)*pattern_values_length); 3540 for(int i=0;i<pattern_values_length;i++) 3541 sscanf(argv[3+i],"%u",pattern_values+i); 3542 3543 errhead(); fprintf(stderr,"pattern values: "); 3544 for(int i=0;i<pattern_values_length;i++) 3545 fprintf(stderr, "%x ", *(pattern_values+i)); 3546 fprintf(stderr,"\n"); 3547 3548 unsigned char* input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*pattern_values_length); //circular buffer 3549 unsigned char* output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*values_after); 3550 int input_index = 0; 3551 int valid_values = 0; 3552 for(;;) 3553 { 3554 FEOF_CHECK; 3555 unsigned char cchar = input_buffer[input_index++]=(unsigned char)fgetc(stdin); 3556 if(valid_values<pattern_values_length) { valid_values++; continue; } 3557 if(input_index>=pattern_values_length) input_index=0; 3558 int match=1; 3559 //fprintf(stderr, "ov1: "); 3560 //for(int i=0;i<pattern_values_length;i++) fprintf(stderr, "%02x ", input_buffer[i]); 3561 //fprintf(stderr, "\nov2: "); 3562 //for(int i=0;i<pattern_values_length;i++) fprintf(stderr, "%02x ", pattern_values[i]); 3563 //fprintf(stderr, "\n"); 3564 3565 //fprintf(stderr, "v1: "); 3566 //for(int i=input_index;i<pattern_values_length;i++) fprintf(stderr, "%s%02x ", ((input_buffer[i])?"\x1B[34m":"\x1B[0m"), input_buffer[i]); 3567 //for(int i=0;i<input_index;i++) fprintf(stderr, "%s%02x ", ((input_buffer[i])?"\x1B[34m":"\x1B[0m"), input_buffer[i]); 3568 //fprintf(stderr, "\x1B[0m %02x\n", cchar); 3569 3570 //fprintf(stderr, "========\n"); 3571 int j=0; 3572 for(int i=input_index;i<pattern_values_length;i++) 3573 { 3574 //fprintf(stderr, "%02x ~ %02x\n", input_buffer[i], pattern_values[j]); 3575 if(input_buffer[i]!=pattern_values[j++]) { match=0; break;} 3576 } 3577 //fprintf(stderr, "~~~~~~~~\n"); 3578 if(input_index!=0 && match) 3579 { 3580 for(int i=0;i<input_index;i++) 3581 { 3582 //fprintf(stderr, "%02x ~ %02x\n", input_buffer[i], pattern_values[j]); 3583 if(input_buffer[i]!=pattern_values[j++]) { match=0; break;} 3584 } 3585 } 3586 3587 //if(match) fprintf(stderr, "j=%d\n", j); 3588 if(match ) 3589 { 3590 valid_values = 0; 3591 //fprintf(stderr,"matched!\n"); 3592 fread(output_buffer, sizeof(unsigned char), values_after, stdin); 3593 fwrite(output_buffer, sizeof(unsigned char), values_after, stdout); 3594 } 3595 TRY_YIELD; 3596 } 3597 } 3598 3599 if(!strcmp(argv[1],"none")) 3600 { 3601 return 0; 3602 } 3603 3604 if(argv[1][0]=='?' && argv[1][1]=='?') 3605 { 3606 char buffer[1000]; 3607 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); 3608 fprintf(stderr, "csdr ??: %s\n", buffer); 3609 system(buffer); 3610 return 0; 3611 } 3612 3613 if(argv[1][0]=='?') 3614 { 3615 char buffer[1000]; 3616 snprintf(buffer, 1000-1, "csdr 2>&1 | grep -i %s", argv[1]+1); 3617 fprintf(stderr, "csdr ?: %s\n", buffer); 3618 system(buffer); 3619 return 0; 3620 } 3621 3622 if(argv[1][0]=='=') 3623 { 3624 char buffer[100]; 3625 snprintf(buffer, 100-1, "python -c \"import os, sys\nfrom math import *\nprint %s\"", argv[1]+1); 3626 system(buffer); 3627 return 0; 3628 } 3629 3630 fprintf(stderr,"csdr: function name given in argument 1 (%s) does not exist. Possible causes:\n- You mistyped the commandline.\n- You need to update csdr to a newer version (if available).\n", argv[1]); return -1; 3631 }