diff --git a/Makefile b/Makefile index 4db95f1d..e86c7480 100644 --- a/Makefile +++ b/Makefile @@ -29,11 +29,17 @@ LIBSOURCES = fft_fftw.c libcsdr_wrapper.c #SOURCES = csdr.c $(LIBSOURCES) cpufeature = $(if $(findstring $(1),$(shell cat /proc/cpuinfo)),$(2)) +kcmdfeature = $(if $(findstring $(1),$(shell cat /proc/cmdline)),$(2)) +dpkghostarch = $(if $(findstring $(1),$(shell dpkg --print-architecture)),$(2)) PARAMS_SSE = $(call cpufeature,sse,-msse) $(call cpufeature,sse2,-msse2) $(call cpufeature,sse3,-msse3) $(call cpufeature,sse4a,-msse4a) $(call cpufeature,sse4_1,-msse4.1) $(call cpufeature,sse4_2,-msse4.2 -msse4) -mfpmath=sse PARAMS_NEON = -mfloat-abi=hard -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mvectorize-with-neon-quad -funsafe-math-optimizations -Wformat=0 -DNEON_OPTS #tnx Jan Szumiec for the Raspberry Pi support -PARAMS_RASPI = -mfloat-abi=hard -mcpu=arm1176jzf-s -mfpu=vfp -funsafe-math-optimizations -Wformat=0 -PARAMS_ARM = $(if $(call cpufeature,BCM2708,dummy-text),$(PARAMS_RASPI),$(PARAMS_NEON)) +PARAMS_RASPI_3 = -mfloat-abi=hard -mcpu=arm1176jzf-s -mfpu=vfp -funsafe-math-optimizations -Wformat=0 +PARAMS_RASPI_4_ARMHF = -mcpu=cortex-a72 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits -mtune=cortex-a72 -funsafe-math-optimizations -Wformat=0 +PARAMS_RASPI_4_ARM64 = -mcpu=cortex-a72 -mtune=cortex-a72 -funsafe-math-optimizations -Wformat=0 +PARAMS_RASPI_4 = $(if $(call dpkghostarch,arm64,dummy-text),$(PARAMS_RASPI_4_ARM64),$(PARAMS_RASPI_4_ARMHF)) +PARAMS_RASPI = $(if $(call kcmdfeature,bcm2709,dummy-text),$(PARAMS_RASPI_4),$(PARAMS_RASPI_3)) +PARAMS_ARM = $(if $(call kcmdfeature,bcm270,dummy-text),$(PARAMS_RASPI),$(PARAMS_NEON)) PARAMS_SIMD = $(if $(call cpufeature,sse,dummy-text),$(PARAMS_SSE),$(PARAMS_ARM)) PARAMS_LOOPVECT = -O3 -ffast-math -fdump-tree-vect-details -dumpbase dumpvect PARAMS_LIBS = -g -lm -lrt -lfftw3f -DUSE_FFTW -DLIBCSDR_GPL -DUSE_IMA_ADPCM diff --git a/README.md b/README.md index cbc77214..b76d4ae6 100755 --- a/README.md +++ b/README.md @@ -1040,6 +1040,31 @@ Syntax: ---- +### [binary_decoder_f_u8](#binary_decoder_f_u8) + +Syntax: + + csdr binary_decoder_f_u8 [min_samples_per_symbol] + +It tries to find symbol boundaries then has an algorithm for deciding whether each symbol is a 1 or a 0 the result of which it then outputs. +For this to function, a data preamble of either 5's or A's is helpful. + +If a symbol boundary occurs before samples_per_symbol samples have been processed since the last symbol boundary, what has been processed so far is output as a valid symbol only if at least min_samples_per_symbol have been processed (otherwise it is discarded). +min_samples_per_symbol defaults to 3/4 of samples_per_symbol. + +---- + +### [binary_to_ascii_u8_u8](#binary_to_ascii_u8_u8) + +Syntax: + + csdr binary_to_ascii_u8_u8 + +* If the input sample is 0, it outputs '0' (0x30). +* If the input sample is not 0, it outputs '1' (0x31). + +---- + ### [serial_line_decoder_f_u8](#serial_line_decoder_f_u8) Syntax: diff --git a/csdr.c b/csdr.c index 27dbf6dc..fe5c026d 100755 --- a/csdr.c +++ b/csdr.c @@ -138,6 +138,8 @@ char usage[]= " duplicate_samples_ntimes_u8_u8 \n" " bpsk_costas_loop_cc [--dd | --decision_directed] [--output_error | --output_dphase | --output_nco | --output_combined ]\n" " binary_slicer_f_u8\n" +" binary_decoder_f_u8 [min_samples_per_symbol]\n" +" binary_to_ascii_u8_u8\n" " simple_agc_cc [reference [max_gain]]\n" " firdes_peak_c [window [--octave]]\n" " peaks_fir_cc [peak_rate × N]\n" @@ -2487,6 +2489,54 @@ int main(int argc, char *argv[]) return 0; } + if(!strcmp(argv[1],"binary_decoder_f_u8")) + { + int samples_per_symbol; + int min_samples_per_symbol; + int output_size; + + if(argc<=2) return badsyntax("need required parameter (samples_per_symbol)"); + sscanf(argv[2],"%d",&samples_per_symbol); + + if(argc>3) + { + sscanf(argv[3],"%d",&min_samples_per_symbol); + } + else + { + min_samples_per_symbol = (samples_per_symbol*3)/4; + } + + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + if(!FREAD_R) break; + output_size = binary_decoder_f_u8( input_buffer, + (unsigned char*)output_buffer, + the_bufsize, + samples_per_symbol, + min_samples_per_symbol); + fwrite(output_buffer, sizeof(unsigned char), output_size, stdout); + TRY_YIELD; + } + return 0; + } + + if(!strcmp(argv[1],"binary_to_ascii_u8_u8")) + { + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + FEOF_CHECK; + if(!FREAD_U8) break; + binary_to_ascii_u8_u8((unsigned char*)input_buffer, (unsigned char*)output_buffer, the_bufsize); + FWRITE_U8; + TRY_YIELD; + } + return 0; + } + if(!strcmp(argv[1],"serial_line_decoder_f_u8")) // [databits [stopbits]] { bigbufs=1; diff --git a/libcsdr.c b/libcsdr.c index 9751bba4..063db994 100755 --- a/libcsdr.c +++ b/libcsdr.c @@ -1277,10 +1277,10 @@ void apply_precalculated_window_c(complexf* input, complexf* output, int size, f void apply_precalculated_window_f(float* input, float* output, int size, float *windowt) { - for(int i=0;i 0; } +int binary_decoder_f_u8(float* input, + unsigned char* output, + int input_size, + int samples_per_symbol, + int min_samples_per_symbol) +{ + static float previous_sample; + static float sample_accumulator; + static int sample_offset; + + int i; + int output_size = 0; + float sample; + + //notice rising edges crossing zero and assume they coincide with a symbol boundary. + //add all samples within a symbol and base the output on whether this accumulation is overall positive or negative. + + for(i=0;i= 0)) + { + //if we've almost got a symbol, accept it and publish early. + if(sample_offset >= min_samples_per_symbol) + { + output[output_size] = (sample_accumulator > 0); + output_size++; + //fprintf(stderr, "symbol (%d:%f:%d)\n", sample_offset, sample_accumulator, output[output_size]); + } + + sample_accumulator = 0; + sample_offset = 0; + } + + sample_accumulator += sample; + sample_offset++; + if(sample_offset == samples_per_symbol) + { + output[output_size] = (sample_accumulator > 0); + output_size++; + //fprintf(stderr, "symbol (%d:%f:%d)\n", sample_offset, sample_accumulator, output[output_size]); + + sample_accumulator = 0; + sample_offset = 0; + } + + previous_sample = input[i]; + } + + return(output_size); +} + +void binary_to_ascii_u8_u8(unsigned char* input, + unsigned char* output, + int input_size) +{ + for(int i=0;i