diff --git a/.gitignore b/.gitignore index 6ad1e60..2e9d50e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Makefile /config.log /config.status /stamp-h1 +autom4te.cache diff --git a/aclocal.m4 b/aclocal.m4 index f7ad44b..35e579d 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -180,6 +180,61 @@ else fi[]dnl ])# PKG_CHECK_MODULES + +# PKG_INSTALLDIR(DIRECTORY) +# ------------------------- +# Substitutes the variable pkgconfigdir as the location where a module +# should install pkg-config .pc files. By default the directory is +# $libdir/pkgconfig, but the default can be changed by passing +# DIRECTORY. The user can override through the --with-pkgconfigdir +# parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +]) dnl PKG_INSTALLDIR + + +# PKG_NOARCH_INSTALLDIR(DIRECTORY) +# ------------------------- +# Substitutes the variable noarch_pkgconfigdir as the location where a +# module should install arch-independent pkg-config .pc files. By +# default the directory is $datadir/pkgconfig, but the default can be +# changed by passing DIRECTORY. The user can override through the +# --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +]) dnl PKG_NOARCH_INSTALLDIR + + +# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ------------------------------------------- +# Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])# PKG_CHECK_VAR + # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software # Foundation, Inc. # diff --git a/src/.gitignore b/src/.gitignore index 11df00b..608b661 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,3 +1,4 @@ /minimodem /minimodem.1 /minimodem.1.html +/minimodem.exe diff --git a/src/Makefile.am b/src/Makefile.am index 5704382..7e79a88 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,15 +42,20 @@ FSK_SRC = fsk.h fsk.c BAUDOT_SRC = baudot.h baudot.c +UIC_SRC = uic_codes.h uic_codes.c + DATABITS_SRC = \ databits.h \ databits_ascii.c \ databits_binary.c \ databits_callerid.c \ - databits_baudot.c $(BAUDOT_SRC) + databits_baudot.c $(BAUDOT_SRC) \ + databits_uic.c $(UIC_SRC) + +MISC_SRC = misc.h misc.c minimodem_LDADD = $(DEPS_LIBS) -minimodem_SOURCES = minimodem.c $(DATABITS_SRC) $(FSK_SRC) $(SIMPLEAUDIO_SRC) +minimodem_SOURCES = minimodem.c $(DATABITS_SRC) $(FSK_SRC) $(SIMPLEAUDIO_SRC) $(MISC_SRC) minimodem.1.html: minimodem.1 Makefile diff --git a/src/Makefile.in b/src/Makefile.in index 1d1cfc7..19d845a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -83,15 +83,17 @@ CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) am__objects_1 = baudot.$(OBJEXT) -am__objects_2 = databits_ascii.$(OBJEXT) databits_binary.$(OBJEXT) \ +am__objects_2 = uic_codes.$(OBJEXT) +am__objects_3 = databits_ascii.$(OBJEXT) databits_binary.$(OBJEXT) \ databits_callerid.$(OBJEXT) databits_baudot.$(OBJEXT) \ - $(am__objects_1) -am__objects_3 = fsk.$(OBJEXT) -am__objects_4 = simpleaudio.$(OBJEXT) simple-tone-generator.$(OBJEXT) \ + $(am__objects_1) databits_uic.$(OBJEXT) $(am__objects_2) +am__objects_4 = fsk.$(OBJEXT) +am__objects_5 = simpleaudio.$(OBJEXT) simple-tone-generator.$(OBJEXT) \ simpleaudio-pulse.$(OBJEXT) simpleaudio-alsa.$(OBJEXT) \ simpleaudio-benchmark.$(OBJEXT) simpleaudio-sndfile.$(OBJEXT) -am_minimodem_OBJECTS = minimodem.$(OBJEXT) $(am__objects_2) \ - $(am__objects_3) $(am__objects_4) +am__objects_6 = misc.$(OBJEXT) +am_minimodem_OBJECTS = minimodem.$(OBJEXT) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) $(am__objects_6) minimodem_OBJECTS = $(am_minimodem_OBJECTS) am__DEPENDENCIES_1 = minimodem_DEPENDENCIES = $(am__DEPENDENCIES_1) @@ -247,15 +249,18 @@ SIMPLEAUDIO_SRC = \ FSK_SRC = fsk.h fsk.c BAUDOT_SRC = baudot.h baudot.c +UIC_SRC = uic_codes.h uic_codes.c DATABITS_SRC = \ databits.h \ databits_ascii.c \ databits_binary.c \ databits_callerid.c \ - databits_baudot.c $(BAUDOT_SRC) + databits_baudot.c $(BAUDOT_SRC) \ + databits_uic.c $(UIC_SRC) +MISC_SRC = misc.h misc.c minimodem_LDADD = $(DEPS_LIBS) -minimodem_SOURCES = minimodem.c $(DATABITS_SRC) $(FSK_SRC) $(SIMPLEAUDIO_SRC) +minimodem_SOURCES = minimodem.c $(DATABITS_SRC) $(FSK_SRC) $(SIMPLEAUDIO_SRC) $(MISC_SRC) all: all-am .SUFFIXES: @@ -347,14 +352,17 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/databits_baudot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/databits_binary.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/databits_callerid.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/databits_uic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minimodem.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple-tone-generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simpleaudio-alsa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simpleaudio-benchmark.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simpleaudio-pulse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simpleaudio-sndfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simpleaudio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uic_codes.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/databits.h b/src/databits.h index 50a5da1..09ac867 100644 --- a/src/databits.h +++ b/src/databits.h @@ -22,7 +22,7 @@ typedef int (databits_encoder)( typedef unsigned int (databits_decoder)( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ); + unsigned long long bits, unsigned int n_databits ); int @@ -30,7 +30,7 @@ databits_encode_ascii8( unsigned int *databits_outp, char char_out ); unsigned int databits_decode_ascii8( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ); + unsigned long long bits, unsigned int n_databits ); #include "baudot.h" @@ -40,7 +40,7 @@ databits_decode_ascii8( char *dataout_p, unsigned int dataout_size, unsigned int databits_decode_baudot( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ); + unsigned long long bits, unsigned int n_databits ); int @@ -48,11 +48,17 @@ databits_encode_binary( unsigned int *databits_outp, char char_out ); unsigned int databits_decode_binary( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ); + unsigned long long bits, unsigned int n_databits ); unsigned int databits_decode_callerid( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ); + unsigned long long bits, unsigned int n_databits ); +unsigned int +databits_decode_uic_ground( char *dataout_p, unsigned int dataout_size, + unsigned long long bits, unsigned int n_databits ); +unsigned int +databits_decode_uic_train( char *dataout_p, unsigned int dataout_size, + unsigned long long bits, unsigned int n_databits ); diff --git a/src/databits_ascii.c b/src/databits_ascii.c index 5269fc9..a40b54d 100644 --- a/src/databits_ascii.c +++ b/src/databits_ascii.c @@ -34,7 +34,7 @@ databits_encode_ascii8( unsigned int *databits_outp, char char_out ) /* returns nbytes decoded */ unsigned int databits_decode_ascii8( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ) + unsigned long long bits, unsigned int n_databits ) { if ( ! dataout_p ) // databits processor reset: noop return 0; diff --git a/src/databits_baudot.c b/src/databits_baudot.c index 3a2e8b1..f39da3d 100644 --- a/src/databits_baudot.c +++ b/src/databits_baudot.c @@ -28,7 +28,7 @@ /* returns nbytes decoded */ unsigned int databits_decode_baudot( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ) + unsigned long long bits, unsigned int n_databits ) { if ( ! dataout_p ) { // databits processor reset: reset Baudot state baudot_reset(); diff --git a/src/databits_binary.c b/src/databits_binary.c index cbdd66c..72dacc7 100644 --- a/src/databits_binary.c +++ b/src/databits_binary.c @@ -28,7 +28,7 @@ // returns nbytes decoded unsigned int databits_decode_binary( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ) + unsigned long long bits, unsigned int n_databits ) { if ( ! dataout_p ) // databits processor reset: noop return 0; diff --git a/src/databits_callerid.c b/src/databits_callerid.c index 9d8b932..c4bb1f0 100644 --- a/src/databits_callerid.c +++ b/src/databits_callerid.c @@ -157,7 +157,7 @@ decode_cid_reset() /* returns nbytes decoded */ unsigned int databits_decode_callerid( char *dataout_p, unsigned int dataout_size, - unsigned int bits, unsigned int n_databits ) + unsigned long long bits, unsigned int n_databits ) { if ( ! dataout_p ) // databits processor reset return decode_cid_reset(); @@ -183,7 +183,7 @@ databits_decode_callerid( char *dataout_p, unsigned int dataout_size, // Collect input bytes until we've collected as many as the message // length byte says there will be, plus two (the message type byte // and the checksum byte) - unsigned int cid_msglen = cid_buf[1]; + unsigned long long cid_msglen = cid_buf[1]; if ( cid_ndata < cid_msglen + 2) return 0; diff --git a/src/databits_uic.c b/src/databits_uic.c new file mode 100755 index 0000000..ddb3fa8 --- /dev/null +++ b/src/databits_uic.c @@ -0,0 +1,75 @@ +/* + * databits_uic.c + * + * Copyright (C) 2014 Marcos Vives Del Sol + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "databits.h" +#include "uic_codes.h" +#include "misc.h" + +/* + * UIC-751-3 Ground-train decoder + */ + +unsigned int +databits_decode_uic(char *output, + unsigned long long input, + unsigned int type) +{ + int written; + + if (!output) { + return 0; + } + + unsigned int code = (unsigned int) bit_reverse(bit_window(input, 24, 8), 8); + written = sprintf(output, "Train ID: %X%X%X%X%X%X - Message: %02X (%s)\n", + (unsigned int) bit_window(input, 0, 4), + (unsigned int) bit_window(input, 4, 4), + (unsigned int) bit_window(input, 8, 4), + (unsigned int) bit_window(input, 12, 4), + (unsigned int) bit_window(input, 16, 4), + (unsigned int) bit_window(input, 20, 4), + code, + uic_message_meaning(code, type) + ); + + return written; +} + +unsigned int +databits_decode_uic_ground(char *output, + unsigned int outputSize, + unsigned long long input, + unsigned int inputSize) +{ + return databits_decode_uic(output, + input, + UIC_TYPE_GROUNDTRAIN); +} + +unsigned int +databits_decode_uic_train(char *output, + unsigned int outputSize, + unsigned long long input, + unsigned int inputSize) +{ + return databits_decode_uic(output, + input, + UIC_TYPE_TRAINGROUND); +} diff --git a/src/fsk.c b/src/fsk.c index a6cc926..a261f36 100644 --- a/src/fsk.c +++ b/src/fsk.c @@ -178,13 +178,13 @@ fsk_bit_analyze( fsk_plan *fskp, float *samples, unsigned int bit_nsamples, static float fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit, int n_bits, const char *expect_bits_string, - unsigned int *bits_outp, float *ampl_outp ) + unsigned long long *bits_outp, float *ampl_outp ) { unsigned int bit_nsamples = (float)(samples_per_bit + 0.5); - unsigned int bit_values[32]; - float bit_sig_mags[32]; - float bit_noise_mags[32]; + unsigned int bit_values[64]; + float bit_sig_mags[64]; + float bit_noise_mags[64]; unsigned int bit_begin_sample; int bitnum; @@ -422,7 +422,7 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit, // into the bits_outp word. *bits_outp = 0; for ( bitnum=0; bitnum 0 ) - simpleaudio_tone(sa_out, bfsk_space_f, + simpleaudio_tone(sa_out, invert_start_stop ? bfsk_mark_f : bfsk_space_f, bit_nsamples * bfsk_nstartbits); // start for ( i=0; i> i ) & 1; + unsigned int bit; + if (bfsk_msb_first) { + bit = ( bits >> (n_data_bits - i - 1) ) & 1; + } else { + bit = ( bits >> i ) & 1; + } + float tone_freq = bit == 1 ? bfsk_mark_f : bfsk_space_f; simpleaudio_tone(sa_out, tone_freq, bit_nsamples); } if ( bfsk_nstopbits > 0 ) - simpleaudio_tone(sa_out, bfsk_mark_f, + simpleaudio_tone(sa_out, invert_start_stop ? bfsk_space_f : bfsk_mark_f, bit_nsamples * bfsk_nstopbits); // stop } @@ -107,6 +116,8 @@ static void fsk_transmit_stdin( int n_data_bits, float bfsk_nstartbits, float bfsk_nstopbits, + int invert_start_stop, + int bfsk_msb_first, unsigned int bfsk_do_tx_sync_bytes, unsigned int bfsk_sync_byte, databits_encoder encode @@ -151,19 +162,19 @@ static void fsk_transmit_stdin( tx_transmitting = 1; /* emit leader tone (mark) */ for ( j=0; j= 0 ) + expect_bits_string[j] = ( (bfsk_sync_byte>>i)&1 ) + '0'; + else + expect_bits_string[j] = 'd'; + } + if ( bfsk_nstopbits != 0.0 ) + expect_bits_string[j++] = stop_bit_value; + expect_bits_string[j] = 0; + + return j; +} + int main( int argc, char*argv[] ) { @@ -374,8 +434,13 @@ main( int argc, char*argv[] ) float bfsk_nstopbits = -1; unsigned int bfsk_do_rx_sync = 0; unsigned int bfsk_do_tx_sync_bytes = 0; - unsigned int bfsk_sync_byte = -1; + unsigned long long bfsk_sync_byte = -1; unsigned int bfsk_n_data_bits = 0; + int bfsk_msb_first = 0; + char *expect_data_string = NULL; + char *expect_sync_string = NULL; + unsigned int expect_n_bits; + int invert_start_stop = 0; int autodetect_shift; char *filename = NULL; @@ -436,8 +501,10 @@ main( int argc, char*argv[] ) enum { MINIMODEM_OPT_UNUSED=256, // placeholder + MINIMODEM_OPT_MSBFIRST, MINIMODEM_OPT_STARTBITS, MINIMODEM_OPT_STOPBITS, + MINIMODEM_OPT_INVERT_START_STOP, MINIMODEM_OPT_SYNC_BYTE, MINIMODEM_OPT_LUT, MINIMODEM_OPT_FLOAT_SAMPLES, @@ -464,6 +531,7 @@ main( int argc, char*argv[] ) { "ascii", 0, 0, '8' }, { "", 0, 0, '7' }, { "baudot", 0, 0, '5' }, + { "msb-first", 0, 0, MINIMODEM_OPT_MSBFIRST }, { "file", 1, 0, 'f' }, { "bandwidth", 1, 0, 'b' }, { "volume", 1, 0, 'v' }, @@ -471,6 +539,7 @@ main( int argc, char*argv[] ) { "space", 1, 0, 'S' }, { "startbits", 1, 0, MINIMODEM_OPT_STARTBITS }, { "stopbits", 1, 0, MINIMODEM_OPT_STOPBITS }, + { "invert-start-stop", 0, 0, MINIMODEM_OPT_INVERT_START_STOP }, { "sync-byte", 1, 0, MINIMODEM_OPT_SYNC_BYTE }, { "quiet", 0, 0, 'q' }, { "alsa", 2, 0, 'A' }, @@ -528,6 +597,9 @@ main( int argc, char*argv[] ) bfsk_databits_decode = databits_decode_baudot; bfsk_databits_encode = databits_encode_baudot; break; + case MINIMODEM_OPT_MSBFIRST: + bfsk_msb_first = 1; + break; case 'b': band_width = atof(optarg); assert( band_width != 0 ); @@ -557,6 +629,9 @@ main( int argc, char*argv[] ) bfsk_nstopbits = atof(optarg); assert( bfsk_nstopbits >= 0 ); break; + case MINIMODEM_OPT_INVERT_START_STOP: + invert_start_stop = 1; + break; case MINIMODEM_OPT_SYNC_BYTE: bfsk_do_rx_sync = 1; bfsk_do_tx_sync_bytes = 16; @@ -671,6 +746,24 @@ main( int argc, char*argv[] ) bfsk_databits_decode = databits_decode_callerid; bfsk_data_rate = 1200; bfsk_n_data_bits = 8; + } else if ( strncasecmp(modem_mode, "uic-train", 9) == 0 || strncasecmp(modem_mode, "uic-ground", 10) == 0 ) { + if ( TX_mode ) { + fprintf(stderr, "E: uic-751-3 --tx mode is not supported.\n"); + return 1; + } + // http://ec.europa.eu/transport/rail/interoperability/doc/ccs-tsi-en-annex.pdf + if (modem_mode[4] == 't' || modem_mode[4] == 'T') + bfsk_databits_decode = databits_decode_uic_train; + else + bfsk_databits_decode = databits_decode_uic_ground; + bfsk_data_rate = 600; + bfsk_n_data_bits = 39; + bfsk_mark_f = 1300; + bfsk_space_f = 1700; + bfsk_nstartbits = 8; + bfsk_nstopbits = 0; + expect_data_string = "11110010ddddddddddddddddddddddddddddddddddddddd"; + expect_n_bits = 47; } else { bfsk_data_rate = atof(modem_mode); if ( bfsk_n_data_bits == 0 ) @@ -778,6 +871,8 @@ main( int argc, char*argv[] ) bfsk_n_data_bits, bfsk_nstartbits, bfsk_nstopbits, + invert_start_stop, + bfsk_msb_first, bfsk_do_tx_sync_bytes, bfsk_sync_byte, bfsk_databits_encode @@ -788,7 +883,6 @@ main( int argc, char*argv[] ) return 0; } - /* * Open the input audio stream */ @@ -837,19 +931,6 @@ main( int argc, char*argv[] ) nbits += bfsk_n_data_bits; nbits += 1; // stop bit (first whole stop bit) - // FIXME EXPLAIN +1 goes with extra bit when scanning - size_t samplebuf_size = ceilf(nsamples_per_bit) * (nbits+1); - samplebuf_size *= 2; // account for the half-buf filling method -#define SAMPLE_BUF_DIVISOR 12 -#ifdef SAMPLE_BUF_DIVISOR - // For performance, use a larger samplebuf_size than necessary - if ( samplebuf_size < sample_rate / SAMPLE_BUF_DIVISOR ) - samplebuf_size = sample_rate / SAMPLE_BUF_DIVISOR; -#endif - float *samplebuf = malloc(samplebuf_size * sizeof(float)); - size_t samples_nvalid = 0; - debug_log("samplebuf_size=%zu\n", samplebuf_size); - /* * Run the main loop */ @@ -891,6 +972,38 @@ main( int argc, char*argv[] ) float frame_n_bits = bfsk_n_data_bits + bfsk_nstartbits + bfsk_nstopbits; unsigned int frame_nsamples = nsamples_per_bit * frame_n_bits + 0.5; + char expect_data_string_buffer[64]; + if (expect_data_string == NULL) { + expect_data_string = expect_data_string_buffer; + expect_n_bits = build_expect_bit_string(expect_data_string, bfsk_nstartbits, bfsk_n_data_bits, bfsk_nstopbits, invert_start_stop, (unsigned long long) -1); + } + //fprintf(stderr, "eds = '%s' (%lu)\n", expect_data_string, strlen(expect_data_string)); + + char expect_sync_string_buffer[64]; + if (expect_sync_string == NULL && bfsk_do_rx_sync && (long long) bfsk_sync_byte >= 0) { + expect_sync_string = expect_sync_string_buffer; + build_expect_bit_string(expect_sync_string, bfsk_nstartbits, bfsk_n_data_bits, bfsk_nstopbits, invert_start_stop, bfsk_sync_byte); + } else { + expect_sync_string = expect_data_string; + } + //fprintf(stderr, "ess = '%s' (%lu)\n", expect_sync_string, strlen(expect_sync_string)); + + unsigned int expect_nsamples = nsamples_per_bit * expect_n_bits; + + size_t samplebuf_size = expect_nsamples * 2; // account for the half-buf filling method +#define SAMPLE_BUF_DIVISOR 12 +#ifdef SAMPLE_BUF_DIVISOR + // For performance, use a larger samplebuf_size than necessary + if ( samplebuf_size < sample_rate / SAMPLE_BUF_DIVISOR ) + { + debug_log("buffer too small (%i), ceiling to %i", samplebuf_size, sample_rate / SAMPLE_BUF_DIVISOR); + samplebuf_size = sample_rate / SAMPLE_BUF_DIVISOR; + } +#endif + float *samplebuf = malloc(samplebuf_size * sizeof(float)); + size_t samples_nvalid = 0; + debug_log("samplebuf_size=%zu\n", samplebuf_size); + float track_amplitude = 0.0; float peak_confidence = 0.0; @@ -987,47 +1100,7 @@ main( int argc, char*argv[] ) */ debug_log( "--------------------------\n"); - - // example expect_bits_string - // 0123456789A - // isddddddddp i == idle bit (a.k.a. prev_stop bit) - // s == start bit d == data bits p == stop bit - // ebs = "10dddddddd1" <-- expected mark/space framing pattern - // - // NOTE! expect_n_bits ends up being (frame_n_bits+1), because - // we expect the prev_stop bit in addition to this frame's own - // (start + n_data_bits + stop) bits. But for each decoded frame, - // we will advance just frame_n_bits worth of samples, leaving us - // pointing at our stop bit -- it becomes the next frame's prev_stop. - // - // prev_stop--v - // start--v v--stop - // char *expect_bits_string = "10dddddddd1"; - // - char expect_bits_string[32]; - int j = 0; - if ( bfsk_nstopbits != 0.0 ) - expect_bits_string[j++] = '1'; - int i; - // Nb. only integer number of start bits works (for rx) - for ( i=0; i>i)&1 ) + '0'; - else - expect_bits_string[j] = 'd'; - } - if ( bfsk_nstopbits != 0.0 ) - expect_bits_string[j++] = '1'; - expect_bits_string[j++] = 0; - - - unsigned int expect_n_bits = strlen(expect_bits_string); - unsigned int expect_nsamples = nsamples_per_bit * expect_n_bits; - - // fprintf(stderr, "ebs = '%s' (%lu) ; expect_nsamples=%u samples_nvalid=%lu\n", expect_bits_string, strlen(expect_bits_string), expect_nsamples, samples_nvalid); - + //fprintf(stderr, "%i --- %i\n", samples_nvalid, expect_nsamples); if ( samples_nvalid < expect_nsamples ) break; @@ -1053,7 +1126,7 @@ main( int argc, char*argv[] ) try_step_nsamples = 1; float confidence, amplitude; - unsigned int bits = 0; + unsigned long long bits = 0; /* Note: frame_start_sample is actually the sample where the * prev_stop bit begins (since the "frame" includes the prev_stop). */ unsigned int frame_start_sample = 0; @@ -1069,7 +1142,7 @@ main( int argc, char*argv[] ) try_max_nsamples, try_step_nsamples, try_confidence_search_limit, - expect_bits_string, + carrier ? expect_data_string : expect_sync_string, &bits, &litude, &frame_start_sample @@ -1170,14 +1243,14 @@ main( int argc, char*argv[] ) try_step_nsamples = 1; try_confidence_search_limit = INFINITY; float confidence2, amplitude2; - unsigned int bits2; + unsigned long long bits2; unsigned int frame_start_sample2; confidence2 = fsk_find_frame(fskp, samplebuf, expect_nsamples, try_first_sample, try_max_nsamples, try_step_nsamples, try_confidence_search_limit, - expect_bits_string, + carrier ? expect_data_string : expect_sync_string, &bits2, &litude2, &frame_start_sample2 @@ -1224,9 +1297,10 @@ main( int argc, char*argv[] ) */ // chop off framing bits - unsigned int frame_bits_shift = bfsk_nstartbits; - unsigned int frame_bits_mask = (int)(1<> frame_bits_shift ) & frame_bits_mask; + bits = bit_window(bits, bfsk_nstartbits, bfsk_n_data_bits); + if (bfsk_msb_first) { + bits = bit_reverse(bits, bfsk_n_data_bits); + } unsigned int dataout_size = 4096; char dataoutbuf[4096]; diff --git a/src/misc.c b/src/misc.c new file mode 100755 index 0000000..c7b31fa --- /dev/null +++ b/src/misc.c @@ -0,0 +1,46 @@ +/* + * misc.c + * + * Copyright (C) 2014 Marcos Vives Del Sol + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "misc.h" + +// Reverses the ordering of the bits on an integer +unsigned long long +bit_reverse(unsigned long long value, + unsigned int bits) +{ + unsigned int out = 0; + + while (bits--) { + out = (out << 1) | (value & 1); + value >>= 1; + } + + return out; +} + +// Gets "bits" bits from "value" starting "offset" bits from the start +unsigned long long +bit_window(unsigned long long value, + unsigned int offset, + unsigned int bits) +{ + unsigned long long mask = (1ULL << bits) - 1; + value = (value >> offset) & mask; + return value; +} diff --git a/src/misc.h b/src/misc.h new file mode 100755 index 0000000..009b2e9 --- /dev/null +++ b/src/misc.h @@ -0,0 +1,27 @@ +/* + * misc.h + * + * Copyright (C) 2014 Marcos Vives Del Sol + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +unsigned long long +bit_reverse(unsigned long long value, + unsigned int bits); + +unsigned long long +bit_window(unsigned long long value, + unsigned int offset, + unsigned int bits); diff --git a/src/uic_codes.c b/src/uic_codes.c new file mode 100755 index 0000000..9b3cafe --- /dev/null +++ b/src/uic_codes.c @@ -0,0 +1,68 @@ +/* + * uic_codes.c + * + * Copyright (C) 2014 Marcos Vives Del Sol + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include "uic_codes.h" + +uic_message uic_ground_to_train_messages[] = { + { 0x00, "Test" }, + { 0x02, "Run slower" }, + { 0x03, "Extension of telegram" }, + { 0x04, "Run faster" }, + { 0x06, "Written order" }, + { 0x08, "Speech" }, + { 0x09, "Emergency stop" }, + { 0x0C, "Announcem. by loudspeaker" }, + { 0x55, "Idle" }, + { -1, NULL } +}; + +uic_message uic_train_to_ground_messages[] = { + { 0x08, "Communic. desired" }, + { 0x0A, "Acknowl. of order" }, + { 0x06, "Advice" }, + { 0x00, "Test" }, + { 0x09, "Train staff wish to comm." }, + { 0x0C, "Telephone link desired" }, + { 0x03, "Extension of telegram" }, + { -1, NULL } +}; + +const char * uic_message_meaning(unsigned int code, + unsigned int type) +{ + uic_message * messages; + if (type == UIC_TYPE_GROUNDTRAIN) { + messages = uic_ground_to_train_messages; + } else if (type == UIC_TYPE_TRAINGROUND) { + messages = uic_train_to_ground_messages; + } else { + assert(0); + } + + while (messages->code != -1) { + if (messages->code == code) { + return messages->meaning; + } + messages++; + } + + return "Unknown"; +} diff --git a/src/uic_codes.h b/src/uic_codes.h new file mode 100755 index 0000000..e72a10f --- /dev/null +++ b/src/uic_codes.h @@ -0,0 +1,34 @@ +/* + * uic_codes.h + * + * Copyright (C) 2014 Marcos Vives Del Sol + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +typedef struct { + unsigned int code; + char * meaning; +} uic_message; + +enum { + UIC_TYPE_GROUNDTRAIN, + UIC_TYPE_TRAINGROUND, +}; + +extern uic_message uic_ground_to_train_messages[]; +extern uic_message uic_train_to_ground_messages[]; + +const char * uic_message_meaning(unsigned int code, + unsigned int type);