From 25d01f73d843f4a54ec22f73095c7fb7ee2842d9 Mon Sep 17 00:00:00 2001 From: Marcos Vives Del Sol Date: Fri, 15 Aug 2014 23:29:27 +0200 Subject: [PATCH] Add UIC-751-3 decoding and optional MSB-first TX/RX [ kamal: cleanup ] --- src/Makefile.am | 5 +++- src/Makefile.in | 19 +++++++----- src/databits.h | 32 ++++++++++++++++++++ src/databits_uic.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++ src/minimodem.c | 52 +++++++++++++++++++++++++++----- src/uic_codes.c | 68 ++++++++++++++++++++++++++++++++++++++++++ src/uic_codes.h | 34 +++++++++++++++++++++ 7 files changed, 268 insertions(+), 16 deletions(-) create mode 100755 src/databits_uic.c create mode 100755 src/uic_codes.c create mode 100755 src/uic_codes.h diff --git a/src/Makefile.am b/src/Makefile.am index 5704382..1e6468f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,12 +42,15 @@ 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) minimodem_LDADD = $(DEPS_LIBS) minimodem_SOURCES = minimodem.c $(DATABITS_SRC) $(FSK_SRC) $(SIMPLEAUDIO_SRC) diff --git a/src/Makefile.in b/src/Makefile.in index 877217e..666da62 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -111,15 +111,16 @@ 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_minimodem_OBJECTS = minimodem.$(OBJEXT) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) minimodem_OBJECTS = $(am_minimodem_OBJECTS) am__DEPENDENCIES_1 = minimodem_DEPENDENCIES = $(am__DEPENDENCIES_1) @@ -314,12 +315,14 @@ 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) minimodem_LDADD = $(DEPS_LIBS) minimodem_SOURCES = minimodem.c $(DATABITS_SRC) $(FSK_SRC) $(SIMPLEAUDIO_SRC) @@ -417,6 +420,7 @@ 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)/simple-tone-generator.Po@am__quote@ @@ -425,6 +429,7 @@ distclean-compile: @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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/databits.h b/src/databits.h index ba9c12b..bb2cf88 100644 --- a/src/databits.h +++ b/src/databits.h @@ -17,6 +17,32 @@ * along with this program. If not, see . */ +// Reverses the ordering of the bits on an integer +static inline 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 +static inline 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; +} + typedef int (databits_encoder)( unsigned int *databits_outp, char char_out ); @@ -55,4 +81,10 @@ unsigned int databits_decode_callerid( char *dataout_p, unsigned int dataout_size, 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_uic.c b/src/databits_uic.c new file mode 100755 index 0000000..02da420 --- /dev/null +++ b/src/databits_uic.c @@ -0,0 +1,74 @@ +/* + * 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" + +/* + * 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/minimodem.c b/src/minimodem.c index d80ed50..a4d7b8c 100644 --- a/src/minimodem.c +++ b/src/minimodem.c @@ -81,7 +81,8 @@ static void fsk_transmit_frame( float bfsk_mark_f, float bfsk_space_f, float bfsk_nstartbits, - float bfsk_nstopbits + float bfsk_nstopbits, + int bfsk_msb_first ) { int i; @@ -89,7 +90,13 @@ static void fsk_transmit_frame( simpleaudio_tone(sa_out, 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); } @@ -107,6 +114,7 @@ static void fsk_transmit_stdin( int n_data_bits, float bfsk_nstartbits, float bfsk_nstopbits, + int bfsk_msb_first, unsigned int bfsk_do_tx_sync_bytes, unsigned int bfsk_sync_byte, databits_encoder encode @@ -156,14 +164,14 @@ static void fsk_transmit_stdin( for ( j=0; j> 32), (unsigned int)bits, bfsk_n_data_bits, bfsk_nstartbits, (unsigned int)(frame_bits_mask >> 32), (unsigned int)(frame_bits_mask)); - bits = ( bits >> 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); + } + debug_log("Input: %08x%08x - Databits: %i - Shift: %i\n", (unsigned int)(bits >> 32), (unsigned int)bits, bfsk_n_data_bits, bfsk_nstartbits); unsigned int dataout_size = 4096; char dataoutbuf[4096]; 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);