diff --git a/README.md b/README.md index 0035732..c133c91 100755 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ Most of the code is available under the permissive BSD license, with some option How to compile -------------- - make - sudo make install + make + sudo make install The project was only tested on Linux. It has the following dependencies: `libfftw3-dev` @@ -24,7 +24,7 @@ To run the examples, you will also need /dev/null + rtl_sdr -s 2400000 -f 104300000 -g 20 - | csdr convert_u8_f | csdr fft_cc 1024 1200000 HAMMING --octave | octave -i > /dev/null - We calculate the Fast Fourier Transform by `csdr fft_cc` on the first 1024 samples of every block of 1200000 complex samples coming after each other. (We calculate FFT from 1024 samples and then skip 1200000-1024=1198976 samples. This way we will calculate FFT two times every second.) - The window used for FFT is the Hamming window, and the output consists of commands that can be directly interpreted by GNU Octave which plots us the spectrum. @@ -153,7 +153,7 @@ Optional parameters have safe defaults, for more info look at the code. Syntax: - csdr realpart_cf + csdr realpart_cf It takes the real part of the complex signal, and throws away the imaginary part. @@ -163,7 +163,7 @@ It takes the real part of the complex signal, and throws away the imaginary part Syntax: - csdr clipdetect_ff + csdr clipdetect_ff It clones the signal (the input and the output is the same), but it prints a warning on `stderr` if any sample value is out of the -1.0 ... 1.0 range. @@ -173,7 +173,7 @@ It clones the signal (the input and the output is the same), but it prints a war Syntax: - csdr limit_ff [max_amplitude] + csdr limit_ff [max_amplitude] The input signal amplitude will not be let out of the `-max_amplitude ... max_amplitude` range. @@ -183,7 +183,7 @@ The input signal amplitude will not be let out of the `-max_amplitude ... max_am Syntax: - csdr gain_ff + csdr gain_ff It multiplies all samples by `gain`. @@ -193,7 +193,7 @@ It multiplies all samples by `gain`. Syntax: - csdr clone + csdr clone It copies the input to the output. @@ -203,7 +203,7 @@ It copies the input to the output. Syntax: - csdr through + csdr through It copies the input to the output, while also displaying the data rate going through it. @@ -213,7 +213,7 @@ It copies the input to the output, while also displaying the data rate going thr Syntax: - csdr none + csdr none The `csdr` process just exits with 0. @@ -223,7 +223,7 @@ The `csdr` process just exits with 0. Syntax: - csdr yes_f [buf_times] + csdr yes_f [buf_times] It outputs continously the `to_repeat` float number. @@ -237,7 +237,7 @@ Else, after outputing `buf_times` number of buffers (the size of which is stated Syntax: - csdr detect_nan_ff + csdr detect_nan_ff Along with copying its input samples to the output, it prints a warning message to *stderr* if it finds any IEEE floating point NaN values among the samples. @@ -247,7 +247,7 @@ Along with copying its input samples to the output, it prints a warning message Syntax: - csdr dump_f + csdr dump_f It prints all floating point input samples as text. @@ -265,7 +265,7 @@ Aliases for this function: `floatdump_f` Syntax: - csdr dump_u8 + csdr dump_u8 It prints all input bytes as text, in hexadecimal form. @@ -277,7 +277,7 @@ Alternatively, you can use the `xxd` command (built into most Linux distribution Syntax: - csdr flowcontrol + csdr flowcontrol It limits the data rate of a stream to a given `data_rate` number of bytes per second. @@ -289,7 +289,7 @@ It copies `data_rate / reads_per_second` bytes from the input to the output, doi Syntax: - csdr shift_math_cc + csdr shift_math_cc It shifts the signal in the frequency domain by `rate`. @@ -305,7 +305,7 @@ Internally, a sine and cosine wave is generated, and this function uses `math.h` Syntax: - csdr shift_addition_cc + csdr shift_addition_cc Operation is the same as for `shift_math_cc`. @@ -317,7 +317,7 @@ Internally, this function uses trigonometric addition formulas to generate sine Syntax: - csdr shift_addition_cc_test + csdr shift_addition_cc_test This function was used to test the accuracy of the method above. @@ -327,7 +327,7 @@ This function was used to test the accuracy of the method above. Syntax: - csdr shift_table_cc [table_size] + csdr shift_table_cc [table_size] Operation is the same as with `shift_math_cc`. @@ -341,7 +341,7 @@ The higher the table size is, the smaller the phase error is. Syntax: - csdr shift_addfast_cc + csdr shift_addfast_cc Operation is the same as for `shift_math_cc`. @@ -353,7 +353,7 @@ Internally, this function uses a NEON-accelerated algorithm on capable systems, Syntax: - csdr shift_unroll_cc + csdr shift_unroll_cc Operation is the same as for `shift_math_cc`. @@ -367,7 +367,7 @@ The loop in this function unrolls quite well if compiled on a PC. It was the fas Syntax: - csdr decimating_shift_addition_cc [decimation] + csdr decimating_shift_addition_cc [decimation] It shifts the input signal in the frequency domain, and also decimates it, without filtering. It will be useful as a part of the FFT channelizer implementation (to be done). @@ -379,7 +379,7 @@ It cannot be used as a channelizer by itself, use `fir_decimate_cc` instead. Syntax: - csdr dcblock_ff + csdr dcblock_ff This is a DC blocking IIR filter. @@ -389,7 +389,7 @@ This is a DC blocking IIR filter. Syntax: - csdr fastdcblock_ff + csdr fastdcblock_ff This is a DC blocker that works based on the average of the buffer. @@ -399,7 +399,7 @@ This is a DC blocker that works based on the average of the buffer. Syntax: - csdr fmdemod_atan_cf + csdr fmdemod_atan_cf It is an FM demodulator that internally uses the `atan` function in `math.h`, so it is not so fast. @@ -409,7 +409,7 @@ It is an FM demodulator that internally uses the `atan` function in `math.h`, so Syntax: - csdr fmdemod_quadri_cf + csdr fmdemod_quadri_cf It is an FM demodulator that is based on the quadri-correlator method, and it can be effectively auto-vectorized, so it should be faster. @@ -419,7 +419,7 @@ It is an FM demodulator that is based on the quadri-correlator method, and it ca Syntax: - csdr fmdemod_quadri_novect_cf + csdr fmdemod_quadri_novect_cf It has more easily understandable code than the previous one, but can't be auto-vectorized. @@ -429,7 +429,7 @@ It has more easily understandable code than the previous one, but can't be auto- Syntax: - csdr deemphasis_wfm_ff + csdr deemphasis_wfm_ff It does de-emphasis with the given RC time constant `tau`. @@ -443,13 +443,13 @@ In Europe, `tau` should be chosen as `50e-6`, and in the USA, `tau` should be `7 Syntax: - csdr deemphasis_nfm_ff + csdr deemphasis_nfm_ff It does de-emphasis on narrow-band FM for communication equipment (e.g. two-way radios). It uses fixed filters so it works only on predefined sample rates, for the actual list of them run: - cat libcsdr.c | grep DNFMFF_ADD_ARRAY + cat libcsdr.c | grep DNFMFF_ADD_ARRAY ---- @@ -457,7 +457,7 @@ It uses fixed filters so it works only on predefined sample rates, for the actua Syntax: - csdr amdemod_cf + csdr amdemod_cf It is an AM demodulator that uses `sqrt`. On some architectures `sqrt` can be directly calculated by dedicated CPU instructions, but on others it may be slower. @@ -467,7 +467,7 @@ It is an AM demodulator that uses `sqrt`. On some architectures `sqrt` can be di Syntax: - csdr amdemod_estimator_cf + csdr amdemod_estimator_cf It is an AM demodulator that uses an estimation method that is faster but less accurate than `amdemod_cf`. @@ -477,7 +477,7 @@ It is an AM demodulator that uses an estimation method that is faster but less a Syntax: - csdr firdes_lowpass_f [window [--octave]] + csdr firdes_lowpass_f [window [--octave]] Low-pass FIR filter design function to output real taps, with a `cutoff_rate` proportional to the sampling frequency, using the windowed sinc filter design method. @@ -501,7 +501,7 @@ The `--octave` parameter lets you directly view the filter response in `octave`. Syntax: - csdr firdes_bandpass_c [window [--octave]] + csdr firdes_bandpass_c [window [--octave]] Band-pass FIR filter design function to output complex taps. @@ -515,7 +515,7 @@ Other parameters were explained above at `firdes_lowpass_f`. Syntax: - csdr fir_decimate_cc [transition_bw [window]] + csdr fir_decimate_cc [transition_bw [window]] It is a decimator that keeps one sample out of `decimation_factor` samples. @@ -527,7 +527,7 @@ To avoid aliasing, it runs a filter on the signal and removes spectral component Syntax: - csdr fir_interpolate_cc [transition_bw [window]] + csdr fir_interpolate_cc [transition_bw [window]] It is an interpolator that generates `interpolation_factor` number of output samples from one input sample. @@ -541,7 +541,7 @@ To avoid aliasing, it runs a filter on the signal and removes spectral component Syntax: - csdr rational_resampler_ff [transition_bw [window]] + csdr rational_resampler_ff [transition_bw [window]] It is a resampler that takes integer values of `interpolation` and `decimation`. The output sample rate will be `interpolation / decimation × input_sample_rate`. @@ -554,7 +554,7 @@ The output sample rate will be `interpolation / decimation × input_sample_rate` Syntax: - csdr fractional_decimator_ff [num_poly_points ( [transition_bw [window]] | --prefilter )] + csdr fractional_decimator_ff [num_poly_points ( [transition_bw [window]] | --prefilter )] It can decimate by a floating point ratio. @@ -571,7 +571,7 @@ It can filter the signal with an anti-aliasing FIR filter before applying the La Syntax: - csdr old_fractional_decimator_ff [transition_bw [window]] + csdr old_fractional_decimator_ff [transition_bw [window]] This is the deprecated, old algorithm to decimate by a floating point ratio, superseded by `fractional_decimator_ff`. @@ -583,7 +583,7 @@ This is the deprecated, old algorithm to decimate by a floating point ratio, sup Syntax: - csdr bandpass_fir_fft_cc [window] + csdr bandpass_fir_fft_cc [window] It performs a bandpass FIR filter on complex samples, using FFT and the overlap-add method. @@ -595,7 +595,7 @@ Parameters are described under `firdes_bandpass_c` and `firdes_lowpass_f`. Syntax: - csdr agc_ff [hang_time [reference [attack_rate [decay_rate [max_gain [attack_wait [filter_alpha]]]]]]] + csdr agc_ff [hang_time [reference [attack_rate [decay_rate [max_gain [attack_wait [filter_alpha]]]]]]] It is an automatic gain control function. @@ -615,7 +615,7 @@ Its default parameters work best for an audio signal sampled at 48000 Hz. Syntax: - csdr fastagc_ff [block_size [reference]] + csdr fastagc_ff [block_size [reference]] It is a faster AGC that linearly changes the gain, taking the highest amplitude peak in the buffer into consideration. Its output will never exceed `-reference ... reference`. @@ -625,7 +625,7 @@ It is a faster AGC that linearly changes the gain, taking the highest amplitude Syntax: - csdr fft_cc [window [--octave] [--benchmark]] + csdr fft_cc [window [--octave] [--benchmark]] It performs an FFT on the first `fft_size` samples out of `out_of_every_n_samples`, thus skipping `out_of_every_n_samples - fft_size` samples in the input. @@ -639,7 +639,7 @@ FFTW can be faster if we let it optimalize a while before starting the first tra Syntax: - csdr fft_benchmark [--benchmark] + csdr fft_benchmark [--benchmark] It measures the time taken to process `fft_cycles` transforms of `fft_size`. It lets FFTW optimalize if used with the `--benchmark` switch. @@ -650,7 +650,7 @@ It lets FFTW optimalize if used with the `--benchmark` switch. Syntax: - csdr logpower_cf [add_db] + csdr logpower_cf [add_db] Calculates `10*log10(i^2+q^2)+add_db` for the input complex samples. It is useful for drawing power spectrum graphs. @@ -666,7 +666,7 @@ Syntax: Syntax: - csdr csdr encode_ima_adpcm_i16_u8 + csdr csdr encode_ima_adpcm_i16_u8 Encodes the audio stream to IMA ADPCM, which decreases the size to 25% of the original. @@ -676,7 +676,7 @@ Encodes the audio stream to IMA ADPCM, which decreases the size to 25% of the or Syntax: - csdr decode_ima_adpcm_u8_i16 + csdr decode_ima_adpcm_u8_i16 Decodes the audio stream from IMA ADPCM. @@ -686,7 +686,7 @@ Decodes the audio stream from IMA ADPCM. Syntax: - csdr compress_fft_adpcm_f_u8 + csdr compress_fft_adpcm_f_u8 Encodes the FFT output vectors of `fft_size`. It should be used on the data output from `logpower_cf`. @@ -694,7 +694,7 @@ It resets the ADPCM encoder at the beginning of every vector, and to compensate The actual number of padding samples can be determined by running: - cat csdr.c | grep "define COMPRESS_FFT_PAD_N" + cat csdr.c | grep "define COMPRESS_FFT_PAD_N" ---- @@ -702,7 +702,7 @@ The actual number of padding samples can be determined by running: Syntax: - csdr fft_exchange_sides_ff + csdr fft_exchange_sides_ff It exchanges the first and second part of the FFT vector, to prepare it for the waterfall/spectrum display. It should operate on the data output from `logpower_cf`. @@ -712,7 +712,7 @@ It exchanges the first and second part of the FFT vector, to prepare it for the Syntax: - csdr dsb_fc [q_value] + csdr dsb_fc [q_value] It converts a real signal to a double sideband complex signal centered around DC. @@ -728,7 +728,7 @@ With `q_value = 0` it is an AM-DSB/SC modulator. If you want to get an AM-DSB si Syntax: - csdr add_dcoffset_cc + csdr add_dcoffset_cc It adds a DC offset to the complex signal: `i_output = 0.5 + i_input / 2, q_output = q_input / 2` @@ -738,7 +738,7 @@ It adds a DC offset to the complex signal: `i_output = 0.5 + i_input / 2, q_outp Syntax: - csdr convert_f_samplerf + csdr convert_f_samplerf It converts a real signal to the `-mRF` input format of [https://github.com/F5OEO/rpitx](rpitx), so it allows you to generate frequency modulation. The input signal will be the modulating signal. The `` parameter is the value for `rpitx` indicating the time to wait between samples. For a sampling rate of 48 ksps, this is 20833. @@ -748,7 +748,7 @@ It converts a real signal to the `-mRF` input format of [https://github.com/F5OE Syntax: - csdr fmmod_fc + csdr fmmod_fc It generates a complex FM modulated output from a real input signal. @@ -758,7 +758,7 @@ It generates a complex FM modulated output from a real input signal. Syntax: - csdr fixed_amplitude_cc + csdr fixed_amplitude_cc It changes the amplitude of every complex input sample to a fixed value. It does not change the phase information of the samples. @@ -768,17 +768,17 @@ It changes the amplitude of every complex input sample to a fixed value. It does Syntax: - csdr mono2stereo_s16 + csdr mono2stereo_s16 It doubles every input sample. Example: if the input samples are 16 bit signed integers: - 23 -452 3112 + 23 -452 3112 The output will be: - 23 23 -452 -452 3112 3112 + 23 23 -452 -452 3112 3112 ---- @@ -786,11 +786,11 @@ The output will be: Syntax: - csdr setbuf + csdr setbuf See the [buffer sizes](#buffer_sizes) section. - squelch_and_smeter_cc --fifo --outfifo + squelch_and_smeter_cc --fifo --outfifo This is a controllable squelch, which reads the squelch level input from `` and writes the power level output to ``. Both input and output are in the format of `%g\n`. While calculating the power level, it takes only every `` sample into consideration. It writes the S-meter value for every `` buffer to ``. If the squelch level is set to 0, it it forces the squelch to be open. If the squelch is closed, it fills the output with zero. @@ -800,7 +800,7 @@ This is a controllable squelch, which reads the squelch level input from ` + csdr fifo It is similar to `clone`, but internally it uses a circular buffer. It reads as much as possible from the input. It discards input samples if the input buffer is full. @@ -810,7 +810,7 @@ It is similar to `clone`, but internally it uses a circular buffer. It reads as Syntax: - csdr psk31_varicode_encoder_u8_u8 + csdr psk31_varicode_encoder_u8_u8 It encodes ASCII characters into varicode for PSK31 transmission. It puts a `00` sequence between the varicode characters (which acts as a separator). @@ -832,7 +832,7 @@ For this input, the output of `psk31_varicode_encoder_u8_u8` will be the followi Syntax: - csdr repeat_u8 [resonator_rate × N]\n" + csdr repeat_u8 [resonator_rate × N]\n" It repeatedly outputs a set of data bytes (given with decimal numbers). @@ -849,7 +849,7 @@ For example, `csdr repeat_u8 1 1 0 0` will output: Syntax: - csdr uniform_noise_f + csdr uniform_noise_f It outputs uniform white noise. All samples are within the range [-1.0, 1.0]. @@ -859,7 +859,7 @@ It outputs uniform white noise. All samples are within the range [-1.0, 1.0]. Syntax: - csdr gaussian_noise_c + csdr gaussian_noise_c It outputs Gaussian white noise. All samples are within the unit circle. @@ -869,7 +869,7 @@ It outputs Gaussian white noise. All samples are within the unit circle. Syntax: - csdr pack_bits_8to1_u8_u8 + csdr pack_bits_8to1_u8_u8 It serializes the bytes on the input: it outputs each bit of the input byte as a single byte valued 0x00 or 0x01, starting from the lowest bit and going to the highest bit. @@ -895,7 +895,7 @@ For consequtive 0x02, 0x03, 0xff bytes on the input, the output will be: Syntax: - csdr awgn_cc [--snrshow] + csdr awgn_cc [--snrshow] It adds white noise with the given SNR to a signal assumed to be of 0 dB power. @@ -907,7 +907,7 @@ If the `--snrshow` switch is given, it also shows the actual SNR based on the ca Syntax: - csdr add_n_zero_samples_at_beginning_f + csdr add_n_zero_samples_at_beginning_f When the function is executed, it furst writes `` 32-bit floating point zeros at the output, after that it just clones the input at the output. @@ -917,7 +917,7 @@ When the function is executed, it furst writes `` 32-bit floatin Syntax: - csdr ? + csdr ? You can search the functions available in `csdr` just as if you typed: `csdr 2>&1 | grep ` @@ -925,7 +925,7 @@ You can search the functions available in `csdr` just as if you typed: `csdr 2>& Syntax: - csdr = + csdr = When running complicated `csdr` commands, we usually run into using `python` to calculate certain parameters. @@ -933,19 +933,19 @@ This function can eliminate some typing and make our command clearer. Instead of having to write: - csdr shift_addition_cc $(python -c "print 1200/2400000.") + csdr shift_addition_cc $(python -c "print 1200/2400000.") ...we can type: - csdr shift_addition_cc $(csdr =1200/2400000.) + csdr shift_addition_cc $(csdr =1200/2400000.) If using parenthesis inside the expression, it needs to be escaped (as `bash` would want to parse it): - csdr shift_addition_cc $(csdr =\(1200+300\)/2400000) + csdr shift_addition_cc $(csdr =\(1200+300\)/2400000) Another solution is using single quotes to wrap the expression: - csdr shift_addition_cc $(csdr '=(1200+300)/2400000.') + csdr shift_addition_cc $(csdr '=(1200+300)/2400000.') Current version of `csdr` executes the following python script for this function: @@ -961,21 +961,21 @@ This means that one can also call math functions like `sqrt()`. Some parameters can be changed while the `csdr` process is running. To achieve this, some `csdr` functions have special parameters. You have to supply a fifo previously created by the `mkfifo` command. Processing will only start after the first control command has been received by `csdr` over the FIFO. - shift_addition_cc --fifo + shift_addition_cc --fifo By writing to the given FIFO file with the syntax below, you can control the shift rate: - \n + \n E.g. you can send `-0.3\n` Processing will only start after the first control command has been received by `csdr` over the FIFO. - bandpass_fir_fft_cc --fifo [window] + bandpass_fir_fft_cc --fifo [window] By writing to the given FIFO file with the syntax below, you can control the shift rate: - \n + \n E.g. you can send `-0.05 0.02\n` @@ -1043,17 +1043,17 @@ To compile *sdr.js*, first get Emscripten. To install and build dependencies (for now, only FFTW3): - make emcc-get-deps + make emcc-get-deps To compile *sdr.js* (which will be created in the `sdr.js` subdirectory): - make emcc + make emcc You can test *sdr.js* by opening *sdr.html*. It contains a test for *firdes_lowpass_f* for this time. To remove *sdr.js* and the compiled dependencies: - make emcc-clean + make emcc-clean ## [nmux](#nmux) diff --git a/csdr.c b/csdr.c index 04a330d..52f1c66 100755 --- a/csdr.c +++ b/csdr.c @@ -169,73 +169,73 @@ int bigbufs = 0; int badsyntax(char* why) { - if(why==0) fprintf(stderr, "%s", usage); - else fprintf(stderr, "csdr: %s\n\n", why); - return -1; + if(why==0) fprintf(stderr, "%s", usage); + else fprintf(stderr, "csdr: %s\n\n", why); + return -1; } int clipdetect_ff(float* input, int input_size) { - for(int i=0;i1.0) { fprintf(stderr, "csdr clipdetect_ff: Signal value above 1.0!\n"); return 1; } - } - return 0; + for(int i=0;i1.0) { fprintf(stderr, "csdr clipdetect_ff: Signal value above 1.0!\n"); return 1; } + } + return 0; } int clone_(int bufsize_param) { - unsigned char* clone_buffer; - clone_buffer = (unsigned char*)malloc(bufsize_param*sizeof(unsigned char)); - for(;;) - { - fread(clone_buffer, sizeof(unsigned char), bufsize_param, stdin); - fwrite(clone_buffer, sizeof(unsigned char), bufsize_param, stdout); - TRY_YIELD; - } + unsigned char* clone_buffer; + clone_buffer = (unsigned char*)malloc(bufsize_param*sizeof(unsigned char)); + for(;;) + { + fread(clone_buffer, sizeof(unsigned char), bufsize_param, stdin); + fwrite(clone_buffer, sizeof(unsigned char), bufsize_param, stdout); + TRY_YIELD; + } } -#define FREAD_U8 fread (input_buffer, sizeof(unsigned char), the_bufsize, stdin) -#define FWRITE_U8 fwrite (output_buffer, sizeof(unsigned char), the_bufsize, stdout) -#define FREAD_R fread (input_buffer, sizeof(float), the_bufsize, stdin) -#define FREAD_C fread (input_buffer, sizeof(float)*2, the_bufsize, stdin) -#define FWRITE_R fwrite (output_buffer, sizeof(float), the_bufsize, stdout) -#define FWRITE_C fwrite (output_buffer, sizeof(float)*2, the_bufsize, stdout) -#define FEOF_CHECK if(feof(stdin)) return 0 +#define FREAD_U8 fread (input_buffer, sizeof(unsigned char), the_bufsize, stdin) +#define FWRITE_U8 fwrite (output_buffer, sizeof(unsigned char), the_bufsize, stdout) +#define FREAD_R fread (input_buffer, sizeof(float), the_bufsize, stdin) +#define FREAD_C fread (input_buffer, sizeof(float)*2, the_bufsize, stdin) +#define FWRITE_R fwrite (output_buffer, sizeof(float), the_bufsize, stdout) +#define FWRITE_C fwrite (output_buffer, sizeof(float)*2, the_bufsize, stdout) +#define FEOF_CHECK if(feof(stdin)) return 0 //#define BIG_FREAD_C fread(input_buffer, sizeof(float)*2, BIG_BUFSIZE, stdin) //#define BIG_FWRITE_C fwrite(output_buffer, sizeof(float)*2, BIG_BUFSIZE, stdout) int init_fifo(int argc, char *argv[]) { - if(argc>=4) - { - if(!strcmp(argv[2],"--fifo")) - { - fprintf(stderr,"csdr: fifo control mode on\n"); - int fd = open(argv[3], O_RDONLY); - int flags = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - return fd; - } - else if(!strcmp(argv[2],"--fd")) - { - //to use this: - //1. Create a pipe(pipedesc) in your process. - //2. fork() and execl() your process to run csdr, and give pipedesc[0] as parameter after --fd - // Note: when forking, the child process will get a copy of the file descriptor table! That's why this - // works at all, as file descriptor indexes are normally not transferable between processes, except for a *NIX socket way which is quite complicated... - //3. From your parent process, write into pipedesc[1]. - //This is implemented in ddcd, check there to see how to do it! - int fd; - if(sscanf(argv[3], "%d",&fd)<=0) return 0; - fprintf(stderr,"csdr: fd control mode on, fd=%d\n", fd); - int flags = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - return fd; - } - } - return 0; + if(argc>=4) + { + if(!strcmp(argv[2],"--fifo")) + { + fprintf(stderr,"csdr: fifo control mode on\n"); + int fd = open(argv[3], O_RDONLY); + int flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + return fd; + } + else if(!strcmp(argv[2],"--fd")) + { + //to use this: + //1. Create a pipe(pipedesc) in your process. + //2. fork() and execl() your process to run csdr, and give pipedesc[0] as parameter after --fd + // Note: when forking, the child process will get a copy of the file descriptor table! That's why this + // works at all, as file descriptor indexes are normally not transferable between processes, except for a *NIX socket way which is quite complicated... + //3. From your parent process, write into pipedesc[1]. + //This is implemented in ddcd, check there to see how to do it! + int fd; + if(sscanf(argv[3], "%d",&fd)<=0) return 0; + fprintf(stderr,"csdr: fd control mode on, fd=%d\n", fd); + int flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + return fd; + } + } + return 0; } @@ -244,38 +244,38 @@ int init_fifo(int argc, char *argv[]) int read_fifo_ctl(int fd, char* format, ...) { - if(!fd) return 0; - static char buffer[RFCTL_BUFSIZE]; - static int buffer_index=0; - int bytes_read=read(fd,buffer+buffer_index,(RFCTL_BUFSIZE-buffer_index)*sizeof(char)); - if(bytes_read<=0) return 0; + if(!fd) return 0; + static char buffer[RFCTL_BUFSIZE]; + static int buffer_index=0; + int bytes_read=read(fd,buffer+buffer_index,(RFCTL_BUFSIZE-buffer_index)*sizeof(char)); + if(bytes_read<=0) return 0; - int prev_newline_at=0; - int last_newline_at=0; - for(int i=0;i\" at the beginning of the chain! Falling back to default buffer size: " STRINGIFY_VALUE(SETBUF_DEFAULT_BUFSIZE)); return SETBUF_DEFAULT_BUFSIZE; } - if(recv_first[1]<=0) { badsyntax("warning! Invalid buffer size." ); return 0; } - return recv_first[1]; + if(!env_csdr_dynamic_bufsize_on) return (bigbufs) ? env_csdr_fixed_big_bufsize : env_csdr_fixed_bufsize; + int recv_first[2]; + fread(recv_first, sizeof(int), 2, stdin); + if(memcmp(recv_first, SETBUF_PREAMBLE, sizeof(char)*4)!=0) + { badsyntax("warning! Did not match preamble on the beginning of the stream. You should put \"csdr setbuf \" at the beginning of the chain! Falling back to default buffer size: " STRINGIFY_VALUE(SETBUF_DEFAULT_BUFSIZE)); return SETBUF_DEFAULT_BUFSIZE; } + if(recv_first[1]<=0) { badsyntax("warning! Invalid buffer size." ); return 0; } + return recv_first[1]; } @@ -308,1381 +308,1381 @@ char **argv_global; int unitround(int what) { - if(what<=0) return UNITROUND_UNIT; - return ((what-1)&~(UNITROUND_UNIT-1))+UNITROUND_UNIT; + if(what<=0) return UNITROUND_UNIT; + return ((what-1)&~(UNITROUND_UNIT-1))+UNITROUND_UNIT; } int initialize_buffers() { - if(!(the_bufsize=getbufsize())) return 0; - the_bufsize=unitround(the_bufsize); - if(env_csdr_print_bufsizes) fprintf(stderr,"%s %s: buffer size set to %d\n",argv_global[0], argv_global[1], the_bufsize); - input_buffer = (float*) malloc(the_bufsize*sizeof(float) * 2); //need the 2× because we might also put complex floats into it - output_buffer = (float*) malloc(the_bufsize*sizeof(float) * 2); - buffer_u8 = (unsigned char*)malloc(the_bufsize*sizeof(unsigned char)); - buffer_i16 = (short*) malloc(the_bufsize*sizeof(short)); - temp_f = (float*) malloc(the_bufsize*sizeof(float) * 4); - if(the_bufsize<=4096) //this is hacky, should be done correctly - { - fcntl(STDIN_FILENO, F_SETPIPE_SZ, 4096); - fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 4096); - } - return the_bufsize; + if(!(the_bufsize=getbufsize())) return 0; + the_bufsize=unitround(the_bufsize); + if(env_csdr_print_bufsizes) fprintf(stderr,"%s %s: buffer size set to %d\n",argv_global[0], argv_global[1], the_bufsize); + input_buffer = (float*) malloc(the_bufsize*sizeof(float) * 2); //need the 2× because we might also put complex floats into it + output_buffer = (float*) malloc(the_bufsize*sizeof(float) * 2); + buffer_u8 = (unsigned char*)malloc(the_bufsize*sizeof(unsigned char)); + buffer_i16 = (short*) malloc(the_bufsize*sizeof(short)); + temp_f = (float*) malloc(the_bufsize*sizeof(float) * 4); + if(the_bufsize<=4096) //this is hacky, should be done correctly + { + fcntl(STDIN_FILENO, F_SETPIPE_SZ, 4096); + fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 4096); + } + return the_bufsize; } int sendbufsize(int size) { - if(size<=4096) - { - fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 4096); - } - //The first word is a preamble, "csdr". - //If the next csdr process detects it, sets the buffer size according to the second word - if(!env_csdr_dynamic_bufsize_on) return env_csdr_fixed_bufsize; - if(env_csdr_print_bufsizes) fprintf(stderr,"%s %s: next process proposed input buffer size is %d\n",argv_global[0], argv_global[1], size); - int send_first[2]; - memcpy((char*)send_first, SETBUF_PREAMBLE, 4*sizeof(char)); - send_first[1] = size; - fwrite(send_first, sizeof(int), 2, stdout); - return size; + if(size<=4096) + { + fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 4096); + } + //The first word is a preamble, "csdr". + //If the next csdr process detects it, sets the buffer size according to the second word + if(!env_csdr_dynamic_bufsize_on) return env_csdr_fixed_bufsize; + if(env_csdr_print_bufsizes) fprintf(stderr,"%s %s: next process proposed input buffer size is %d\n",argv_global[0], argv_global[1], size); + int send_first[2]; + memcpy((char*)send_first, SETBUF_PREAMBLE, 4*sizeof(char)); + send_first[1] = size; + fwrite(send_first, sizeof(int), 2, stdout); + return size; } int parse_env() { - char* envtmp; - envtmp=getenv("CSDR_DYNAMIC_BUFSIZE_ON"); - //fprintf(stderr, "envtmp: %s\n",envtmp); - if(envtmp) - { - env_csdr_dynamic_bufsize_on = !!atoi(envtmp); - env_csdr_fixed_bufsize = 0; - } - else - { - envtmp=getenv("CSDR_FIXED_BUFSIZE"); - if(envtmp) - { - env_csdr_fixed_big_bufsize = env_csdr_fixed_bufsize = atoi(envtmp); - } - } - envtmp=getenv("CSDR_PRINT_BUFSIZES"); - if(envtmp) - { - env_csdr_print_bufsizes = atoi(envtmp); - } + char* envtmp; + envtmp=getenv("CSDR_DYNAMIC_BUFSIZE_ON"); + //fprintf(stderr, "envtmp: %s\n",envtmp); + if(envtmp) + { + env_csdr_dynamic_bufsize_on = !!atoi(envtmp); + env_csdr_fixed_bufsize = 0; + } + else + { + envtmp=getenv("CSDR_FIXED_BUFSIZE"); + if(envtmp) + { + env_csdr_fixed_big_bufsize = env_csdr_fixed_bufsize = atoi(envtmp); + } + } + envtmp=getenv("CSDR_PRINT_BUFSIZES"); + if(envtmp) + { + env_csdr_print_bufsizes = atoi(envtmp); + } } int main(int argc, char *argv[]) { - parse_env(); - argv_global=argv; - if(argc<=1) return badsyntax(0); - if(!strcmp(argv[1],"--help")) return badsyntax(0); + parse_env(); + argv_global=argv; + if(argc<=1) return badsyntax(0); + if(!strcmp(argv[1],"--help")) return badsyntax(0); - fcntl(STDIN_FILENO, F_SETPIPE_SZ, 65536*32); - fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 65536*32); - //fprintf(stderr, "csdr: F_SETPIPE_SZ\n"); + fcntl(STDIN_FILENO, F_SETPIPE_SZ, 65536*32); + fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 65536*32); + //fprintf(stderr, "csdr: F_SETPIPE_SZ\n"); - if(!strcmp(argv[1],"setbuf")) - { - if(argc<=2) return badsyntax("need required parameter (buffer size)"); - sscanf(argv[2],"%d",&the_bufsize); - if(the_bufsize<=0) return badsyntax("buffer size <= 0 is invalid"); - sendbufsize(the_bufsize); - clone_(the_bufsize); //After sending the buffer size out, just copy stdin to stdout - } + if(!strcmp(argv[1],"setbuf")) + { + if(argc<=2) return badsyntax("need required parameter (buffer size)"); + sscanf(argv[2],"%d",&the_bufsize); + if(the_bufsize<=0) return badsyntax("buffer size <= 0 is invalid"); + sendbufsize(the_bufsize); + clone_(the_bufsize); //After sending the buffer size out, just copy stdin to stdout + } - if(!strcmp(argv[1],"clone")) - { - if(!sendbufsize(initialize_buffers())) return -2; - clone_(the_bufsize); - } + if(!strcmp(argv[1],"clone")) + { + if(!sendbufsize(initialize_buffers())) return -2; + clone_(the_bufsize); + } #define SET_NONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) - if(!strcmp(argv[1],"fifo")) - { - if(!sendbufsize(initialize_buffers())) return -2; + if(!strcmp(argv[1],"fifo")) + { + if(!sendbufsize(initialize_buffers())) return -2; - int fifo_buffer_size; - if(argc<=2) return badsyntax("need required parameter (buffer_size)"); - sscanf(argv[2],"%d",&fifo_buffer_size); - int fifo_num_buffers; - if(argc<=3) return badsyntax("need required parameter (number of buffers)"); - sscanf(argv[3],"%d",&fifo_num_buffers); + int fifo_buffer_size; + if(argc<=2) return badsyntax("need required parameter (buffer_size)"); + sscanf(argv[2],"%d",&fifo_buffer_size); + int fifo_num_buffers; + if(argc<=3) return badsyntax("need required parameter (number of buffers)"); + sscanf(argv[3],"%d",&fifo_num_buffers); - char** fifo_buffers = (char**)malloc(sizeof(char*)*fifo_num_buffers); - for(int i=0;i STDIN_FILENO) ? STDOUT_FILENO : STDIN_FILENO) + 1; + int highfd = ((STDOUT_FILENO > STDIN_FILENO) ? STDOUT_FILENO : STDIN_FILENO) + 1; - int fifo_actual_buffer_wr = fifo_num_buffers - 1; - int fifo_actual_buffer_rd = 0; - int fifo_actual_buffer_wr_pos = 0; - int fifo_actual_buffer_rd_pos = 0; - int fifo_error = 0; - int fifo_overrun_shown = 0; + int fifo_actual_buffer_wr = fifo_num_buffers - 1; + int fifo_actual_buffer_rd = 0; + int fifo_actual_buffer_wr_pos = 0; + int fifo_actual_buffer_rd_pos = 0; + int fifo_error = 0; + int fifo_overrun_shown = 0; - for(;;) - { - select(highfd, &read_fds, NULL, NULL, NULL); + for(;;) + { + select(highfd, &read_fds, NULL, NULL, NULL); - //try to read until buffer is full - if(FD_ISSET(STDIN_FILENO, &read_fds)) for(;;) - { - 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); - //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); - if(!read_bytes || ((read_bytes<0)&&(fifo_error=read_bytes)) ) break; - fifo_actual_buffer_rd_pos+=read_bytes; - if(!((fifo_actual_buffer_rd==fifo_actual_buffer_wr-1)||(fifo_actual_buffer_wr==0&&fifo_actual_buffer_rd==fifo_num_buffers-1))) - { - if(fifo_actual_buffer_rd_pos==fifo_buffer_size) - { - fifo_overrun_shown = 0; - fifo_actual_buffer_rd++; - fifo_actual_buffer_rd_pos = 0; - if(fifo_actual_buffer_rd>=fifo_num_buffers) fifo_actual_buffer_rd=0; - } - } - else - { - if(fifo_actual_buffer_rd_pos==fifo_buffer_size) - { - fifo_actual_buffer_rd_pos = 0; //rewrite same buffer - if(!fifo_overrun_shown) { fifo_overrun_shown=1; fprintf(stderr, "fifo: circular buffer full, dropping samples\n"); } - } - } - } - //try to write until buffer is empty - if(FD_ISSET(STDOUT_FILENO, &write_fds)) for(;;) - { - if(fifo_actual_buffer_wr == fifo_actual_buffer_rd) break; - 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); - //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); - if(!written_bytes || ((written_bytes<0)&&(fifo_error=written_bytes)) ) break; - fifo_actual_buffer_wr_pos+=written_bytes; - if(fifo_actual_buffer_wr_pos==fifo_buffer_size) - { - fifo_actual_buffer_wr++; - fifo_actual_buffer_wr_pos = 0; - if(fifo_actual_buffer_wr>=fifo_num_buffers) fifo_actual_buffer_wr=0; - } + //try to read until buffer is full + if(FD_ISSET(STDIN_FILENO, &read_fds)) for(;;) + { + 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); + //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); + if(!read_bytes || ((read_bytes<0)&&(fifo_error=read_bytes)) ) break; + fifo_actual_buffer_rd_pos+=read_bytes; + if(!((fifo_actual_buffer_rd==fifo_actual_buffer_wr-1)||(fifo_actual_buffer_wr==0&&fifo_actual_buffer_rd==fifo_num_buffers-1))) + { + if(fifo_actual_buffer_rd_pos==fifo_buffer_size) + { + fifo_overrun_shown = 0; + fifo_actual_buffer_rd++; + fifo_actual_buffer_rd_pos = 0; + if(fifo_actual_buffer_rd>=fifo_num_buffers) fifo_actual_buffer_rd=0; + } + } + else + { + if(fifo_actual_buffer_rd_pos==fifo_buffer_size) + { + fifo_actual_buffer_rd_pos = 0; //rewrite same buffer + if(!fifo_overrun_shown) { fifo_overrun_shown=1; fprintf(stderr, "fifo: circular buffer full, dropping samples\n"); } + } + } + } + //try to write until buffer is empty + if(FD_ISSET(STDOUT_FILENO, &write_fds)) for(;;) + { + if(fifo_actual_buffer_wr == fifo_actual_buffer_rd) break; + 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); + //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); + if(!written_bytes || ((written_bytes<0)&&(fifo_error=written_bytes)) ) break; + fifo_actual_buffer_wr_pos+=written_bytes; + if(fifo_actual_buffer_wr_pos==fifo_buffer_size) + { + fifo_actual_buffer_wr++; + fifo_actual_buffer_wr_pos = 0; + if(fifo_actual_buffer_wr>=fifo_num_buffers) fifo_actual_buffer_wr=0; + } - } - if(fifo_error&&errno!=11) { fprintf(stderr,"fifo: fifo_error (%d)", errno); return -1; } - } + } + if(fifo_error&&errno!=11) { fprintf(stderr,"fifo: fifo_error (%d)", errno); return -1; } + } - return -1; + return -1; - } + } - if(!strcmp(argv[1],"convert_u8_f")) - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - fread(buffer_u8, sizeof(unsigned char), the_bufsize, stdin); - convert_u8_f(buffer_u8, output_buffer, the_bufsize); - FWRITE_R; - TRY_YIELD; - } - } - if(!strcmp(argv[1],"convert_f_u8")) //not tested - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_R; - convert_f_u8(input_buffer, buffer_u8, the_bufsize); - fwrite(buffer_u8, sizeof(unsigned char), the_bufsize, stdout); - TRY_YIELD; - } - } - if(!strcmp(argv[1],"convert_s8_f")) - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - fread((signed char*)buffer_u8, sizeof(signed char), the_bufsize, stdin); - convert_s8_f((signed char*)buffer_u8, output_buffer, the_bufsize); - FWRITE_R; - TRY_YIELD; - } - } - if(!strcmp(argv[1],"convert_f_s8")) //not tested - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_R; - convert_f_s8(input_buffer, (signed char*)buffer_u8, the_bufsize); - fwrite((signed char*)buffer_u8, sizeof(signed char), the_bufsize, stdout); - TRY_YIELD; - } - } - if((!strcmp(argv[1],"convert_f_i16")) || (!strcmp(argv[1],"convert_f_s16"))) - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_R; - convert_f_i16(input_buffer, buffer_i16, the_bufsize); - fwrite(buffer_i16, sizeof(short), the_bufsize, stdout); - TRY_YIELD; - } - } - if((!strcmp(argv[1],"convert_i16_f")) || (!strcmp(argv[1],"convert_s16_f"))) - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - fread(buffer_i16, sizeof(short), the_bufsize, stdin); - convert_i16_f(buffer_i16, output_buffer, the_bufsize); - FWRITE_R; - TRY_YIELD; - } - } - if(!strcmp(argv[1],"convert_f_s24")) - { - int bigendian = (argc>2) && (!strcmp(argv[2],"--bigendian")); - unsigned char* s24buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*3); - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_R; - convert_f_s24(input_buffer, s24buffer, the_bufsize, bigendian); - fwrite(s24buffer, sizeof(unsigned char)*3, the_bufsize, stdout); - TRY_YIELD; - } - } - if(!strcmp(argv[1],"convert_s24_f")) - { - int bigendian = (argc>2) && (!strcmp(argv[2],"--bigendian")); - unsigned char* s24buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*3); - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - fread(s24buffer, sizeof(unsigned char)*3, the_bufsize, stdin); - convert_s24_f(s24buffer, output_buffer, the_bufsize, bigendian); - FWRITE_R; - TRY_YIELD; - } - } - if(!strcmp(argv[1],"realpart_cf")) - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_C; - for(int i=0;i=3) sscanf(argv[2],"%g",&max_amplitude); - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_R; - limit_ff(input_buffer, output_buffer, the_bufsize, max_amplitude); - FWRITE_R; - TRY_YIELD; - } - } - if(!strcmp(argv[1],"yes_f")) - { - if(argc<=2) return badsyntax("need required parameter (to_repeat)"); - float to_repeat; - sscanf(argv[2],"%g",&to_repeat); - int buf_times = 0; - if(argc>=4) sscanf(argv[3],"%d",&buf_times); - if(!sendbufsize(initialize_buffers())) return -2; - for(int i=0;i/dev/null - //csdr yes_f 1 1000000 | time csdr shift_addition_cc 0.2 >/dev/null - //csdr yes_f 1 1000000 | time csdr shift_table_cc 0.2 >/dev/null + if(!strcmp(argv[1],"convert_u8_f")) + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + fread(buffer_u8, sizeof(unsigned char), the_bufsize, stdin); + convert_u8_f(buffer_u8, output_buffer, the_bufsize); + FWRITE_R; + TRY_YIELD; + } + } + if(!strcmp(argv[1],"convert_f_u8")) //not tested + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + FREAD_R; + convert_f_u8(input_buffer, buffer_u8, the_bufsize); + fwrite(buffer_u8, sizeof(unsigned char), the_bufsize, stdout); + TRY_YIELD; + } + } + if(!strcmp(argv[1],"convert_s8_f")) + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + fread((signed char*)buffer_u8, sizeof(signed char), the_bufsize, stdin); + convert_s8_f((signed char*)buffer_u8, output_buffer, the_bufsize); + FWRITE_R; + TRY_YIELD; + } + } + if(!strcmp(argv[1],"convert_f_s8")) //not tested + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + FREAD_R; + convert_f_s8(input_buffer, (signed char*)buffer_u8, the_bufsize); + fwrite((signed char*)buffer_u8, sizeof(signed char), the_bufsize, stdout); + TRY_YIELD; + } + } + if((!strcmp(argv[1],"convert_f_i16")) || (!strcmp(argv[1],"convert_f_s16"))) + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + FREAD_R; + convert_f_i16(input_buffer, buffer_i16, the_bufsize); + fwrite(buffer_i16, sizeof(short), the_bufsize, stdout); + TRY_YIELD; + } + } + if((!strcmp(argv[1],"convert_i16_f")) || (!strcmp(argv[1],"convert_s16_f"))) + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + fread(buffer_i16, sizeof(short), the_bufsize, stdin); + convert_i16_f(buffer_i16, output_buffer, the_bufsize); + FWRITE_R; + TRY_YIELD; + } + } + if(!strcmp(argv[1],"convert_f_s24")) + { + int bigendian = (argc>2) && (!strcmp(argv[2],"--bigendian")); + unsigned char* s24buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*3); + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + FREAD_R; + convert_f_s24(input_buffer, s24buffer, the_bufsize, bigendian); + fwrite(s24buffer, sizeof(unsigned char)*3, the_bufsize, stdout); + TRY_YIELD; + } + } + if(!strcmp(argv[1],"convert_s24_f")) + { + int bigendian = (argc>2) && (!strcmp(argv[2],"--bigendian")); + unsigned char* s24buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*3); + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + fread(s24buffer, sizeof(unsigned char)*3, the_bufsize, stdin); + convert_s24_f(s24buffer, output_buffer, the_bufsize, bigendian); + FWRITE_R; + TRY_YIELD; + } + } + if(!strcmp(argv[1],"realpart_cf")) + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + FREAD_C; + for(int i=0;i=3) sscanf(argv[2],"%g",&max_amplitude); + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + FREAD_R; + limit_ff(input_buffer, output_buffer, the_bufsize, max_amplitude); + FWRITE_R; + TRY_YIELD; + } + } + if(!strcmp(argv[1],"yes_f")) + { + if(argc<=2) return badsyntax("need required parameter (to_repeat)"); + float to_repeat; + sscanf(argv[2],"%g",&to_repeat); + int buf_times = 0; + if(argc>=4) sscanf(argv[3],"%d",&buf_times); + if(!sendbufsize(initialize_buffers())) return -2; + for(int i=0;i/dev/null + //csdr yes_f 1 1000000 | time csdr shift_addition_cc 0.2 >/dev/null + //csdr yes_f 1 1000000 | time csdr shift_table_cc 0.2 >/dev/null - if(!strcmp(argv[1],"shift_table_cc")) - { - bigbufs=1; - if(argc<=2) return badsyntax("need required parameter (rate)"); - float starting_phase=0; - float rate; - int table_size=65536; - sscanf(argv[2],"%g",&rate); - if(argc>3) sscanf(argv[3],"%d",&table_size); - if(!sendbufsize(initialize_buffers())) return -2; - shift_table_data_t table_data=shift_table_init(table_size); - fprintf(stderr,"shift_table_cc: LUT initialized\n"); - for(;;) - { - FEOF_CHECK; - if(!FREAD_C) break; - starting_phase=shift_table_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, table_data, starting_phase); - FWRITE_C; - TRY_YIELD; - } - return 0; - } + if(!strcmp(argv[1],"shift_table_cc")) + { + bigbufs=1; + if(argc<=2) return badsyntax("need required parameter (rate)"); + float starting_phase=0; + float rate; + int table_size=65536; + sscanf(argv[2],"%g",&rate); + if(argc>3) sscanf(argv[3],"%d",&table_size); + if(!sendbufsize(initialize_buffers())) return -2; + shift_table_data_t table_data=shift_table_init(table_size); + fprintf(stderr,"shift_table_cc: LUT initialized\n"); + for(;;) + { + FEOF_CHECK; + if(!FREAD_C) break; + starting_phase=shift_table_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, table_data, starting_phase); + FWRITE_C; + TRY_YIELD; + } + return 0; + } - if(!strcmp(argv[1],"shift_addfast_cc")) - { - bigbufs=1; + if(!strcmp(argv[1],"shift_addfast_cc")) + { + bigbufs=1; - float starting_phase=0; - float rate; + float starting_phase=0; + float rate; - int fd; - if(fd=init_fifo(argc,argv)) - { - while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); - } - else - { - if(argc<=2) return badsyntax("need required parameter (rate)"); - sscanf(argv[2],"%g",&rate); - } + int fd; + if(fd=init_fifo(argc,argv)) + { + while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); + } + else + { + if(argc<=2) return badsyntax("need required parameter (rate)"); + sscanf(argv[2],"%g",&rate); + } - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - shift_addfast_data_t data=shift_addfast_init(rate); - fprintf(stderr,"shift_addfast_cc: reinitialized to %g\n",rate); - int remain, current_size; - float* ibufptr; - float* obufptr; - for(;;) - { - FEOF_CHECK; - if(!FREAD_C) break; - remain=the_bufsize; - ibufptr=input_buffer; - obufptr=output_buffer; - while(remain) - { - current_size=(remain>1024)?1024:remain; - starting_phase=shift_addfast_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase); - ibufptr+=current_size*2; - obufptr+=current_size*2; - remain-=current_size; - } - FWRITE_C; - if(read_fifo_ctl(fd,"%g\n",&rate)) break; - TRY_YIELD; - } - } - return 0; - } + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + shift_addfast_data_t data=shift_addfast_init(rate); + fprintf(stderr,"shift_addfast_cc: reinitialized to %g\n",rate); + int remain, current_size; + float* ibufptr; + float* obufptr; + for(;;) + { + FEOF_CHECK; + if(!FREAD_C) break; + remain=the_bufsize; + ibufptr=input_buffer; + obufptr=output_buffer; + while(remain) + { + current_size=(remain>1024)?1024:remain; + starting_phase=shift_addfast_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase); + ibufptr+=current_size*2; + obufptr+=current_size*2; + remain-=current_size; + } + FWRITE_C; + if(read_fifo_ctl(fd,"%g\n",&rate)) break; + TRY_YIELD; + } + } + return 0; + } - if(!strcmp(argv[1],"shift_unroll_cc")) - { - bigbufs=1; + if(!strcmp(argv[1],"shift_unroll_cc")) + { + bigbufs=1; - float starting_phase=0; - float rate; + float starting_phase=0; + float rate; - int fd; - if(fd=init_fifo(argc,argv)) - { - while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); - } - else - { - if(argc<=2) return badsyntax("need required parameter (rate)"); - sscanf(argv[2],"%g",&rate); - } + int fd; + if(fd=init_fifo(argc,argv)) + { + while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); + } + else + { + if(argc<=2) return badsyntax("need required parameter (rate)"); + sscanf(argv[2],"%g",&rate); + } - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - shift_unroll_data_t data=shift_unroll_init(rate, 1024); - fprintf(stderr,"shift_unroll_cc: reinitialized to %g\n",rate); - int remain, current_size; - float* ibufptr; - float* obufptr; - for(;;) - { - FEOF_CHECK; - if(!FREAD_C) break; - remain=the_bufsize; - ibufptr=input_buffer; - obufptr=output_buffer; - while(remain) - { - current_size=(remain>1024)?1024:remain; - starting_phase=shift_unroll_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase); - ibufptr+=current_size*2; - obufptr+=current_size*2; - remain-=current_size; - } - FWRITE_C; - if(read_fifo_ctl(fd,"%g\n",&rate)) break; - TRY_YIELD; - } - } - return 0; - } + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + shift_unroll_data_t data=shift_unroll_init(rate, 1024); + fprintf(stderr,"shift_unroll_cc: reinitialized to %g\n",rate); + int remain, current_size; + float* ibufptr; + float* obufptr; + for(;;) + { + FEOF_CHECK; + if(!FREAD_C) break; + remain=the_bufsize; + ibufptr=input_buffer; + obufptr=output_buffer; + while(remain) + { + current_size=(remain>1024)?1024:remain; + starting_phase=shift_unroll_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase); + ibufptr+=current_size*2; + obufptr+=current_size*2; + remain-=current_size; + } + FWRITE_C; + if(read_fifo_ctl(fd,"%g\n",&rate)) break; + TRY_YIELD; + } + } + return 0; + } #ifdef LIBCSDR_GPL - if(!strcmp(argv[1],"decimating_shift_addition_cc")) - { - bigbufs=1; - if(argc<=2) return badsyntax("need required parameter (rate)"); - float starting_phase=0; - float rate; - int decimation=1; - sscanf(argv[2],"%g",&rate); - if(argc>3) sscanf(argv[3],"%d",&decimation); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize/decimation); - shift_addition_data_t d=decimating_shift_addition_init(rate, decimation); - decimating_shift_addition_status_t s; - s.decimation_remain=0; - s.starting_phase=0; - for(;;) - { - FEOF_CHECK; - if(!FREAD_C) break; - s=decimating_shift_addition_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, d, decimation, s); - fwrite(output_buffer, sizeof(float)*2, s.output_size, stdout); - TRY_YIELD; - } - return 0; - } + if(!strcmp(argv[1],"decimating_shift_addition_cc")) + { + bigbufs=1; + if(argc<=2) return badsyntax("need required parameter (rate)"); + float starting_phase=0; + float rate; + int decimation=1; + sscanf(argv[2],"%g",&rate); + if(argc>3) sscanf(argv[3],"%d",&decimation); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize/decimation); + shift_addition_data_t d=decimating_shift_addition_init(rate, decimation); + decimating_shift_addition_status_t s; + s.decimation_remain=0; + s.starting_phase=0; + for(;;) + { + FEOF_CHECK; + if(!FREAD_C) break; + s=decimating_shift_addition_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, d, decimation, s); + fwrite(output_buffer, sizeof(float)*2, s.output_size, stdout); + TRY_YIELD; + } + return 0; + } - if(!strcmp(argv[1],"shift_addition_cc")) - { - bigbufs=1; + if(!strcmp(argv[1],"shift_addition_cc")) + { + bigbufs=1; - float starting_phase=0; - float rate; + float starting_phase=0; + float rate; - int fd; - if(fd=init_fifo(argc,argv)) - { - while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); - } - else - { - if(argc<=2) return badsyntax("need required parameter (rate)"); - sscanf(argv[2],"%g",&rate); - } + int fd; + if(fd=init_fifo(argc,argv)) + { + while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); + } + else + { + if(argc<=2) return badsyntax("need required parameter (rate)"); + sscanf(argv[2],"%g",&rate); + } - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - shift_addition_data_t data=shift_addition_init(rate); - fprintf(stderr,"shift_addition_cc: reinitialized to %g\n",rate); - int remain, current_size; - float* ibufptr; - float* obufptr; - for(;;) - { - FEOF_CHECK; - if(!FREAD_C) break; - remain=the_bufsize; - ibufptr=input_buffer; - obufptr=output_buffer; - while(remain) - { - current_size=(remain>1024)?1024:remain; - starting_phase=shift_addition_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, data, starting_phase); - ibufptr+=current_size*2; - obufptr+=current_size*2; - remain-=current_size; - } - FWRITE_C; - if(read_fifo_ctl(fd,"%g\n",&rate)) break; - TRY_YIELD; - } - } - return 0; - } + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + shift_addition_data_t data=shift_addition_init(rate); + fprintf(stderr,"shift_addition_cc: reinitialized to %g\n",rate); + int remain, current_size; + float* ibufptr; + float* obufptr; + for(;;) + { + FEOF_CHECK; + if(!FREAD_C) break; + remain=the_bufsize; + ibufptr=input_buffer; + obufptr=output_buffer; + while(remain) + { + current_size=(remain>1024)?1024:remain; + starting_phase=shift_addition_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, data, starting_phase); + ibufptr+=current_size*2; + obufptr+=current_size*2; + remain-=current_size; + } + FWRITE_C; + if(read_fifo_ctl(fd,"%g\n",&rate)) break; + TRY_YIELD; + } + } + return 0; + } - if(!strcmp(argv[1],"shift_addition_cc_test")) - { - if(argc<=2) return badsyntax("need required parameter (rate)"); - float rate; - sscanf(argv[2],"%g",&rate); - //if(initialize_buffers()) return -2; //most likely we don't need this here - shift_addition_data_t data=shift_addition_init(rate); - shift_addition_cc_test(data); - return 0; - } + if(!strcmp(argv[1],"shift_addition_cc_test")) + { + if(argc<=2) return badsyntax("need required parameter (rate)"); + float rate; + sscanf(argv[2],"%g",&rate); + //if(initialize_buffers()) return -2; //most likely we don't need this here + shift_addition_data_t data=shift_addition_init(rate); + shift_addition_cc_test(data); + return 0; + } #endif - if(!strcmp(argv[1],"dcblock_ff")) - { - static dcblock_preserve_t dcp; //will be 0 as .bss is set to 0 - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_R; - dcp=dcblock_ff(input_buffer, output_buffer, the_bufsize, 0, dcp); - FWRITE_R; - TRY_YIELD; - } - } + if(!strcmp(argv[1],"dcblock_ff")) + { + static dcblock_preserve_t dcp; //will be 0 as .bss is set to 0 + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + FREAD_R; + dcp=dcblock_ff(input_buffer, output_buffer, the_bufsize, 0, dcp); + FWRITE_R; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"fastdcblock_ff")) - { - int dcblock_bufsize=SETBUF_DEFAULT_BUFSIZE; - if(argc>=3) sscanf(argv[2],"%d",&dcblock_bufsize); - float* dcblock_buffer=(float*)malloc(sizeof(float)*dcblock_bufsize); - static float last_dc_level=0.0; - getbufsize(); //it is just dummy - sendbufsize(dcblock_bufsize); - for(;;) - { - FEOF_CHECK; - fread(dcblock_buffer, sizeof(float), dcblock_bufsize, stdin); - last_dc_level=fastdcblock_ff(dcblock_buffer, dcblock_buffer, dcblock_bufsize, last_dc_level); - fwrite(dcblock_buffer, sizeof(float), dcblock_bufsize, stdout); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"fastdcblock_ff")) + { + int dcblock_bufsize=SETBUF_DEFAULT_BUFSIZE; + if(argc>=3) sscanf(argv[2],"%d",&dcblock_bufsize); + float* dcblock_buffer=(float*)malloc(sizeof(float)*dcblock_bufsize); + static float last_dc_level=0.0; + getbufsize(); //it is just dummy + sendbufsize(dcblock_bufsize); + for(;;) + { + FEOF_CHECK; + fread(dcblock_buffer, sizeof(float), dcblock_bufsize, stdin); + last_dc_level=fastdcblock_ff(dcblock_buffer, dcblock_buffer, dcblock_bufsize, last_dc_level); + fwrite(dcblock_buffer, sizeof(float), dcblock_bufsize, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"fmdemod_atan_cf")) - { - if(!sendbufsize(initialize_buffers())) return -2; - float last_phase=0; - for(;;) - { - FEOF_CHECK; - FREAD_C; - if(feof(stdin)) return 0; - last_phase=fmdemod_atan_cf((complexf*)input_buffer, output_buffer, the_bufsize, last_phase); - FWRITE_R; - TRY_YIELD; - } - } - if(!strcmp(argv[1],"fmdemod_quadri_cf")) - { - if(!sendbufsize(initialize_buffers())) return -2; - complexf last_sample; - last_sample.i=0.; - last_sample.q=0.; - for(;;) - { - FEOF_CHECK; - FREAD_C; - last_sample=fmdemod_quadri_cf((complexf*)input_buffer, output_buffer, the_bufsize, temp_f, last_sample); - FWRITE_R; - TRY_YIELD; - } - } - if(!strcmp(argv[1],"fmdemod_quadri_novect_cf")) - { - if(!sendbufsize(initialize_buffers())) return -2; - complexf last_sample; - last_sample.i=0.; - last_sample.q=0.; - for(;;) - { - FEOF_CHECK; - FREAD_C; - last_sample=fmdemod_quadri_novect_cf((complexf*)input_buffer, output_buffer, the_bufsize, last_sample); - FWRITE_R; - TRY_YIELD; - } - } - if(!strcmp(argv[1],"deemphasis_wfm_ff")) - { - if(argc<=3) return badsyntax("need required parameters (sample rate, tau)"); - if(!sendbufsize(initialize_buffers())) return -2; - int sample_rate; - sscanf(argv[2],"%d",&sample_rate); - float tau; - sscanf(argv[3],"%g",&tau); - fprintf(stderr,"deemphasis_wfm_ff: tau = %g, sample_rate = %d\n",tau,sample_rate); - float last_output=0; - for(;;) - { - FEOF_CHECK; - FREAD_R; - last_output=deemphasis_wfm_ff(input_buffer, output_buffer, the_bufsize, tau, sample_rate, last_output); - FWRITE_R; - TRY_YIELD; - } - } + if(!strcmp(argv[1],"fmdemod_atan_cf")) + { + if(!sendbufsize(initialize_buffers())) return -2; + float last_phase=0; + for(;;) + { + FEOF_CHECK; + FREAD_C; + if(feof(stdin)) return 0; + last_phase=fmdemod_atan_cf((complexf*)input_buffer, output_buffer, the_bufsize, last_phase); + FWRITE_R; + TRY_YIELD; + } + } + if(!strcmp(argv[1],"fmdemod_quadri_cf")) + { + if(!sendbufsize(initialize_buffers())) return -2; + complexf last_sample; + last_sample.i=0.; + last_sample.q=0.; + for(;;) + { + FEOF_CHECK; + FREAD_C; + last_sample=fmdemod_quadri_cf((complexf*)input_buffer, output_buffer, the_bufsize, temp_f, last_sample); + FWRITE_R; + TRY_YIELD; + } + } + if(!strcmp(argv[1],"fmdemod_quadri_novect_cf")) + { + if(!sendbufsize(initialize_buffers())) return -2; + complexf last_sample; + last_sample.i=0.; + last_sample.q=0.; + for(;;) + { + FEOF_CHECK; + FREAD_C; + last_sample=fmdemod_quadri_novect_cf((complexf*)input_buffer, output_buffer, the_bufsize, last_sample); + FWRITE_R; + TRY_YIELD; + } + } + if(!strcmp(argv[1],"deemphasis_wfm_ff")) + { + if(argc<=3) return badsyntax("need required parameters (sample rate, tau)"); + if(!sendbufsize(initialize_buffers())) return -2; + int sample_rate; + sscanf(argv[2],"%d",&sample_rate); + float tau; + sscanf(argv[3],"%g",&tau); + fprintf(stderr,"deemphasis_wfm_ff: tau = %g, sample_rate = %d\n",tau,sample_rate); + float last_output=0; + for(;;) + { + FEOF_CHECK; + FREAD_R; + last_output=deemphasis_wfm_ff(input_buffer, output_buffer, the_bufsize, tau, sample_rate, last_output); + FWRITE_R; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"detect_nan_ff")) - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_R; - int nan_detect=0; - for(int i=0; i=4) sscanf(argv[3],"%g",&transition_bw); + float transition_bw = 0.05; + if(argc>=4) sscanf(argv[3],"%g",&transition_bw); - window_t window = WINDOW_DEFAULT; - if(argc>=5) - { - window=firdes_get_window_from_string(argv[4]); - } - else fprintf(stderr,"fir_decimate_cc: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>=5) + { + window=firdes_get_window_from_string(argv[4]); + } + else fprintf(stderr,"fir_decimate_cc: window = %s\n",firdes_get_string_from_window(window)); - int taps_length=firdes_filter_len(transition_bw); - fprintf(stderr,"fir_decimate_cc: taps_length = %d\n",taps_length); + int taps_length=firdes_filter_len(transition_bw); + fprintf(stderr,"fir_decimate_cc: taps_length = %d\n",taps_length); - 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 - //fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize); + 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 + //fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize/factor); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize/factor); - int padded_taps_length = taps_length; - float *taps; + int padded_taps_length = taps_length; + float *taps; #define NEON_ALIGNMENT (4*4*2) #ifdef NEON_OPTS - fprintf(stderr,"taps_length = %d\n", taps_length); - padded_taps_length = taps_length+(NEON_ALIGNMENT/4)-1 - ((taps_length+(NEON_ALIGNMENT/4)-1)%(NEON_ALIGNMENT/4)); - fprintf(stderr,"padded_taps_length = %d\n", padded_taps_length); + fprintf(stderr,"taps_length = %d\n", taps_length); + padded_taps_length = taps_length+(NEON_ALIGNMENT/4)-1 - ((taps_length+(NEON_ALIGNMENT/4)-1)%(NEON_ALIGNMENT/4)); + fprintf(stderr,"padded_taps_length = %d\n", padded_taps_length); - taps = (float*) (float*)malloc((padded_taps_length+NEON_ALIGNMENT)*sizeof(float)); - fprintf(stderr,"taps = %x\n", taps); - taps = (float*)((((unsigned)taps)+NEON_ALIGNMENT-1) & ~(NEON_ALIGNMENT-1)); - fprintf(stderr,"taps = %x\n", taps); - for(int i=0;i= 1); + int factor; + sscanf(argv[2],"%d",&factor); + assert(factor >= 1); - float transition_bw = 0.05; - if(argc>=4) sscanf(argv[3],"%g",&transition_bw); - assert(transition_bw >= 0 && transition_bw < 1.); + float transition_bw = 0.05; + if(argc>=4) sscanf(argv[3],"%g",&transition_bw); + assert(transition_bw >= 0 && transition_bw < 1.); - window_t window = WINDOW_DEFAULT; - if(argc>=5) - { - window=firdes_get_window_from_string(argv[4]); - } - else fprintf(stderr,"fir_interpolate_cc: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>=5) + { + window=firdes_get_window_from_string(argv[4]); + } + else fprintf(stderr,"fir_interpolate_cc: window = %s\n",firdes_get_string_from_window(window)); - int taps_length=firdes_filter_len(transition_bw); - fprintf(stderr,"fir_interpolate_cc: taps_length = %d\n",taps_length); - assert(taps_length > 0); + int taps_length=firdes_filter_len(transition_bw); + fprintf(stderr,"fir_interpolate_cc: taps_length = %d\n",taps_length); + assert(taps_length > 0); - 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 - //fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize); + 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 + //fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize*factor); - assert(the_bufsize > 0); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize*factor); + assert(the_bufsize > 0); - float *taps; - taps=(float*)malloc(taps_length*sizeof(float)); - assert(taps); + float *taps; + taps=(float*)malloc(taps_length*sizeof(float)); + assert(taps); - firdes_lowpass_f(taps,taps_length,0.5/(float)factor,window); + firdes_lowpass_f(taps,taps_length,0.5/(float)factor,window); - int input_skip=0; - int output_size=0; - float* interp_output_buffer = (float*)malloc(sizeof(float)*2*the_bufsize*factor); - for(;;) - { - FEOF_CHECK; - output_size=fir_interpolate_cc((complexf*)input_buffer, (complexf*)interp_output_buffer, the_bufsize, factor, taps, taps_length); - //fprintf(stderr, "os %d\n",output_size); - fwrite(interp_output_buffer, sizeof(complexf), output_size, stdout); - TRY_YIELD; - input_skip=output_size/factor; - memmove((complexf*)input_buffer,((complexf*)input_buffer)+input_skip,(the_bufsize-input_skip)*sizeof(complexf)); //memmove lets the source and destination overlap - fread(((complexf*)input_buffer)+(the_bufsize-input_skip), sizeof(complexf), input_skip, stdin); - //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)); - } - } + int input_skip=0; + int output_size=0; + float* interp_output_buffer = (float*)malloc(sizeof(float)*2*the_bufsize*factor); + for(;;) + { + FEOF_CHECK; + output_size=fir_interpolate_cc((complexf*)input_buffer, (complexf*)interp_output_buffer, the_bufsize, factor, taps, taps_length); + //fprintf(stderr, "os %d\n",output_size); + fwrite(interp_output_buffer, sizeof(complexf), output_size, stdout); + TRY_YIELD; + input_skip=output_size/factor; + memmove((complexf*)input_buffer,((complexf*)input_buffer)+input_skip,(the_bufsize-input_skip)*sizeof(complexf)); //memmove lets the source and destination overlap + fread(((complexf*)input_buffer)+(the_bufsize-input_skip), sizeof(complexf), input_skip, stdin); + //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)); + } + } - /*if(!strcmp(argv[1],"ejw_test")) - { - printf("ejqd=["); - complexf ejw; - float phase=0; - for(int i=0;i<63;i++) - { - e_powj(&ejw,phase); - phase+=PI*0.3; - printf("%g+(%g)*i ",iof(&ejw,0),qof(&ejw,0)); - } - printf("];"); - return 0; - }*/ - if(!strcmp(argv[1],"firdes_lowpass_f")) - { - //Process the params - if(argc<=3) return badsyntax("need required parameters (cutoff_rate, length)"); + /*if(!strcmp(argv[1],"ejw_test")) + { + printf("ejqd=["); + complexf ejw; + float phase=0; + for(int i=0;i<63;i++) + { + e_powj(&ejw,phase); + phase+=PI*0.3; + printf("%g+(%g)*i ",iof(&ejw,0),qof(&ejw,0)); + } + printf("];"); + return 0; + }*/ + if(!strcmp(argv[1],"firdes_lowpass_f")) + { + //Process the params + if(argc<=3) return badsyntax("need required parameters (cutoff_rate, length)"); - float cutoff_rate; - sscanf(argv[2],"%g",&cutoff_rate); + float cutoff_rate; + sscanf(argv[2],"%g",&cutoff_rate); - int length; - sscanf(argv[3],"%d",&length); - if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd"); + int length; + sscanf(argv[3],"%d",&length); + if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd"); - window_t window = WINDOW_DEFAULT; - if(argc>=5) - { - window=firdes_get_window_from_string(argv[4]); - } - else fprintf(stderr,"firdes_lowpass_f: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>=5) + { + window=firdes_get_window_from_string(argv[4]); + } + else fprintf(stderr,"firdes_lowpass_f: window = %s\n",firdes_get_string_from_window(window)); - int octave=(argc>=6 && !strcmp("--octave",argv[5])); + int octave=(argc>=6 && !strcmp("--octave",argv[5])); - float* taps=(float*)malloc(sizeof(float)*length); + float* taps=(float*)malloc(sizeof(float)*length); - //Make the filter - firdes_lowpass_f(taps,length,cutoff_rate,window); + //Make the filter + firdes_lowpass_f(taps,length,cutoff_rate,window); - //Do the output - if(octave) printf("taps=["); - for(int i=0;i=6) - { - window=firdes_get_window_from_string(argv[5]); - } - else fprintf(stderr,"firdes_bandpass_c: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>=6) + { + window=firdes_get_window_from_string(argv[5]); + } + else fprintf(stderr,"firdes_bandpass_c: window = %s\n",firdes_get_string_from_window(window)); - int octave=(argc>=7 && !strcmp("--octave",argv[6])); + int octave=(argc>=7 && !strcmp("--octave",argv[6])); - complexf* taps=(complexf*)malloc(sizeof(complexf)*length); + complexf* taps=(complexf*)malloc(sizeof(complexf)*length); - //Make the filter - firdes_bandpass_c(taps, length, low_cut, high_cut, window); + //Make the filter + firdes_bandpass_c(taps, length, low_cut, high_cut, window); - //Do the output - if(octave) printf("taps=["); - for(int i=0;i=3) sscanf(argv[2],"%hd",&hang_time); + if(!strcmp(argv[1],"agc_ff")) + { + //Process the params + //Explanation of what these actually do is in the DSP source. + //These good default values are for SSB sampled at 48000 kHz. + short hang_time=200; + if(argc>=3) sscanf(argv[2],"%hd",&hang_time); - float reference=0.2; - if(argc>=4) sscanf(argv[3],"%g",&reference); + float reference=0.2; + if(argc>=4) sscanf(argv[3],"%g",&reference); - float attack_rate=0.01; - if(argc>=5) sscanf(argv[4],"%g",&attack_rate); + float attack_rate=0.01; + if(argc>=5) sscanf(argv[4],"%g",&attack_rate); - float decay_rate=0.0001; - if(argc>=6) sscanf(argv[5],"%g",&decay_rate); + float decay_rate=0.0001; + if(argc>=6) sscanf(argv[5],"%g",&decay_rate); - float max_gain=65536; - if(argc>=7) sscanf(argv[6],"%g",&max_gain); + float max_gain=65536; + if(argc>=7) sscanf(argv[6],"%g",&max_gain); - short attack_wait=0; - if(argc>=8) sscanf(argv[7],"%hd",&attack_wait); + short attack_wait=0; + if(argc>=8) sscanf(argv[7],"%hd",&attack_wait); - float filter_alpha=0.999;//0.001; - if(argc>=9) sscanf(argv[8],"%g",&filter_alpha); + float filter_alpha=0.999;//0.001; + if(argc>=9) sscanf(argv[8],"%g",&filter_alpha); - if(!sendbufsize(initialize_buffers())) return -2; + if(!sendbufsize(initialize_buffers())) return -2; - float last_gain=1.0; - for(;;) - { - FEOF_CHECK; - FREAD_R; - 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); - FWRITE_R; - TRY_YIELD; - } - } + float last_gain=1.0; + for(;;) + { + FEOF_CHECK; + FREAD_R; + 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); + FWRITE_R; + TRY_YIELD; + } + } #endif - if(!strcmp(argv[1],"fastagc_ff")) - { + if(!strcmp(argv[1],"fastagc_ff")) + { - static fastagc_ff_t input; //is in .bss and gets cleared to zero before main() + static fastagc_ff_t input; //is in .bss and gets cleared to zero before main() - input.input_size=1024; - if(argc>=3) sscanf(argv[2],"%d",&input.input_size); + input.input_size=1024; + if(argc>=3) sscanf(argv[2],"%d",&input.input_size); - getbufsize(); //dummy - sendbufsize(input.input_size); + getbufsize(); //dummy + sendbufsize(input.input_size); - input.reference=1.0; - if(argc>=4) sscanf(argv[3],"%g",&input.reference); + input.reference=1.0; + if(argc>=4) sscanf(argv[3],"%g",&input.reference); - //input.max_peak_ratio=12.0; - //if(argc>=5) sscanf(argv[3],"%g",&input.max_peak_ratio); + //input.max_peak_ratio=12.0; + //if(argc>=5) sscanf(argv[3],"%g",&input.max_peak_ratio); - input.buffer_1=(float*)calloc(input.input_size,sizeof(float)); - input.buffer_2=(float*)calloc(input.input_size,sizeof(float)); - input.buffer_input=(float*)malloc(sizeof(float)*input.input_size); - float* agc_output_buffer=(float*)malloc(sizeof(float)*input.input_size); - for(;;) - { - FEOF_CHECK; - fread(input.buffer_input, sizeof(float), input.input_size, stdin); - fastagc_ff(&input, agc_output_buffer); - fwrite(agc_output_buffer, sizeof(float), input.input_size, stdout); - TRY_YIELD; - } - } + input.buffer_1=(float*)calloc(input.input_size,sizeof(float)); + input.buffer_2=(float*)calloc(input.input_size,sizeof(float)); + input.buffer_input=(float*)malloc(sizeof(float)*input.input_size); + float* agc_output_buffer=(float*)malloc(sizeof(float)*input.input_size); + for(;;) + { + FEOF_CHECK; + fread(input.buffer_input, sizeof(float), input.input_size, stdin); + fastagc_ff(&input, agc_output_buffer); + fwrite(agc_output_buffer, sizeof(float), input.input_size, stdout); + TRY_YIELD; + } + } - int suboptimal; - if( (suboptimal=!strcmp(argv[1],"suboptimal_rational_resampler_ff"))||(!strcmp(argv[1],"rational_resampler_ff")) ) - { + int suboptimal; + if( (suboptimal=!strcmp(argv[1],"suboptimal_rational_resampler_ff"))||(!strcmp(argv[1],"rational_resampler_ff")) ) + { - //last@2014-11-06: ./docompile; ./csdr yes_f 1.0 | ./csdr suboptimal_rational_resampler_ff 5 2 + //last@2014-11-06: ./docompile; ./csdr yes_f 1.0 | ./csdr suboptimal_rational_resampler_ff 5 2 - //Process the params - if(argc<=3) return badsyntax("need required parameters (interpolation, decimation)"); - int interpolation; - sscanf(argv[2],"%d",&interpolation); - int decimation; - sscanf(argv[3],"%d",&decimation); + //Process the params + if(argc<=3) return badsyntax("need required parameters (interpolation, decimation)"); + int interpolation; + sscanf(argv[2],"%d",&interpolation); + int decimation; + sscanf(argv[3],"%d",&decimation); - float transition_bw=0.05; - if(argc>=5) sscanf(argv[4],"%g",&transition_bw); + float transition_bw=0.05; + if(argc>=5) sscanf(argv[4],"%g",&transition_bw); - window_t window = WINDOW_DEFAULT; - if(argc>=6) - { - window=firdes_get_window_from_string(argv[5]); - } - else fprintf(stderr,"rational_resampler_ff: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>=6) + { + window=firdes_get_window_from_string(argv[5]); + } + else fprintf(stderr,"rational_resampler_ff: window = %s\n",firdes_get_string_from_window(window)); - if(suboptimal) fprintf(stderr,"note: suboptimal rational resampler chosen.\n"); + if(suboptimal) fprintf(stderr,"note: suboptimal rational resampler chosen.\n"); - if(!initialize_buffers()) return -2; + if(!initialize_buffers()) return -2; - if(decimation==1&&interpolation==1) { sendbufsize(the_bufsize); clone_(the_bufsize); } //copy input to output in this special case (and stick in this function). + if(decimation==1&&interpolation==1) { sendbufsize(the_bufsize); clone_(the_bufsize); } //copy input to output in this special case (and stick in this function). - //Alloc output buffer - int resampler_output_buffer_size=(the_bufsize*interpolation)/decimation; - sendbufsize(resampler_output_buffer_size); - float* resampler_output_buffer=(float*)malloc(sizeof(float)*resampler_output_buffer_size); - float* suboptimal_resampler_temp_buffer = (suboptimal)?(float*)malloc(sizeof(float)*the_bufsize*interpolation):NULL; + //Alloc output buffer + int resampler_output_buffer_size=(the_bufsize*interpolation)/decimation; + sendbufsize(resampler_output_buffer_size); + float* resampler_output_buffer=(float*)malloc(sizeof(float)*resampler_output_buffer_size); + float* suboptimal_resampler_temp_buffer = (suboptimal)?(float*)malloc(sizeof(float)*the_bufsize*interpolation):NULL; - //Generate filter taps - int taps_length = firdes_filter_len(transition_bw); - float* taps = (float*)malloc(sizeof(float)*taps_length); - rational_resampler_get_lowpass_f(taps, taps_length, interpolation, decimation, window); + //Generate filter taps + int taps_length = firdes_filter_len(transition_bw); + float* taps = (float*)malloc(sizeof(float)*taps_length); + rational_resampler_get_lowpass_f(taps, taps_length, interpolation, decimation, window); - static rational_resampler_ff_t d; //in .bss => initialized to zero + static rational_resampler_ff_t d; //in .bss => initialized to zero - for(;;) - { - FEOF_CHECK; - if(d.input_processed==0) d.input_processed=the_bufsize; - else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed)); - fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin); - //if(suboptimal) d=suboptimal_rational_resampler_ff(input_buffer, resampler_output_buffer, the_bufsize, interpolation, decimation, taps, taps_length, suboptimal_resampler_temp_buffer); else - d=rational_resampler_ff(input_buffer, resampler_output_buffer, the_bufsize, interpolation, decimation, taps, taps_length, d.last_taps_delay); - //fprintf(stderr,"resampled %d %d, %d\n",d.output_size, d.input_processed, d.input_processed); - fwrite(resampler_output_buffer, sizeof(float), d.output_size, stdout); - TRY_YIELD; - } - } + for(;;) + { + FEOF_CHECK; + if(d.input_processed==0) d.input_processed=the_bufsize; + else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed)); + fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin); + //if(suboptimal) d=suboptimal_rational_resampler_ff(input_buffer, resampler_output_buffer, the_bufsize, interpolation, decimation, taps, taps_length, suboptimal_resampler_temp_buffer); else + d=rational_resampler_ff(input_buffer, resampler_output_buffer, the_bufsize, interpolation, decimation, taps, taps_length, d.last_taps_delay); + //fprintf(stderr,"resampled %d %d, %d\n",d.output_size, d.input_processed, d.input_processed); + fwrite(resampler_output_buffer, sizeof(float), d.output_size, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"fractional_decimator_ff")) - { - //Process the params - if(argc<=2) return badsyntax("need required parameters (rate)"); - float rate; - sscanf(argv[2],"%g",&rate); + if(!strcmp(argv[1],"fractional_decimator_ff")) + { + //Process the params + if(argc<=2) return badsyntax("need required parameters (rate)"); + float rate; + sscanf(argv[2],"%g",&rate); - int num_poly_points = 12; - if(argc>=4) sscanf(argv[3],"%d",&num_poly_points); - if(num_poly_points&1) return badsyntax("num_poly_points should be even"); - if(num_poly_points<2) return badsyntax("num_poly_points should be >= 2"); + int num_poly_points = 12; + if(argc>=4) sscanf(argv[3],"%d",&num_poly_points); + if(num_poly_points&1) return badsyntax("num_poly_points should be even"); + if(num_poly_points<2) return badsyntax("num_poly_points should be >= 2"); - int use_prefilter = 0; - float transition_bw=0.03; - window_t window = WINDOW_DEFAULT; - if(argc>=5) - { - if(!strcmp(argv[4], "--prefilter")) - { - fprintf(stderr, "fractional_decimator_ff: using prefilter with default values\n"); - use_prefilter = 1; - } - else - { - sscanf(argv[4],"%g",&transition_bw); - if(argc>=6) window = firdes_get_window_from_string(argv[5]); - } - } - fprintf(stderr,"fractional_decimator_ff: use_prefilter = %d, num_poly_points = %d, transition_bw = %g, window = %s\n", - use_prefilter, num_poly_points, transition_bw, firdes_get_string_from_window(window)); + int use_prefilter = 0; + float transition_bw=0.03; + window_t window = WINDOW_DEFAULT; + if(argc>=5) + { + if(!strcmp(argv[4], "--prefilter")) + { + fprintf(stderr, "fractional_decimator_ff: using prefilter with default values\n"); + use_prefilter = 1; + } + else + { + sscanf(argv[4],"%g",&transition_bw); + if(argc>=6) window = firdes_get_window_from_string(argv[5]); + } + } + fprintf(stderr,"fractional_decimator_ff: use_prefilter = %d, num_poly_points = %d, transition_bw = %g, window = %s\n", + use_prefilter, num_poly_points, transition_bw, firdes_get_string_from_window(window)); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize / rate); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize / rate); - if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function). + if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function). - //Generate filter taps - int taps_length = 0; - float* taps = NULL; - if(use_prefilter) - { - taps_length = firdes_filter_len(transition_bw); - fprintf(stderr,"fractional_decimator_ff: taps_length = %d\n",taps_length); - taps = (float*)malloc(sizeof(float)*taps_length); - firdes_lowpass_f(taps, taps_length, 0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff - //for(int=0;i=4) sscanf(argv[3],"%g",&transition_bw); + float transition_bw=0.03; + if(argc>=4) sscanf(argv[3],"%g",&transition_bw); - window_t window = WINDOW_DEFAULT; - if(argc>=5) - { - window = firdes_get_window_from_string(argv[4]); - } - else fprintf(stderr,"old_fractional_decimator_ff: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>=5) + { + window = firdes_get_window_from_string(argv[4]); + } + else fprintf(stderr,"old_fractional_decimator_ff: window = %s\n",firdes_get_string_from_window(window)); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize / rate); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize / rate); - if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function). + if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function). - //Generate filter taps - int taps_length = firdes_filter_len(transition_bw); - fprintf(stderr,"old_fractional_decimator_ff: taps_length = %d\n",taps_length); - float* taps = (float*)malloc(sizeof(float)*taps_length); - firdes_lowpass_f(taps, taps_length, 0.59*0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff - //for(int=0;i initialized to zero - for(;;) - { - FEOF_CHECK; - if(d.input_processed==0) d.input_processed=the_bufsize; - else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed)); - fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin); - d = old_fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, rate, taps, taps_length, d); - fwrite(output_buffer, sizeof(float), d.output_size, stdout); - TRY_YIELD; - } - } + static old_fractional_decimator_ff_t d; //in .bss => initialized to zero + for(;;) + { + FEOF_CHECK; + if(d.input_processed==0) d.input_processed=the_bufsize; + else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed)); + fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin); + d = old_fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, rate, taps, taps_length, d); + fwrite(output_buffer, sizeof(float), d.output_size, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"fft_cc")) - { - if(argc<=3) return badsyntax("need required parameters (fft_size, out_of_every_n_samples)"); - int fft_size; - sscanf(argv[2],"%d",&fft_size); - if(log2n(fft_size)==-1) return badsyntax("fft_size should be power of 2"); - int every_n_samples; - sscanf(argv[3],"%d",&every_n_samples); - int benchmark=0; - int octave=0; - window_t window = WINDOW_DEFAULT; - if(argc>=5) - { - window=firdes_get_window_from_string(argv[4]); - } - if(argc>=6) - { - benchmark|=!strcmp("--benchmark",argv[5]); - octave|=!strcmp("--octave",argv[5]); - } - if(argc>=7) - { - benchmark|=!strcmp("--benchmark",argv[6]); - octave|=!strcmp("--octave",argv[6]); - } + if(!strcmp(argv[1],"fft_cc")) + { + if(argc<=3) return badsyntax("need required parameters (fft_size, out_of_every_n_samples)"); + int fft_size; + sscanf(argv[2],"%d",&fft_size); + if(log2n(fft_size)==-1) return badsyntax("fft_size should be power of 2"); + int every_n_samples; + sscanf(argv[3],"%d",&every_n_samples); + int benchmark=0; + int octave=0; + window_t window = WINDOW_DEFAULT; + if(argc>=5) + { + window=firdes_get_window_from_string(argv[4]); + } + if(argc>=6) + { + benchmark|=!strcmp("--benchmark",argv[5]); + octave|=!strcmp("--octave",argv[5]); + } + if(argc>=7) + { + benchmark|=!strcmp("--benchmark",argv[6]); + octave|=!strcmp("--octave",argv[6]); + } - if(!initialize_buffers()) return -2; - sendbufsize(fft_size); + if(!initialize_buffers()) return -2; + sendbufsize(fft_size); - //make FFT plan - complexf* input=(complexf*)fft_malloc(sizeof(complexf)*fft_size); - complexf* windowed=(complexf*)fft_malloc(sizeof(complexf)*fft_size); - complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_size); - if(benchmark) fprintf(stderr,"fft_cc: benchmarking..."); - FFT_PLAN_T* plan=make_fft_c2c(fft_size, windowed, output, 1, benchmark); - if(benchmark) fprintf(stderr," done\n"); - if(octave) printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); - float *windowt; - windowt = precalculate_window(fft_size, window); - for(;;) - { - FEOF_CHECK; - if(every_n_samples>fft_size) - { - fread(input, sizeof(complexf), fft_size, stdin); - //skipping samples before next FFT (but fseek doesn't work for pipes) - for(int seek_remain=every_n_samples-fft_size;seek_remain>0;seek_remain-=the_bufsize) - { - fread(temp_f, sizeof(complexf), MIN_M(the_bufsize,seek_remain), stdin); - } - } - else - { - //overlapped FFT - for(int i=0;i=3) sscanf(argv[2],"%g",&add_db); + //make FFT plan + complexf* input=(complexf*)fft_malloc(sizeof(complexf)*fft_size); + complexf* windowed=(complexf*)fft_malloc(sizeof(complexf)*fft_size); + complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_size); + if(benchmark) fprintf(stderr,"fft_cc: benchmarking..."); + FFT_PLAN_T* plan=make_fft_c2c(fft_size, windowed, output, 1, benchmark); + if(benchmark) fprintf(stderr," done\n"); + if(octave) printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); + float *windowt; + windowt = precalculate_window(fft_size, window); + for(;;) + { + FEOF_CHECK; + if(every_n_samples>fft_size) + { + fread(input, sizeof(complexf), fft_size, stdin); + //skipping samples before next FFT (but fseek doesn't work for pipes) + for(int seek_remain=every_n_samples-fft_size;seek_remain>0;seek_remain-=the_bufsize) + { + fread(temp_f, sizeof(complexf), MIN_M(the_bufsize,seek_remain), stdin); + } + } + else + { + //overlapped FFT + for(int i=0;i=3) sscanf(argv[2],"%g",&add_db); - if(!sendbufsize(initialize_buffers())) return -2; + if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - fread(input_buffer, sizeof(complexf), the_bufsize, stdin); - logpower_cf((complexf*)input_buffer,output_buffer, the_bufsize, add_db); - fwrite(output_buffer, sizeof(float), the_bufsize, stdout); - TRY_YIELD; - } - } + for(;;) + { + FEOF_CHECK; + fread(input_buffer, sizeof(complexf), the_bufsize, stdin); + logpower_cf((complexf*)input_buffer,output_buffer, the_bufsize, add_db); + fwrite(output_buffer, sizeof(float), the_bufsize, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"logaveragepower_cf")) - { - bigbufs=1; - if(argc<=4) return badsyntax("need required parameters (add_db, table_size, avgnumber)"); - float add_db=0; - int avgnumber=0; - int fft_size=0; - - sscanf(argv[2],"%g",&add_db); - sscanf(argv[3],"%d",&fft_size); - sscanf(argv[4],"%d",&avgnumber); - - float *input = malloc(sizeof(float)*2 * fft_size); - float *output = malloc(sizeof(float) * fft_size); + if(!strcmp(argv[1],"logaveragepower_cf")) + { + bigbufs=1; + if(argc<=4) return badsyntax("need required parameters (add_db, table_size, avgnumber)"); + float add_db=0; + int avgnumber=0; + int fft_size=0; + + sscanf(argv[2],"%g",&add_db); + sscanf(argv[3],"%d",&fft_size); + sscanf(argv[4],"%d",&avgnumber); + + float *input = malloc(sizeof(float)*2 * fft_size); + float *output = malloc(sizeof(float) * fft_size); - add_db -= 10.0*log10(avgnumber); - for(;;) - { - int i,n; - for(i = 0; i < fft_size; i++) { - output[i] = 0; - } - FEOF_CHECK; - for(n = 0; n < avgnumber; n++) { - fread (input, sizeof(float)*2, fft_size, stdin); - accumulate_power_cf((complexf*)input, output, fft_size); - } - log_ff(output, output, fft_size, add_db); - fwrite (output, sizeof(float), fft_size, stdout); - TRY_YIELD; - } - return 0; - } + add_db -= 10.0*log10(avgnumber); + for(;;) + { + int i,n; + for(i = 0; i < fft_size; i++) { + output[i] = 0; + } + FEOF_CHECK; + for(n = 0; n < avgnumber; n++) { + fread (input, sizeof(float)*2, fft_size, stdin); + accumulate_power_cf((complexf*)input, output, fft_size); + } + log_ff(output, output, fft_size, add_db); + fwrite (output, sizeof(float), fft_size, stdout); + TRY_YIELD; + } + return 0; + } - if(!strcmp(argv[1],"fft_exchange_sides_ff")) - { - if(argc<=2) return badsyntax("need required parameters (fft_size)"); - int fft_size; - sscanf(argv[2],"%d",&fft_size); - if(!getbufsize()) return -2; //dummy - sendbufsize(fft_size); - float* input_buffer_s1 = (float*)malloc(sizeof(float)*fft_size/2); - float* input_buffer_s2 = (float*)malloc(sizeof(float)*fft_size/2); - for(;;) - { - FEOF_CHECK; - fread(input_buffer_s1, sizeof(float), fft_size/2, stdin); - fread(input_buffer_s2, sizeof(float), fft_size/2, stdin); - fwrite(input_buffer_s2, sizeof(float), fft_size/2, stdout); - fwrite(input_buffer_s1, sizeof(float), fft_size/2, stdout); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"fft_exchange_sides_ff")) + { + if(argc<=2) return badsyntax("need required parameters (fft_size)"); + int fft_size; + sscanf(argv[2],"%d",&fft_size); + if(!getbufsize()) return -2; //dummy + sendbufsize(fft_size); + float* input_buffer_s1 = (float*)malloc(sizeof(float)*fft_size/2); + float* input_buffer_s2 = (float*)malloc(sizeof(float)*fft_size/2); + for(;;) + { + FEOF_CHECK; + fread(input_buffer_s1, sizeof(float), fft_size/2, stdin); + fread(input_buffer_s2, sizeof(float), fft_size/2, stdin); + fwrite(input_buffer_s2, sizeof(float), fft_size/2, stdout); + fwrite(input_buffer_s1, sizeof(float), fft_size/2, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"fft_one_side_ff")) - { - if(argc<=2) return badsyntax("need required parameters (fft_size)"); - int fft_size; - sscanf(argv[2],"%d",&fft_size); - if(!getbufsize()) return -2; - sendbufsize(fft_size); - float* input_buffer_s1 = (float*)malloc(sizeof(float)*fft_size/2); - float* input_buffer_s2 = (float*)malloc(sizeof(float)*fft_size/2); - for(;;) - { - FEOF_CHECK; - fread(input_buffer_s1, sizeof(float), fft_size/2, stdin); - fread(input_buffer_s2, sizeof(float), fft_size/2, stdin); - fwrite(input_buffer_s1, sizeof(float), fft_size/2, stdout); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"fft_one_side_ff")) + { + if(argc<=2) return badsyntax("need required parameters (fft_size)"); + int fft_size; + sscanf(argv[2],"%d",&fft_size); + if(!getbufsize()) return -2; + sendbufsize(fft_size); + float* input_buffer_s1 = (float*)malloc(sizeof(float)*fft_size/2); + float* input_buffer_s2 = (float*)malloc(sizeof(float)*fft_size/2); + for(;;) + { + FEOF_CHECK; + fread(input_buffer_s1, sizeof(float), fft_size/2, stdin); + fread(input_buffer_s2, sizeof(float), fft_size/2, stdin); + fwrite(input_buffer_s1, sizeof(float), fft_size/2, stdout); + TRY_YIELD; + } + } #ifdef USE_IMA_ADPCM @@ -1693,1209 +1693,1209 @@ int main(int argc, char *argv[]) //so we just add data to become garbage and get skipped. //COMPRESS_FFT_PAD_N should be even. - if(!strcmp(argv[1],"compress_fft_adpcm_f_u8")) - { - if(argc<=2) return badsyntax("need required parameters (fft_size)"); - int fft_size; - sscanf(argv[2],"%d",&fft_size); - int real_data_size=fft_size+COMPRESS_FFT_PAD_N; - if(!getbufsize()) return -2; //dummy - sendbufsize(real_data_size); - float* input_buffer_cwa = (float*)malloc(sizeof(float)*real_data_size); - short* temp_buffer_cwa = (short*)malloc(sizeof(short)*real_data_size); - unsigned char* output_buffer_cwa = (unsigned char*)malloc(sizeof(unsigned char)*(real_data_size/2)); - ima_adpcm_state_t d; - d.index=d.previousValue=0; - for(;;) - { - FEOF_CHECK; - fread(input_buffer_cwa+COMPRESS_FFT_PAD_N, sizeof(float), fft_size, stdin); - for(int i=0;i=5)&&!strcmp(argv[4],"--benchmark"); - fprintf(stderr,"fft_benchmark: FFT library used: %s\n",FFT_LIBRARY_USED); + int benchmark=(argc>=5)&&!strcmp(argv[4],"--benchmark"); + fprintf(stderr,"fft_benchmark: FFT library used: %s\n",FFT_LIBRARY_USED); - complexf* input=(complexf*)fft_malloc(sizeof(complexf)*fft_size); - complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_size); + complexf* input=(complexf*)fft_malloc(sizeof(complexf)*fft_size); + complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_size); - //fill input with random data - srand(time(NULL)); - for(int i=0;i=6) window=firdes_get_window_from_string(argv[5]); - else fprintf(stderr,"bandpass_fir_fft_cc: window = %s\n",firdes_get_string_from_window(window)); + if(!strcmp(argv[1],"bandpass_fir_fft_cc")) //this command does not exist as a separate function + { + float low_cut; + float high_cut; + float transition_bw; + window_t window = WINDOW_DEFAULT; + int fd; + if(fd=init_fifo(argc,argv)) + { + while(!read_fifo_ctl(fd,"%g %g\n",&low_cut,&high_cut)) usleep(10000); + if(argc<=4) return badsyntax("need more required parameters (transition_bw)"); + } + else + { + if(argc<=4) return badsyntax("need required parameters (low_cut, high_cut, transition_bw)"); + sscanf(argv[2],"%g",&low_cut); + sscanf(argv[3],"%g",&high_cut); + } + sscanf(argv[4],"%g",&transition_bw); + if(argc>=6) window=firdes_get_window_from_string(argv[5]); + else fprintf(stderr,"bandpass_fir_fft_cc: window = %s\n",firdes_get_string_from_window(window)); - //calculate the FFT size and the other length parameters - int taps_length=firdes_filter_len(transition_bw); //the number of non-zero taps - int fft_size=next_pow2(taps_length); //we will have to pad the taps with zeros until the next power of 2 for FFT - //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. - if (fft_size-taps_length<200) fft_size<<=1; - int input_size = fft_size - taps_length + 1; - int overlap_length = taps_length - 1; - fprintf(stderr,"bandpass_fir_fft_cc: (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 ); - if (fft_size<=2) return badsyntax("FFT size error."); + //calculate the FFT size and the other length parameters + int taps_length=firdes_filter_len(transition_bw); //the number of non-zero taps + int fft_size=next_pow2(taps_length); //we will have to pad the taps with zeros until the next power of 2 for FFT + //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. + if (fft_size-taps_length<200) fft_size<<=1; + int input_size = fft_size - taps_length + 1; + int overlap_length = taps_length - 1; + fprintf(stderr,"bandpass_fir_fft_cc: (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 ); + if (fft_size<=2) return badsyntax("FFT size error."); - if(!sendbufsize(getbufsize())) return -2; + if(!sendbufsize(getbufsize())) return -2; - //prepare making the filter and doing FFT on it - complexf* taps=(complexf*)calloc(sizeof(complexf),fft_size); //initialize to zero - complexf* taps_fft=(complexf*)malloc(sizeof(complexf)*fft_size); - FFT_PLAN_T* plan_taps = make_fft_c2c(fft_size, taps, taps_fft, 1, 0); //forward, don't benchmark (we need this only once) + //prepare making the filter and doing FFT on it + complexf* taps=(complexf*)calloc(sizeof(complexf),fft_size); //initialize to zero + complexf* taps_fft=(complexf*)malloc(sizeof(complexf)*fft_size); + FFT_PLAN_T* plan_taps = make_fft_c2c(fft_size, taps, taps_fft, 1, 0); //forward, don't benchmark (we need this only once) - //make FFT plans for continously processing the input - complexf* input = fft_malloc(fft_size*sizeof(complexf)); - complexf* input_fourier = fft_malloc(fft_size*sizeof(complexf)); - FFT_PLAN_T* plan_forward = make_fft_c2c(fft_size, input, input_fourier, 1, 1); //forward, do benchmark + //make FFT plans for continously processing the input + complexf* input = fft_malloc(fft_size*sizeof(complexf)); + complexf* input_fourier = fft_malloc(fft_size*sizeof(complexf)); + FFT_PLAN_T* plan_forward = make_fft_c2c(fft_size, input, input_fourier, 1, 1); //forward, do benchmark - complexf* output_fourier = fft_malloc(fft_size*sizeof(complexf)); - complexf* output_1 = fft_malloc(fft_size*sizeof(complexf)); - complexf* output_2 = fft_malloc(fft_size*sizeof(complexf)); - //we create 2x output buffers so that one will preserve the previous overlap: - FFT_PLAN_T* plan_inverse_1 = make_fft_c2c(fft_size, output_fourier, output_1, 0, 1); //inverse, do benchmark - FFT_PLAN_T* plan_inverse_2 = make_fft_c2c(fft_size, output_fourier, output_2, 0, 1); - //we initialize this buffer to 0 as it will be taken as the overlap source for the first time: - for(int i=0;ioutput,i)=qof(plan_inverse_2->output,i)=0; + complexf* output_fourier = fft_malloc(fft_size*sizeof(complexf)); + complexf* output_1 = fft_malloc(fft_size*sizeof(complexf)); + complexf* output_2 = fft_malloc(fft_size*sizeof(complexf)); + //we create 2x output buffers so that one will preserve the previous overlap: + FFT_PLAN_T* plan_inverse_1 = make_fft_c2c(fft_size, output_fourier, output_1, 0, 1); //inverse, do benchmark + FFT_PLAN_T* plan_inverse_2 = make_fft_c2c(fft_size, output_fourier, output_2, 0, 1); + //we initialize this buffer to 0 as it will be taken as the overlap source for the first time: + for(int i=0;ioutput,i)=qof(plan_inverse_2->output,i)=0; - for(int i=input_size;ioutput + input_size; //+ fft_size - overlap_length; - apply_fir_fft_cc (plan_forward, plan_inverse, taps_fft, last_overlap, overlap_length); - int returned=fwrite(plan_inverse->output, sizeof(complexf), input_size, stdout); - if(read_fifo_ctl(fd,"%g %g\n",&low_cut,&high_cut)) break; - TRY_YIELD; - } - } + for(int odd=0;;odd=!odd) //the processing loop + { + FEOF_CHECK; + fread(input, sizeof(complexf), input_size, stdin); + FFT_PLAN_T* plan_inverse = (odd)?plan_inverse_2:plan_inverse_1; + FFT_PLAN_T* plan_contains_last_overlap = (odd)?plan_inverse_1:plan_inverse_2; //the other + complexf* last_overlap = (complexf*)plan_contains_last_overlap->output + input_size; //+ fft_size - overlap_length; + apply_fir_fft_cc (plan_forward, plan_inverse, taps_fft, last_overlap, overlap_length); + int returned=fwrite(plan_inverse->output, sizeof(complexf), input_size, stdout); + if(read_fifo_ctl(fd,"%g %g\n",&low_cut,&high_cut)) break; + TRY_YIELD; + } + } - } + } #ifdef USE_IMA_ADPCM #define IMA_ADPCM_BUFSIZE BUFSIZE - if( (!strcmp(argv[1],"encode_ima_adpcm_i16_u8"))||(!strcmp(argv[1],"encode_ima_adpcm_s16_u8")) ) - { - if(!sendbufsize(initialize_buffers()/2)) return -2; - ima_adpcm_state_t d; - d.index=d.previousValue=0; - for(;;) - { - FEOF_CHECK; - fread(buffer_i16, sizeof(short), the_bufsize, stdin); - d=encode_ima_adpcm_i16_u8(buffer_i16, buffer_u8, the_bufsize, d); - fwrite(buffer_u8, sizeof(unsigned char), the_bufsize/2, stdout); - TRY_YIELD; - } - } + if( (!strcmp(argv[1],"encode_ima_adpcm_i16_u8"))||(!strcmp(argv[1],"encode_ima_adpcm_s16_u8")) ) + { + if(!sendbufsize(initialize_buffers()/2)) return -2; + ima_adpcm_state_t d; + d.index=d.previousValue=0; + for(;;) + { + FEOF_CHECK; + fread(buffer_i16, sizeof(short), the_bufsize, stdin); + d=encode_ima_adpcm_i16_u8(buffer_i16, buffer_u8, the_bufsize, d); + fwrite(buffer_u8, sizeof(unsigned char), the_bufsize/2, stdout); + TRY_YIELD; + } + } - if( (!strcmp(argv[1],"decode_ima_adpcm_u8_i16"))||(!strcmp(argv[1],"decode_ima_adpcm_u8_s16")) ) - { - ima_adpcm_state_t d; - d.index=d.previousValue=0; - if(!sendbufsize(initialize_buffers()*2)) return -2; - for(;;) - { - FEOF_CHECK; - fread(buffer_u8, sizeof(unsigned char), the_bufsize, stdin); - d=decode_ima_adpcm_u8_i16(buffer_u8, buffer_i16, the_bufsize, d); - fwrite(buffer_i16, sizeof(short), the_bufsize*2, stdout); - TRY_YIELD; - } - } + if( (!strcmp(argv[1],"decode_ima_adpcm_u8_i16"))||(!strcmp(argv[1],"decode_ima_adpcm_u8_s16")) ) + { + ima_adpcm_state_t d; + d.index=d.previousValue=0; + if(!sendbufsize(initialize_buffers()*2)) return -2; + for(;;) + { + FEOF_CHECK; + fread(buffer_u8, sizeof(unsigned char), the_bufsize, stdin); + d=decode_ima_adpcm_u8_i16(buffer_u8, buffer_i16, the_bufsize, d); + fwrite(buffer_i16, sizeof(short), the_bufsize*2, stdout); + TRY_YIELD; + } + } #endif - if(!strcmp(argv[1],"flowcontrol")) - { - if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)"); - int data_rate; - sscanf(argv[2],"%d",&data_rate); - int reads_per_second; - sscanf(argv[3],"%d",&reads_per_second); - int flowcontrol_bufsize=ceil(1.*(double)data_rate/reads_per_second); - if(!getbufsize()) return -2; - sendbufsize(flowcontrol_bufsize); - unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize); - int flowcontrol_sleep=floor(1000000./reads_per_second); - fprintf(stderr, "flowcontrol: flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_bufsize, flowcontrol_sleep); - for(;;) - { - FEOF_CHECK; - fread(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdin); - fwrite(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdout); - usleep(flowcontrol_sleep); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"flowcontrol")) + { + if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)"); + int data_rate; + sscanf(argv[2],"%d",&data_rate); + int reads_per_second; + sscanf(argv[3],"%d",&reads_per_second); + int flowcontrol_bufsize=ceil(1.*(double)data_rate/reads_per_second); + if(!getbufsize()) return -2; + sendbufsize(flowcontrol_bufsize); + unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize); + int flowcontrol_sleep=floor(1000000./reads_per_second); + fprintf(stderr, "flowcontrol: flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_bufsize, flowcontrol_sleep); + for(;;) + { + FEOF_CHECK; + fread(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdin); + fwrite(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdout); + usleep(flowcontrol_sleep); + TRY_YIELD; + } + } #if 0 - if(!strcmp(argv[1],"flowcontrol")) - { - if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)"); + if(!strcmp(argv[1],"flowcontrol")) + { + if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)"); - int data_rate; - sscanf(argv[2],"%d",&data_rate); + int data_rate; + sscanf(argv[2],"%d",&data_rate); - int reads_per_second=0; - if(strcmp(argv[3],"auto")) sscanf(argv[3],"%d",&reads_per_second); + int reads_per_second=0; + if(strcmp(argv[3],"auto")) sscanf(argv[3],"%d",&reads_per_second); - float prebuffer=2; - if(argc>4) sscanf(argv[4],"%g",&prebuffer); + float prebuffer=2; + if(argc>4) sscanf(argv[4],"%g",&prebuffer); - int thrust=10; - if(argc>5) sscanf(argv[5],"%d",&thrust); + int thrust=10; + if(argc>5) sscanf(argv[5],"%d",&thrust); - int flowcontrol_readsize, flowcontrol_bufsize, got_bufsize; + int flowcontrol_readsize, flowcontrol_bufsize, got_bufsize; - if(!(got_bufsize=getbufsize())) return -2; + if(!(got_bufsize=getbufsize())) return -2; - if(reads_per_second) - { - flowcontrol_readsize=ceil(1.*(double)data_rate/reads_per_second); - } - else - { - flowcontrol_readsize=got_bufsize; - reads_per_second=data_rate/flowcontrol_readsize; - } - flowcontrol_bufsize=flowcontrol_readsize*floor(reads_per_second*prebuffer); + if(reads_per_second) + { + flowcontrol_readsize=ceil(1.*(double)data_rate/reads_per_second); + } + else + { + flowcontrol_readsize=got_bufsize; + reads_per_second=data_rate/flowcontrol_readsize; + } + flowcontrol_bufsize=flowcontrol_readsize*floor(reads_per_second*prebuffer); - int flowcontrol_bufindex=0; - unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize); - int flowcontrol_sleep=floor(1000000./reads_per_second); + int flowcontrol_bufindex=0; + unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize); + int flowcontrol_sleep=floor(1000000./reads_per_second); - fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK); + fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK); - sendbufsize(flowcontrol_readsize); - fflush(stdout); + sendbufsize(flowcontrol_readsize); + fflush(stdout); - int flowcontrol_is_buffering = 1; - int read_return; + int flowcontrol_is_buffering = 1; + int read_return; - struct timespec start_time, end_time; + struct timespec start_time, end_time; - unsigned long long int all_bytes_written=0; - int test=0; + unsigned long long int all_bytes_written=0; + int test=0; - fprintf(stderr, "flowcontrol: flowcontrol_readsize = %d, flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_readsize, flowcontrol_bufsize, flowcontrol_sleep); - for (; ;) //my friend has told me that this is like two smileys ;) - { - FEOF_CHECK; - fprintf(stderr, "r"); - read_return=read(STDIN_FILENO, flowcontrol_buffer+flowcontrol_bufindex, sizeof(unsigned char) * (flowcontrol_bufsize-flowcontrol_bufindex) ); - fprintf(stderr, "t"); - if(read_return>0) flowcontrol_bufindex+=read_return; + fprintf(stderr, "flowcontrol: flowcontrol_readsize = %d, flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_readsize, flowcontrol_bufsize, flowcontrol_sleep); + for (; ;) //my friend has told me that this is like two smileys ;) + { + FEOF_CHECK; + fprintf(stderr, "r"); + read_return=read(STDIN_FILENO, flowcontrol_buffer+flowcontrol_bufindex, sizeof(unsigned char) * (flowcontrol_bufsize-flowcontrol_bufindex) ); + fprintf(stderr, "t"); + if(read_return>0) flowcontrol_bufindex+=read_return; - if(flowcontrol_is_buffering) - { - fprintf(stderr, "flowcontrol: buffering, flowcontrol_bufindex = %d\n", flowcontrol_bufindex); - if(flowcontrol_bufindex==flowcontrol_bufsize) { flowcontrol_is_buffering = 0; clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); } - else if(read_return<=0) continue; - } - else { - clock_gettime(CLOCK_MONOTONIC_RAW, &end_time); - int thrust_added=0; - while( (all_bytes_written+thrust*flowcontrol_readsize) / TIME_TAKEN(start_time,end_time) < data_rate ) - { - thrust_added |= thrust++; - } - //if(!(test++%10)) fprintf(stderr, "abw=%g\n", all_bytes_written / TIME_TAKEN(start_time,end_time)); - /*if(!thrust_added && TIME_TAKEN(start_time,end_time)>50) - { - clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); - all_bytes_written=0; - }*/ - while(all_bytes_written>data_rate && TIME_TAKEN(start_time,end_time)>1) - { - all_bytes_written-=data_rate; - start_time.tv_sec++; - } - do - { - //if(thrust) fprintf(stderr, "flowcontrol: %d .. thrust\n", thrust); - write(STDOUT_FILENO, flowcontrol_buffer, flowcontrol_readsize); - fflush(stdout); - //fsync(STDOUT_FILENO); - memmove(flowcontrol_buffer, flowcontrol_buffer+flowcontrol_readsize, flowcontrol_bufindex-flowcontrol_readsize); - flowcontrol_bufindex -= flowcontrol_readsize; - all_bytes_written += flowcontrol_readsize; - } while(thrust && thrust-- && flowcontrol_bufindex>=flowcontrol_readsize); - } + if(flowcontrol_is_buffering) + { + fprintf(stderr, "flowcontrol: buffering, flowcontrol_bufindex = %d\n", flowcontrol_bufindex); + if(flowcontrol_bufindex==flowcontrol_bufsize) { flowcontrol_is_buffering = 0; clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); } + else if(read_return<=0) continue; + } + else { + clock_gettime(CLOCK_MONOTONIC_RAW, &end_time); + int thrust_added=0; + while( (all_bytes_written+thrust*flowcontrol_readsize) / TIME_TAKEN(start_time,end_time) < data_rate ) + { + thrust_added |= thrust++; + } + //if(!(test++%10)) fprintf(stderr, "abw=%g\n", all_bytes_written / TIME_TAKEN(start_time,end_time)); + /*if(!thrust_added && TIME_TAKEN(start_time,end_time)>50) + { + clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); + all_bytes_written=0; + }*/ + while(all_bytes_written>data_rate && TIME_TAKEN(start_time,end_time)>1) + { + all_bytes_written-=data_rate; + start_time.tv_sec++; + } + do + { + //if(thrust) fprintf(stderr, "flowcontrol: %d .. thrust\n", thrust); + write(STDOUT_FILENO, flowcontrol_buffer, flowcontrol_readsize); + fflush(stdout); + //fsync(STDOUT_FILENO); + memmove(flowcontrol_buffer, flowcontrol_buffer+flowcontrol_readsize, flowcontrol_bufindex-flowcontrol_readsize); + flowcontrol_bufindex -= flowcontrol_readsize; + all_bytes_written += flowcontrol_readsize; + } while(thrust && thrust-- && flowcontrol_bufindex>=flowcontrol_readsize); + } - usleep(flowcontrol_sleep); - TRY_YIELD; - } - } + usleep(flowcontrol_sleep); + TRY_YIELD; + } + } #endif - if(!strcmp(argv[1],"through")) - { - struct timespec start_time, end_time; - if(!sendbufsize(initialize_buffers())) return -2; + if(!strcmp(argv[1],"through")) + { + struct timespec start_time, end_time; + if(!sendbufsize(initialize_buffers())) return -2; - int time_now_sec=0; - int buffer_count=0; + int time_now_sec=0; + int buffer_count=0; - unsigned char* through_buffer; - through_buffer = (unsigned char*)malloc(the_bufsize*sizeof(float)); + unsigned char* through_buffer; + through_buffer = (unsigned char*)malloc(the_bufsize*sizeof(float)); - for(;;) - { - FEOF_CHECK; - fread(through_buffer, sizeof(float), the_bufsize, stdin); + for(;;) + { + FEOF_CHECK; + fread(through_buffer, sizeof(float), the_bufsize, stdin); - if(!time_now_sec) - { - time_now_sec=1; - clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); - } - else - { - clock_gettime(CLOCK_MONOTONIC_RAW, &end_time); - float timetaken; - if(time_now_sec<(timetaken=TIME_TAKEN(start_time,end_time))) - { - fprintf( stderr, "through: %lu bytes/s, buffer #%d\n", (unsigned long)floor((float)buffer_count*the_bufsize*sizeof(float)/timetaken), buffer_count ); - time_now_sec=ceil(timetaken); - } - } - fwrite(through_buffer, sizeof(float), the_bufsize, stdout); - buffer_count++; - TRY_YIELD; - } - } + if(!time_now_sec) + { + time_now_sec=1; + clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); + } + else + { + clock_gettime(CLOCK_MONOTONIC_RAW, &end_time); + float timetaken; + if(time_now_sec<(timetaken=TIME_TAKEN(start_time,end_time))) + { + fprintf( stderr, "through: %lu bytes/s, buffer #%d\n", (unsigned long)floor((float)buffer_count*the_bufsize*sizeof(float)/timetaken), buffer_count ); + time_now_sec=ceil(timetaken); + } + } + fwrite(through_buffer, sizeof(float), the_bufsize, stdout); + buffer_count++; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"dsb_fc")) - { - float q_value = 0; - if(argc>=3) sscanf(argv[2],"%g",&q_value); + if(!strcmp(argv[1],"dsb_fc")) + { + float q_value = 0; + if(argc>=3) sscanf(argv[2],"%g",&q_value); - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_R; - for(int i=0;i)"); - fprintf(stderr, "squelch_and_power_cc: initial squelch level is %g\n", squelch_level); - if((argc<=5)||((argc>5)&&(strcmp(argv[4],"--outfifo")))) return badsyntax("need required parameter (--outfifo )"); - int fd2 = open(argv[5], O_WRONLY); - if(fd2==-1) return badsyntax("error while opening --outfifo"); - int flags = fcntl(fd2, F_GETFL, 0); - fcntl(fd2, F_SETFL, flags | O_NONBLOCK); - if(argc<=6) return badsyntax("need required parameter (use_every_nth)"); - sscanf(argv[6],"%d",&decimation); - if(decimation<=0) return badsyntax("use_every_nth <= 0 is invalid"); - if(argc<=7) return badsyntax("need required parameter (report_every_nth)"); - sscanf(argv[7],"%d",&report_every_nth); - if(report_every_nth<=0) return badsyntax("report_every_nth <= 0 is invalid"); - for(;;) - { - FEOF_CHECK; - FREAD_C; //read input data - power = get_power_c((complexf*)input_buffer, the_bufsize, decimation); - if(report_cntr++>report_every_nth) - { - report_cntr=0; - power_value_buf_size=snprintf(power_value_buf,100,"%g\n",power); - write(fd2,power_value_buf,power_value_buf_size*sizeof(char)); - } - if(squelch_level==0||power>=squelch_level) - { - //fprintf(stderr,"P"); - fwrite(input_buffer, sizeof(complexf), the_bufsize, stdout); - } - else - { - //fprintf(stderr,"S"); - fwrite(zerobuf, sizeof(complexf), the_bufsize, stdout); - } - if(read_fifo_ctl(fd,"%g\n",&squelch_level)) fprintf(stderr, "squelch_and_power_cc: new squelch level is %g\n", squelch_level); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"squelch_and_smeter_cc")) + { + if(!sendbufsize(initialize_buffers())) return -2; + float power; + float squelch_level; + int decimation; + int report_every_nth; + int fd; + char power_value_buf[101]; + int power_value_buf_size; + int report_cntr=0; + complexf* zerobuf = (complexf*)malloc(sizeof(complexf)*the_bufsize); + for(int i=0;i)"); + fprintf(stderr, "squelch_and_power_cc: initial squelch level is %g\n", squelch_level); + if((argc<=5)||((argc>5)&&(strcmp(argv[4],"--outfifo")))) return badsyntax("need required parameter (--outfifo )"); + int fd2 = open(argv[5], O_WRONLY); + if(fd2==-1) return badsyntax("error while opening --outfifo"); + int flags = fcntl(fd2, F_GETFL, 0); + fcntl(fd2, F_SETFL, flags | O_NONBLOCK); + if(argc<=6) return badsyntax("need required parameter (use_every_nth)"); + sscanf(argv[6],"%d",&decimation); + if(decimation<=0) return badsyntax("use_every_nth <= 0 is invalid"); + if(argc<=7) return badsyntax("need required parameter (report_every_nth)"); + sscanf(argv[7],"%d",&report_every_nth); + if(report_every_nth<=0) return badsyntax("report_every_nth <= 0 is invalid"); + for(;;) + { + FEOF_CHECK; + FREAD_C; //read input data + power = get_power_c((complexf*)input_buffer, the_bufsize, decimation); + if(report_cntr++>report_every_nth) + { + report_cntr=0; + power_value_buf_size=snprintf(power_value_buf,100,"%g\n",power); + write(fd2,power_value_buf,power_value_buf_size*sizeof(char)); + } + if(squelch_level==0||power>=squelch_level) + { + //fprintf(stderr,"P"); + fwrite(input_buffer, sizeof(complexf), the_bufsize, stdout); + } + else + { + //fprintf(stderr,"S"); + fwrite(zerobuf, sizeof(complexf), the_bufsize, stdout); + } + if(read_fifo_ctl(fd,"%g\n",&squelch_level)) fprintf(stderr, "squelch_and_power_cc: new squelch level is %g\n", squelch_level); + TRY_YIELD; + } + } - /* - ______ _ _____ _____ _____ - | ____| | | | __ \| __ \ / ____| - | |__ __ _ ___| |_| | | | | | | | - | __/ _` / __| __| | | | | | | | - | | | (_| \__ \ |_| |__| | |__| | |____ - |_| \__,_|___/\__|_____/|_____/ \_____| + /* + ______ _ _____ _____ _____ + | ____| | | | __ \| __ \ / ____| + | |__ __ _ ___| |_| | | | | | | | + | __/ _` / __| __| | | | | | | | + | | | (_| \__ \ |_| |__| | |__| | |____ + |_| \__,_|___/\__|_____/|_____/ \_____| - */ + */ - if( !strcmp(argv[1],"fastddc_fwd_cc") ) // [transition_bw [window]] - { - - int decimation; - if(argc<=2) return badsyntax("need required parameter (decimation)"); - sscanf(argv[2],"%d",&decimation); - - float transition_bw = 0.05; - if(argc>3) sscanf(argv[3],"%g",&transition_bw); + if( !strcmp(argv[1],"fastddc_fwd_cc") ) // [transition_bw [window]] + { + + int decimation; + if(argc<=2) return badsyntax("need required parameter (decimation)"); + sscanf(argv[2],"%d",&decimation); + + float transition_bw = 0.05; + if(argc>3) sscanf(argv[3],"%g",&transition_bw); - window_t window = WINDOW_DEFAULT; - if(argc>4) window=firdes_get_window_from_string(argv[4]); - else fprintf(stderr,"fastddc_fwd_cc: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>4) window=firdes_get_window_from_string(argv[4]); + else fprintf(stderr,"fastddc_fwd_cc: window = %s\n",firdes_get_string_from_window(window)); - fastddc_t ddc; - if(fastddc_init(&ddc, transition_bw, decimation, 0)) { badsyntax("error in fastddc_init()"); return 1; } - fastddc_print(&ddc,"fastddc_fwd_cc"); + fastddc_t ddc; + if(fastddc_init(&ddc, transition_bw, decimation, 0)) { badsyntax("error in fastddc_init()"); return 1; } + fastddc_print(&ddc,"fastddc_fwd_cc"); - if(!initialize_buffers()) return -2; - sendbufsize(ddc.fft_size); + if(!initialize_buffers()) return -2; + sendbufsize(ddc.fft_size); - //make FFT plan - complexf* input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); - complexf* windowed = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); - complexf* output = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); + //make FFT plan + complexf* input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); + complexf* windowed = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); + complexf* output = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); - for(int i=0;i [transition_bw [window]] - { - float shift_rate; - int plusarg=0; + if( !strcmp(argv[1],"fastddc_inv_cc") ) // [transition_bw [window]] + { + float shift_rate; + int plusarg=0; - int fd; - if(fd=init_fifo(argc,argv)) - { - while(!read_fifo_ctl(fd,"%g\n",&shift_rate)) usleep(10000); - plusarg=1; - } - else - { - if(argc<=2) return badsyntax("need required parameter (rate)"); - sscanf(argv[2],"%g",&shift_rate); - } + int fd; + if(fd=init_fifo(argc,argv)) + { + while(!read_fifo_ctl(fd,"%g\n",&shift_rate)) usleep(10000); + plusarg=1; + } + else + { + if(argc<=2) return badsyntax("need required parameter (rate)"); + sscanf(argv[2],"%g",&shift_rate); + } - int decimation; - if(argc<=3+plusarg) return badsyntax("need required parameter (decimation)"); - sscanf(argv[3+plusarg],"%d",&decimation); - //fprintf(stderr, "dec=%d %d\n", decimation); + int decimation; + if(argc<=3+plusarg) return badsyntax("need required parameter (decimation)"); + sscanf(argv[3+plusarg],"%d",&decimation); + //fprintf(stderr, "dec=%d %d\n", decimation); - float transition_bw = 0.05; - if(argc>4+plusarg) sscanf(argv[4+plusarg],"%g",&transition_bw); + float transition_bw = 0.05; + if(argc>4+plusarg) sscanf(argv[4+plusarg],"%g",&transition_bw); - window_t window = WINDOW_DEFAULT; - if(argc>5+plusarg) window=firdes_get_window_from_string(argv[5+plusarg]); - else fprintf(stderr,"fastddc_apply_cc: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>5+plusarg) window=firdes_get_window_from_string(argv[5+plusarg]); + else fprintf(stderr,"fastddc_apply_cc: window = %s\n",firdes_get_string_from_window(window)); - for(;;) - { + for(;;) + { - fastddc_t ddc; - if(fastddc_init(&ddc, transition_bw, decimation, shift_rate)) { badsyntax("error in fastddc_init()"); return 1; } - fastddc_print(&ddc,"fastddc_inv_cc"); + fastddc_t ddc; + if(fastddc_init(&ddc, transition_bw, decimation, shift_rate)) { badsyntax("error in fastddc_init()"); return 1; } + fastddc_print(&ddc,"fastddc_inv_cc"); - if(!initialize_buffers()) return -2; - sendbufsize(ddc.post_input_size/ddc.post_decimation); //TODO not exactly correct + if(!initialize_buffers()) return -2; + sendbufsize(ddc.post_input_size/ddc.post_decimation); //TODO not exactly correct - //prepare making the filter and doing FFT on it - complexf* taps=(complexf*)calloc(sizeof(complexf),ddc.fft_size); //initialize to zero - complexf* taps_fft=(complexf*)malloc(sizeof(complexf)*ddc.fft_size); - 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) + //prepare making the filter and doing FFT on it + complexf* taps=(complexf*)calloc(sizeof(complexf),ddc.fft_size); //initialize to zero + complexf* taps_fft=(complexf*)malloc(sizeof(complexf)*ddc.fft_size); + 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) - //make the filter - float filter_half_bw = 0.5/decimation; - fprintf(stderr, "fastddc_inv_cc: 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); - firdes_bandpass_c(taps, ddc.taps_length, (-shift_rate)-filter_half_bw, (-shift_rate)+filter_half_bw, window); - fft_execute(plan_taps); - fft_swap_sides(taps_fft,ddc.fft_size); + //make the filter + float filter_half_bw = 0.5/decimation; + fprintf(stderr, "fastddc_inv_cc: 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); + firdes_bandpass_c(taps, ddc.taps_length, (-shift_rate)-filter_half_bw, (-shift_rate)+filter_half_bw, window); + fft_execute(plan_taps); + fft_swap_sides(taps_fft,ddc.fft_size); - //make FFT plan - complexf* inv_input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_inv_size); - complexf* inv_output = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_inv_size); - fprintf(stderr,"fastddc_inv_cc: benchmarking FFT..."); - FFT_PLAN_T* plan_inverse = make_fft_c2c(ddc.fft_inv_size, inv_input, inv_output, 0, 1); //inverse, do benchmark - fprintf(stderr," done\n"); - - //alloc. buffers - complexf* input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); - complexf* output = (complexf*)fft_malloc(sizeof(complexf)*ddc.post_input_size); + //make FFT plan + complexf* inv_input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_inv_size); + complexf* inv_output = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_inv_size); + fprintf(stderr,"fastddc_inv_cc: benchmarking FFT..."); + FFT_PLAN_T* plan_inverse = make_fft_c2c(ddc.fft_inv_size, inv_input, inv_output, 0, 1); //inverse, do benchmark + fprintf(stderr," done\n"); + + //alloc. buffers + complexf* input = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size); + complexf* output = (complexf*)fft_malloc(sizeof(complexf)*ddc.post_input_size); - decimating_shift_addition_status_t shift_stat; - bzero(&shift_stat, sizeof(shift_stat)); - for(;;) - { - FEOF_CHECK; - fread(input, sizeof(complexf), ddc.fft_size, stdin); - shift_stat = fastddc_inv_cc(input, output, &ddc, plan_inverse, taps_fft, shift_stat); - fwrite(output, sizeof(complexf), shift_stat.output_size, stdout); - //fprintf(stderr, "ss os = %d\n", shift_stat.output_size); - TRY_YIELD; - if(read_fifo_ctl(fd,"%g\n",&shift_rate)) break; - } + decimating_shift_addition_status_t shift_stat; + bzero(&shift_stat, sizeof(shift_stat)); + for(;;) + { + FEOF_CHECK; + fread(input, sizeof(complexf), ddc.fft_size, stdin); + shift_stat = fastddc_inv_cc(input, output, &ddc, plan_inverse, taps_fft, shift_stat); + fwrite(output, sizeof(complexf), shift_stat.output_size, stdout); + //fprintf(stderr, "ss os = %d\n", shift_stat.output_size); + TRY_YIELD; + if(read_fifo_ctl(fd,"%g\n",&shift_rate)) break; + } - } - } + } + } - if( !strcmp(argv[1], "_fft2octave") ) - { - int fft_size; - if(argc<=2) return badsyntax("need required parameter (fft_size)"); - sscanf(argv[2],"%d",&fft_size); + if( !strcmp(argv[1], "_fft2octave") ) + { + int fft_size; + if(argc<=2) return badsyntax("need required parameter (fft_size)"); + sscanf(argv[2],"%d",&fft_size); - complexf* fft_input=(complexf*)malloc(sizeof(complexf)*fft_size); - initialize_buffers(); - if(!sendbufsize(fft_size)) return -2; + complexf* fft_input=(complexf*)malloc(sizeof(complexf)*fft_size); + initialize_buffers(); + if(!sendbufsize(fft_size)) return -2; - printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); - for(;;) - { - FEOF_CHECK; - fread(fft_input, sizeof(complexf), fft_size, stdin); - printf("fftdata=["); - //we have to swap the two parts of the array to get a valid spectrum - for(int i=fft_size/2;i initialized to 0 - unsigned char output; - if(!sendbufsize(initialize_buffers())) return -2; - unsigned char i=0; - for(;;) - { - if((output=rtty_baudot_decoder_push(&status_baudot, getchar()))) { putchar(output); fflush(stdout); } - if(i++) continue; //do the following at every 256th execution of the loop body: - FEOF_CHECK; - TRY_YIELD; - } - } + if(!strcmp(argv[1],"rtty_line_decoder_u8_u8")) + { + static rtty_baudot_decoder_t status_baudot; //created on .bss -> initialized to 0 + unsigned char output; + if(!sendbufsize(initialize_buffers())) return -2; + unsigned char i=0; + for(;;) + { + if((output=rtty_baudot_decoder_push(&status_baudot, getchar()))) { putchar(output); fflush(stdout); } + if(i++) continue; //do the following at every 256th execution of the loop body: + FEOF_CHECK; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"rtty_baudot2ascii_u8_u8")) - { - unsigned char fig_mode = 0; - unsigned char output; - if(!sendbufsize(initialize_buffers())) return -2; - unsigned char i=0; - for(;;) - { - if((output=rtty_baudot_decoder_lookup(&fig_mode, getchar()))) { putchar(output); fflush(stdout); } - if(i++) continue; //do the following at every 256th execution of the loop body: - FEOF_CHECK; - TRY_YIELD; - } - } + if(!strcmp(argv[1],"rtty_baudot2ascii_u8_u8")) + { + unsigned char fig_mode = 0; + unsigned char output; + if(!sendbufsize(initialize_buffers())) return -2; + unsigned char i=0; + for(;;) + { + if((output=rtty_baudot_decoder_lookup(&fig_mode, getchar()))) { putchar(output); fflush(stdout); } + if(i++) continue; //do the following at every 256th execution of the loop body: + FEOF_CHECK; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"binary_slicer_f_u8")) - { - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - if(!FREAD_R) break; - binary_slicer_f_u8(input_buffer, (unsigned char*)output_buffer, the_bufsize); - FWRITE_U8; - TRY_YIELD; - } - return 0; - } + if(!strcmp(argv[1],"binary_slicer_f_u8")) + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + if(!FREAD_R) break; + binary_slicer_f_u8(input_buffer, (unsigned char*)output_buffer, the_bufsize); + FWRITE_U8; + TRY_YIELD; + } + return 0; + } - if(!strcmp(argv[1],"serial_line_decoder_f_u8")) - { - bigbufs=1; + if(!strcmp(argv[1],"serial_line_decoder_f_u8")) + { + bigbufs=1; - serial_line_t serial; + serial_line_t serial; - if(argc<=2) return badsyntax("need required parameter (samples_per_bits)"); - sscanf(argv[2],"%f",&serial.samples_per_bits); - if(serial.samples_per_bits<1) return badsyntax("samples_per_bits should be at least 1."); - 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]); + if(argc<=2) return badsyntax("need required parameter (samples_per_bits)"); + sscanf(argv[2],"%f",&serial.samples_per_bits); + if(serial.samples_per_bits<1) return badsyntax("samples_per_bits should be at least 1."); + 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]); - serial.databits=8; - if(argc>3) sscanf(argv[3],"%d",&serial.databits); - if(serial.databits>8 || serial.databits<1) return badsyntax("databits should be between 1 and 8."); + serial.databits=8; + if(argc>3) sscanf(argv[3],"%d",&serial.databits); + if(serial.databits>8 || serial.databits<1) return badsyntax("databits should be between 1 and 8."); - serial.stopbits=1; - if(argc>4) sscanf(argv[4],"%f",&serial.stopbits); - if(serial.stopbits<1) return badsyntax("stopbits should be equal or above 1."); + serial.stopbits=1; + if(argc>4) sscanf(argv[4],"%f",&serial.stopbits); + if(serial.stopbits<1) return badsyntax("stopbits should be equal or above 1."); - serial.bit_sampling_width_ratio = 0.4; - serial.input_used=0; + serial.bit_sampling_width_ratio = 0.4; + serial.input_used=0; - if(!sendbufsize(initialize_buffers())) return -2; + if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - if(serial.input_used) - { - memmove(input_buffer, input_buffer+serial.input_used, sizeof(float)*(the_bufsize-serial.input_used)); - fread(input_buffer+(the_bufsize-serial.input_used), sizeof(float), serial.input_used, stdin); - } - else fread(input_buffer, sizeof(float), the_bufsize, stdin); //should happen only on the first run - serial_line_decoder_f_u8(&serial,input_buffer, (unsigned char*)output_buffer, the_bufsize); - //printf("now in | "); - if(serial.input_used==0) { fprintf(stderr, "%s: error: serial_line_decoder_f_u8() got stuck.\n", argv[1]); return -3; } - //printf("now out %d | ", serial.output_size); - fwrite(output_buffer, sizeof(unsigned char), serial.output_size, stdout); - TRY_YIELD; - } - } + for(;;) + { + FEOF_CHECK; + if(serial.input_used) + { + memmove(input_buffer, input_buffer+serial.input_used, sizeof(float)*(the_bufsize-serial.input_used)); + fread(input_buffer+(the_bufsize-serial.input_used), sizeof(float), serial.input_used, stdin); + } + else fread(input_buffer, sizeof(float), the_bufsize, stdin); //should happen only on the first run + serial_line_decoder_f_u8(&serial,input_buffer, (unsigned char*)output_buffer, the_bufsize); + //printf("now in | "); + if(serial.input_used==0) { fprintf(stderr, "%s: error: serial_line_decoder_f_u8() got stuck.\n", argv[1]); return -3; } + //printf("now out %d | ", serial.output_size); + fwrite(output_buffer, sizeof(unsigned char), serial.output_size, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"pll_cc")) - { - pll_t pll; + if(!strcmp(argv[1],"pll_cc")) + { + pll_t pll; - if(argc<=2) return badsyntax("need required parameter (pll_type)"); - sscanf(argv[2],"%d",(int*)&pll.pll_type); - if(pll.pll_type == PLL_P_CONTROLLER) - { - float alpha = 0.01; - if(argc>3) sscanf(argv[3],"%f",&alpha); - pll_cc_init_p_controller(&pll, alpha); - } - else if(pll.pll_type == PLL_PI_CONTROLLER) - { - float bandwidth = 0.01, ko = 10, kd=0.1, damping_factor = 0.707; - if(argc>3) sscanf(argv[3],"%f",&bandwidth); - if(argc>4) sscanf(argv[4],"%f",&damping_factor); - if(argc>5) sscanf(argv[5],"%f",&ko); - if(argc>6) sscanf(argv[6],"%f",&kd); - pll_cc_init_pi_controller(&pll, bandwidth, ko, kd, damping_factor); - fprintf(stderr, "bw=%f damping=%f ko=%f kd=%f alpha=%f beta=%f\n", bandwidth, damping_factor, ko, kd, pll.alpha, pll.beta); - // 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]); - } - else return badsyntax("invalid pll_type. Valid values are:\n\t1: PLL_P_CONTROLLER\n\t2: PLL_PI_CONTROLLER"); + if(argc<=2) return badsyntax("need required parameter (pll_type)"); + sscanf(argv[2],"%d",(int*)&pll.pll_type); + if(pll.pll_type == PLL_P_CONTROLLER) + { + float alpha = 0.01; + if(argc>3) sscanf(argv[3],"%f",&alpha); + pll_cc_init_p_controller(&pll, alpha); + } + else if(pll.pll_type == PLL_PI_CONTROLLER) + { + float bandwidth = 0.01, ko = 10, kd=0.1, damping_factor = 0.707; + if(argc>3) sscanf(argv[3],"%f",&bandwidth); + if(argc>4) sscanf(argv[4],"%f",&damping_factor); + if(argc>5) sscanf(argv[5],"%f",&ko); + if(argc>6) sscanf(argv[6],"%f",&kd); + pll_cc_init_pi_controller(&pll, bandwidth, ko, kd, damping_factor); + fprintf(stderr, "bw=%f damping=%f ko=%f kd=%f alpha=%f beta=%f\n", bandwidth, damping_factor, ko, kd, pll.alpha, pll.beta); + // 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]); + } + else return badsyntax("invalid pll_type. Valid values are:\n\t1: PLL_P_CONTROLLER\n\t2: PLL_PI_CONTROLLER"); - if(!sendbufsize(initialize_buffers())) return -2; + if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - FEOF_CHECK; - FREAD_C; - //fprintf(stderr, "| i"); - // pll_cc(&pll, (complexf*)input_buffer, output_buffer, NULL, the_bufsize); - // fwrite(output_buffer, sizeof(float), the_bufsize, stdout); - pll_cc(&pll, (complexf*)input_buffer, NULL, (complexf*)output_buffer, the_bufsize); - fwrite(output_buffer, sizeof(complexf), the_bufsize, stdout); - //fprintf(stderr, "| o"); - TRY_YIELD; - } - } + for(;;) + { + FEOF_CHECK; + FREAD_C; + //fprintf(stderr, "| i"); + // pll_cc(&pll, (complexf*)input_buffer, output_buffer, NULL, the_bufsize); + // fwrite(output_buffer, sizeof(float), the_bufsize, stdout); + pll_cc(&pll, (complexf*)input_buffer, NULL, (complexf*)output_buffer, the_bufsize); + fwrite(output_buffer, sizeof(complexf), the_bufsize, stdout); + //fprintf(stderr, "| o"); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"timing_recovery_cc")) // [--add_q [--output_error | --output_indexes | --octave ]] - { - if(argc<=2) return badsyntax("need required parameter (algorithm)"); - timing_recovery_algorithm_t algorithm = timing_recovery_get_algorithm_from_string(argv[2]); - //if(algorithm == TIMING_RECOVERY_ALGORITHM_DEFAULT) - // fprintf(stderr,"#timing_recovery_cc: algorithm = %s\n",timing_recovery_get_string_from_algorithm(algorithm)); - if(argc<=3) return badsyntax("need required parameter (decimation factor)"); - int decimation; - sscanf(argv[3],"%d",&decimation); - if(decimation<=4 || decimation&3) return badsyntax("decimation factor should be a positive integer divisible by 4"); + if(!strcmp(argv[1],"timing_recovery_cc")) // [--add_q [--output_error | --output_indexes | --octave ]] + { + if(argc<=2) return badsyntax("need required parameter (algorithm)"); + timing_recovery_algorithm_t algorithm = timing_recovery_get_algorithm_from_string(argv[2]); + //if(algorithm == TIMING_RECOVERY_ALGORITHM_DEFAULT) + // fprintf(stderr,"#timing_recovery_cc: algorithm = %s\n",timing_recovery_get_string_from_algorithm(algorithm)); + if(argc<=3) return badsyntax("need required parameter (decimation factor)"); + int decimation; + sscanf(argv[3],"%d",&decimation); + if(decimation<=4 || decimation&3) return badsyntax("decimation factor should be a positive integer divisible by 4"); - int add_q = (argc>=5 && !strcmp(argv[4], "--add_q")); + int add_q = (argc>=5 && !strcmp(argv[4], "--add_q")); - int debug_n = 0; - int output_error = 0; - int output_indexes = 0; - if(argc>=7 && !strcmp(argv[5], "--octave")) debug_n = atoi(argv[6]); - if(debug_n<0) return badsyntax("debug_n should be >= 0"); + int debug_n = 0; + int output_error = 0; + int output_indexes = 0; + if(argc>=7 && !strcmp(argv[5], "--octave")) debug_n = atoi(argv[6]); + if(debug_n<0) return badsyntax("debug_n should be >= 0"); if(argc>=6 && !strcmp(argv[5], "--output_error")) output_error = 1; - float* timing_error = NULL; - if(output_error) timing_error = (float*)malloc(sizeof(float)*the_bufsize); + float* timing_error = NULL; + if(output_error) timing_error = (float*)malloc(sizeof(float)*the_bufsize); if(argc>=6 && !strcmp(argv[5], "--output_indexes")) output_indexes = 1; - unsigned* sampled_indexes = NULL; - if(output_indexes) sampled_indexes = (unsigned*)malloc(sizeof(float)*the_bufsize); + unsigned* sampled_indexes = NULL; + if(output_indexes) sampled_indexes = (unsigned*)malloc(sizeof(float)*the_bufsize); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize/decimation); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize/decimation); - timing_recovery_state_t state = timing_recovery_init(algorithm, decimation, add_q); + timing_recovery_state_t state = timing_recovery_init(algorithm, decimation, add_q); - int debug_i=0; - state.debug_writefiles = 1; - state.debug_force = !!debug_n; //should remove that later - FREAD_C; + int debug_i=0; + state.debug_writefiles = 1; + state.debug_force = !!debug_n; //should remove that later + FREAD_C; unsigned buffer_start_counter = 0; - for(;;) - { - FEOF_CHECK; - if(debug_n && ++debug_i%debug_n==0) timing_recovery_trigger_debug(&state, 3); - timing_recovery_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, timing_error, (int*)sampled_indexes, &state); - //fprintf(stderr, "trcc is=%d, os=%d, ip=%d\n",the_bufsize, state.output_size, state.input_processed); - if(timing_error) fwrite(timing_error, sizeof(float), state.output_size, stdout); + for(;;) + { + FEOF_CHECK; + if(debug_n && ++debug_i%debug_n==0) timing_recovery_trigger_debug(&state, 3); + timing_recovery_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, timing_error, (int*)sampled_indexes, &state); + //fprintf(stderr, "trcc is=%d, os=%d, ip=%d\n",the_bufsize, state.output_size, state.input_processed); + if(timing_error) fwrite(timing_error, sizeof(float), state.output_size, stdout); else if(sampled_indexes) { for(int i=0;i 0"); - if(argc<=3) return badsyntax("need required parameter (out_of_n_samples)"); - int out_of_n_samples = 0; - sscanf(argv[3], "%d", &out_of_n_samples); - if(out_of_n_samples4) mode2d = !strcmp(argv[4], "--2d"); - complexf* read_buf = (complexf*)malloc(sizeof(complexf)*the_bufsize); + if(!strcmp(argv[1],"octave_complex_c")) + { + if(argc<=2) return badsyntax("need required parameter (samples_to_plot)"); + int samples_to_plot = 0; + sscanf(argv[2], "%d", &samples_to_plot); + if(samples_to_plot<=0) return badsyntax("Number of samples to plot should be > 0"); + if(argc<=3) return badsyntax("need required parameter (out_of_n_samples)"); + int out_of_n_samples = 0; + sscanf(argv[3], "%d", &out_of_n_samples); + if(out_of_n_samples4) mode2d = !strcmp(argv[4], "--2d"); + complexf* read_buf = (complexf*)malloc(sizeof(complexf)*the_bufsize); - if(!sendbufsize(initialize_buffers())) return -2; - for(;;) - { - fread(read_buf, sizeof(complexf), samples_to_plot, stdin); - printf("N = %d;\nisig = [", samples_to_plot); - for(int i=0;i0;seek_remain-=samples_to_plot) - { - fread(read_buf, sizeof(complexf), MIN_M(samples_to_plot,seek_remain), stdin); - } - FEOF_CHECK; - TRY_YIELD; - } - } + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + fread(read_buf, sizeof(complexf), samples_to_plot, stdin); + printf("N = %d;\nisig = [", samples_to_plot); + for(int i=0;i0;seek_remain-=samples_to_plot) + { + fread(read_buf, sizeof(complexf), MIN_M(samples_to_plot,seek_remain), stdin); + } + FEOF_CHECK; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"psk_modulator_u8_c")) // - { - int n_psk; - if(argc<=2) return badsyntax("need required parameter (n_psk)"); - sscanf(argv[2],"%d",&n_psk); - if(n_psk<=0 || n_psk>256) return badsyntax("n_psk should be between 1 and 256"); + if(!strcmp(argv[1],"psk_modulator_u8_c")) // + { + int n_psk; + if(argc<=2) return badsyntax("need required parameter (n_psk)"); + sscanf(argv[2],"%d",&n_psk); + if(n_psk<=0 || n_psk>256) return badsyntax("n_psk should be between 1 and 256"); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize); - for(;;) - { - FEOF_CHECK; - fread((unsigned char*)input_buffer, sizeof(unsigned char), the_bufsize, stdin); - psk_modulator_u8_c((unsigned char*)input_buffer, (complexf*)output_buffer, the_bufsize, n_psk); - FWRITE_C; - TRY_YIELD; - } - } + for(;;) + { + FEOF_CHECK; + fread((unsigned char*)input_buffer, sizeof(unsigned char), the_bufsize, stdin); + psk_modulator_u8_c((unsigned char*)input_buffer, (complexf*)output_buffer, the_bufsize, n_psk); + FWRITE_C; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"duplicate_samples_ntimes_u8_u8")) // - { - int sample_size_bytes = 0, ntimes = 0; - if(argc<=2) return badsyntax("need required parameter (sample_size_bytes)"); - sscanf(argv[2],"%d",&sample_size_bytes); - if(sample_size_bytes<=0) return badsyntax("sample_size_bytes should be >0"); - if(argc<=3) return badsyntax("need required parameter (ntimes)"); - sscanf(argv[3],"%d",&ntimes); - if(ntimes<=0) return badsyntax("ntimes should be >0"); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize*ntimes); - unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*sample_size_bytes); - unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*sample_size_bytes*ntimes); - for(;;) - { - FEOF_CHECK; - fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize*sample_size_bytes, stdin); - duplicate_samples_ntimes_u8_u8(local_input_buffer, local_output_buffer, the_bufsize*sample_size_bytes, sample_size_bytes, ntimes); - fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize*sample_size_bytes*ntimes, stdout); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"duplicate_samples_ntimes_u8_u8")) // + { + int sample_size_bytes = 0, ntimes = 0; + if(argc<=2) return badsyntax("need required parameter (sample_size_bytes)"); + sscanf(argv[2],"%d",&sample_size_bytes); + if(sample_size_bytes<=0) return badsyntax("sample_size_bytes should be >0"); + if(argc<=3) return badsyntax("need required parameter (ntimes)"); + sscanf(argv[3],"%d",&ntimes); + if(ntimes<=0) return badsyntax("ntimes should be >0"); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize*ntimes); + unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*sample_size_bytes); + unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*sample_size_bytes*ntimes); + for(;;) + { + FEOF_CHECK; + fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize*sample_size_bytes, stdin); + duplicate_samples_ntimes_u8_u8(local_input_buffer, local_output_buffer, the_bufsize*sample_size_bytes, sample_size_bytes, ntimes); + fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize*sample_size_bytes*ntimes, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"psk31_interpolate_sine_cc")) // - { - int interpolation; - if(argc<=2) return badsyntax("need required parameter (interpolation)"); - sscanf(argv[2],"%d",&interpolation); - if(interpolation<=0) return badsyntax("interpolation should be >0"); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize*interpolation); - complexf* local_output_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize*interpolation); - complexf last_input; - iof(&last_input,0) = 0; - qof(&last_input,0) = 0; - for(;;) - { - FEOF_CHECK; - FREAD_C; - last_input = psk31_interpolate_sine_cc((complexf*)input_buffer, local_output_buffer, the_bufsize, interpolation, last_input); - fwrite((void*)local_output_buffer, sizeof(complexf), the_bufsize*interpolation, stdout); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"psk31_interpolate_sine_cc")) // + { + int interpolation; + if(argc<=2) return badsyntax("need required parameter (interpolation)"); + sscanf(argv[2],"%d",&interpolation); + if(interpolation<=0) return badsyntax("interpolation should be >0"); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize*interpolation); + complexf* local_output_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize*interpolation); + complexf last_input; + iof(&last_input,0) = 0; + qof(&last_input,0) = 0; + for(;;) + { + FEOF_CHECK; + FREAD_C; + last_input = psk31_interpolate_sine_cc((complexf*)input_buffer, local_output_buffer, the_bufsize, interpolation, last_input); + fwrite((void*)local_output_buffer, sizeof(complexf), the_bufsize*interpolation, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"pack_bits_8to1_u8_u8")) - { - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize*8); - unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); - unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*8); - for(;;) - { - FEOF_CHECK; - fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); - pack_bits_8to1_u8_u8(local_input_buffer, local_output_buffer, the_bufsize); - fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize*8, stdout); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"pack_bits_8to1_u8_u8")) + { + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize*8); + unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); + unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*8); + for(;;) + { + FEOF_CHECK; + fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); + pack_bits_8to1_u8_u8(local_input_buffer, local_output_buffer, the_bufsize); + fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize*8, stdout); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"psk31_varicode_encoder_u8_u8")) - { - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize*8); - int output_max_size=the_bufsize*30; - int output_size; - int input_processed; - unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); - unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*output_max_size); - fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); - for(;;) - { - psk31_varicode_encoder_u8_u8(local_input_buffer, local_output_buffer, the_bufsize, output_max_size, &input_processed, &output_size); - //fprintf(stderr, "os = %d\n", output_size); - fwrite((void*)local_output_buffer, sizeof(unsigned char), output_size, stdout); - FEOF_CHECK; - memmove(local_input_buffer, local_input_buffer+input_processed, the_bufsize-input_processed); - fread(input_buffer+the_bufsize-input_processed, sizeof(unsigned char), input_processed, stdin); - TRY_YIELD; - } - } + if(!strcmp(argv[1],"psk31_varicode_encoder_u8_u8")) + { + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize*8); + int output_max_size=the_bufsize*30; + int output_size; + int input_processed; + unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); + unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*output_max_size); + fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); + for(;;) + { + psk31_varicode_encoder_u8_u8(local_input_buffer, local_output_buffer, the_bufsize, output_max_size, &input_processed, &output_size); + //fprintf(stderr, "os = %d\n", output_size); + fwrite((void*)local_output_buffer, sizeof(unsigned char), output_size, stdout); + FEOF_CHECK; + memmove(local_input_buffer, local_input_buffer+input_processed, the_bufsize-input_processed); + fread(input_buffer+the_bufsize-input_processed, sizeof(unsigned char), input_processed, stdin); + TRY_YIELD; + } + } - if(!strcmp(argv[1],"dump_u8")) - { - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize*3); - unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize); - for(;;) - { - FEOF_CHECK; - fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin); - for(int i=0;i - { - float samples_per_bits; - if(argc<=2) return badsyntax("need required parameter (samples_per_bits)"); - sscanf(argv[2],"%f",&samples_per_bits); - if(samples_per_bits<=0) return badsyntax("samples_per_bits should be > 0"); + if(!strcmp(argv[1],"bpsk_costas_loop_cc")) // + { + float samples_per_bits; + if(argc<=2) return badsyntax("need required parameter (samples_per_bits)"); + sscanf(argv[2],"%f",&samples_per_bits); + if(samples_per_bits<=0) return badsyntax("samples_per_bits should be > 0"); - bpsk_costas_loop_state_t state = init_bpsk_costas_loop_cc(samples_per_bits); + bpsk_costas_loop_state_t state = init_bpsk_costas_loop_cc(samples_per_bits); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize); - for(;;) - { - FEOF_CHECK; - FREAD_C; - bpsk_costas_loop_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, &state); - FWRITE_C; - TRY_YIELD; - } - } + for(;;) + { + FEOF_CHECK; + FREAD_C; + bpsk_costas_loop_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, &state); + FWRITE_C; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"simple_agc_cc")) // [reference [max_gain]] - { - float rate; - if(argc<=2) return badsyntax("need required parameter (rate)"); - sscanf(argv[2],"%f",&rate); - if(rate<=0) return badsyntax("rate should be > 0"); + if(!strcmp(argv[1],"simple_agc_cc")) // [reference [max_gain]] + { + float rate; + if(argc<=2) return badsyntax("need required parameter (rate)"); + sscanf(argv[2],"%f",&rate); + if(rate<=0) return badsyntax("rate should be > 0"); - float reference = 1.; - if(argc>3) sscanf(argv[3],"%f",&reference); - if(reference<=0) return badsyntax("reference should be > 0"); + float reference = 1.; + if(argc>3) sscanf(argv[3],"%f",&reference); + if(reference<=0) return badsyntax("reference should be > 0"); - float max_gain = 65535.; - if(argc>4) sscanf(argv[4],"%f",&max_gain); - if(max_gain<=0) return badsyntax("max_gain should be > 0"); + float max_gain = 65535.; + if(argc>4) sscanf(argv[4],"%f",&max_gain); + if(max_gain<=0) return badsyntax("max_gain should be > 0"); - float current_gain = 1.; + float current_gain = 1.; - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize); - for(;;) - { - FEOF_CHECK; - FREAD_C; - simple_agc_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, reference, max_gain, ¤t_gain); - FWRITE_C; - TRY_YIELD; - } - } + for(;;) + { + FEOF_CHECK; + FREAD_C; + simple_agc_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, reference, max_gain, ¤t_gain); + FWRITE_C; + TRY_YIELD; + } + } - if(!strcmp(argv[1],"firdes_resonator_c")) // [window [--octave]] - { - //Process the params - if(argc<=3) return badsyntax("need required parameters (rate, length)"); + if(!strcmp(argv[1],"firdes_resonator_c")) // [window [--octave]] + { + //Process the params + if(argc<=3) return badsyntax("need required parameters (rate, length)"); - float rate; - sscanf(argv[2],"%g",&rate); - int length; - sscanf(argv[3],"%d",&length); - if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd"); + float rate; + sscanf(argv[2],"%g",&rate); + int length; + sscanf(argv[3],"%d",&length); + if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd"); - window_t window = WINDOW_DEFAULT; - if(argc>=5) - { - window=firdes_get_window_from_string(argv[4]); - } - else fprintf(stderr,"firdes_resonator_c: window = %s\n",firdes_get_string_from_window(window)); + window_t window = WINDOW_DEFAULT; + if(argc>=5) + { + window=firdes_get_window_from_string(argv[4]); + } + else fprintf(stderr,"firdes_resonator_c: window = %s\n",firdes_get_string_from_window(window)); - int octave=(argc>=6 && !strcmp("--octave",argv[5])); + int octave=(argc>=6 && !strcmp("--octave",argv[5])); - complexf* taps=(complexf*)malloc(sizeof(complexf)*length); + complexf* taps=(complexf*)malloc(sizeof(complexf)*length); - //Make the filter - firdes_add_resonator_c(taps, length, rate, window, 0, 1); + //Make the filter + firdes_add_resonator_c(taps, length, rate, window, 0, 1); - //Do the output - if(octave) printf("taps=["); - for(int i=0;i - { - //rule of thumb: bw = 2/taps_length, which does not equal to transition_bw + if(!strcmp(argv[1],"resonators_fir_cc")) // + { + //rule of thumb: bw = 2/taps_length, which does not equal to transition_bw - if(argc<=2) return badsyntax("need required parameter (taps_length)"); - int taps_length; - sscanf(argv[2],"%d",&taps_length); + if(argc<=2) return badsyntax("need required parameter (taps_length)"); + int taps_length; + sscanf(argv[2],"%d",&taps_length); - int num_resonators = argc-3; - float* resonator_rate = (float*)malloc(sizeof(float)*num_resonators); - for(int i=0;i is missing."); float snr_db = 0; - sscanf(argv[2],"%f",&snr_db); + sscanf(argv[2],"%f",&snr_db); FILE* awgnfile = NULL; if(argc>=5 && !strcmp(argv[3],"--awgnfile")) { @@ -2926,8 +2926,8 @@ int main(int argc, char *argv[]) float a_signal=signal_amplitude_per_noise/(signal_amplitude_per_noise+1.0); float a_noise=1.0/(signal_amplitude_per_noise+1.0); fprintf(stderr, "csdr awgn_cc: a_signal = %f, a_noise = %f\n", a_signal, a_noise); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize); complexf* awgn_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize); for(;;) { @@ -2968,100 +2968,119 @@ int main(int argc, char *argv[]) if(!strcmp(argv[1], "uniform_noise_f")) { FILE* urandom = init_get_random_samples_f(); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize); for(;;) { FEOF_CHECK; get_random_samples_f(output_buffer, the_bufsize, urandom); FWRITE_R; TRY_YIELD; - } + } } if(!strcmp(argv[1], "gaussian_noise_c")) { FILE* urandom = init_get_random_samples_f(); - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize); for(;;) { FEOF_CHECK; get_random_gaussian_samples_c((complexf*)output_buffer, the_bufsize, urandom); FWRITE_C; TRY_YIELD; - } + } } - if(!strcmp(argv[1], "normalized_timing_variance_u32_f")) // [--debug] - { + if(!strcmp(argv[1], "normalized_timing_variance_u32_f")) // [--debug] + { int samples_per_symbol = 0; if(argc<=2) return badsyntax("required parameter is missing."); - sscanf(argv[2],"%d",&samples_per_symbol); + sscanf(argv[2],"%d",&samples_per_symbol); int initial_sample_offset = 0; if(argc<=3) return badsyntax("required parameter is missing."); - sscanf(argv[3],"%d",&initial_sample_offset); + sscanf(argv[3],"%d",&initial_sample_offset); int debug_print = 0; if(argc>4 && !strcmp(argv[4],"--debug")) debug_print = 1; - if(!initialize_buffers()) return -2; - sendbufsize(the_bufsize); - float* temp_buffer = (float*)malloc(sizeof(float)*the_bufsize); + if(!initialize_buffers()) return -2; + sendbufsize(the_bufsize); + float* temp_buffer = (float*)malloc(sizeof(float)*the_bufsize); for(;;) { FEOF_CHECK; - FREAD_R; //doesn't count, reads 4 bytes per sample anyway + FREAD_R; //doesn't count, reads 4 bytes per sample anyway float nv = normalized_timing_variance_u32_f((unsigned*)input_buffer, temp_buffer, the_bufsize, samples_per_symbol, initial_sample_offset, debug_print); - fwrite(&nv, sizeof(float), 1, stdout); - fprintf(stderr, "csdr normalized_timing_variance_u32_f: normalized variance = %f\n", nv); + fwrite(&nv, sizeof(float), 1, stdout); + fprintf(stderr, "csdr normalized_timing_variance_u32_f: normalized variance = %f\n", nv); TRY_YIELD; } - } + } - if(!strcmp(argv[1], "add_n_zero_samples_at_beginning_f")) // - { + if(!strcmp(argv[1], "add_n_zero_samples_at_beginning_f")) // + { int n_zero_samples = 0; if(argc<=2) return badsyntax("required parameter is missing."); - sscanf(argv[2],"%d",&n_zero_samples); - if(!sendbufsize(initialize_buffers())) return -2; + sscanf(argv[2],"%d",&n_zero_samples); + if(!sendbufsize(initialize_buffers())) return -2; float* zeros=(float*)calloc(sizeof(float),n_zero_samples); fwrite(zeros, sizeof(float), n_zero_samples, stdout); clone_(the_bufsize); } +/* + if(!strcmp(argv[1], "matched_filter_cc")) // + { + int samples_per_symbol = 0; + if(argc<=2) return badsyntax("required parameter is missing."); + sscanf(argv[2],"%d",&samples_per_symbol); + int num_taps = 0; + if(argc<=2) return badsyntax("required parameter is missing."); + sscanf(argv[2],"%d",&num_taps); + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + FREAD_C; + FWRITE_C; + TRY_YIELD; + } + } +*/ - if(!strcmp(argv[1],"none")) - { - return 0; - } + if(!strcmp(argv[1],"none")) + { + return 0; + } - if(argv[1][0]=='?' && argv[1][1]=='?') - { - char buffer[1000]; - snprintf(buffer, 1000-1, "xdg-open https://github.com/simonyiszk/csdr/blob/master/README.md#$(csdr ?%s | head -n1 | awk '{print $1;}')", argv[1]+2); - fprintf(stderr, "csdr ??: %s\n", buffer); - system(buffer); - return 0; - } + if(argv[1][0]=='?' && argv[1][1]=='?') + { + char buffer[1000]; + snprintf(buffer, 1000-1, "xdg-open https://github.com/simonyiszk/csdr/blob/master/README.md#$(csdr ?%s | head -n1 | awk '{print $1;}')", argv[1]+2); + fprintf(stderr, "csdr ??: %s\n", buffer); + system(buffer); + return 0; + } - if(argv[1][0]=='?') - { - char buffer[1000]; - snprintf(buffer, 1000-1, "csdr 2>&1 | grep %s", argv[1]+1); - fprintf(stderr, "csdr ?: %s\n", buffer); - system(buffer); - return 0; - } + if(argv[1][0]=='?') + { + char buffer[1000]; + snprintf(buffer, 1000-1, "csdr 2>&1 | grep %s", argv[1]+1); + fprintf(stderr, "csdr ?: %s\n", buffer); + system(buffer); + return 0; + } - if(argv[1][0]=='=') - { - char buffer[100]; - snprintf(buffer, 100-1, "python -c \"import os, sys\nfrom math import *\nprint %s\"", argv[1]+1); - system(buffer); - return 0; - } + if(argv[1][0]=='=') + { + char buffer[100]; + snprintf(buffer, 100-1, "python -c \"import os, sys\nfrom math import *\nprint %s\"", argv[1]+1); + system(buffer); + return 0; + } - 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; + 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; } diff --git a/libcsdr.c b/libcsdr.c index 177a095..f2ea3e8 100755 --- a/libcsdr.c +++ b/libcsdr.c @@ -52,55 +52,55 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define MFIRDES_GWS(NAME) \ - if(!strcmp( #NAME , input )) return WINDOW_ ## NAME; + if(!strcmp( #NAME , input )) return WINDOW_ ## NAME; window_t firdes_get_window_from_string(char* input) { - MFIRDES_GWS(BOXCAR); - MFIRDES_GWS(BLACKMAN); - MFIRDES_GWS(HAMMING); - return WINDOW_DEFAULT; + MFIRDES_GWS(BOXCAR); + MFIRDES_GWS(BLACKMAN); + MFIRDES_GWS(HAMMING); + return WINDOW_DEFAULT; } #define MFIRDES_GSW(NAME) \ - if(window == WINDOW_ ## NAME) return #NAME; + if(window == WINDOW_ ## NAME) return #NAME; char* firdes_get_string_from_window(window_t window) { - MFIRDES_GSW(BOXCAR); - MFIRDES_GSW(BLACKMAN); - MFIRDES_GSW(HAMMING); - return "INVALID"; + MFIRDES_GSW(BOXCAR); + MFIRDES_GSW(BLACKMAN); + MFIRDES_GSW(HAMMING); + return "INVALID"; } float firdes_wkernel_blackman(float rate) { - //Explanation at Chapter 16 of dspguide.com, page 2 - //Blackman window has better stopband attentuation and passband ripple than Hamming, but it has slower rolloff. - rate=0.5+rate/2; - return 0.42-0.5*cos(2*PI*rate)+0.08*cos(4*PI*rate); + //Explanation at Chapter 16 of dspguide.com, page 2 + //Blackman window has better stopband attentuation and passband ripple than Hamming, but it has slower rolloff. + rate=0.5+rate/2; + return 0.42-0.5*cos(2*PI*rate)+0.08*cos(4*PI*rate); } float firdes_wkernel_hamming(float rate) { - //Explanation at Chapter 16 of dspguide.com, page 2 - //Hamming window has worse stopband attentuation and passband ripple than Blackman, but it has faster rolloff. - rate=0.5+rate/2; - return 0.54-0.46*cos(2*PI*rate); + //Explanation at Chapter 16 of dspguide.com, page 2 + //Hamming window has worse stopband attentuation and passband ripple than Blackman, but it has faster rolloff. + rate=0.5+rate/2; + return 0.54-0.46*cos(2*PI*rate); } float firdes_wkernel_boxcar(float rate) -{ //"Dummy" window kernel, do not use; an unwindowed FIR filter may have bad frequency response - return 1.0; +{ //"Dummy" window kernel, do not use; an unwindowed FIR filter may have bad frequency response + return 1.0; } float (*firdes_get_window_kernel(window_t window))(float) { - if(window==WINDOW_HAMMING) return firdes_wkernel_hamming; - else if(window==WINDOW_BLACKMAN) return firdes_wkernel_blackman; - else if(window==WINDOW_BOXCAR) return firdes_wkernel_boxcar; - else return firdes_get_window_kernel(WINDOW_DEFAULT); + if(window==WINDOW_HAMMING) return firdes_wkernel_hamming; + else if(window==WINDOW_BLACKMAN) return firdes_wkernel_blackman; + else if(window==WINDOW_BOXCAR) return firdes_wkernel_boxcar; + else return firdes_get_window_kernel(WINDOW_DEFAULT); } /* @@ -115,62 +115,62 @@ float (*firdes_get_window_kernel(window_t window))(float) */ void firdes_lowpass_f(float *output, int length, float cutoff_rate, window_t window) -{ //Generates symmetric windowed sinc FIR filter real taps - // length should be odd - // cutoff_rate is (cutoff frequency/sampling frequency) - //Explanation at Chapter 16 of dspguide.com - int middle=length/2; - float temp; - float (*window_function)(float) = firdes_get_window_kernel(window); - output[middle]=2*PI*cutoff_rate*window_function(0); - for(int i=1; i<=middle; i++) //@@firdes_lowpass_f: calculate taps - { - output[middle-i]=output[middle+i]=(sin(2*PI*cutoff_rate*i)/i)*window_function((float)i/middle); - //printf("%g %d %d %d %d | %g\n",output[middle-i],i,middle,middle+i,middle-i,sin(2*PI*cutoff_rate*i)); - } +{ //Generates symmetric windowed sinc FIR filter real taps + // length should be odd + // cutoff_rate is (cutoff frequency/sampling frequency) + //Explanation at Chapter 16 of dspguide.com + int middle=length/2; + float temp; + float (*window_function)(float) = firdes_get_window_kernel(window); + output[middle]=2*PI*cutoff_rate*window_function(0); + for(int i=1; i<=middle; i++) //@@firdes_lowpass_f: calculate taps + { + output[middle-i]=output[middle+i]=(sin(2*PI*cutoff_rate*i)/i)*window_function((float)i/middle); + //printf("%g %d %d %d %d | %g\n",output[middle-i],i,middle,middle+i,middle-i,sin(2*PI*cutoff_rate*i)); + } - //Normalize filter kernel - float sum=0; - for(int i=0;i2*PI) phase-=2*PI; //@@firdes_bandpass_c - while(phase<0) phase+=2*PI; - iof(output,i)=cosval*realtaps[i]; - qof(output,i)=sinval*realtaps[i]; - //output[i] := realtaps[i] * e^j*w - } + float phase=0, sinval, cosval; + for(int i=0; i2*PI) phase-=2*PI; //@@firdes_bandpass_c + while(phase<0) phase+=2*PI; + iof(output,i)=cosval*realtaps[i]; + qof(output,i)=sinval*realtaps[i]; + //output[i] := realtaps[i] * e^j*w + } } int firdes_filter_len(float transition_bw) { - int result=4.0/transition_bw; - if (result%2==0) result++; //number of symmetric FIR filter taps should be odd - return result; + int result=4.0/transition_bw; + if (result%2==0) result++; //number of symmetric FIR filter taps should be odd + return result; } /* @@ -185,135 +185,135 @@ int firdes_filter_len(float transition_bw) float shift_math_cc(complexf *input, complexf* output, int input_size, float rate, float starting_phase) { - rate*=2; - //Shifts the complex spectrum. Basically a complex mixer. This version uses cmath. - float phase=starting_phase; - float phase_increment=rate*PI; - float cosval, sinval; - for(int i=0;i2*PI) phase-=2*PI; //@shift_math_cc: normalize phase - while(phase<0) phase+=2*PI; - } - return phase; + rate*=2; + //Shifts the complex spectrum. Basically a complex mixer. This version uses cmath. + float phase=starting_phase; + float phase_increment=rate*PI; + float cosval, sinval; + for(int i=0;i2*PI) phase-=2*PI; //@shift_math_cc: normalize phase + while(phase<0) phase+=2*PI; + } + return phase; } shift_table_data_t shift_table_init(int table_size) { - //RTODO - shift_table_data_t output; - output.table=(float*)malloc(sizeof(float)*table_size); - output.table_size=table_size; - for(int i=0;i1)?-1:1; //in quadrant 2 and 3 - cos_sign=(quadrant&&quadrant<3)?-1:1; //in quadrant 1 and 2 - sinval=sin_sign*table_data.table[sin_index]; - cosval=cos_sign*table_data.table[cos_index]; - //we multiply two complex numbers. - //how? enter this to maxima (software) for explanation: - // (a+b*%i)*(c+d*%i), rectform; - iof(output,i)=cosval*iof(input,i)-sinval*qof(input,i); - qof(output,i)=sinval*iof(input,i)+cosval*qof(input,i); - phase+=phase_increment; - while(phase>2*PI) phase-=2*PI; //@shift_math_cc: normalize phase - while(phase<0) phase+=2*PI; - } - return phase; + //RTODO + rate*=2; + //Shifts the complex spectrum. Basically a complex mixer. This version uses a pre-built sine table. + float phase=starting_phase; + float phase_increment=rate*PI; + float cosval, sinval; + for(int i=0;i1)?-1:1; //in quadrant 2 and 3 + cos_sign=(quadrant&&quadrant<3)?-1:1; //in quadrant 1 and 2 + sinval=sin_sign*table_data.table[sin_index]; + cosval=cos_sign*table_data.table[cos_index]; + //we multiply two complex numbers. + //how? enter this to maxima (software) for explanation: + // (a+b*%i)*(c+d*%i), rectform; + iof(output,i)=cosval*iof(input,i)-sinval*qof(input,i); + qof(output,i)=sinval*iof(input,i)+cosval*qof(input,i); + phase+=phase_increment; + while(phase>2*PI) phase-=2*PI; //@shift_math_cc: normalize phase + while(phase<0) phase+=2*PI; + } + return phase; } shift_unroll_data_t shift_unroll_init(float rate, int size) { - shift_unroll_data_t output; - output.phase_increment=2*rate*PI; - output.size = size; - output.dsin=(float*)malloc(sizeof(float)*size); - output.dcos=(float*)malloc(sizeof(float)*size); - float myphase = 0; - for(int i=0;iPI) myphase-=2*PI; - while(myphase<-PI) myphase+=2*PI; - output.dsin[i]=sin(myphase); - output.dcos[i]=cos(myphase); - } - return output; + shift_unroll_data_t output; + output.phase_increment=2*rate*PI; + output.size = size; + output.dsin=(float*)malloc(sizeof(float)*size); + output.dcos=(float*)malloc(sizeof(float)*size); + float myphase = 0; + for(int i=0;iPI) myphase-=2*PI; + while(myphase<-PI) myphase+=2*PI; + output.dsin[i]=sin(myphase); + output.dcos[i]=cos(myphase); + } + return output; } float shift_unroll_cc(complexf *input, complexf* output, int input_size, shift_unroll_data_t* d, float starting_phase) { - //input_size should be multiple of 4 - //fprintf(stderr, "shift_addfast_cc: input_size = %d\n", input_size); - float cos_start=cos(starting_phase); - float sin_start=sin(starting_phase); - register float cos_val, sin_val; - for(int i=0;idcos[i] - sin_start * d->dsin[i]; - sin_val = sin_start * d->dcos[i] + cos_start * d->dsin[i]; - iof(output,i)=cos_val*iof(input,i)-sin_val*qof(input,i); - qof(output,i)=sin_val*iof(input,i)+cos_val*qof(input,i); - } - starting_phase+=input_size*d->phase_increment; - while(starting_phase>PI) starting_phase-=2*PI; - while(starting_phase<-PI) starting_phase+=2*PI; - return starting_phase; + //input_size should be multiple of 4 + //fprintf(stderr, "shift_addfast_cc: input_size = %d\n", input_size); + float cos_start=cos(starting_phase); + float sin_start=sin(starting_phase); + register float cos_val, sin_val; + for(int i=0;idcos[i] - sin_start * d->dsin[i]; + sin_val = sin_start * d->dcos[i] + cos_start * d->dsin[i]; + iof(output,i)=cos_val*iof(input,i)-sin_val*qof(input,i); + qof(output,i)=sin_val*iof(input,i)+cos_val*qof(input,i); + } + starting_phase+=input_size*d->phase_increment; + while(starting_phase>PI) starting_phase-=2*PI; + while(starting_phase<-PI) starting_phase+=2*PI; + return starting_phase; } shift_addfast_data_t shift_addfast_init(float rate) { - shift_addfast_data_t output; - output.phase_increment=2*rate*PI; - for(int i=0;i<4;i++) - { - output.dsin[i]=sin(output.phase_increment*(i+1)); - output.dcos[i]=cos(output.phase_increment*(i+1)); - } - return output; + shift_addfast_data_t output; + output.phase_increment=2*rate*PI; + for(int i=0;i<4;i++) + { + output.dsin[i]=sin(output.phase_increment*(i+1)); + output.dcos[i]=cos(output.phase_increment*(i+1)); + } + return output; } #ifdef NEON_OPTS @@ -321,76 +321,76 @@ shift_addfast_data_t shift_addfast_init(float rate) float shift_addfast_cc(complexf *input, complexf* output, int input_size, shift_addfast_data_t* d, float starting_phase) { - //input_size should be multiple of 4 - float cos_start[4], sin_start[4]; - float cos_vals[4], sin_vals[4]; - for(int i=0;i<4;i++) - { - cos_start[i] = cos(starting_phase); - sin_start[i] = sin(starting_phase); - } + //input_size should be multiple of 4 + float cos_start[4], sin_start[4]; + float cos_vals[4], sin_vals[4]; + for(int i=0;i<4;i++) + { + cos_start[i] = cos(starting_phase); + sin_start[i] = sin(starting_phase); + } - float* pdcos = d->dcos; - float* pdsin = d->dsin; - register float* pinput = (float*)input; - register float* pinput_end = (float*)(input+input_size); - register float* poutput = (float*)output; + float* pdcos = d->dcos; + float* pdsin = d->dsin; + register float* pinput = (float*)input; + register float* pinput_end = (float*)(input+input_size); + register float* poutput = (float*)output; - //Register map: - #define RDCOS "q0" //dcos, dsin - #define RDSIN "q1" - #define RCOSST "q2" //cos_start, sin_start - #define RSINST "q3" - #define RCOSV "q4" //cos_vals, sin_vals - #define RSINV "q5" - #define ROUTI "q6" //output_i, output_q - #define ROUTQ "q7" - #define RINPI "q8" //input_i, input_q - #define RINPQ "q9" - #define R3(x,y,z) x ", " y ", " z "\n\t" + //Register map: + #define RDCOS "q0" //dcos, dsin + #define RDSIN "q1" + #define RCOSST "q2" //cos_start, sin_start + #define RSINST "q3" + #define RCOSV "q4" //cos_vals, sin_vals + #define RSINV "q5" + #define ROUTI "q6" //output_i, output_q + #define ROUTQ "q7" + #define RINPI "q8" //input_i, input_q + #define RINPQ "q9" + #define R3(x,y,z) x ", " y ", " z "\n\t" - asm volatile( //(the range of q is q0-q15) - " vld1.32 {" RDCOS "}, [%[pdcos]]\n\t" - " vld1.32 {" RDSIN "}, [%[pdsin]]\n\t" - " vld1.32 {" RCOSST "}, [%[cos_start]]\n\t" - " vld1.32 {" RSINST "}, [%[sin_start]]\n\t" - "for_addfast: vld2.32 {" RINPI "-" RINPQ "}, [%[pinput]]!\n\t" //load q0 and q1 directly from the memory address stored in pinput, with interleaving (so that we get the I samples in RINPI and the Q samples in RINPQ), also increment the memory address in pinput (hence the "!" mark) + asm volatile( //(the range of q is q0-q15) + " vld1.32 {" RDCOS "}, [%[pdcos]]\n\t" + " vld1.32 {" RDSIN "}, [%[pdsin]]\n\t" + " vld1.32 {" RCOSST "}, [%[cos_start]]\n\t" + " vld1.32 {" RSINST "}, [%[sin_start]]\n\t" + "for_addfast: vld2.32 {" RINPI "-" RINPQ "}, [%[pinput]]!\n\t" //load q0 and q1 directly from the memory address stored in pinput, with interleaving (so that we get the I samples in RINPI and the Q samples in RINPQ), also increment the memory address in pinput (hence the "!" mark) - //C version: - //cos_vals[j] = cos_start * d->dcos[j] - sin_start * d->dsin[j]; - //sin_vals[j] = sin_start * d->dcos[j] + cos_start * d->dsin[j]; + //C version: + //cos_vals[j] = cos_start * d->dcos[j] - sin_start * d->dsin[j]; + //sin_vals[j] = sin_start * d->dcos[j] + cos_start * d->dsin[j]; - " vmul.f32 " R3(RCOSV, RCOSST, RDCOS) //cos_vals[i] = cos_start * d->dcos[i] - " vmls.f32 " R3(RCOSV, RSINST, RDSIN) //cos_vals[i] -= sin_start * d->dsin[i] - " vmul.f32 " R3(RSINV, RSINST, RDCOS) //sin_vals[i] = sin_start * d->dcos[i] - " vmla.f32 " R3(RSINV, RCOSST, RDSIN) //sin_vals[i] += cos_start * d->dsin[i] + " vmul.f32 " R3(RCOSV, RCOSST, RDCOS) //cos_vals[i] = cos_start * d->dcos[i] + " vmls.f32 " R3(RCOSV, RSINST, RDSIN) //cos_vals[i] -= sin_start * d->dsin[i] + " vmul.f32 " R3(RSINV, RSINST, RDCOS) //sin_vals[i] = sin_start * d->dcos[i] + " vmla.f32 " R3(RSINV, RCOSST, RDSIN) //sin_vals[i] += cos_start * d->dsin[i] - //C version: - //iof(output,4*i+j)=cos_vals[j]*iof(input,4*i+j)-sin_vals[j]*qof(input,4*i+j); - //qof(output,4*i+j)=sin_vals[j]*iof(input,4*i+j)+cos_vals[j]*qof(input,4*i+j); - " vmul.f32 " R3(ROUTI, RCOSV, RINPI) //output_i = cos_vals * input_i - " vmls.f32 " R3(ROUTI, RSINV, RINPQ) //output_i -= sin_vals * input_q - " vmul.f32 " R3(ROUTQ, RSINV, RINPI) //output_q = sin_vals * input_i - " vmla.f32 " R3(ROUTQ, RCOSV, RINPQ) //output_i += cos_vals * input_q + //C version: + //iof(output,4*i+j)=cos_vals[j]*iof(input,4*i+j)-sin_vals[j]*qof(input,4*i+j); + //qof(output,4*i+j)=sin_vals[j]*iof(input,4*i+j)+cos_vals[j]*qof(input,4*i+j); + " vmul.f32 " R3(ROUTI, RCOSV, RINPI) //output_i = cos_vals * input_i + " vmls.f32 " R3(ROUTI, RSINV, RINPQ) //output_i -= sin_vals * input_q + " vmul.f32 " R3(ROUTQ, RSINV, RINPI) //output_q = sin_vals * input_i + " vmla.f32 " R3(ROUTQ, RCOSV, RINPQ) //output_i += cos_vals * input_q - " vst2.32 {" ROUTI "-" ROUTQ "}, [%[poutput]]!\n\t" //store the outputs in memory - //" add %[poutput],%[poutput],#32\n\t" - " vdup.32 " RCOSST ", d9[1]\n\t" // cos_start[0-3] = cos_vals[3] - " vdup.32 " RSINST ", d11[1]\n\t" // sin_start[0-3] = sin_vals[3] + " vst2.32 {" ROUTI "-" ROUTQ "}, [%[poutput]]!\n\t" //store the outputs in memory + //" add %[poutput],%[poutput],#32\n\t" + " vdup.32 " RCOSST ", d9[1]\n\t" // cos_start[0-3] = cos_vals[3] + " vdup.32 " RSINST ", d11[1]\n\t" // sin_start[0-3] = sin_vals[3] - " cmp %[pinput], %[pinput_end]\n\t" //if(pinput != pinput_end) - " bcc for_addfast\n\t" // then goto for_addfast - : - [pinput]"+r"(pinput), [poutput]"+r"(poutput) //output operand list -> C variables that we will change from ASM - : - [pinput_end]"r"(pinput_end), [pdcos]"r"(pdcos), [pdsin]"r"(pdsin), [sin_start]"r"(sin_start), [cos_start]"r"(cos_start) //input operand list - : - "memory", "q0", "q1", "q2", "q4", "q5", "q6", "q7", "q8", "q9", "cc" //clobber list - ); - starting_phase+=input_size*d->phase_increment; - while(starting_phase>PI) starting_phase-=2*PI; - while(starting_phase<-PI) starting_phase+=2*PI; - return starting_phase; + " cmp %[pinput], %[pinput_end]\n\t" //if(pinput != pinput_end) + " bcc for_addfast\n\t" // then goto for_addfast + : + [pinput]"+r"(pinput), [poutput]"+r"(poutput) //output operand list -> C variables that we will change from ASM + : + [pinput_end]"r"(pinput_end), [pdcos]"r"(pdcos), [pdsin]"r"(pdsin), [sin_start]"r"(sin_start), [cos_start]"r"(cos_start) //input operand list + : + "memory", "q0", "q1", "q2", "q4", "q5", "q6", "q7", "q8", "q9", "cc" //clobber list + ); + starting_phase+=input_size*d->phase_increment; + while(starting_phase>PI) starting_phase-=2*PI; + while(starting_phase<-PI) starting_phase+=2*PI; + return starting_phase; } #else @@ -399,66 +399,66 @@ float shift_addfast_cc(complexf *input, complexf* output, int input_size, shift_ #if 1 #define SADF_L1(j) cos_vals_ ## j = cos_start * dcos_ ## j - sin_start * dsin_ ## j; \ - sin_vals_ ## j = sin_start * dcos_ ## j + cos_start * dsin_ ## j; + sin_vals_ ## j = sin_start * dcos_ ## j + cos_start * dsin_ ## j; #define SADF_L2(j) iof(output,4*i+j)=(cos_vals_ ## j)*iof(input,4*i+j)-(sin_vals_ ## j)*qof(input,4*i+j); \ - qof(output,4*i+j)=(sin_vals_ ## j)*iof(input,4*i+j)+(cos_vals_ ## j)*qof(input,4*i+j); + qof(output,4*i+j)=(sin_vals_ ## j)*iof(input,4*i+j)+(cos_vals_ ## j)*qof(input,4*i+j); float shift_addfast_cc(complexf *input, complexf* output, int input_size, shift_addfast_data_t* d, float starting_phase) { - //input_size should be multiple of 4 - //fprintf(stderr, "shift_addfast_cc: input_size = %d\n", input_size); - float cos_start=cos(starting_phase); - float sin_start=sin(starting_phase); - float register cos_vals_0, cos_vals_1, cos_vals_2, cos_vals_3, - sin_vals_0, sin_vals_1, sin_vals_2, sin_vals_3, - dsin_0 = d->dsin[0], dsin_1 = d->dsin[1], dsin_2 = d->dsin[2], dsin_3 = d->dsin[3], - dcos_0 = d->dcos[0], dcos_1 = d->dcos[1], dcos_2 = d->dcos[2], dcos_3 = d->dcos[3]; + //input_size should be multiple of 4 + //fprintf(stderr, "shift_addfast_cc: input_size = %d\n", input_size); + float cos_start=cos(starting_phase); + float sin_start=sin(starting_phase); + float register cos_vals_0, cos_vals_1, cos_vals_2, cos_vals_3, + sin_vals_0, sin_vals_1, sin_vals_2, sin_vals_3, + dsin_0 = d->dsin[0], dsin_1 = d->dsin[1], dsin_2 = d->dsin[2], dsin_3 = d->dsin[3], + dcos_0 = d->dcos[0], dcos_1 = d->dcos[1], dcos_2 = d->dcos[2], dcos_3 = d->dcos[3]; - for(int i=0;iphase_increment; - while(starting_phase>PI) starting_phase-=2*PI; - while(starting_phase<-PI) starting_phase+=2*PI; - return starting_phase; + for(int i=0;iphase_increment; + while(starting_phase>PI) starting_phase-=2*PI; + while(starting_phase<-PI) starting_phase+=2*PI; + return starting_phase; } #else float shift_addfast_cc(complexf *input, complexf* output, int input_size, shift_addfast_data_t* d, float starting_phase) { - //input_size should be multiple of 4 - //fprintf(stderr, "shift_addfast_cc: input_size = %d\n", input_size); - float cos_start=cos(starting_phase); - float sin_start=sin(starting_phase); - float cos_vals[4], sin_vals[4]; - for(int i=0;idcos[j] - sin_start * d->dsin[j]; - sin_vals[j] = sin_start * d->dcos[j] + cos_start * d->dsin[j]; - } - for(int j=0;j<4;j++) //@shift_addfast_cc - { - iof(output,4*i+j)=cos_vals[j]*iof(input,4*i+j)-sin_vals[j]*qof(input,4*i+j); - qof(output,4*i+j)=sin_vals[j]*iof(input,4*i+j)+cos_vals[j]*qof(input,4*i+j); - } - cos_start = cos_vals[3]; - sin_start = sin_vals[3]; - } - starting_phase+=input_size*d->phase_increment; - while(starting_phase>PI) starting_phase-=2*PI; - while(starting_phase<-PI) starting_phase+=2*PI; - return starting_phase; + //input_size should be multiple of 4 + //fprintf(stderr, "shift_addfast_cc: input_size = %d\n", input_size); + float cos_start=cos(starting_phase); + float sin_start=sin(starting_phase); + float cos_vals[4], sin_vals[4]; + for(int i=0;idcos[j] - sin_start * d->dsin[j]; + sin_vals[j] = sin_start * d->dcos[j] + cos_start * d->dsin[j]; + } + for(int j=0;j<4;j++) //@shift_addfast_cc + { + iof(output,4*i+j)=cos_vals[j]*iof(input,4*i+j)-sin_vals[j]*qof(input,4*i+j); + qof(output,4*i+j)=sin_vals[j]*iof(input,4*i+j)+cos_vals[j]*qof(input,4*i+j); + } + cos_start = cos_vals[3]; + sin_start = sin_vals[3]; + } + starting_phase+=input_size*d->phase_increment; + while(starting_phase>PI) starting_phase-=2*PI; + while(starting_phase<-PI) starting_phase+=2*PI; + return starting_phase; } #endif @@ -471,81 +471,81 @@ float shift_addfast_cc(complexf *input, complexf* output, int input_size, shift_ int fir_decimate_cc(complexf *input, complexf *output, int input_size, int decimation, float *taps, int taps_length) { - //Theory: http://www.dspguru.com/dsp/faqs/multirate/decimation - //It uses real taps. It returns the number of output samples actually written. - //It needs overlapping input based on its returned value: - //number of processed input samples = returned value * decimation factor - //The output buffer should be at least input_length / 3. - // i: input index | ti: tap index | oi: output index - int oi=0; - for(int i=0; iinput_size) break; - register float* pinput=(float*)&(input[i]); - register float* ptaps=taps; - register float* ptaps_end=taps+taps_length; - float quad_acciq [8]; + //Theory: http://www.dspguru.com/dsp/faqs/multirate/decimation + //It uses real taps. It returns the number of output samples actually written. + //It needs overlapping input based on its returned value: + //number of processed input samples = returned value * decimation factor + //The output buffer should be at least input_length / 3. + // i: input index | ti: tap index | oi: output index + int oi=0; + for(int i=0; iinput_size) break; + register float* pinput=(float*)&(input[i]); + register float* ptaps=taps; + register float* ptaps_end=taps+taps_length; + float quad_acciq [8]; /* -q0, q1: input signal I sample and Q sample -q2: taps +q0, q1: input signal I sample and Q sample +q2: taps q4, q5: accumulator for I branch and Q branch (will be the output) */ - asm volatile( - " veor q4, q4\n\t" - " veor q5, q5\n\t" - "for_fdccasm: vld2.32 {q0-q1}, [%[pinput]]!\n\t" //load q0 and q1 directly from the memory address stored in pinput, with interleaving (so that we get the I samples in q0 and the Q samples in q1), also increment the memory address in pinput (hence the "!" mark) //http://community.arm.com/groups/processors/blog/2010/03/17/coding-for-neon--part-1-load-and-stores - " vld1.32 {q2}, [%[ptaps]]!\n\t" - " vmla.f32 q4, q0, q2\n\t" //quad_acc_i += quad_input_i * quad_taps_1 //http://stackoverflow.com/questions/3240440/how-to-use-the-multiply-and-accumulate-intrinsics-in-arm-cortex-a8 //http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489e/CIHEJBIE.html - " vmla.f32 q5, q1, q2\n\t" //quad_acc_q += quad_input_q * quad_taps_1 - " cmp %[ptaps], %[ptaps_end]\n\t" //if(ptaps != ptaps_end) - " bcc for_fdccasm\n\t" // then goto for_fdcasm - " vst1.32 {q4}, [%[quad_acci]]\n\t" //if the loop is finished, store the two accumulators in memory - " vst1.32 {q5}, [%[quad_accq]]\n\t" - : - [pinput]"+r"(pinput), [ptaps]"+r"(ptaps) //output operand list - : - [ptaps_end]"r"(ptaps_end), [quad_acci]"r"(quad_acciq), [quad_accq]"r"(quad_acciq+4) //input operand list - : - "memory", "q0", "q1", "q2", "q4", "q5", "cc" //clobber list - ); - //original for loops for reference: - //for(int ti=0; ti> [%d] %g \n", n, quad_acciq[n]); - iof(output,oi)=quad_acciq[0]+quad_acciq[1]+quad_acciq[2]+quad_acciq[3]; //we're still not ready, as we have to add up the contents of a quad accumulator register to get a single accumulated value - qof(output,oi)=quad_acciq[4]+quad_acciq[5]+quad_acciq[6]+quad_acciq[7]; - oi++; - } - return oi; + //for(int n=0;n<8;n++) fprintf(stderr, "\n>> [%d] %g \n", n, quad_acciq[n]); + iof(output,oi)=quad_acciq[0]+quad_acciq[1]+quad_acciq[2]+quad_acciq[3]; //we're still not ready, as we have to add up the contents of a quad accumulator register to get a single accumulated value + qof(output,oi)=quad_acciq[4]+quad_acciq[5]+quad_acciq[6]+quad_acciq[7]; + oi++; + } + return oi; } #else int fir_decimate_cc(complexf *input, complexf *output, int input_size, int decimation, float *taps, int taps_length) { - //Theory: http://www.dspguru.com/dsp/faqs/multirate/decimation - //It uses real taps. It returns the number of output samples actually written. - //It needs overlapping input based on its returned value: - //number of processed input samples = returned value * decimation factor - //The output buffer should be at least input_length / 3. - // i: input index | ti: tap index | oi: output index - int oi=0; - for(int i=0; iinput_size) break; - float acci=0; - for(int ti=0; tiinput_size) break; + float acci=0; + for(int ti=0; tiinput_size) break; - float acci=0; - int taps_halflength = taps_length/2; - for(int ti=0; tiinput_size) break; + float acci=0; + int taps_halflength = taps_length/2; + for(int ti=0; ti input_size*interpolation) break; - for(int ip=0; ip input_size*interpolation) break; + for(int ip=0; ipinput_size) break; //we can't compute the FIR filter to some input samples at the end - //fprintf(stderr,"outer loop | oi = %d | startingi = %d | taps delay = %d\n",oi,startingi,delayi); - for(int i=0; i<(taps_length-delayi)/interpolation; i++) //@rational_resampler_ff (inner loop) - { - //fprintf(stderr,"inner loop | input index = %d | tap index = %d | acc = %g\n",startingi+ii,i,acc); - acc+=input[startingi+i]*taps[delayi+i*interpolation]; - } - output[oi]=acc*interpolation; - } - rational_resampler_ff_t d; - d.input_processed=startingi; - d.output_size=oi; - d.last_taps_delay=delayi; - return d; + //Theory: http://www.dspguru.com/dsp/faqs/multirate/resampling + //oi: output index, i: tap index + int output_size=input_size*interpolation/decimation; + int oi; + int startingi, delayi; + //fprintf(stderr,"rational_resampler_ff | interpolation = %d | decimation = %d\ntaps_length = %d | input_size = %d | output_size = %d | last_taps_delay = %d\n",interpolation,decimation,taps_length,input_size,output_size,last_taps_delay); + for (oi=0; oiinput_size) break; //we can't compute the FIR filter to some input samples at the end + //fprintf(stderr,"outer loop | oi = %d | startingi = %d | taps delay = %d\n",oi,startingi,delayi); + for(int i=0; i<(taps_length-delayi)/interpolation; i++) //@rational_resampler_ff (inner loop) + { + //fprintf(stderr,"inner loop | input index = %d | tap index = %d | acc = %g\n",startingi+ii,i,acc); + acc+=input[startingi+i]*taps[delayi+i*interpolation]; + } + output[oi]=acc*interpolation; + } + rational_resampler_ff_t d; + d.input_processed=startingi; + d.output_size=oi; + d.last_taps_delay=delayi; + return d; } /* @@ -665,186 +665,186 @@ values of [oi, startingi, taps delay] in the outer loop should be: void rational_resampler_get_lowpass_f(float* output, int output_size, int interpolation, int decimation, window_t window) { - //See 4.1.6 at: http://www.dspguru.com/dsp/faqs/multirate/resampling - float cutoff_for_interpolation=1.0/interpolation; - float cutoff_for_decimation=1.0/decimation; - float cutoff = (cutoff_for_interpolationrate); - if(DEBUG_ASSERT) assert(d->rate > 1.0); - if(DEBUG_ASSERT) assert(d->where >= -d->xifirst); - int oi=0; //output index - int index_high; + //This routine can handle floating point decimation rates. + //It applies polynomial interpolation to samples that are taken into consideration from a pre-filtered input. + //The pre-filter can be switched off by applying taps=NULL. + //fprintf(stderr, "drate=%f\n", d->rate); + if(DEBUG_ASSERT) assert(d->rate > 1.0); + if(DEBUG_ASSERT) assert(d->where >= -d->xifirst); + int oi=0; //output index + int index_high; #define FD_INDEX_LOW (index_high-1) - //we optimize to calculate ceilf(where) only once every iteration, so we do it here: - for(;(index_high=ceilf(d->where))+d->num_poly_points+d->taps_lengthwhere+=d->rate) //@fractional_decimator_ff - { - //d->num_poly_points above is theoretically more than we could have here, but this makes the spectrum look good - int sxifirst = FD_INDEX_LOW + d->xifirst; - int sxilast = FD_INDEX_LOW + d->xilast; - if(d->taps) - for(int wi=0;winum_poly_points;wi++) d->filtered_buf[wi] = fir_one_pass_ff(input+FD_INDEX_LOW+wi, d->taps, d->taps_length); - else - for(int wi=0;winum_poly_points;wi++) d->filtered_buf[wi] = *(input+FD_INDEX_LOW+wi); - int id=0; - float xwhere = d->where - FD_INDEX_LOW; - for(int xi=d->xifirst;xi<=d->xilast;xi++) - { - d->coeffs_buf[id]=1; - for(int xj=d->xifirst;xj<=d->xilast;xj++) - { - if(xi!=xj) d->coeffs_buf[id] *= (xwhere-xj); - } - id++; - } - float acc = 0; - for(int i=0;inum_poly_points;i++) - { - acc += (d->coeffs_buf[i]/d->poly_precalc_denomiator[i])*d->filtered_buf[i]; //(xnom/xden)*yn - } - output[oi++]=acc; - } - d->input_processed = FD_INDEX_LOW + d->xifirst; - d->where -= d->input_processed; - d->output_size = oi; + //we optimize to calculate ceilf(where) only once every iteration, so we do it here: + for(;(index_high=ceilf(d->where))+d->num_poly_points+d->taps_lengthwhere+=d->rate) //@fractional_decimator_ff + { + //d->num_poly_points above is theoretically more than we could have here, but this makes the spectrum look good + int sxifirst = FD_INDEX_LOW + d->xifirst; + int sxilast = FD_INDEX_LOW + d->xilast; + if(d->taps) + for(int wi=0;winum_poly_points;wi++) d->filtered_buf[wi] = fir_one_pass_ff(input+FD_INDEX_LOW+wi, d->taps, d->taps_length); + else + for(int wi=0;winum_poly_points;wi++) d->filtered_buf[wi] = *(input+FD_INDEX_LOW+wi); + int id=0; + float xwhere = d->where - FD_INDEX_LOW; + for(int xi=d->xifirst;xi<=d->xilast;xi++) + { + d->coeffs_buf[id]=1; + for(int xj=d->xifirst;xj<=d->xilast;xj++) + { + if(xi!=xj) d->coeffs_buf[id] *= (xwhere-xj); + } + id++; + } + float acc = 0; + for(int i=0;inum_poly_points;i++) + { + acc += (d->coeffs_buf[i]/d->poly_precalc_denomiator[i])*d->filtered_buf[i]; //(xnom/xden)*yn + } + output[oi++]=acc; + } + d->input_processed = FD_INDEX_LOW + d->xifirst; + d->where -= d->input_processed; + d->output_size = oi; } /* * Some notes to myself on the circular buffer I wanted to implement here: - int last_input_samplewhere_shouldbe = (index_high-1)+xifirst; - int last_input_offset = last_input_samplewhere_shouldbe - d->last_input_samplewhere; - if(last_input_offset < num_poly_points) - { - //if we can move the last_input circular buffer, we move, and add the new samples at the end - d->last_inputs_startsat += last_input_offset; - d->last_inputs_startsat %= num_poly_points; - int num_copied_samples = 0; - for(int i=0; ilast_inputs_circbuf[i]= - } - d->last_input_samplewhere = d->las - } - However, I think I should just rather do a continuous big buffer. + int last_input_samplewhere_shouldbe = (index_high-1)+xifirst; + int last_input_offset = last_input_samplewhere_shouldbe - d->last_input_samplewhere; + if(last_input_offset < num_poly_points) + { + //if we can move the last_input circular buffer, we move, and add the new samples at the end + d->last_inputs_startsat += last_input_offset; + d->last_inputs_startsat %= num_poly_points; + int num_copied_samples = 0; + for(int i=0; ilast_inputs_circbuf[i]= + } + d->last_input_samplewhere = d->las + } + However, I think I should just rather do a continuous big buffer. */ void apply_fir_fft_cc(FFT_PLAN_T* plan, FFT_PLAN_T* plan_inverse, complexf* taps_fft, complexf* last_overlap, int overlap_size) { - //use the overlap & add method for filtering + //use the overlap & add method for filtering - //calculate FFT on input buffer - fft_execute(plan); + //calculate FFT on input buffer + fft_execute(plan); - //multiply the filter and the input - complexf* in = plan->output; - complexf* out = plan_inverse->input; + //multiply the filter and the input + complexf* in = plan->output; + complexf* out = plan_inverse->input; - for(int i=0;isize;i++) //@apply_fir_fft_cc: multiplication - { - iof(out,i)=iof(in,i)*iof(taps_fft,i)-qof(in,i)*qof(taps_fft,i); - qof(out,i)=iof(in,i)*qof(taps_fft,i)+qof(in,i)*iof(taps_fft,i); - } + for(int i=0;isize;i++) //@apply_fir_fft_cc: multiplication + { + iof(out,i)=iof(in,i)*iof(taps_fft,i)-qof(in,i)*qof(taps_fft,i); + qof(out,i)=iof(in,i)*qof(taps_fft,i)+qof(in,i)*iof(taps_fft,i); + } - //calculate inverse FFT on multiplied buffer - fft_execute(plan_inverse); + //calculate inverse FFT on multiplied buffer + fft_execute(plan_inverse); - //add the overlap of the previous segment - complexf* result = plan_inverse->output; + //add the overlap of the previous segment + complexf* result = plan_inverse->output; - for(int i=0;isize;i++) //@apply_fir_fft_cc: normalize by fft_size - { - iof(result,i)/=plan->size; - qof(result,i)/=plan->size; - } + for(int i=0;isize;i++) //@apply_fir_fft_cc: normalize by fft_size + { + iof(result,i)/=plan->size; + qof(result,i)/=plan->size; + } - for(int i=0;imax_iq) max_iq=abs_q; - float min_iq=abs_i; - if(abs_qmax_iq) max_iq=abs_q; + float min_iq=abs_i; + if(abs_qinput_size;i++) //@fastagc_ff: peak search - { - float val=fabs(input->buffer_input[i]); - if(val>peak_input) peak_input=val; - } + //Get the peak value of new input buffer + float peak_input=0; + for(int i=0;iinput_size;i++) //@fastagc_ff: peak search + { + float val=fabs(input->buffer_input[i]); + if(val>peak_input) peak_input=val; + } - //Determine the maximal peak out of the three blocks - float target_peak=peak_input; - if(target_peakpeak_2) target_peak=input->peak_2; - if(target_peakpeak_1) target_peak=input->peak_1; + //Determine the maximal peak out of the three blocks + float target_peak=peak_input; + if(target_peakpeak_2) target_peak=input->peak_2; + if(target_peakpeak_1) target_peak=input->peak_1; - //we change the gain linearly on the apply_block from the last_gain to target_gain. - float target_gain=input->reference/target_peak; - if(target_gain>FASTAGC_MAX_GAIN) target_gain=FASTAGC_MAX_GAIN; - //fprintf(stderr, "target_gain: %g\n",target_gain); + //we change the gain linearly on the apply_block from the last_gain to target_gain. + float target_gain=input->reference/target_peak; + if(target_gain>FASTAGC_MAX_GAIN) target_gain=FASTAGC_MAX_GAIN; + //fprintf(stderr, "target_gain: %g\n",target_gain); - for(int i=0;iinput_size;i++) //@fastagc_ff: apply gain - { - float rate=(float)i/input->input_size; - float gain=input->last_gain*(1.0-rate)+target_gain*rate; - output[i]=input->buffer_1[i]*gain; - } + for(int i=0;iinput_size;i++) //@fastagc_ff: apply gain + { + float rate=(float)i/input->input_size; + float gain=input->last_gain*(1.0-rate)+target_gain*rate; + output[i]=input->buffer_1[i]*gain; + } - //Shift the three buffers - float* temp_pointer=input->buffer_1; - input->buffer_1=input->buffer_2; - input->peak_1=input->peak_2; - input->buffer_2=input->buffer_input; - input->peak_2=peak_input; - input->buffer_input=temp_pointer; - input->last_gain=target_gain; - //fprintf(stderr,"target_gain=%g\n", target_gain); + //Shift the three buffers + float* temp_pointer=input->buffer_1; + input->buffer_1=input->buffer_2; + input->peak_1=input->peak_2; + input->buffer_2=input->buffer_input; + input->peak_2=peak_input; + input->buffer_input=temp_pointer; + input->last_gain=target_gain; + //fprintf(stderr,"target_gain=%g\n", target_gain); } /* @@ -1003,19 +1003,19 @@ void fastagc_ff(fastagc_ff_t* input, float* output) float fmdemod_atan_cf(complexf* input, float *output, int input_size, float last_phase) { - //GCC most likely won't vectorize nor atan, nor atan2. - //For more comments, look at: https://github.com/simonyiszk/minidemod/blob/master/minidemod-wfm-atan.c - float phase, dphase; - for (int i=0; iPI) dphase-=2*PI; - output[i]=dphase/PI; - last_phase=phase; - } - return last_phase; + //GCC most likely won't vectorize nor atan, nor atan2. + //For more comments, look at: https://github.com/simonyiszk/minidemod/blob/master/minidemod-wfm-atan.c + float phase, dphase; + for (int i=0; iPI) dphase-=2*PI; + output[i]=dphase/PI; + last_phase=phase; + } + return last_phase; } #define fmdemod_quadri_K 0.340447550238101026565118445432744920253753662109375 @@ -1023,56 +1023,56 @@ float fmdemod_atan_cf(complexf* input, float *output, int input_size, float last complexf fmdemod_quadri_novect_cf(complexf* input, float* output, int input_size, complexf last_sample) { - output[0]=fmdemod_quadri_K*(iof(input,0)*(qof(input,0)-last_sample.q)-qof(input,0)*(iof(input,0)-last_sample.i))/(iof(input,0)*iof(input,0)+qof(input,0)*qof(input,0)); - for (int i=1; i tau = 75e-6 - WFM transmission in EU: 50 us -> tau = 50e-6 - More info at: http://www.cliftonlaboratories.com/fm_receivers_and_de-emphasis.htm - Simulate in octave: tau=75e-6; dt=1/48000; alpha = dt/(tau+dt); freqz([alpha],[1 -(1-alpha)]) - */ - float dt = 1.0/sample_rate; - float alpha = dt/(tau+dt); - if(is_nan(last_output)) last_output=0.0; //if last_output is NaN - output[0]=alpha*input[0]+(1-alpha)*last_output; - for (int i=1;i tau = 75e-6 + WFM transmission in EU: 50 us -> tau = 50e-6 + More info at: http://www.cliftonlaboratories.com/fm_receivers_and_de-emphasis.htm + Simulate in octave: tau=75e-6; dt=1/48000; alpha = dt/(tau+dt); freqz([alpha],[1 -(1-alpha)]) + */ + float dt = 1.0/sample_rate; + float alpha = dt/(tau+dt); + if(is_nan(last_output)) last_output=0.0; //if last_output is NaN + output[0]=alpha*input[0]+(1-alpha)*last_output; + for (int i=1;ioutput[i])?-max_amplitude:output[i]; - } + for (int i=0; ioutput[i])?-max_amplitude:output[i]; + } } void gain_ff(float* input, float* output, int input_size, float gain) { - for(int i=0;iPI) phase-=2*PI; - while(phase<=-PI) phase+=2*PI; - iof(output,i)=cos(phase); - qof(output,i)=sin(phase); - } - return phase; + float phase=last_phase; + for(int i=0;iPI) phase-=2*PI; + while(phase<=-PI) phase+=2*PI; + iof(output,i)=cos(phase); + qof(output,i)=sin(phase); + } + return phase; } void fixed_amplitude_cc(complexf* input, complexf* output, int input_size, float new_amplitude) { - for(int i=0;i 0) ? new_amplitude / amplitude_now : 0; - iof(output,i)=iof(input,i)*gain; - qof(output,i)=qof(input,i)*gain; - } + //A faster solution: + float amplitude_now = sqrt(iof(input,i)*iof(input,i)+qof(input,i)*qof(input,i)); + float gain = (amplitude_now > 0) ? new_amplitude / amplitude_now : 0; + iof(output,i)=iof(input,i)*gain; + qof(output,i)=qof(input,i)*gain; + } } /* @@ -1219,97 +1219,97 @@ void fixed_amplitude_cc(complexf* input, complexf* output, int input_size, float int log2n(int x) { - int result=-1; - for(int i=0;i<31;i++) - { - if((x>>i)&1) //@@log2n - { - if (result==-1) result=i; - else return -1; - } - } - return result; + int result=-1; + for(int i=0;i<31;i++) + { + if((x>>i)&1) //@@log2n + { + if (result==-1) result=i; + else return -1; + } + } + return result; } int next_pow2(int x) { - int pow2; - //portability? (31 is the problem) - for(int i=0;i<31;i++) - { - if(x<(pow2=1< - { .code = 0b1010101111, .bitcount=10, .ascii=0x3f }, //? - { .code = 0b1010111101, .bitcount=10, .ascii=0x40 }, //@ - { .code = 0b1111101, .bitcount=7, .ascii=0x41 }, //A - { .code = 0b11101011, .bitcount=8, .ascii=0x42 }, //B - { .code = 0b10101101, .bitcount=8, .ascii=0x43 }, //C - { .code = 0b10110101, .bitcount=8, .ascii=0x44 }, //D - { .code = 0b1110111, .bitcount=7, .ascii=0x45 }, //E - { .code = 0b11011011, .bitcount=8, .ascii=0x46 }, //F - { .code = 0b11111101, .bitcount=8, .ascii=0x47 }, //G - { .code = 0b101010101, .bitcount=9, .ascii=0x48 }, //H - { .code = 0b1111111, .bitcount=7, .ascii=0x49 }, //I - { .code = 0b111111101, .bitcount=9, .ascii=0x4a }, //J - { .code = 0b101111101, .bitcount=9, .ascii=0x4b }, //K - { .code = 0b11010111, .bitcount=8, .ascii=0x4c }, //L - { .code = 0b10111011, .bitcount=8, .ascii=0x4d }, //M - { .code = 0b11011101, .bitcount=8, .ascii=0x4e }, //N - { .code = 0b10101011, .bitcount=8, .ascii=0x4f }, //O - { .code = 0b11010101, .bitcount=8, .ascii=0x50 }, //P - { .code = 0b111011101, .bitcount=9, .ascii=0x51 }, //Q - { .code = 0b10101111, .bitcount=8, .ascii=0x52 }, //R - { .code = 0b1101111, .bitcount=7, .ascii=0x53 }, //S - { .code = 0b1101101, .bitcount=7, .ascii=0x54 }, //T - { .code = 0b101010111, .bitcount=9, .ascii=0x55 }, //U - { .code = 0b110110101, .bitcount=9, .ascii=0x56 }, //V - { .code = 0b101011101, .bitcount=9, .ascii=0x57 }, //W - { .code = 0b101110101, .bitcount=9, .ascii=0x58 }, //X - { .code = 0b101111011, .bitcount=9, .ascii=0x59 }, //Y - { .code = 0b1010101101, .bitcount=10, .ascii=0x5a }, //Z - { .code = 0b111110111, .bitcount=9, .ascii=0x5b }, //[ - { .code = 0b111101111, .bitcount=9, .ascii=0x5c }, //\ - { .code = 0b111111011, .bitcount=9, .ascii=0x5d }, //] - { .code = 0b1010111111, .bitcount=10, .ascii=0x5e }, //^ - { .code = 0b101101101, .bitcount=9, .ascii=0x5f }, //_ - { .code = 0b1011011111, .bitcount=10, .ascii=0x60 }, //` - { .code = 0b1011, .bitcount=4, .ascii=0x61 }, //a - { .code = 0b1011111, .bitcount=7, .ascii=0x62 }, //b - { .code = 0b101111, .bitcount=6, .ascii=0x63 }, //c - { .code = 0b101101, .bitcount=6, .ascii=0x64 }, //d - { .code = 0b11, .bitcount=2, .ascii=0x65 }, //e - { .code = 0b111101, .bitcount=6, .ascii=0x66 }, //f - { .code = 0b1011011, .bitcount=7, .ascii=0x67 }, //g - { .code = 0b101011, .bitcount=6, .ascii=0x68 }, //h - { .code = 0b1101, .bitcount=4, .ascii=0x69 }, //i - { .code = 0b111101011, .bitcount=9, .ascii=0x6a }, //j - { .code = 0b10111111, .bitcount=8, .ascii=0x6b }, //k - { .code = 0b11011, .bitcount=5, .ascii=0x6c }, //l - { .code = 0b111011, .bitcount=6, .ascii=0x6d }, //m - { .code = 0b1111, .bitcount=4, .ascii=0x6e }, //n - { .code = 0b111, .bitcount=3, .ascii=0x6f }, //o - { .code = 0b111111, .bitcount=6, .ascii=0x70 }, //p - { .code = 0b110111111, .bitcount=9, .ascii=0x71 }, //q - { .code = 0b10101, .bitcount=5, .ascii=0x72 }, //r - { .code = 0b10111, .bitcount=5, .ascii=0x73 }, //s - { .code = 0b101, .bitcount=3, .ascii=0x74 }, //t - { .code = 0b110111, .bitcount=6, .ascii=0x75 }, //u - { .code = 0b1111011, .bitcount=7, .ascii=0x76 }, //v - { .code = 0b1101011, .bitcount=7, .ascii=0x77 }, //w - { .code = 0b11011111, .bitcount=8, .ascii=0x78 }, //x - { .code = 0b1011101, .bitcount=7, .ascii=0x79 }, //y - { .code = 0b111010101, .bitcount=9, .ascii=0x7a }, //z - { .code = 0b1010110111, .bitcount=10, .ascii=0x7b }, //{ - { .code = 0b110111011, .bitcount=9, .ascii=0x7c }, //| - { .code = 0b1010110101, .bitcount=10, .ascii=0x7d }, //} - { .code = 0b1011010111, .bitcount=10, .ascii=0x7e }, //~ - { .code = 0b1110110101, .bitcount=10, .ascii=0x7f }, //DEL + { .code = 0b1010101011, .bitcount=10, .ascii=0x00 }, //NUL, null + { .code = 0b1011011011, .bitcount=10, .ascii=0x01 }, //SOH, start of heading + { .code = 0b1011101101, .bitcount=10, .ascii=0x02 }, //STX, start of text + { .code = 0b1101110111, .bitcount=10, .ascii=0x03 }, //ETX, end of text + { .code = 0b1011101011, .bitcount=10, .ascii=0x04 }, //EOT, end of transmission + { .code = 0b1101011111, .bitcount=10, .ascii=0x05 }, //ENQ, enquiry + { .code = 0b1011101111, .bitcount=10, .ascii=0x06 }, //ACK, acknowledge + { .code = 0b1011111101, .bitcount=10, .ascii=0x07 }, //BEL, bell + { .code = 0b1011111111, .bitcount=10, .ascii=0x08 }, //BS, backspace + { .code = 0b11101111, .bitcount=8, .ascii=0x09 }, //TAB, horizontal tab + { .code = 0b11101, .bitcount=5, .ascii=0x0a }, //LF, NL line feed, new line + { .code = 0b1101101111, .bitcount=10, .ascii=0x0b }, //VT, vertical tab + { .code = 0b1011011101, .bitcount=10, .ascii=0x0c }, //FF, NP form feed, new page + { .code = 0b11111, .bitcount=5, .ascii=0x0d }, //CR, carriage return (overwrite) + { .code = 0b1101110101, .bitcount=10, .ascii=0x0e }, //SO, shift out + { .code = 0b1110101011, .bitcount=10, .ascii=0x0f }, //SI, shift in + { .code = 0b1011110111, .bitcount=10, .ascii=0x10 }, //DLE, data link escape + { .code = 0b1011110101, .bitcount=10, .ascii=0x11 }, //DC1, device control 1 + { .code = 0b1110101101, .bitcount=10, .ascii=0x12 }, //DC2, device control 2 + { .code = 0b1110101111, .bitcount=10, .ascii=0x13 }, //DC3, device control 3 + { .code = 0b1101011011, .bitcount=10, .ascii=0x14 }, //DC4, device control 4 + { .code = 0b1101101011, .bitcount=10, .ascii=0x15 }, //NAK, negative acknowledge + { .code = 0b1101101101, .bitcount=10, .ascii=0x16 }, //SYN, synchronous idle + { .code = 0b1101010111, .bitcount=10, .ascii=0x17 }, //ETB, end of trans. block + { .code = 0b1101111011, .bitcount=10, .ascii=0x18 }, //CAN, cancel + { .code = 0b1101111101, .bitcount=10, .ascii=0x19 }, //EM, end of medium + { .code = 0b1110110111, .bitcount=10, .ascii=0x1a }, //SUB, substitute + { .code = 0b1101010101, .bitcount=10, .ascii=0x1b }, //ESC, escape + { .code = 0b1101011101, .bitcount=10, .ascii=0x1c }, //FS, file separator + { .code = 0b1110111011, .bitcount=10, .ascii=0x1d }, //GS, group separator + { .code = 0b1011111011, .bitcount=10, .ascii=0x1e }, //RS, record separator + { .code = 0b1101111111, .bitcount=10, .ascii=0x1f }, //US, unit separator + { .code = 0b1, .bitcount=1, .ascii=0x20 }, //szóköz + { .code = 0b111111111, .bitcount=9, .ascii=0x21 }, //! + { .code = 0b101011111, .bitcount=9, .ascii=0x22 }, //" + { .code = 0b111110101, .bitcount=9, .ascii=0x23 }, //# + { .code = 0b111011011, .bitcount=9, .ascii=0x24 }, //$ + { .code = 0b1011010101, .bitcount=10, .ascii=0x25 }, //% + { .code = 0b1010111011, .bitcount=10, .ascii=0x26 }, //& + { .code = 0b101111111, .bitcount=9, .ascii=0x27 }, //' + { .code = 0b11111011, .bitcount=8, .ascii=0x28 }, //( + { .code = 0b11110111, .bitcount=8, .ascii=0x29 }, //) + { .code = 0b101101111, .bitcount=9, .ascii=0x2a }, //* + { .code = 0b111011111, .bitcount=9, .ascii=0x2b }, //+ + { .code = 0b1110101, .bitcount=7, .ascii=0x2c }, //, + { .code = 0b110101, .bitcount=6, .ascii=0x2d }, //- + { .code = 0b1010111, .bitcount=7, .ascii=0x2e }, //. + { .code = 0b110101111, .bitcount=9, .ascii=0x2f }, /// + { .code = 0b10110111, .bitcount=8, .ascii=0x30 }, //0 + { .code = 0b10111101, .bitcount=8, .ascii=0x31 }, //1 + { .code = 0b11101101, .bitcount=8, .ascii=0x32 }, //2 + { .code = 0b11111111, .bitcount=8, .ascii=0x33 }, //3 + { .code = 0b101110111, .bitcount=9, .ascii=0x34 }, //4 + { .code = 0b101011011, .bitcount=9, .ascii=0x35 }, //5 + { .code = 0b101101011, .bitcount=9, .ascii=0x36 }, //6 + { .code = 0b110101101, .bitcount=9, .ascii=0x37 }, //7 + { .code = 0b110101011, .bitcount=9, .ascii=0x38 }, //8 + { .code = 0b110110111, .bitcount=9, .ascii=0x39 }, //9 + { .code = 0b11110101, .bitcount=8, .ascii=0x3a }, //: + { .code = 0b110111101, .bitcount=9, .ascii=0x3b }, //; + { .code = 0b111101101, .bitcount=9, .ascii=0x3c }, //< + { .code = 0b1010101, .bitcount=7, .ascii=0x3d }, //= + { .code = 0b111010111, .bitcount=9, .ascii=0x3e }, //> + { .code = 0b1010101111, .bitcount=10, .ascii=0x3f }, //? + { .code = 0b1010111101, .bitcount=10, .ascii=0x40 }, //@ + { .code = 0b1111101, .bitcount=7, .ascii=0x41 }, //A + { .code = 0b11101011, .bitcount=8, .ascii=0x42 }, //B + { .code = 0b10101101, .bitcount=8, .ascii=0x43 }, //C + { .code = 0b10110101, .bitcount=8, .ascii=0x44 }, //D + { .code = 0b1110111, .bitcount=7, .ascii=0x45 }, //E + { .code = 0b11011011, .bitcount=8, .ascii=0x46 }, //F + { .code = 0b11111101, .bitcount=8, .ascii=0x47 }, //G + { .code = 0b101010101, .bitcount=9, .ascii=0x48 }, //H + { .code = 0b1111111, .bitcount=7, .ascii=0x49 }, //I + { .code = 0b111111101, .bitcount=9, .ascii=0x4a }, //J + { .code = 0b101111101, .bitcount=9, .ascii=0x4b }, //K + { .code = 0b11010111, .bitcount=8, .ascii=0x4c }, //L + { .code = 0b10111011, .bitcount=8, .ascii=0x4d }, //M + { .code = 0b11011101, .bitcount=8, .ascii=0x4e }, //N + { .code = 0b10101011, .bitcount=8, .ascii=0x4f }, //O + { .code = 0b11010101, .bitcount=8, .ascii=0x50 }, //P + { .code = 0b111011101, .bitcount=9, .ascii=0x51 }, //Q + { .code = 0b10101111, .bitcount=8, .ascii=0x52 }, //R + { .code = 0b1101111, .bitcount=7, .ascii=0x53 }, //S + { .code = 0b1101101, .bitcount=7, .ascii=0x54 }, //T + { .code = 0b101010111, .bitcount=9, .ascii=0x55 }, //U + { .code = 0b110110101, .bitcount=9, .ascii=0x56 }, //V + { .code = 0b101011101, .bitcount=9, .ascii=0x57 }, //W + { .code = 0b101110101, .bitcount=9, .ascii=0x58 }, //X + { .code = 0b101111011, .bitcount=9, .ascii=0x59 }, //Y + { .code = 0b1010101101, .bitcount=10, .ascii=0x5a }, //Z + { .code = 0b111110111, .bitcount=9, .ascii=0x5b }, //[ + { .code = 0b111101111, .bitcount=9, .ascii=0x5c }, //\ + { .code = 0b111111011, .bitcount=9, .ascii=0x5d }, //] + { .code = 0b1010111111, .bitcount=10, .ascii=0x5e }, //^ + { .code = 0b101101101, .bitcount=9, .ascii=0x5f }, //_ + { .code = 0b1011011111, .bitcount=10, .ascii=0x60 }, //` + { .code = 0b1011, .bitcount=4, .ascii=0x61 }, //a + { .code = 0b1011111, .bitcount=7, .ascii=0x62 }, //b + { .code = 0b101111, .bitcount=6, .ascii=0x63 }, //c + { .code = 0b101101, .bitcount=6, .ascii=0x64 }, //d + { .code = 0b11, .bitcount=2, .ascii=0x65 }, //e + { .code = 0b111101, .bitcount=6, .ascii=0x66 }, //f + { .code = 0b1011011, .bitcount=7, .ascii=0x67 }, //g + { .code = 0b101011, .bitcount=6, .ascii=0x68 }, //h + { .code = 0b1101, .bitcount=4, .ascii=0x69 }, //i + { .code = 0b111101011, .bitcount=9, .ascii=0x6a }, //j + { .code = 0b10111111, .bitcount=8, .ascii=0x6b }, //k + { .code = 0b11011, .bitcount=5, .ascii=0x6c }, //l + { .code = 0b111011, .bitcount=6, .ascii=0x6d }, //m + { .code = 0b1111, .bitcount=4, .ascii=0x6e }, //n + { .code = 0b111, .bitcount=3, .ascii=0x6f }, //o + { .code = 0b111111, .bitcount=6, .ascii=0x70 }, //p + { .code = 0b110111111, .bitcount=9, .ascii=0x71 }, //q + { .code = 0b10101, .bitcount=5, .ascii=0x72 }, //r + { .code = 0b10111, .bitcount=5, .ascii=0x73 }, //s + { .code = 0b101, .bitcount=3, .ascii=0x74 }, //t + { .code = 0b110111, .bitcount=6, .ascii=0x75 }, //u + { .code = 0b1111011, .bitcount=7, .ascii=0x76 }, //v + { .code = 0b1101011, .bitcount=7, .ascii=0x77 }, //w + { .code = 0b11011111, .bitcount=8, .ascii=0x78 }, //x + { .code = 0b1011101, .bitcount=7, .ascii=0x79 }, //y + { .code = 0b111010101, .bitcount=9, .ascii=0x7a }, //z + { .code = 0b1010110111, .bitcount=10, .ascii=0x7b }, //{ + { .code = 0b110111011, .bitcount=9, .ascii=0x7c }, //| + { .code = 0b1010110101, .bitcount=10, .ascii=0x7d }, //} + { .code = 0b1011010111, .bitcount=10, .ascii=0x7e }, //~ + { .code = 0b1110110101, .bitcount=10, .ascii=0x7f }, //DEL }; unsigned long long psk31_varicode_masklen_helper[] = { - 0b0000000000000000000000000000000000000000000000000000000000000000, - 0b0000000000000000000000000000000000000000000000000000000000000001, - 0b0000000000000000000000000000000000000000000000000000000000000011, - 0b0000000000000000000000000000000000000000000000000000000000000111, - 0b0000000000000000000000000000000000000000000000000000000000001111, - 0b0000000000000000000000000000000000000000000000000000000000011111, - 0b0000000000000000000000000000000000000000000000000000000000111111, - 0b0000000000000000000000000000000000000000000000000000000001111111, - 0b0000000000000000000000000000000000000000000000000000000011111111, - 0b0000000000000000000000000000000000000000000000000000000111111111, - 0b0000000000000000000000000000000000000000000000000000001111111111, - 0b0000000000000000000000000000000000000000000000000000011111111111, - 0b0000000000000000000000000000000000000000000000000000111111111111, - 0b0000000000000000000000000000000000000000000000000001111111111111, - 0b0000000000000000000000000000000000000000000000000011111111111111, - 0b0000000000000000000000000000000000000000000000000111111111111111, - 0b0000000000000000000000000000000000000000000000001111111111111111, - 0b0000000000000000000000000000000000000000000000011111111111111111, - 0b0000000000000000000000000000000000000000000000111111111111111111, - 0b0000000000000000000000000000000000000000000001111111111111111111, - 0b0000000000000000000000000000000000000000000011111111111111111111, - 0b0000000000000000000000000000000000000000000111111111111111111111, - 0b0000000000000000000000000000000000000000001111111111111111111111, - 0b0000000000000000000000000000000000000000011111111111111111111111, - 0b0000000000000000000000000000000000000000111111111111111111111111, - 0b0000000000000000000000000000000000000001111111111111111111111111, - 0b0000000000000000000000000000000000000011111111111111111111111111, - 0b0000000000000000000000000000000000000111111111111111111111111111, - 0b0000000000000000000000000000000000001111111111111111111111111111, - 0b0000000000000000000000000000000000011111111111111111111111111111, - 0b0000000000000000000000000000000000111111111111111111111111111111, - 0b0000000000000000000000000000000001111111111111111111111111111111, - 0b0000000000000000000000000000000011111111111111111111111111111111, - 0b0000000000000000000000000000000111111111111111111111111111111111, - 0b0000000000000000000000000000001111111111111111111111111111111111, - 0b0000000000000000000000000000011111111111111111111111111111111111, - 0b0000000000000000000000000000111111111111111111111111111111111111, - 0b0000000000000000000000000001111111111111111111111111111111111111, - 0b0000000000000000000000000011111111111111111111111111111111111111, - 0b0000000000000000000000000111111111111111111111111111111111111111, - 0b0000000000000000000000001111111111111111111111111111111111111111, - 0b0000000000000000000000011111111111111111111111111111111111111111, - 0b0000000000000000000000111111111111111111111111111111111111111111, - 0b0000000000000000000001111111111111111111111111111111111111111111, - 0b0000000000000000000011111111111111111111111111111111111111111111, - 0b0000000000000000000111111111111111111111111111111111111111111111, - 0b0000000000000000001111111111111111111111111111111111111111111111, - 0b0000000000000000011111111111111111111111111111111111111111111111, - 0b0000000000000000111111111111111111111111111111111111111111111111, - 0b0000000000000001111111111111111111111111111111111111111111111111, - 0b0000000000000011111111111111111111111111111111111111111111111111, - 0b0000000000000111111111111111111111111111111111111111111111111111, - 0b0000000000001111111111111111111111111111111111111111111111111111, - 0b0000000000011111111111111111111111111111111111111111111111111111, - 0b0000000000111111111111111111111111111111111111111111111111111111, - 0b0000000001111111111111111111111111111111111111111111111111111111, - 0b0000000011111111111111111111111111111111111111111111111111111111, - 0b0000000111111111111111111111111111111111111111111111111111111111, - 0b0000001111111111111111111111111111111111111111111111111111111111, - 0b0000011111111111111111111111111111111111111111111111111111111111, - 0b0000111111111111111111111111111111111111111111111111111111111111, - 0b0001111111111111111111111111111111111111111111111111111111111111, - 0b0011111111111111111111111111111111111111111111111111111111111111, - 0b0111111111111111111111111111111111111111111111111111111111111111 + 0b0000000000000000000000000000000000000000000000000000000000000000, + 0b0000000000000000000000000000000000000000000000000000000000000001, + 0b0000000000000000000000000000000000000000000000000000000000000011, + 0b0000000000000000000000000000000000000000000000000000000000000111, + 0b0000000000000000000000000000000000000000000000000000000000001111, + 0b0000000000000000000000000000000000000000000000000000000000011111, + 0b0000000000000000000000000000000000000000000000000000000000111111, + 0b0000000000000000000000000000000000000000000000000000000001111111, + 0b0000000000000000000000000000000000000000000000000000000011111111, + 0b0000000000000000000000000000000000000000000000000000000111111111, + 0b0000000000000000000000000000000000000000000000000000001111111111, + 0b0000000000000000000000000000000000000000000000000000011111111111, + 0b0000000000000000000000000000000000000000000000000000111111111111, + 0b0000000000000000000000000000000000000000000000000001111111111111, + 0b0000000000000000000000000000000000000000000000000011111111111111, + 0b0000000000000000000000000000000000000000000000000111111111111111, + 0b0000000000000000000000000000000000000000000000001111111111111111, + 0b0000000000000000000000000000000000000000000000011111111111111111, + 0b0000000000000000000000000000000000000000000000111111111111111111, + 0b0000000000000000000000000000000000000000000001111111111111111111, + 0b0000000000000000000000000000000000000000000011111111111111111111, + 0b0000000000000000000000000000000000000000000111111111111111111111, + 0b0000000000000000000000000000000000000000001111111111111111111111, + 0b0000000000000000000000000000000000000000011111111111111111111111, + 0b0000000000000000000000000000000000000000111111111111111111111111, + 0b0000000000000000000000000000000000000001111111111111111111111111, + 0b0000000000000000000000000000000000000011111111111111111111111111, + 0b0000000000000000000000000000000000000111111111111111111111111111, + 0b0000000000000000000000000000000000001111111111111111111111111111, + 0b0000000000000000000000000000000000011111111111111111111111111111, + 0b0000000000000000000000000000000000111111111111111111111111111111, + 0b0000000000000000000000000000000001111111111111111111111111111111, + 0b0000000000000000000000000000000011111111111111111111111111111111, + 0b0000000000000000000000000000000111111111111111111111111111111111, + 0b0000000000000000000000000000001111111111111111111111111111111111, + 0b0000000000000000000000000000011111111111111111111111111111111111, + 0b0000000000000000000000000000111111111111111111111111111111111111, + 0b0000000000000000000000000001111111111111111111111111111111111111, + 0b0000000000000000000000000011111111111111111111111111111111111111, + 0b0000000000000000000000000111111111111111111111111111111111111111, + 0b0000000000000000000000001111111111111111111111111111111111111111, + 0b0000000000000000000000011111111111111111111111111111111111111111, + 0b0000000000000000000000111111111111111111111111111111111111111111, + 0b0000000000000000000001111111111111111111111111111111111111111111, + 0b0000000000000000000011111111111111111111111111111111111111111111, + 0b0000000000000000000111111111111111111111111111111111111111111111, + 0b0000000000000000001111111111111111111111111111111111111111111111, + 0b0000000000000000011111111111111111111111111111111111111111111111, + 0b0000000000000000111111111111111111111111111111111111111111111111, + 0b0000000000000001111111111111111111111111111111111111111111111111, + 0b0000000000000011111111111111111111111111111111111111111111111111, + 0b0000000000000111111111111111111111111111111111111111111111111111, + 0b0000000000001111111111111111111111111111111111111111111111111111, + 0b0000000000011111111111111111111111111111111111111111111111111111, + 0b0000000000111111111111111111111111111111111111111111111111111111, + 0b0000000001111111111111111111111111111111111111111111111111111111, + 0b0000000011111111111111111111111111111111111111111111111111111111, + 0b0000000111111111111111111111111111111111111111111111111111111111, + 0b0000001111111111111111111111111111111111111111111111111111111111, + 0b0000011111111111111111111111111111111111111111111111111111111111, + 0b0000111111111111111111111111111111111111111111111111111111111111, + 0b0001111111111111111111111111111111111111111111111111111111111111, + 0b0011111111111111111111111111111111111111111111111111111111111111, + 0b0111111111111111111111111111111111111111111111111111111111111111 }; const int n_psk31_varicode_items = sizeof(psk31_varicode_items) / sizeof(psk31_varicode_item_t); char psk31_varicode_decoder_push(unsigned long long* status_shr, unsigned char symbol) { - *status_shr=((*status_shr)<<1)|(!!symbol); //shift new bit in shift register - //fprintf(stderr,"*status_shr = %llx\n", *status_shr); - if((*status_shr)&0xFFF==0) return 0; - for(int i=0;i>>>>>>>> %d %x %c\n", i, psk31_varicode_items[i].ascii, psk31_varicode_items[i].ascii);*/ return psk31_varicode_items[i].ascii; } + *status_shr=((*status_shr)<<1)|(!!symbol); //shift new bit in shift register + //fprintf(stderr,"*status_shr = %llx\n", *status_shr); + if((*status_shr)&0xFFF==0) return 0; + for(int i=0;i>>>>>>>> %d %x %c\n", i, psk31_varicode_items[i].ascii, psk31_varicode_items[i].ascii);*/ return psk31_varicode_items[i].ascii; } - } - return 0; + } + return 0; } void psk31_varicode_encoder_u8_u8(unsigned char* input, unsigned char* output, int input_size, int output_max_size, int* input_processed, int* output_size) { - (*output_size)=0; - for((*input_processed)=0; (*input_processed)>(current_varicode.bitcount-bi-1))&1 : 0; - (*output_size)++; - output_max_size--; - } - break; - } - } - } + (*output_size)=0; + for((*input_processed)=0; (*input_processed)>(current_varicode.bitcount-bi-1))&1 : 0; + (*output_size)++; + output_max_size--; + } + break; + } + } + } } rtty_baudot_item_t rtty_baudot_items[] = { - { .code = 0b00000, .ascii_letter=0, .ascii_figure=0 }, - { .code = 0b10000, .ascii_letter='E', .ascii_figure='3' }, - { .code = 0b01000, .ascii_letter='\n', .ascii_figure='\n' }, - { .code = 0b11000, .ascii_letter='A', .ascii_figure='-' }, - { .code = 0b00100, .ascii_letter=' ', .ascii_figure=' ' }, - { .code = 0b10100, .ascii_letter='S', .ascii_figure='\'' }, - { .code = 0b01100, .ascii_letter='I', .ascii_figure='8' }, - { .code = 0b11100, .ascii_letter='U', .ascii_figure='7' }, - { .code = 0b00010, .ascii_letter='\r', .ascii_figure='\r' }, - { .code = 0b10010, .ascii_letter='D', .ascii_figure='#' }, - { .code = 0b01010, .ascii_letter='R', .ascii_figure='4' }, - { .code = 0b11010, .ascii_letter='J', .ascii_figure='\a' }, - { .code = 0b00110, .ascii_letter='N', .ascii_figure=',' }, - { .code = 0b10110, .ascii_letter='F', .ascii_figure='@' }, - { .code = 0b01110, .ascii_letter='C', .ascii_figure=':' }, - { .code = 0b11110, .ascii_letter='K', .ascii_figure='(' }, - { .code = 0b00001, .ascii_letter='T', .ascii_figure='5' }, - { .code = 0b10001, .ascii_letter='Z', .ascii_figure='+' }, - { .code = 0b01001, .ascii_letter='L', .ascii_figure=')' }, - { .code = 0b11001, .ascii_letter='W', .ascii_figure='2' }, - { .code = 0b00101, .ascii_letter='H', .ascii_figure='$' }, - { .code = 0b10101, .ascii_letter='Y', .ascii_figure='6' }, - { .code = 0b01101, .ascii_letter='P', .ascii_figure='0' }, - { .code = 0b11101, .ascii_letter='Q', .ascii_figure='1' }, - { .code = 0b00011, .ascii_letter='O', .ascii_figure='9' }, - { .code = 0b10011, .ascii_letter='B', .ascii_figure='?' }, - { .code = 0b01011, .ascii_letter='G', .ascii_figure='*' }, - { .code = 0b00111, .ascii_letter='M', .ascii_figure='.' }, - { .code = 0b10111, .ascii_letter='X', .ascii_figure='/' }, - { .code = 0b01111, .ascii_letter='V', .ascii_figure='=' } + { .code = 0b00000, .ascii_letter=0, .ascii_figure=0 }, + { .code = 0b10000, .ascii_letter='E', .ascii_figure='3' }, + { .code = 0b01000, .ascii_letter='\n', .ascii_figure='\n' }, + { .code = 0b11000, .ascii_letter='A', .ascii_figure='-' }, + { .code = 0b00100, .ascii_letter=' ', .ascii_figure=' ' }, + { .code = 0b10100, .ascii_letter='S', .ascii_figure='\'' }, + { .code = 0b01100, .ascii_letter='I', .ascii_figure='8' }, + { .code = 0b11100, .ascii_letter='U', .ascii_figure='7' }, + { .code = 0b00010, .ascii_letter='\r', .ascii_figure='\r' }, + { .code = 0b10010, .ascii_letter='D', .ascii_figure='#' }, + { .code = 0b01010, .ascii_letter='R', .ascii_figure='4' }, + { .code = 0b11010, .ascii_letter='J', .ascii_figure='\a' }, + { .code = 0b00110, .ascii_letter='N', .ascii_figure=',' }, + { .code = 0b10110, .ascii_letter='F', .ascii_figure='@' }, + { .code = 0b01110, .ascii_letter='C', .ascii_figure=':' }, + { .code = 0b11110, .ascii_letter='K', .ascii_figure='(' }, + { .code = 0b00001, .ascii_letter='T', .ascii_figure='5' }, + { .code = 0b10001, .ascii_letter='Z', .ascii_figure='+' }, + { .code = 0b01001, .ascii_letter='L', .ascii_figure=')' }, + { .code = 0b11001, .ascii_letter='W', .ascii_figure='2' }, + { .code = 0b00101, .ascii_letter='H', .ascii_figure='$' }, + { .code = 0b10101, .ascii_letter='Y', .ascii_figure='6' }, + { .code = 0b01101, .ascii_letter='P', .ascii_figure='0' }, + { .code = 0b11101, .ascii_letter='Q', .ascii_figure='1' }, + { .code = 0b00011, .ascii_letter='O', .ascii_figure='9' }, + { .code = 0b10011, .ascii_letter='B', .ascii_figure='?' }, + { .code = 0b01011, .ascii_letter='G', .ascii_figure='*' }, + { .code = 0b00111, .ascii_letter='M', .ascii_figure='.' }, + { .code = 0b10111, .ascii_letter='X', .ascii_figure='/' }, + { .code = 0b01111, .ascii_letter='V', .ascii_figure='=' } }; const int n_rtty_baudot_items = sizeof(rtty_baudot_items) / sizeof(rtty_baudot_item_t); char rtty_baudot_decoder_lookup(unsigned char* fig_mode, unsigned char c) { - if(c==RTTY_FIGURE_MODE_SELECT_CODE) { *fig_mode=1; return 0; } - if(c==RTTY_LETTER_MODE_SELECT_CODE) { *fig_mode=0; return 0; } - for(int i=0;istate) - { - case RTTY_BAUDOT_WAITING_STOP_PULSE: - if(symbol==1) { s->state = RTTY_BAUDOT_WAITING_START_PULSE; if(s->character_received) return rtty_baudot_decoder_lookup(&s->fig_mode, s->shr&31); } - //If the character data is followed by a stop pulse, then we go on to wait for the next character. - else s->character_received = 0; - //The character should be followed by a stop pulse. If the stop pulse is missing, that is certainly an error. - //In that case, we remove forget the character we just received. - break; - case RTTY_BAUDOT_WAITING_START_PULSE: - s->character_received = 0; - if(symbol==0) { s->state = RTTY_BAUDOT_RECEIVING_DATA; s->shr = s->bit_cntr = 0; } - //Any number of high bits can come after each other, until interrupted with a low bit (start pulse) to indicate - //the beginning of a new character. If we get this start pulse, we go on to wait for the characters. We also - //clear the variables used for counting (bit_cntr) and storing (shr) the data bits. - break; - case RTTY_BAUDOT_RECEIVING_DATA: - s->shr = (s->shr<<1)|(!!symbol); - //We store 5 bits into our shift register - if(s->bit_cntr++==4) { s->state = RTTY_BAUDOT_WAITING_STOP_PULSE; s->character_received = 1; } - //If this is the 5th bit stored, then we wait for the stop pulse. - break; - default: break; - } - return 0; + //For RTTY waveforms, check this: http://www.ham.hu/radiosatvitel/szoveg/RTTY/kepek/rtty.gif + //RTTY is much like an UART data transfer with 1 start bit, 5 data bits and 1 stop bit. + //The start pulse and stop pulse are used for synchronization. + symbol=!!symbol; //We want symbol to be 0 or 1. + switch(s->state) + { + case RTTY_BAUDOT_WAITING_STOP_PULSE: + if(symbol==1) { s->state = RTTY_BAUDOT_WAITING_START_PULSE; if(s->character_received) return rtty_baudot_decoder_lookup(&s->fig_mode, s->shr&31); } + //If the character data is followed by a stop pulse, then we go on to wait for the next character. + else s->character_received = 0; + //The character should be followed by a stop pulse. If the stop pulse is missing, that is certainly an error. + //In that case, we remove forget the character we just received. + break; + case RTTY_BAUDOT_WAITING_START_PULSE: + s->character_received = 0; + if(symbol==0) { s->state = RTTY_BAUDOT_RECEIVING_DATA; s->shr = s->bit_cntr = 0; } + //Any number of high bits can come after each other, until interrupted with a low bit (start pulse) to indicate + //the beginning of a new character. If we get this start pulse, we go on to wait for the characters. We also + //clear the variables used for counting (bit_cntr) and storing (shr) the data bits. + break; + case RTTY_BAUDOT_RECEIVING_DATA: + s->shr = (s->shr<<1)|(!!symbol); + //We store 5 bits into our shift register + if(s->bit_cntr++==4) { s->state = RTTY_BAUDOT_WAITING_STOP_PULSE; s->character_received = 1; } + //If this is the 5th bit stored, then we wait for the stop pulse. + break; + default: break; + } + return 0; } #define DEBUG_SERIAL_LINE_DECODER 0 //What has not been checked: // behaviour on 1.5 stop bits -// check all exit conditions +// check all exit conditions void serial_line_decoder_f_u8(serial_line_t* s, float* input, unsigned char* output, int input_size) { - static int abs_samples_helper = 0; - abs_samples_helper += s->input_used; - int iabs_samples_helper = abs_samples_helper; - s->output_size = 0; - s->input_used = 0; - short* output_s = (short*)output; - unsigned* output_u = (unsigned*)output; - for(;;) - { - //we find the start bit (first negative edge on the line) - int startbit_start = -1; - int i; - for(i=1;i 0) { startbit_start=i; break; } + static int abs_samples_helper = 0; + abs_samples_helper += s->input_used; + int iabs_samples_helper = abs_samples_helper; + s->output_size = 0; + s->input_used = 0; + short* output_s = (short*)output; + unsigned* output_u = (unsigned*)output; + for(;;) + { + //we find the start bit (first negative edge on the line) + int startbit_start = -1; + int i; + for(i=1;i 0) { startbit_start=i; break; } - if(startbit_start == -1) { s->input_used += i; DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:startbit_not_found (+%d)\n", s->input_used); return; } - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:startbit_found at %d (%d)\n", startbit_start, iabs_samples_helper + startbit_start); + if(startbit_start == -1) { s->input_used += i; DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:startbit_not_found (+%d)\n", s->input_used); return; } + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:startbit_found at %d (%d)\n", startbit_start, iabs_samples_helper + startbit_start); - //If the stop bit would be too far so that we reached the end of the buffer, then we return failed. - //The caller can rearrange the buffer so that the whole character fits into it. - float all_bits = 1 + s->databits + s->stopbits; - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:all_bits = %f\n", all_bits); - if(startbit_start + s->samples_per_bits * all_bits >= input_size) { s->input_used += MAX_M(0,startbit_start-2); DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_stopbit_too_far (+%d)\n", s->input_used); return; } + //If the stop bit would be too far so that we reached the end of the buffer, then we return failed. + //The caller can rearrange the buffer so that the whole character fits into it. + float all_bits = 1 + s->databits + s->stopbits; + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:all_bits = %f\n", all_bits); + if(startbit_start + s->samples_per_bits * all_bits >= input_size) { s->input_used += MAX_M(0,startbit_start-2); DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_stopbit_too_far (+%d)\n", s->input_used); return; } - //We do the actual sampling. - int di; //databit counter - unsigned shr = 0; - for(di=0; di < s->databits; di++) - { - int databit_start = startbit_start + (1+di+(0.5*(1-s->bit_sampling_width_ratio))) * s->samples_per_bits; - int databit_end = startbit_start + (1+di+(0.5*(1+s->bit_sampling_width_ratio))) * s->samples_per_bits; - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:databit_start = %d (%d)\n", databit_start, iabs_samples_helper+databit_start); - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:databit_end = %d (%d)\n", databit_end, iabs_samples_helper+databit_end); - float databit_acc = 0; - for(i=databit_start;i0)); - shr=(shr<<1)|!!(databit_acc>0); - } - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:shr = 0x%x, %d\n", shr, shr); + //We do the actual sampling. + int di; //databit counter + unsigned shr = 0; + for(di=0; di < s->databits; di++) + { + int databit_start = startbit_start + (1+di+(0.5*(1-s->bit_sampling_width_ratio))) * s->samples_per_bits; + int databit_end = startbit_start + (1+di+(0.5*(1+s->bit_sampling_width_ratio))) * s->samples_per_bits; + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:databit_start = %d (%d)\n", databit_start, iabs_samples_helper+databit_start); + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:databit_end = %d (%d)\n", databit_end, iabs_samples_helper+databit_end); + float databit_acc = 0; + for(i=databit_start;i0)); + shr=(shr<<1)|!!(databit_acc>0); + } + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:shr = 0x%x, %d\n", shr, shr); - //We check if the stopbit is correct. - int stopbit_start = startbit_start + (1+s->databits) * s->samples_per_bits + (s->stopbits * 0.5 * (1-s->bit_sampling_width_ratio)) * s->samples_per_bits; - int stopbit_end = startbit_start + (1+s->databits) * s->samples_per_bits + (s->stopbits * 0.5 * (1+s->bit_sampling_width_ratio)) * s->samples_per_bits; - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_start = %d (%d)\n", stopbit_start, iabs_samples_helper+stopbit_start); - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_end = %d (%d)\n", stopbit_end, iabs_samples_helper+stopbit_end); - float stopbit_acc = 0; - for(i=stopbit_start;iinput_used += MIN_M(startbit_start + 1, input_size); DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_stopbit_faulty (+%d)\n", s->input_used); return; } - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_found\n"); + //We check if the stopbit is correct. + int stopbit_start = startbit_start + (1+s->databits) * s->samples_per_bits + (s->stopbits * 0.5 * (1-s->bit_sampling_width_ratio)) * s->samples_per_bits; + int stopbit_end = startbit_start + (1+s->databits) * s->samples_per_bits + (s->stopbits * 0.5 * (1+s->bit_sampling_width_ratio)) * s->samples_per_bits; + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_start = %d (%d)\n", stopbit_start, iabs_samples_helper+stopbit_start); + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_end = %d (%d)\n", stopbit_end, iabs_samples_helper+stopbit_end); + float stopbit_acc = 0; + for(i=stopbit_start;iinput_used += MIN_M(startbit_start + 1, input_size); DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_stopbit_faulty (+%d)\n", s->input_used); return; } + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_found\n"); - //we write the output sample - if(s->databits <= 8) output[s->output_size] = shr; - else if(s->databits <= 16) output_s[s->output_size] = shr; - else output_u[s->output_size] = shr; - s->output_size++; + //we write the output sample + if(s->databits <= 8) output[s->output_size] = shr; + else if(s->databits <= 16) output_s[s->output_size] = shr; + else output_u[s->output_size] = shr; + s->output_size++; - int samples_used_up_now = MIN_M(startbit_start + all_bits * s->samples_per_bits, input_size); - s->input_used += samples_used_up_now; - input += samples_used_up_now; - input_size -= samples_used_up_now; - iabs_samples_helper += samples_used_up_now; - if(!input_size) { DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_no_more_input (+%d)\n", s->input_used); return; } - } - DEBUG_SERIAL_LINE_DECODER && fprintf(stderr, "sld: >> output_size = %d (+%d)\n", s->output_size, s->input_used); + int samples_used_up_now = MIN_M(startbit_start + all_bits * s->samples_per_bits, input_size); + s->input_used += samples_used_up_now; + input += samples_used_up_now; + input_size -= samples_used_up_now; + iabs_samples_helper += samples_used_up_now; + if(!input_size) { DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_no_more_input (+%d)\n", s->input_used); return; } + } + DEBUG_SERIAL_LINE_DECODER && fprintf(stderr, "sld: >> output_size = %d (+%d)\n", s->output_size, s->input_used); } void binary_slicer_f_u8(float* input, unsigned char* output, int input_size) { - for(int i=0;i 0; + for(int i=0;i 0; } void psk_modulator_u8_c(unsigned char* input, complexf* output, int input_size, int n_psk) { - //outputs one complex sample per input symbol - float phase_increment = (2*M_PI)/n_psk; - for(int i=0;i>bi)&1; + for(int i=0; i>bi)&1; } unsigned char differential_codec(unsigned char* input, unsigned char* output, int input_size, int encode, unsigned char state) { - if(!encode) - for(int i=0;ialpha = (damping_factor*2*bandwidth_omega)/(ko*kd); - float sampling_rate = 1; //the bandwidth is normalized to the sampling rate - p->beta = (bandwidth_omega*bandwidth_omega)/(sampling_rate*ko*kd); - p->iir_temp = p->dphase = p->output_phase = 0; + //kd: detector gain + //ko: VCO gain + float bandwidth_omega = 2*M_PI*bandwidth; + p->alpha = (damping_factor*2*bandwidth_omega)/(ko*kd); + float sampling_rate = 1; //the bandwidth is normalized to the sampling rate + p->beta = (bandwidth_omega*bandwidth_omega)/(sampling_rate*ko*kd); + p->iir_temp = p->dphase = p->output_phase = 0; } void pll_cc_init_p_controller(pll_t* p, float alpha) { - p->alpha = alpha; - p->dphase=p->output_phase=0; + p->alpha = alpha; + p->dphase=p->output_phase=0; } void pll_cc(pll_t* p, complexf* input, float* output_dphase, complexf* output_nco, int input_size) { - for(int i=0;ioutput_phase += p->dphase; - while(p->output_phase>PI) p->output_phase-=2*PI; - while(p->output_phase<-PI) p->output_phase+=2*PI; - complexf current_nco; - iof(¤t_nco,0) = sin(p->output_phase); - qof(¤t_nco,0) = cos(p->output_phase); - if(output_nco) output_nco[i] = current_nco; //we don't output anything if it is a NULL pointer + for(int i=0;ioutput_phase += p->dphase; + while(p->output_phase>PI) p->output_phase-=2*PI; + while(p->output_phase<-PI) p->output_phase+=2*PI; + complexf current_nco; + iof(¤t_nco,0) = sin(p->output_phase); + qof(¤t_nco,0) = cos(p->output_phase); + if(output_nco) output_nco[i] = current_nco; //we don't output anything if it is a NULL pointer - //accurate phase detector: calculating error from phase offset - float input_phase = atan2(iof(input,i),qof(input,i)); - float new_dphase = input_phase - p->output_phase; - while(new_dphase>PI) new_dphase-=2*PI; - while(new_dphase<-PI) new_dphase+=2*PI; + //accurate phase detector: calculating error from phase offset + float input_phase = atan2(iof(input,i),qof(input,i)); + float new_dphase = input_phase - p->output_phase; + while(new_dphase>PI) new_dphase-=2*PI; + while(new_dphase<-PI) new_dphase+=2*PI; - //modeling analog phase detector, which would be abs(input[i] * current_nco) if we had a real output signal, but what if we have complex signals? - //qof(¤t_nco,0)=-qof(¤t_nco,0); //calculate conjugate - //complexf multiply_result; - //cmult(&multiply_result, &input[i], ¤t_nco); - //output_nco[i] = multiply_result; - //float new_dphase = absof(&multiply_result,0); + //modeling analog phase detector, which would be abs(input[i] * current_nco) if we had a real output signal, but what if we have complex signals? + //qof(¤t_nco,0)=-qof(¤t_nco,0); //calculate conjugate + //complexf multiply_result; + //cmult(&multiply_result, &input[i], ¤t_nco); + //output_nco[i] = multiply_result; + //float new_dphase = absof(&multiply_result,0); - if(p->pll_type == PLL_PI_CONTROLLER) - { - p->dphase = new_dphase * p->alpha + p->iir_temp; - p->iir_temp += new_dphase * p->beta; + if(p->pll_type == PLL_PI_CONTROLLER) + { + p->dphase = new_dphase * p->alpha + p->iir_temp; + p->iir_temp += new_dphase * p->beta; - while(p->dphase>PI) p->dphase-=2*PI; //won't need this one - while(p->dphase<-PI) p->dphase+=2*PI; - } - else if(p->pll_type == PLL_P_CONTROLLER) - { - p->dphase = new_dphase * p->alpha; - } - else return; - if(output_dphase) output_dphase[i] = -p->dphase; - //if(output_dphase) output_dphase[i] = new_dphase/10; - } + while(p->dphase>PI) p->dphase-=2*PI; //won't need this one + while(p->dphase<-PI) p->dphase+=2*PI; + } + else if(p->pll_type == PLL_P_CONTROLLER) + { + p->dphase = new_dphase * p->alpha; + } + else return; + if(output_dphase) output_dphase[i] = -p->dphase; + //if(output_dphase) output_dphase[i] = new_dphase/10; + } } void octave_plot_point_on_cplxsig(complexf* signal, int signal_size, float error, int index, int correction_offset, int writefiles, int points_size, ...) { - static int figure_output_counter = 0; - int* points_z = (int*)malloc(sizeof(int)*points_size); - int* points_color = (int*)malloc(sizeof(int)*points_size); - va_list vl; - va_start(vl,points_size); - for(int i=0;idebug_phase=debug_phase; + state->debug_phase=debug_phase; } #define MTIMINGR_HDEBUG 0 void timing_recovery_cc(complexf* input, complexf* output, int input_size, float* timing_error, int* sampled_indexes, timing_recovery_state_t* state) { - //We always assume that the input starts at center of the first symbol cross before the first symbol. - //Last time we consumed that much from the input samples that it is there. - int correction_offset = state->last_correction_offset; - int current_bitstart_index = 0; - int num_samples_bit = state->decimation_rate; - int num_samples_halfbit = state->decimation_rate / 2; - int num_samples_quarterbit = state->decimation_rate / 4; - int num_samples_earlylate_wing = num_samples_bit * state->earlylate_ratio; - int debug_i = state->debug_count; - float error; - int el_point_left_index, el_point_right_index, el_point_mid_index; - int si = 0; - if(state->debug_force) fprintf(stderr, "disp(\"begin timing_recovery_cc\");\n"); - if(MTIMINGR_HDEBUG) fprintf(stderr, "timing_recovery_cc started, nsb = %d, nshb = %d, nsqb = %d\n", num_samples_bit, num_samples_halfbit, num_samples_quarterbit); - { - for(;;) - { - //the MathWorks style algorithm has correction_offset. - //correction_offset = 0; - if(current_bitstart_index + num_samples_halfbit * 3 >= input_size) break; - if(MTIMINGR_HDEBUG) fprintf(stderr, "current_bitstart_index = %d, input_size = %d, correction_offset(prev) = %d\n", - current_bitstart_index, input_size, correction_offset); - - if(correction_offset<=-num_samples_quarterbit*0.9 || correction_offset>=0.9*num_samples_quarterbit) - { - if(MTIMINGR_HDEBUG) fprintf(stderr, "correction_offset = %d, reset to 0!\n", correction_offset); - correction_offset = 0; - } - //should check if the sign of the correction_offset (or disabling it) has an effect on the EVM. - //it is also a possibility to disable multiplying with the magnitude - if(state->algorithm == TIMING_RECOVERY_ALGORITHM_EARLYLATE) - { - //bitstart index should be at symbol edge, maximum effect point is at current_bitstart_index + num_samples_halfbit - el_point_right_index = current_bitstart_index + num_samples_earlylate_wing * 3; - el_point_left_index = current_bitstart_index + num_samples_earlylate_wing * 1 - correction_offset; - el_point_mid_index = current_bitstart_index + num_samples_halfbit; + //We always assume that the input starts at center of the first symbol cross before the first symbol. + //Last time we consumed that much from the input samples that it is there. + int correction_offset = state->last_correction_offset; + int current_bitstart_index = 0; + int num_samples_bit = state->decimation_rate; + int num_samples_halfbit = state->decimation_rate / 2; + int num_samples_quarterbit = state->decimation_rate / 4; + int num_samples_earlylate_wing = num_samples_bit * state->earlylate_ratio; + int debug_i = state->debug_count; + float error; + int el_point_left_index, el_point_right_index, el_point_mid_index; + int si = 0; + if(state->debug_force) fprintf(stderr, "disp(\"begin timing_recovery_cc\");\n"); + if(MTIMINGR_HDEBUG) fprintf(stderr, "timing_recovery_cc started, nsb = %d, nshb = %d, nsqb = %d\n", num_samples_bit, num_samples_halfbit, num_samples_quarterbit); + { + for(;;) + { + //the MathWorks style algorithm has correction_offset. + //correction_offset = 0; + if(current_bitstart_index + num_samples_halfbit * 3 >= input_size) break; + if(MTIMINGR_HDEBUG) fprintf(stderr, "current_bitstart_index = %d, input_size = %d, correction_offset(prev) = %d\n", + current_bitstart_index, input_size, correction_offset); + + if(correction_offset<=-num_samples_quarterbit*0.9 || correction_offset>=0.9*num_samples_quarterbit) + { + if(MTIMINGR_HDEBUG) fprintf(stderr, "correction_offset = %d, reset to 0!\n", correction_offset); + correction_offset = 0; + } + //should check if the sign of the correction_offset (or disabling it) has an effect on the EVM. + //it is also a possibility to disable multiplying with the magnitude + if(state->algorithm == TIMING_RECOVERY_ALGORITHM_EARLYLATE) + { + //bitstart index should be at symbol edge, maximum effect point is at current_bitstart_index + num_samples_halfbit + el_point_right_index = current_bitstart_index + num_samples_earlylate_wing * 3; + el_point_left_index = current_bitstart_index + num_samples_earlylate_wing * 1 - correction_offset; + el_point_mid_index = current_bitstart_index + num_samples_halfbit; if(sampled_indexes) sampled_indexes[si]=el_point_mid_index; - output[si++] = input[el_point_mid_index]; - } - else if(state->algorithm == TIMING_RECOVERY_ALGORITHM_GARDNER) - { - //maximum effect point is at current_bitstart_index - el_point_right_index = current_bitstart_index + num_samples_halfbit * 3; - el_point_left_index = current_bitstart_index + num_samples_halfbit * 1; - el_point_mid_index = current_bitstart_index + num_samples_halfbit * 2; + output[si++] = input[el_point_mid_index]; + } + else if(state->algorithm == TIMING_RECOVERY_ALGORITHM_GARDNER) + { + //maximum effect point is at current_bitstart_index + el_point_right_index = current_bitstart_index + num_samples_halfbit * 3; + el_point_left_index = current_bitstart_index + num_samples_halfbit * 1; + el_point_mid_index = current_bitstart_index + num_samples_halfbit * 2; if(sampled_indexes) sampled_indexes[si]=el_point_left_index; - output[si++] = input[el_point_left_index]; - } - else break; + output[si++] = input[el_point_left_index]; + } + else break; - error = ( iof(input, el_point_right_index) - iof(input, el_point_left_index) ) * iof(input, el_point_mid_index); - if(state->use_q) - { - error += ( qof(input, el_point_right_index) - qof(input, el_point_left_index)) * qof(input, el_point_mid_index); - error /= 2; - } - //Original correction method: this version can only move a single sample in any direction - //current_bitstart_index += num_samples_halfbit * 2 + (error)?((error<0)?1:-1):0; + error = ( iof(input, el_point_right_index) - iof(input, el_point_left_index) ) * iof(input, el_point_mid_index); + if(state->use_q) + { + error += ( qof(input, el_point_right_index) - qof(input, el_point_left_index)) * qof(input, el_point_mid_index); + error /= 2; + } + //Original correction method: this version can only move a single sample in any direction + //current_bitstart_index += num_samples_halfbit * 2 + (error)?((error<0)?1:-1):0; if(timing_error) timing_error[si-1]=error; //it is not written if NULL - - if(error>2) error=2; - if(error<-2) error=-2; - if( state->debug_force || (state->debug_phase >= si && debug_i) ) - { - debug_i--; - if(!debug_i) state->debug_phase = -1; - octave_plot_point_on_cplxsig(input+current_bitstart_index, state->decimation_rate*2, - error, - current_bitstart_index, - correction_offset, - state->debug_writefiles, - 3, - el_point_left_index - current_bitstart_index, 'r', - el_point_right_index - current_bitstart_index, 'r', - el_point_mid_index - current_bitstart_index, 'r', - 0); - } - int error_sign = (state->algorithm == TIMING_RECOVERY_ALGORITHM_GARDNER) ? -1 : 1; - correction_offset = num_samples_halfbit * error_sign * (error/2); - current_bitstart_index += num_samples_bit + correction_offset; - if(si>=input_size) - { - if(MTIMINGR_HDEBUG) fprintf(stderr, "oops_out_of_si!\n"); - break; - } - } - } - state->input_processed = current_bitstart_index; - state->output_size = si; - state->last_correction_offset = correction_offset; + + if(error>2) error=2; + if(error<-2) error=-2; + if( state->debug_force || (state->debug_phase >= si && debug_i) ) + { + debug_i--; + if(!debug_i) state->debug_phase = -1; + octave_plot_point_on_cplxsig(input+current_bitstart_index, state->decimation_rate*2, + error, + current_bitstart_index, + correction_offset, + state->debug_writefiles, + 3, + el_point_left_index - current_bitstart_index, 'r', + el_point_right_index - current_bitstart_index, 'r', + el_point_mid_index - current_bitstart_index, 'r', + 0); + } + int error_sign = (state->algorithm == TIMING_RECOVERY_ALGORITHM_GARDNER) ? -1 : 1; + correction_offset = num_samples_halfbit * error_sign * (error/2); + current_bitstart_index += num_samples_bit + correction_offset; + if(si>=input_size) + { + if(MTIMINGR_HDEBUG) fprintf(stderr, "oops_out_of_si!\n"); + break; + } + } + } + state->input_processed = current_bitstart_index; + state->output_size = si; + state->last_correction_offset = correction_offset; } #define MTIMINGR_GAS(NAME) \ - if(!strcmp( #NAME , input )) return TIMING_RECOVERY_ALGORITHM_ ## NAME; + if(!strcmp( #NAME , input )) return TIMING_RECOVERY_ALGORITHM_ ## NAME; timing_recovery_algorithm_t timing_recovery_get_algorithm_from_string(char* input) { - MTIMINGR_GAS(GARDNER); - MTIMINGR_GAS(EARLYLATE); - return TIMING_RECOVERY_ALGORITHM_DEFAULT; + MTIMINGR_GAS(GARDNER); + MTIMINGR_GAS(EARLYLATE); + return TIMING_RECOVERY_ALGORITHM_DEFAULT; } #define MTIMINGR_GSA(NAME) \ - if(algorithm == TIMING_RECOVERY_ALGORITHM_ ## NAME) return #NAME; + if(algorithm == TIMING_RECOVERY_ALGORITHM_ ## NAME) return #NAME; char* timing_recovery_get_string_from_algorithm(timing_recovery_algorithm_t algorithm) { - MTIMINGR_GSA(GARDNER); - MTIMINGR_GSA(EARLYLATE); - return "INVALID"; + MTIMINGR_GSA(GARDNER); + MTIMINGR_GSA(EARLYLATE); + return "INVALID"; } bpsk_costas_loop_state_t init_bpsk_costas_loop_cc(float samples_per_bits) { - bpsk_costas_loop_state_t state; - state.vco_phase = 0; - state.last_vco_phase_addition = 0; - float virtual_sampling_rate = 10000; - float virtual_data_rate = virtual_sampling_rate / samples_per_bits; - fprintf(stderr, "virtual_sampling_rate = %g, virtual_data_rate = %g\n", virtual_sampling_rate, virtual_data_rate); - float rc_filter_cutoff = virtual_data_rate * 2; //this is so far the best - float rc_filter_rc = 1/(2*M_PI*rc_filter_cutoff); //as of Equation 24 in Feigin - float virtual_sampling_dt = 1.0/virtual_sampling_rate; - fprintf(stderr, "rc_filter_cutoff = %g, rc_filter_rc = %g, virtual_sampling_dt = %g\n", - rc_filter_cutoff, rc_filter_rc, virtual_sampling_dt); - state.rc_filter_alpha = virtual_sampling_dt/(rc_filter_rc+virtual_sampling_dt); //https://en.wikipedia.org/wiki/Low-pass_filter - float rc_filter_omega_cutoff = 2*M_PI*rc_filter_cutoff; - state.vco_phase_addition_multiplier = 8*rc_filter_omega_cutoff / (virtual_sampling_rate); //as of Equation 25 in Feigin, assuming input signal amplitude of 1 (to 1V) and (state.vco_phase_addition_multiplier*), a value in radians, will be added to the vco_phase directly. - fprintf(stderr, "rc_filter_alpha = %g, rc_filter_omega_cutoff = %g, vco_phase_addition_multiplier = %g\n", - state.rc_filter_alpha, rc_filter_omega_cutoff, state.vco_phase_addition_multiplier); - return state; + bpsk_costas_loop_state_t state; + state.vco_phase = 0; + state.last_vco_phase_addition = 0; + float virtual_sampling_rate = 10000; + float virtual_data_rate = virtual_sampling_rate / samples_per_bits; + fprintf(stderr, "virtual_sampling_rate = %g, virtual_data_rate = %g\n", virtual_sampling_rate, virtual_data_rate); + float rc_filter_cutoff = virtual_data_rate * 2; //this is so far the best + float rc_filter_rc = 1/(2*M_PI*rc_filter_cutoff); //as of Equation 24 in Feigin + float virtual_sampling_dt = 1.0/virtual_sampling_rate; + fprintf(stderr, "rc_filter_cutoff = %g, rc_filter_rc = %g, virtual_sampling_dt = %g\n", + rc_filter_cutoff, rc_filter_rc, virtual_sampling_dt); + state.rc_filter_alpha = virtual_sampling_dt/(rc_filter_rc+virtual_sampling_dt); //https://en.wikipedia.org/wiki/Low-pass_filter + float rc_filter_omega_cutoff = 2*M_PI*rc_filter_cutoff; + state.vco_phase_addition_multiplier = 8*rc_filter_omega_cutoff / (virtual_sampling_rate); //as of Equation 25 in Feigin, assuming input signal amplitude of 1 (to 1V) and (state.vco_phase_addition_multiplier*), a value in radians, will be added to the vco_phase directly. + fprintf(stderr, "rc_filter_alpha = %g, rc_filter_omega_cutoff = %g, vco_phase_addition_multiplier = %g\n", + state.rc_filter_alpha, rc_filter_omega_cutoff, state.vco_phase_addition_multiplier); + return state; } void bpsk_costas_loop_cc(complexf* input, complexf* output, int input_size, bpsk_costas_loop_state_t* state) { - int debug = 0; - if(debug) fprintf(stderr, "costas:\n"); - for(int i=0;ivco_phase; - if(debug) fprintf(stderr, "%g | %g\n", input_and_vco_mixed_phase, input_phase), debug--; - complexf input_and_vco_mixed_sample; - e_powj(&input_and_vco_mixed_sample, input_and_vco_mixed_phase); - - complexf vco_sample; - e_powj(&vco_sample, -state->vco_phase); - //cmult(&input_and_vco_mixed_sample, &input[i], &vco_sample);//if this is enabled, the real input sample is used, not the amplitude normalized + int debug = 0; + if(debug) fprintf(stderr, "costas:\n"); + for(int i=0;ivco_phase; + if(debug) fprintf(stderr, "%g | %g\n", input_and_vco_mixed_phase, input_phase), debug--; + complexf input_and_vco_mixed_sample; + e_powj(&input_and_vco_mixed_sample, input_and_vco_mixed_phase); + + complexf vco_sample; + e_powj(&vco_sample, -state->vco_phase); + //cmult(&input_and_vco_mixed_sample, &input[i], &vco_sample);//if this is enabled, the real input sample is used, not the amplitude normalized - float loop_output_i = - input_and_vco_mixed_sample.i * state->rc_filter_alpha + state->last_lpfi_output * (1-state->rc_filter_alpha); - float loop_output_q = - input_and_vco_mixed_sample.q * state->rc_filter_alpha + state->last_lpfq_output * (1-state->rc_filter_alpha); - //loop_output_i = input_and_vco_mixed_sample.i; - //loop_output_q = input_and_vco_mixed_sample.q; - state->last_lpfi_output = loop_output_i; - state->last_lpfq_output = loop_output_q; - float vco_phase_addition = loop_output_i * loop_output_q * state->vco_phase_addition_multiplier; - //vco_phase_addition = vco_phase_addition * state->rc_filter_alpha + state->last_vco_phase_addition * (1-state->rc_filter_alpha); - //state->last_vco_phase_addition = vco_phase_addition; - state->vco_phase += vco_phase_addition; - while(state->vco_phase>PI) state->vco_phase-=2*PI; - while(state->vco_phase<-PI) state->vco_phase+=2*PI; - cmult(&output[i], &input[i], &vco_sample); - } + float loop_output_i = + input_and_vco_mixed_sample.i * state->rc_filter_alpha + state->last_lpfi_output * (1-state->rc_filter_alpha); + float loop_output_q = + input_and_vco_mixed_sample.q * state->rc_filter_alpha + state->last_lpfq_output * (1-state->rc_filter_alpha); + //loop_output_i = input_and_vco_mixed_sample.i; + //loop_output_q = input_and_vco_mixed_sample.q; + state->last_lpfi_output = loop_output_i; + state->last_lpfq_output = loop_output_q; + float vco_phase_addition = loop_output_i * loop_output_q * state->vco_phase_addition_multiplier; + //vco_phase_addition = vco_phase_addition * state->rc_filter_alpha + state->last_vco_phase_addition * (1-state->rc_filter_alpha); + //state->last_vco_phase_addition = vco_phase_addition; + state->vco_phase += vco_phase_addition; + while(state->vco_phase>PI) state->vco_phase-=2*PI; + while(state->vco_phase<-PI) state->vco_phase+=2*PI; + cmult(&output[i], &input[i], &vco_sample); + } } void simple_agc_cc(complexf* input, complexf* output, int input_size, float rate, float reference, float max_gain, float* current_gain) { - float rate_1minus=1-rate; - int debugn = 0; - for(int i=0;imax_gain) ideal_gain = max_gain; - if(ideal_gain<=0) ideal_gain = 0; - //*current_gain += (ideal_gain-(*current_gain))*rate; - *current_gain = (ideal_gain-(*current_gain))*rate + (*current_gain); //*rate_1minus; - //if(debugn<100) fprintf(stderr, "cgain: %g\n", *current_gain), debugn++; - output[i].i=(*current_gain)*input[i].i; - output[i].q=(*current_gain)*input[i].q; - } + float rate_1minus=1-rate; + int debugn = 0; + for(int i=0;imax_gain) ideal_gain = max_gain; + if(ideal_gain<=0) ideal_gain = 0; + //*current_gain += (ideal_gain-(*current_gain))*rate; + *current_gain = (ideal_gain-(*current_gain))*rate + (*current_gain); //*rate_1minus; + //if(debugn<100) fprintf(stderr, "cgain: %g\n", *current_gain), debugn++; + output[i].i=(*current_gain)*input[i].i; + output[i].q=(*current_gain)*input[i].q; + } } void firdes_add_resonator_c(complexf* output, int length, float rate, window_t window, int add, int normalize) { - //add=0: malloc output previously - //add=1: calloc output previously - complexf* taps = (complexf*)malloc(sizeof(complexf)*length); - int middle=length/2; - float phase = 0, phase_addition = -rate*M_PI*2; - float (*window_function)(float) = firdes_get_window_kernel(window); - for(int i=0; i2*M_PI) phase-=2*M_PI; - while(phase<0) phase+=2*M_PI; - } + //add=0: malloc output previously + //add=1: calloc output previously + complexf* taps = (complexf*)malloc(sizeof(complexf)*length); + int middle=length/2; + float phase = 0, phase_addition = -rate*M_PI*2; + float (*window_function)(float) = firdes_get_window_kernel(window); + for(int i=0; i2*M_PI) phase-=2*M_PI; + while(phase<0) phase+=2*M_PI; + } - //Normalize filter kernel - if(add) - for(int i=0;isamples_per_symbol/2) sinearest++; unsigned socorrect = initial_sample_offset+(sinearest*samples_per_symbol); //the sample offset which input[i] should have been, in order to sample at the maximum effect point int sodiff = abs(socorrect-input[i]); - float ndiff = (float)sodiff/samples_per_symbol; + float ndiff = (float)sodiff/samples_per_symbol; ndiff_rad[i] = ndiff*PI; - ndiff_rad_mean = ndiff_rad_mean*(((float)i)/(i+1))+(ndiff_rad[i]/(i+1)); - if(debug_print) fprintf(stderr, "input[%d] = %u, sinearest = %u, socorrect = %u, sodiff = %u, ndiff = %f, ndiff_rad[i] = %f, ndiff_rad_mean = %f\n", i, input[i], sinearest, socorrect, sodiff, ndiff, ndiff_rad[i], ndiff_rad_mean); + ndiff_rad_mean = ndiff_rad_mean*(((float)i)/(i+1))+(ndiff_rad[i]/(i+1)); + if(debug_print) fprintf(stderr, "input[%d] = %u, sinearest = %u, socorrect = %u, sodiff = %u, ndiff = %f, ndiff_rad[i] = %f, ndiff_rad_mean = %f\n", i, input[i], sinearest, socorrect, sodiff, ndiff, ndiff_rad[i], ndiff_rad_mean); } - fprintf(stderr, "ndiff_rad_mean = %f\n", ndiff_rad_mean); + fprintf(stderr, "ndiff_rad_mean = %f\n", ndiff_rad_mean); float result = 0; - for(int i=0;i convert_u8_f + for(int i=0;i convert_u8_f } void convert_f_s8(float* input, signed char* output, int input_size) { - for(int i=0;i1.0) input[i]=1.0; - if(input[i]<-1.0) input[i]=-1.0; - }*/ - for(int i=0;i1.0) input[i]=1.0; + if(input[i]<-1.0) input[i]=-1.0; + }*/ + for(int i=0;i>8); - unsigned char* ptemp=(unsigned char*)&temp; - output[k++]=*ptemp; - output[k++]=*(ptemp+1); - output[k++]=*(ptemp+2); - } - else for(int i=0;i>8); - unsigned char* ptemp=(unsigned char*)&temp; - output[k++]=*(ptemp+2); - output[k++]=*(ptemp+1); - output[k++]=*ptemp; - } + int k=0; + if(bigendian) for(int i=0;i>8); + unsigned char* ptemp=(unsigned char*)&temp; + output[k++]=*ptemp; + output[k++]=*(ptemp+1); + output[k++]=*(ptemp+2); + } + else for(int i=0;i>8); + unsigned char* ptemp=(unsigned char*)&temp; + output[k++]=*(ptemp+2); + output[k++]=*(ptemp+1); + output[k++]=*ptemp; + } } void convert_s24_f(unsigned char* input, float* output, int input_size, int bigendian) { - int k=0; - if(bigendian) for(int i=0;i