From 8d2bc49fb9e0c9a5fbd75aa3cad207608e72bf99 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 30 Jun 2009 23:03:33 +0200 Subject: moved gsm-receiver into directory - preparation to move to airprobe --- src/lib/Assert.h | 67 -- src/lib/Makefile.am | 109 ---- src/lib/decoder/AUTHORS | 1 - src/lib/decoder/Makefile.am | 56 -- src/lib/decoder/a5-1-2.h | 453 -------------- src/lib/decoder/burst_types.h | 214 ------- src/lib/decoder/cch.c | 482 --------------- src/lib/decoder/cch.h | 56 -- src/lib/decoder/fire_crc.c | 179 ------ src/lib/decoder/fire_crc.h | 47 -- src/lib/decoder/gsmstack.c | 206 ------- src/lib/decoder/gsmstack.h | 43 -- src/lib/decoder/gsmtap.h | 41 -- src/lib/decoder/interleave.c | 47 -- src/lib/decoder/interleave.h | 19 - src/lib/decoder/openbtsstuff/AUTHORS | 173 ------ src/lib/decoder/openbtsstuff/Assert.h | 49 -- src/lib/decoder/openbtsstuff/BitVector.cpp | 513 ---------------- src/lib/decoder/openbtsstuff/BitVector.h | 427 ------------- src/lib/decoder/openbtsstuff/GSM610Tables.cpp | 492 --------------- src/lib/decoder/openbtsstuff/GSM610Tables.h | 37 -- src/lib/decoder/openbtsstuff/GSMCommon.cpp | 315 ---------- src/lib/decoder/openbtsstuff/GSMCommon.h | 537 ---------------- src/lib/decoder/openbtsstuff/GSML1FEC.cpp | 256 -------- src/lib/decoder/openbtsstuff/GSML1FEC.h | 146 ----- src/lib/decoder/openbtsstuff/GSMTDMA.cpp | 337 ---------- src/lib/decoder/openbtsstuff/GSMTDMA.h | 358 ----------- src/lib/decoder/openbtsstuff/Makefile.am | 49 -- src/lib/decoder/openbtsstuff/RxBurst.h | 69 --- src/lib/decoder/openbtsstuff/Threads.cpp | 106 ---- src/lib/decoder/openbtsstuff/Threads.h | 150 ----- src/lib/decoder/openbtsstuff/Timeval.cpp | 93 --- src/lib/decoder/openbtsstuff/Timeval.h | 96 --- src/lib/decoder/openbtsstuff/Vector.h | 257 -------- src/lib/decoder/openbtsstuff/VocoderFrame.h | 25 - src/lib/decoder/out_pcap.c | 111 ---- src/lib/decoder/out_pcap.h | 9 - src/lib/decoder/sch.c | 333 ---------- src/lib/decoder/sch.h | 17 - src/lib/decoder/system.h | 11 - src/lib/decoder/tun.c | 125 ---- src/lib/decoder/tun.h | 4 - src/lib/gsm.i | 49 -- src/lib/gsm_constants.h | 150 ----- src/lib/gsm_receiver_cf.cc | 853 -------------------------- src/lib/gsm_receiver_cf.h | 254 -------- src/lib/gsm_receiver_config.cc | 84 --- src/lib/gsm_receiver_config.h | 164 ----- src/lib/viterbi_detector.cc | 554 ----------------- src/lib/viterbi_detector.h | 63 -- 50 files changed, 9286 deletions(-) delete mode 100644 src/lib/Assert.h delete mode 100644 src/lib/Makefile.am delete mode 100644 src/lib/decoder/AUTHORS delete mode 100644 src/lib/decoder/Makefile.am delete mode 100644 src/lib/decoder/a5-1-2.h delete mode 100644 src/lib/decoder/burst_types.h delete mode 100644 src/lib/decoder/cch.c delete mode 100644 src/lib/decoder/cch.h delete mode 100644 src/lib/decoder/fire_crc.c delete mode 100644 src/lib/decoder/fire_crc.h delete mode 100644 src/lib/decoder/gsmstack.c delete mode 100644 src/lib/decoder/gsmstack.h delete mode 100644 src/lib/decoder/gsmtap.h delete mode 100644 src/lib/decoder/interleave.c delete mode 100644 src/lib/decoder/interleave.h delete mode 100644 src/lib/decoder/openbtsstuff/AUTHORS delete mode 100644 src/lib/decoder/openbtsstuff/Assert.h delete mode 100644 src/lib/decoder/openbtsstuff/BitVector.cpp delete mode 100644 src/lib/decoder/openbtsstuff/BitVector.h delete mode 100644 src/lib/decoder/openbtsstuff/GSM610Tables.cpp delete mode 100644 src/lib/decoder/openbtsstuff/GSM610Tables.h delete mode 100644 src/lib/decoder/openbtsstuff/GSMCommon.cpp delete mode 100644 src/lib/decoder/openbtsstuff/GSMCommon.h delete mode 100644 src/lib/decoder/openbtsstuff/GSML1FEC.cpp delete mode 100644 src/lib/decoder/openbtsstuff/GSML1FEC.h delete mode 100644 src/lib/decoder/openbtsstuff/GSMTDMA.cpp delete mode 100644 src/lib/decoder/openbtsstuff/GSMTDMA.h delete mode 100644 src/lib/decoder/openbtsstuff/Makefile.am delete mode 100644 src/lib/decoder/openbtsstuff/RxBurst.h delete mode 100644 src/lib/decoder/openbtsstuff/Threads.cpp delete mode 100644 src/lib/decoder/openbtsstuff/Threads.h delete mode 100644 src/lib/decoder/openbtsstuff/Timeval.cpp delete mode 100644 src/lib/decoder/openbtsstuff/Timeval.h delete mode 100644 src/lib/decoder/openbtsstuff/Vector.h delete mode 100644 src/lib/decoder/openbtsstuff/VocoderFrame.h delete mode 100644 src/lib/decoder/out_pcap.c delete mode 100644 src/lib/decoder/out_pcap.h delete mode 100644 src/lib/decoder/sch.c delete mode 100644 src/lib/decoder/sch.h delete mode 100644 src/lib/decoder/system.h delete mode 100644 src/lib/decoder/tun.c delete mode 100644 src/lib/decoder/tun.h delete mode 100644 src/lib/gsm.i delete mode 100644 src/lib/gsm_constants.h delete mode 100644 src/lib/gsm_receiver_cf.cc delete mode 100644 src/lib/gsm_receiver_cf.h delete mode 100644 src/lib/gsm_receiver_config.cc delete mode 100644 src/lib/gsm_receiver_config.h delete mode 100644 src/lib/viterbi_detector.cc delete mode 100644 src/lib/viterbi_detector.h (limited to 'src/lib') diff --git a/src/lib/Assert.h b/src/lib/Assert.h deleted file mode 100644 index acfb3f7..0000000 --- a/src/lib/Assert.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 . - -*/ - - -#ifndef ASSERT_H -#define ASSERT_H - -#include "stdio.h" -#include - -#define NDEBUG - -/**@name Macros for standard messages. */ -//@{ -#define COUT(text) { std::cout << text << std::endl; } -#define CERR(text) { std::cerr << __FILE__ << ":" << __LINE__ << ": " << text; } -#ifdef NDEBUG -#define DCOUT(text) {} -#define OBJDCOUT(text) {} -#else -#define DCOUT(text) { COUT(__FILE__ << ":" << __LINE__ << " " << text); } -#define OBJDCOUT(text) { DCOUT(this << " " << text); } -#endif -//@} - - -/** This is thrown by assert() so that gdb can catch it. */ - -class Assertion -{ - - public: - - Assertion() { - fprintf( stderr,"Try setting a breakpoint @ %s:%u.\n",__FILE__,__LINE__ ); - return; - } - -}; - -#ifdef NDEBUG -#define assert(EXPR) {}; -#else -/** This replaces the regular assert() with a C++ exception. */ -#include "stdio.h" -#define assert(E) { if (!(E)) { fprintf(stderr,"%s:%u failed assertion '%s'\n",__FILE__,__LINE__,#E); throw Assertion(); } } -#endif - -#endif diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am deleted file mode 100644 index 925eaca..0000000 --- a/src/lib/Makefile.am +++ /dev/null @@ -1,109 +0,0 @@ -# -# Copyright 2004,2005,2006,2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/Makefile.common - -SUBDIRS = decoder -# Install this stuff so that it ends up as the gnuradio.howto module -# This usually ends up at: -# ${prefix}/lib/python${python_version}/site-packages/gnuradio - -ourpythondir = $(grpythondir) -ourlibdir = $(grpyexecdir) - -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES) -# -I$(OPEN_BTS_INCLUDES) - -SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(SWIGGRFLAGS) $(WITH_SWIG_INCLUDES) \ - $(WITH_INCLUDES) - -ALL_IFILES = \ - $(LOCAL_IFILES) \ - $(NON_LOCAL_IFILES) - -NON_LOCAL_IFILES = \ - $(GNURADIO_CORE_INCLUDEDIR)/swig/gnuradio.i - - -LOCAL_IFILES = \ - $(top_srcdir)/src/lib/gsm.i - -# These files are built by SWIG. The first is the C++ glue. -# The second is the python wrapper that loads the _howto shared library -# and knows how to call our extensions. - -BUILT_SOURCES = \ - gsm.cc \ - gsm.py - -# This gets howto.py installed in the right place -ourpython_PYTHON = \ - gsm.py - -ourlib_LTLIBRARIES = _gsm.la - -lib_LTLIBRARIES = libgsmdemod.la - -# These are the source files that go into the shared library -_gsm_la_SOURCES = \ - gsm.cc - -libgsmdemod_la_SOURCES = \ - gsm_receiver_cf.cc \ - gsm_receiver_config.cc \ - viterbi_detector.cc - -# magic flags -_gsm_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version - -# link the library against some comon swig runtime code and the -# c++ standard library -_gsm_la_LIBADD = \ - $(PYTHON_LDFLAGS) \ - libgsmdemod.la \ - -lstdc++ \ - $(DECODER_LA) - -#libgsmdemod_la_LIBADD = - -gsm.cc gsm.py: $(LOCAL_IFILES) $(ALL_IFILES) - $(SWIG) $(SWIGPYTHONARGS) -module gsm -o gsm.cc $(LOCAL_IFILES) - -# These headers get installed in ${prefix}/include/gnuradio -grinclude_HEADERS = \ - gsm_receiver_cf.h \ - gsm_receiver_config.h - -noinst_HEADERS = \ - gsm_constants.h \ - viterbi_detector.h - -# These swig headers get installed in ${prefix}/include/gnuradio/swig -swiginclude_HEADERS = \ - $(LOCAL_IFILES) - - -MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc - -# Don't distribute output of swig -dist-hook: - @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done - @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done diff --git a/src/lib/decoder/AUTHORS b/src/lib/decoder/AUTHORS deleted file mode 100644 index dcc5998..0000000 --- a/src/lib/decoder/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Harald Welte diff --git a/src/lib/decoder/Makefile.am b/src/lib/decoder/Makefile.am deleted file mode 100644 index 1726d68..0000000 --- a/src/lib/decoder/Makefile.am +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2001,2002,2004,2005,2006,2007,2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/Makefile.common - -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) - -SUBDIRS = openbtsstuff - -noinst_LTLIBRARIES = libdecoder.la - -libdecoder_la_LIBADD = \ - openbtsstuff/libopenbtsdecoder.la - -libdecoder_la_SOURCES = \ - sch.c \ - cch.c \ - fire_crc.c \ - gsmstack.c \ - interleave.c \ - out_pcap.c \ - tun.c -# tch.c \ -# conv.c - -noinst_HEADERS = \ - sch.h \ - cch.h \ - fire_crc.h \ - gsmstack.h \ - interleave.h \ - out_pcap.h \ - tun.h \ - system.h \ - gsmtap.h \ - a5-1-2.h -# tch.h \ -# conv.h diff --git a/src/lib/decoder/a5-1-2.h b/src/lib/decoder/a5-1-2.h deleted file mode 100644 index de764ee..0000000 --- a/src/lib/decoder/a5-1-2.h +++ /dev/null @@ -1,453 +0,0 @@ -/* - * A pedagogical implementation of the GSM A5/1 and A5/2 "voice privacy" - * encryption algorithms. - * - * Copyright (C) 1998-1999: Marc Briceno, Ian Goldberg, and David Wagner - * - * The source code below is optimized for instructional value and clarity. - * Performance will be terrible, but that's not the point. - * - * This software may be export-controlled by US law. - * - * This software is free for commercial and non-commercial use as long as - * the following conditions are adhered to. - * Copyright remains the authors' and as such any Copyright notices in - * the code are not to be removed. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The license and distribution terms for any publicly available version - * or derivative of this code cannot be changed. i.e. this code cannot - * simply be copied and put under another distribution license - * [including the GNU Public License]. - * - * Background: The Global System for Mobile communications is the most - * widely deployed digital cellular telephony system in the world. GSM - * makes use of four core cryptographic algorithms, none of which has - * been published by the GSM MOU. This failure to subject the - * algorithms to public review is all the more puzzling given that over - * 215 million GSM subscribers are expected to rely on the claimed - * security of the system. - * - * The four core GSM cryptographic algorithms are: - * A3 authentication algorithm - * A5/1 "stronger" over-the-air voice-privacy algorithm - * A5/2 "weaker" over-the-air voice-privacy algorithm - * A8 voice-privacy key generation algorithm - * - * In April of 1998, our group showed that COMP128, the algorithm used by the - * overwhelming majority of GSM providers for both A3 and A8 functionality - * is fatally flawed and allows for cloning of GSM mobile phones. - * - * Furthermore, we demonstrated that all A8 implementations we could locate, - * including the few that did not use COMP128 for key generation, had been - * deliberately weakened by reducing the keyspace from 64 bits to 54 bits. - * The remaining 10 bits are simply set to zero! - * - * See http://www.scard.org/gsm for additional information. - * - * [May 1999] - * One question so far unanswered is if A5/1, the "stronger" of the two - * widely deployed voice-privacy algorithm is at least as strong as the - * key. Meaning: "Does A5/1 have a work factor of at least 54 bits"? - * Absent a publicly available A5/1 reference implementation, this question - * could not be answered. We hope that our reference implementation below, - * which has been verified against official A5/1 test vectors, will provide - * the cryptographic community with the base on which to construct the - * answer to this important question. - * - * Initial indications about the strength of A5/1 are not encouraging. - * A variant of A5, while not A5/1 itself, has been estimated to have a - * work factor of well below 54 bits. See http://jya.com/crack-a5.htm for - * background information and references. - * - * With COMP128 broken and A5/1 published below, we will now turn our - * attention to A5/2. - * - * [August 1999] - * 19th Annual International Cryptology Conference - Crypto'99 - * Santa Barbara, California - * - * A5/2 has been added to the previously published A5/1 source. Our - * implementation has been verified against official test vectors. - * - * This means that our group has now reverse engineered the entire set - * of cryptographic algorithms used in the overwhelming majority of GSM - * installations, including all the over-the-air "voice privacy" algorithms. - * - * The "voice privacy" algorithm A5/2 proved especially weak. Which perhaps - * should come as no surprise, since even GSM MOU members have admitted that - * A5/2 was designed with heavy input by intelligence agencies to ensure - * breakability. Just how insecure is A5/2? It can be broken in real time - * with a work factor of a mere 16 bits. GSM might just as well use no "voice - * privacy" algorithm at all. - * - * We announced the break of A5/2 at the Crypto'99 Rump Session. - * Details will be published in a scientific paper following soon. - * - * - * -- Marc Briceno - * Voice: +1 (925) 798-4042 - * - */ - - -#include - - -/* Masks for the shift registers */ -#define R1MASK 0x07FFFF /* 19 bits, numbered 0..18 */ -#define R2MASK 0x3FFFFF /* 22 bits, numbered 0..21 */ -#define R3MASK 0x7FFFFF /* 23 bits, numbered 0..22 */ -#ifdef A5_2 -#define R4MASK 0x01FFFF /* 17 bits, numbered 0..16 */ -#endif /* A5_2 */ - - -#ifndef A5_2 -/* Middle bit of each of the three shift registers, for clock control */ -#define R1MID 0x000100 /* bit 8 */ -#define R2MID 0x000400 /* bit 10 */ -#define R3MID 0x000400 /* bit 10 */ -#else /* A5_2 */ -/* A bit of R4 that controls each of the shift registers */ -#define R4TAP1 0x000400 /* bit 10 */ -#define R4TAP2 0x000008 /* bit 3 */ -#define R4TAP3 0x000080 /* bit 7 */ -#endif /* A5_2 */ - - -/* Feedback taps, for clocking the shift registers. - * These correspond to the primitive polynomials - * x^19 + x^5 + x^2 + x + 1, x^22 + x + 1, - * x^23 + x^15 + x^2 + x + 1, and x^17 + x^5 + 1. */ - - -#define R1TAPS 0x072000 /* bits 18,17,16,13 */ -#define R2TAPS 0x300000 /* bits 21,20 */ -#define R3TAPS 0x700080 /* bits 22,21,20,7 */ -#ifdef A5_2 -#define R4TAPS 0x010800 /* bits 16,11 */ -#endif /* A5_2 */ - - -typedef unsigned char byte; -typedef unsigned long word; -typedef word bit; - - -/* Calculate the parity of a 32-bit word, i.e. the sum of its bits modulo 2 -*/ -bit parity(word x) -{ - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - x ^= x >> 2; - x ^= x >> 1; - return x&1; -} - - -/* Clock one shift register. For A5/2, when the last bit of the frame - * is loaded in, one particular bit of each register is forced to '1'; - * that bit is passed in as the last argument. */ -#ifndef A5_2 -word clockone(word reg, word mask, word taps) -{ -#else /* A5_2 */ -word clockone(word reg, word mask, word taps, word loaded_bit) { -#endif /* A5_2 */ - word t = reg & taps; - reg = (reg << 1) & mask; - reg |= parity(t); -#ifdef A5_2 - reg |= loaded_bit; -#endif /* A5_2 */ - return reg; -} - - -/* The three shift registers. They're in global variables to make the code - * easier to understand. - * A better implementation would not use global variables. */ -word R1, R2, R3; -#ifdef A5_2 -word R4; -#endif /* A5_2 */ - - -/* Return 1 iff at least two of the parameter words are non-zero. */ -bit majority(word w1, word w2, word w3) { - int sum = (w1 != 0) + (w2 != 0) + (w3 != 0); - if (sum >= 2) - return 1; - else - return 0; -} - - -/* Clock two or three of R1,R2,R3, with clock control - * according to their middle bits. - * Specifically, we clock Ri whenever Ri's middle bit - * agrees with the majority value of the three middle bits. For A5/2, - * use particular bits of R4 instead of the middle bits. Also, for A5/2, - * always clock R4. - * If allP == 1, clock all three of R1,R2,R3, ignoring their middle bits. - * This is only used for key setup. If loaded == 1, then this is the last - * bit of the frame number, and if we're doing A5/2, we have to set a - * particular bit in each of the four registers. */ -void clock(int allP, int loaded) { -#ifndef A5_2 - bit maj = majority(R1 & R1MID, R2 & R2MID, R3 & R3MID); - if (allP || (((R1&R1MID) != 0) == maj)) - R1 = clockone(R1, R1MASK, R1TAPS); - if (allP || (((R2&R2MID) != 0) == maj)) - R2 = clockone(R2, R2MASK, R2TAPS); - if (allP || (((R3&R3MID) != 0) == maj)) - R3 = clockone(R3, R3MASK, R3TAPS); -#else /* A5_2 */ - bit maj = majority(R4 & R4TAP1, R4 & R4TAP2, R4 & R4TAP3); - if (allP || (((R4&R4TAP1) != 0) == maj)) - R1 = clockone(R1, R1MASK, R1TAPS, loaded << 15); - if (allP || (((R4&R4TAP2) != 0) == maj)) - R2 = clockone(R2, R2MASK, R2TAPS, loaded << 16); - if (allP || (((R4&R4TAP3) != 0) == maj)) - R3 = clockone(R3, R3MASK, R3TAPS, loaded << 18); - R4 = clockone(R4, R4MASK, R4TAPS, loaded << 10); -#endif /* A5_2 */ -} - - -/* Generate an output bit from the current state. - * You grab a bit from each register via the output generation taps; - * then you XOR the resulting three bits. For A5/2, in addition to - * the top bit of each of R1,R2,R3, also XOR in a majority function - * of three particular bits of the register (one of them complemented) - * to make it non-linear. Also, for A5/2, delay the output by one - * clock cycle for some reason. */ -bit getbit() { - bit topbits = (((R1 >> 18) ^ (R2 >> 21) ^ (R3 >> 22)) & 0x01); -#ifndef A5_2 - return topbits; -#else /* A5_2 */ - static bit delaybit = 0; - bit nowbit = delaybit; - delaybit = ( - topbits - ^ majority(R1 & 0x8000, (~R1) & 0x4000, R1 & 0x1000) - ^ majority((~R2) & 0x10000, R2 & 0x2000, R2 & 0x200) - ^ majority(R3 & 0x40000, R3 & 0x10000, (~R3) & 0x2000) - ); - return nowbit; -#endif /* A5_2 */ -} - - -/* Do the A5 key setup. This routine accepts a 64-bit key and - * a 22-bit frame number. */ -void keysetup(byte key_reversed[8], word frame) { - int i; - bit keybit, framebit; - - byte key[8]; - for(i=0; i<8; i++){ - key[i] = key_reversed[7-i]; - } - /* Zero out the shift registers. */ - R1 = R2 = R3 = 0; -#ifdef A5_2 - R4 = 0; -#endif /* A5_2 */ - - - /* Load the key into the shift registers, - * LSB of first byte of key array first, - * clocking each register once for every - * key bit loaded. (The usual clock - * control rule is temporarily disabled.) */ - for (i = 0; i < 64; i++) { - clock(1, 0); /* always clock */ - keybit = (key[i/8] >> (i & 7)) & 1; /* The i-th bit of the key */ - R1 ^= keybit; - R2 ^= keybit; - R3 ^= keybit; -#ifdef A5_2 - R4 ^= keybit; -#endif /* A5_2 */ - } - - - /* Load the frame number into the shift registers, LSB first, - * clocking each register once for every key bit loaded. - * (The usual clock control rule is still disabled.) - * For A5/2, signal when the last bit is being clocked in. */ - for (i = 0; i < 22; i++) { - clock(1, i == 21); /* always clock */ - framebit = (frame >> i) & 1; /* The i-th bit of the frame # */ - R1 ^= framebit; - R2 ^= framebit; - R3 ^= framebit; -#ifdef A5_2 - R4 ^= framebit; -#endif /* A5_2 */ - } - - - /* Run the shift registers for 100 clocks - * to mix the keying material and frame number - * together with output generation disabled, - * so that there is sufficient avalanche. - * We re-enable the majority-based clock control - * rule from now on. */ - for (i = 0; i < 100; i++) { - clock(0, 0); - } - /* For A5/2, we have to load the delayed output bit. This does _not_ - * change the state of the registers. For A5/1, this is a no-op. */ - getbit(); - - - /* Now the key is properly set up. */ -} - - -/* Generate output. We generate 228 bits of - * keystream output. The first 114 bits is for - * the A->B frame; the next 114 bits is for the - * B->A frame. You allocate a 15-byte buffer - * for each direction, and this function fills - * it in. */ -void run(byte AtoBkeystream[], byte BtoAkeystream[]) { - int i; - - - /* Zero out the output buffers. */ - for (i = 0; i <= 113 / 8; i++) - AtoBkeystream[i] = BtoAkeystream[i] = 0; - - - /* Generate 114 bits of keystream for the - * A->B direction. Store it, MSB first. */ - for (i = 0; i < 114; i++) { - clock(0, 0); - AtoBkeystream[i/8] |= getbit() << (7 - (i & 7)); - } - - - /* Generate 114 bits of keystream for the - * B->A direction. Store it, MSB first. */ - for (i = 0; i < 114; i++) { - clock(0, 0); - BtoAkeystream[i/8] |= getbit() << (7 - (i & 7)); - } -} - -void runA51(unsigned char AtoBkeystream[]) { - int i; - - /* Zero out the output buffers. */ - for (i = 0; i < 114; i++) - AtoBkeystream[i] = 0; - - - /* Generate 114 bits of keystream for the - * A->B direction. Store it, MSB first. */ - for (i = 0; i < 114; i++) { - clock(0, 0); - AtoBkeystream[i] = getbit(); - } -} - - -/* Test the code by comparing it against - * a known-good test vector. */ -void test() { -#ifndef A5_2 - byte key[8] = {0x12, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; - word frame = 0x134; - byte goodAtoB[15] = { 0x53, 0x4E, 0xAA, 0x58, 0x2F, 0xE8, 0x15, - 0x1A, 0xB6, 0xE1, 0x85, 0x5A, 0x72, 0x8C, 0x00 - }; - byte goodBtoA[15] = { 0x24, 0xFD, 0x35, 0xA3, 0x5D, 0x5F, 0xB6, - 0x52, 0x6D, 0x32, 0xF9, 0x06, 0xDF, 0x1A, 0xC0 - }; -#else /* A5_2 */ - byte key[8] = {0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - word frame = 0x21; - byte goodAtoB[15] = { 0xf4, 0x51, 0x2c, 0xac, 0x13, 0x59, 0x37, - 0x64, 0x46, 0x0b, 0x72, 0x2d, 0xad, 0xd5, 0x00 - }; - byte goodBtoA[15] = { 0x48, 0x00, 0xd4, 0x32, 0x8e, 0x16, 0xa1, - 0x4d, 0xcd, 0x7b, 0x97, 0x22, 0x26, 0x51, 0x00 - }; -#endif /* A5_2 */ - byte AtoB[15], BtoA[15]; - int i, failed = 0; - - - keysetup(key, frame); - run(AtoB, BtoA); - - - /* Compare against the test vector. */ - for (i = 0; i < 15; i++) - if (AtoB[i] != goodAtoB[i]) - failed = 1; - for (i = 0; i < 15; i++) - if (BtoA[i] != goodBtoA[i]) - failed = 1; - - - /* Print some debugging output. */ - printf("key: 0x"); - for (i = 0; i < 8; i++) - printf("%02X", key[i]); - printf("\n"); - printf("frame number: 0x%06X\n", (unsigned int)frame); - printf("known good output:\n"); - printf(" A->B: 0x"); - for (i = 0; i < 15; i++) - printf("%02X", goodAtoB[i]); - printf(" B->A: 0x"); - for (i = 0; i < 15; i++) - printf("%02X", goodBtoA[i]); - printf("\n"); - printf("observed output:\n"); - printf(" A->B: 0x"); - for (i = 0; i < 15; i++) - printf("%02X", AtoB[i]); - printf(" B->A: 0x"); - for (i = 0; i < 15; i++) - printf("%02X", BtoA[i]); - printf("\n"); - - - if (!failed) { - printf("Self-check succeeded: everything looks ok.\n"); -// exit(0); - } else { - /* Problems! The test vectors didn't compare*/ - printf("\nI don't know why this broke; contact the authors.\n"); - } -} - diff --git a/src/lib/decoder/burst_types.h b/src/lib/decoder/burst_types.h deleted file mode 100644 index ee51f9a..0000000 --- a/src/lib/decoder/burst_types.h +++ /dev/null @@ -1,214 +0,0 @@ -// $Id: burst_types.h,v 1.5 2007/03/14 05:44:53 jl Exp $ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -static const int TB_LEN = 3; -static const int TB_OS1 = 0; -static const int TB_OS2 = 145; -static const unsigned char tail_bits[] = {0, 0, 0}; - -/* - * The normal burst is used to carry information on traffic and control - * channels. - */ - -static const int N_TSC_NUM = 8; // number of training sequence codes -static const int N_TSC_CODE_LEN = 26; // length of tsc -static const int N_TSC_OS = 61; // tsc offset -static const int N_EDATA_LEN_1 = 58; // length of first data section -static const int N_EDATA_OS_1 = 3; // offset of first data section -static const int N_EDATA_LEN_2 = 58; // length of second data section -static const int N_EDATA_OS_2 = 87; // offset of second data section -#if 0 -static const unsigned char n_tsc[][N_TSC_CODE_LEN] = { -/* 0 */ { - 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, - 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 - }, -/* 1 */ { - 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, - 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 - }, -/* 2 */ { - 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, - 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0 - }, -/* 3 */ { - 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, - 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0 - }, -/* 4 */ { - 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, - 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1 - }, -/* 5 */ { - 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, - 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0 - }, -/* 6 */ { - 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, - 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1 - }, -/* 7 */ { - 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0 - } -}; - -#endif - -/* - * The frequency correction burst is used for frequency synchronization - * of the mobile. This is broadcast in TS0 together with the SCH and - * BCCH. - * - * Modulating the bits below causes a spike at 62.5kHz above (below for - * COMPACT) the center frequency. One can use this spike with a narrow - * band filter to accurately determine the center of the channel. - */ -static const int FC_CODE_LEN = 142; -static const int FC_OS = 3; -static const unsigned char fc_fb[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char fc_compact_fb[] = { - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 -}; - - -/* - * The synchronization burst is used for time synchronization of the - * mobile. The bits given below were chosen for their correlation - * properties. The synchronization channel (SCH) contains a long - * training sequence (given below) and carries the TDMA frame number and - * base station identity code. It is broadcast in TS0 in the frame - * following the frequency correction burst. - */ -static const int SB_CODE_LEN = 64; -static const int SB_ETS_OS = 42; -static const int SB_EDATA_LEN_1 = 39; -static const int SB_EDATA_OS_1 = 3; -static const int SB_EDATA_LEN_2 = 39; -static const int SB_EDATA_OS_2 = 106; -static const unsigned char sb_etsc[] = { - 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, - 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1 -}; - -static const unsigned char sb_cts_etsc[] = { - 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, - 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, - 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1 -}; - -static const unsigned char sb_compact_etsc[] = { - 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, - 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, - 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0 -}; - - -/* - * A base tranceiver station must transmit a burst in every timeslot of - * every TDMA frame in channel C0. The dummy burst will be transmitted - * on all timeslots of all TDMA frames for which no other channel - * requires a burst to be transmitted. - */ -static const int D_CODE_LEN = 142; -static const int D_MB_OS = 3; -static const unsigned char d_mb[] = { - 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, - 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, - 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, - 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, - 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, - 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, - 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, - 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 -}; - - -/* - * The access burst is used for random access from a mobile. - */ -static const int AB_ETB_CODE_LEN = 8; -static const int AB_ETB_OS = 0; -static const unsigned char ab_etb[] = { - 0, 0, 1, 1, 1, 0, 1, 0 -}; - -static const int AB_SSB_CODE_LEN = 41; -static const int AB_SSB_OS = 8; -static const unsigned char ab_ssb[] = { - 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, - 0, 0, 1, 1, 1, 1, 0, 0, 0 -}; - -static const unsigned char ab_ts1_ssb[] = { - 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, - 0, 0, 1, 0, 0, 1, 1, 0, 1 -}; - -static const unsigned char ab_ts2_ssb[] = { - 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, - 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, - 1, 0, 1, 1, 1, 0, 1, 1, 1 -}; - - -typedef enum { - burst_n_0, - burst_n_1, - burst_n_2, - burst_n_3, - burst_n_4, - burst_n_5, - burst_n_6, - burst_n_7, - burst_fc, - burst_fc_c, - burst_s, - burst_s_cts, - burst_s_c, - burst_d, - burst_a, - burst_a_ts1, - burst_a_ts2, - burst_not_a_burst -} burst_t; - -static const int N_BURST_TYPES = ((int)(burst_not_a_burst) + 1); - -#ifdef __cplusplus -} -#endif diff --git a/src/lib/decoder/cch.c b/src/lib/decoder/cch.c deleted file mode 100644 index f1da56d..0000000 --- a/src/lib/decoder/cch.c +++ /dev/null @@ -1,482 +0,0 @@ -//TODO: this file shouldn't be part of the GSM Receiver -#include "system.h" -#include -#include -#include -#include -#include - -//#include -//#include -#include -//#include "burst_types.h" -#include "cch.h" -#include "fire_crc.h" - - -/* - * GSM SACCH -- Slow Associated Control Channel - * - * These messages are encoded exactly the same as on the BCCH. - * (Broadcast Control Channel.) - * - * Input: 184 bits - * - * 1. Add parity and flushing bits. (Output 184 + 40 + 4 = 228 bit) - * 2. Convolutional encode. (Output 228 * 2 = 456 bit) - * 3. Interleave. (Output 456 bit) - * 4. Map on bursts. (4 x 156 bit bursts with each 2x57 bit content data) - */ - - -/* - * Parity (FIRE) for the GSM SACCH channel. - * - * g(x) = (x^23 + 1)(x^17 + x^3 + 1) - * = x^40 + x^26 + x^23 + x^17 + x^3 + 1 - */ - -static const unsigned char parity_polynomial[PARITY_SIZE + 1] = { - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, - 1 -}; - -// remainder after dividing data polynomial by g(x) -static const unsigned char parity_remainder[PARITY_SIZE] = { - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1 -}; - - -/* -static void parity_encode(unsigned char *d, unsigned char *p) { - - int i; - unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q; - - memcpy(buf, d, DATA_BLOCK_SIZE); - memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE); - - for(q = buf; q < buf + DATA_BLOCK_SIZE; q++) - if(*q) - for(i = 0; i < PARITY_SIZE + 1; i++) - q[i] ^= parity_polynomial[i]; - for(i = 0; i < PARITY_SIZE; i++) - p[i] = !buf[DATA_BLOCK_SIZE + i]; -} - */ - - -static int parity_check(unsigned char *d) { - - unsigned int i; - unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q; - - memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE); - - for(q = buf; q < buf + DATA_BLOCK_SIZE; q++) - if(*q) - for(i = 0; i < PARITY_SIZE + 1; i++) - q[i] ^= parity_polynomial[i]; - return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE); -} - - -/* - * Convolutional encoding and Viterbi decoding for the GSM SACCH channel. - */ - -/* - * Convolutional encoding: - * - * G_0 = 1 + x^3 + x^4 - * G_1 = 1 + x + x^3 + x^4 - * - * i.e., - * - * c_{2k} = u_k + u_{k - 3} + u_{k - 4} - * c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4} - */ -#define K 5 -#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1) - - -/* - * Given the current state and input bit, what are the output bits? - * - * encode[current_state][input_bit] - */ -static const unsigned int encode[1 << (K - 1)][2] = { - {0, 3}, {3, 0}, {3, 0}, {0, 3}, - {0, 3}, {3, 0}, {3, 0}, {0, 3}, - {1, 2}, {2, 1}, {2, 1}, {1, 2}, - {1, 2}, {2, 1}, {2, 1}, {1, 2} -}; - - -/* - * Given the current state and input bit, what is the next state? - * - * next_state[current_state][input_bit] - */ -static const unsigned int next_state[1 << (K - 1)][2] = { - {0, 8}, {0, 8}, {1, 9}, {1, 9}, - {2, 10}, {2, 10}, {3, 11}, {3, 11}, - {4, 12}, {4, 12}, {5, 13}, {5, 13}, - {6, 14}, {6, 14}, {7, 15}, {7, 15} -}; - - -/* - * Given the previous state and the current state, what input bit caused - * the transition? If it is impossible to transition between the two - * states, the value is 2. - * - * prev_next_state[previous_state][current_state] - */ -static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = { - { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2}, - { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2}, - { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2}, - { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2}, - { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2}, - { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2}, - { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2}, - { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2}, - { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2}, - { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2}, - { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2}, - { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2}, - { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2}, - { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2}, - { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}, - { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1} -}; - - -static inline unsigned int hamming_distance2(unsigned int w) { - - return (w & 1) + !!(w & 2); -} - - -/* -static void conv_encode(unsigned char *data, unsigned char *output) { - - unsigned int i, state = 0, o; - - // encode data - for(i = 0; i < CONV_INPUT_SIZE; i++) { - o = encode[state][data[i]]; - state = next_state[state][data[i]]; - *output++ = !!(o & 2); - *output++ = o & 1; - } -} - */ - - -static int conv_decode(unsigned char *output, unsigned char *data) { - - int i, t; - unsigned int rdata, state, nstate, b, o, distance, accumulated_error, - min_state, min_error, cur_state; - - unsigned int ae[1 << (K - 1)]; - unsigned int nae[1 << (K - 1)]; // next accumulated error - unsigned int state_history[1 << (K - 1)][CONV_INPUT_SIZE + 1]; - - // initialize accumulated error, assume starting state is 0 - for(i = 0; i < (1 << (K - 1)); i++) - ae[i] = nae[i] = MAX_ERROR; - ae[0] = 0; - - // build trellis - for(t = 0; t < CONV_INPUT_SIZE; t++) { - - // get received data symbol - rdata = (data[2 * t] << 1) | data[2 * t + 1]; - - // for each state - for(state = 0; state < (1 << (K - 1)); state++) { - - // make sure this state is possible - if(ae[state] >= MAX_ERROR) - continue; - - // find all states we lead to - for(b = 0; b < 2; b++) { - - // get next state given input bit b - nstate = next_state[state][b]; - - // find output for this transition - o = encode[state][b]; - - // calculate distance from received data - distance = hamming_distance2(rdata ^ o); - - // choose surviving path - accumulated_error = ae[state] + distance; - if(accumulated_error < nae[nstate]) { - - // save error for surviving state - nae[nstate] = accumulated_error; - - // update state history - state_history[nstate][t + 1] = state; - } - } - } - - // get accumulated error ready for next time slice - for(i = 0; i < (1 << (K - 1)); i++) { - ae[i] = nae[i]; - nae[i] = MAX_ERROR; - } - } - - // the final state is the state with the fewest errors - min_state = (unsigned int)-1; - min_error = MAX_ERROR; - for(i = 0; i < (1 << (K - 1)); i++) { - if(ae[i] < min_error) { - min_state = i; - min_error = ae[i]; - } - } - - // trace the path - cur_state = min_state; - for(t = CONV_INPUT_SIZE; t >= 1; t--) { - min_state = cur_state; - cur_state = state_history[cur_state][t]; // get previous - output[t - 1] = prev_next_state[cur_state][min_state]; - } - - // return the number of errors detected (hard-decision) - return min_error; -} - - -/* - * GSM SACCH interleaving and burst mapping - * - * Interleaving: - * - * Given 456 coded input bits, form 4 blocks of 114 bits: - * - * i(B, j) = c(n, k) k = 0, ..., 455 - * n = 0, ..., N, N + 1, ... - * B = B_0 + 4n + (k mod 4) - * j = 2(49k mod 57) + ((k mod 8) div 4) - * - * Mapping on Burst: - * - * e(B, j) = i(B, j) - * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56 - * e(B, 57) = h_l(B) - * e(B, 58) = h_n(B) - * - * Where h_l(B) and h_n(B) are bits in burst B indicating flags. - */ - -/* -static void interleave(unsigned char *data, unsigned char *iBLOCK) { - - int j, k, B; - - // for each bit in input data - for(k = 0; k < CONV_SIZE; k++) { - B = k % 4; - j = 2 * ((49 * k) % 57) + ((k % 8) / 4); - iBLOCK[B * iBLOCK_SIZE + j] = data[k]; - } -} - */ - - -#if 0 -static void decode_interleave(unsigned char *data, unsigned char *iBLOCK) { - - int j, k, B; - - for(k = 0; k < CONV_SIZE; k++) { - B = k % 4; - j = 2 * ((49 * k) % 57) + ((k % 8) / 4); - data[k] = iBLOCK[B * iBLOCK_SIZE + j]; - } -} - -#endif - -/* -static void burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK, - unsigned char hl, unsigned char hn) { - - int j; - - for(j = 0; j < 57; j++) { - eBLOCK[j] = iBLOCK[j]; - eBLOCK[j + 59] = iBLOCK[j + 57]; - } - eBLOCK[57] = hl; - eBLOCK[58] = hn; -} - */ - - -static void decode_burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK, - unsigned char *hl, unsigned char *hn) { - - int j; - - for(j = 0; j < 57; j++) { - iBLOCK[j] = eBLOCK[j]; - iBLOCK[j + 57] = eBLOCK[j + 59]; - } - *hl = eBLOCK[57]; - *hn = eBLOCK[58]; -} - - -/* - * Transmitted bits are sent least-significant first. - */ -static int compress_bits(unsigned char *dbuf, unsigned int dbuf_len, - unsigned char *sbuf, unsigned int sbuf_len) { - - unsigned int i, j, c, pos = 0; - - if(dbuf_len < ((sbuf_len + 7) >> 3)) - return -1; - - for(i = 0; i < sbuf_len; i += 8) { - for(j = 0, c = 0; (j < 8) && (i + j < sbuf_len); j++) - c |= (!!sbuf[i + j]) << j; - dbuf[pos++] = c & 0xff; - } - return pos; -} - - -#if 0 -int get_ns_l3_len(unsigned char *data, unsigned int datalen) { - - if((data[0] & 3) != 1) { - fprintf(stderr, "error: get_ns_l3_len: pseudo-length reserved " - "bits bad (%2.2x)\n", data[0] & 3); - return -1; - } - return (data[0] >> 2); -} - -#endif - - -static unsigned char *decode_sacch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen) { - - int errors, len, data_size; - unsigned char conv_data[CONV_SIZE], iBLOCK[BLOCKS][iBLOCK_SIZE], - hl, hn, decoded_data[PARITY_OUTPUT_SIZE]; - FC_CTX fc_ctx; - - data_size = sizeof ctx->msg; - if(datalen) - *datalen = 0; - - // unmap the bursts - decode_burstmap(iBLOCK[0], burst, &hl, &hn); // XXX ignore stealing bits - decode_burstmap(iBLOCK[1], burst + 116, &hl, &hn); - decode_burstmap(iBLOCK[2], burst + 116 * 2, &hl, &hn); - decode_burstmap(iBLOCK[3], burst + 116 * 3, &hl, &hn); - - // remove interleave - interleave_decode(&ctx->interleave_ctx, conv_data, (unsigned char *)iBLOCK); - //decode_interleave(conv_data, (unsigned char *)iBLOCK); - - // Viterbi decode - errors = conv_decode(decoded_data, conv_data); - //DEBUGF("conv_decode: %d\n", errors); - if (errors) - return NULL; - - // check parity - // If parity check error detected try to fix it. - if (parity_check(decoded_data)) - { - FC_init(&fc_ctx, 40, 184); - unsigned char crc_result[224]; - if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0) - { - errors = -1; - DEBUGF("error: sacch: parity error (%d)\n", errors); - return NULL; - } else { - DEBUGF("Successfully corrected parity bits!\n"); - memcpy(decoded_data, crc_result, sizeof crc_result); - errors = 0; - } - } - - if((len = compress_bits(ctx->msg, data_size, decoded_data, - DATA_BLOCK_SIZE)) < 0) { - fprintf(stderr, "error: compress_bits\n"); - return NULL; - } - if(len < data_size) { - fprintf(stderr, "error: buf too small (%d < %d)\n", - sizeof(ctx->msg), len); - return NULL; - } - - if(datalen) - *datalen = (unsigned int)len; - return ctx->msg; -} - - -/* - * decode_cch - * - * Decode a "common" control channel. Most control channels use - * the same burst, interleave, Viterbi and parity configuration. - * The documentation for the control channels defines SACCH first - * and then just keeps referring to that. - * - * The current (investigated) list is as follows: - * - * BCCH Norm - * BCCH Ext - * PCH - * AGCH - * CBCH (SDCCH/4) - * CBCH (SDCCH/8) - * SDCCH/4 - * SACCH/C4 - * SDCCH/8 - * SACCH/C8 - * - * We provide two functions, one for where all four bursts are - * contiguous, and one where they aren't. - */ -unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen) { - - return decode_sacch(ctx, burst, datalen); -} - - -#if 0 -unsigned char *decode_cch(GS_CTX *ctx, unsigned char *e, unsigned int *datalen) { - - return decode_sacch(ctx, e, e + eBLOCK_SIZE, e + 2 * eBLOCK_SIZE, - e + 3 * eBLOCK_SIZE, datalen); -} -#endif diff --git a/src/lib/decoder/cch.h b/src/lib/decoder/cch.h deleted file mode 100644 index a642721..0000000 --- a/src/lib/decoder/cch.h +++ /dev/null @@ -1,56 +0,0 @@ -//TODO: this file shouldn't be part of the GSM Receiver -#ifndef __GSMSTACK_CCH_H__ -#define __GSMSTACK_CCH_H__ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gsmstack.h" - -/* - * decode_cch - * - * Decode a "common" control channel. Most control channels use - * the same burst, interleave, Viterbi and parity configuration. - * The documentation for the control channels defines SACCH first - * and then just keeps referring to that. - * - * The current (investigated) list is as follows: - * - * BCCH Norm - * BCCH Ext - * PCH - * AGCH - * CBCH (SDCCH/4) - * CBCH (SDCCH/8) - * SDCCH/4 - * SACCH/C4 - * SDCCH/8 - * SACCH/C8 - * - * We provide two functions, one for where all four bursts are - * contiguous, and one where they aren't. - */ - -#define DATA_BLOCK_SIZE 184 -#define PARITY_SIZE 40 -#define FLUSH_BITS_SIZE 4 -#define PARITY_OUTPUT_SIZE (DATA_BLOCK_SIZE + PARITY_SIZE + FLUSH_BITS_SIZE) - -#define CONV_INPUT_SIZE PARITY_OUTPUT_SIZE -#define CONV_SIZE (2 * CONV_INPUT_SIZE) - -#define BLOCKS 4 -#define iBLOCK_SIZE (CONV_SIZE / BLOCKS) -#define eBLOCK_SIZE (iBLOCK_SIZE + 2) - -unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *len); -//unsigned char *decode_cch(GS_CTX *ctx, unsigned char *, unsigned char *, unsigned char *, unsigned char *, unsigned int *len); -//unsigned char *decode_cch(GS_CTX *ctx, unsigned char *, unsigned int *); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/lib/decoder/fire_crc.c b/src/lib/decoder/fire_crc.c deleted file mode 100644 index 7cdfc0b..0000000 --- a/src/lib/decoder/fire_crc.c +++ /dev/null @@ -1,179 +0,0 @@ -//TODO: this file shouldn't be part of the GSM Receiver -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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 2, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "fire_crc.h" -#include -#include - -#define REM(x, y) (x) % (y) - -static int FC_syndrome_shift(FC_CTX *ctx, unsigned int bit); - -static int -outit(int *data, int len) -{ - int i; - - for (i = 0; i < len; i++) - printf("%d ", data[i]); - printf("\n"); -} - -int -FC_init(FC_CTX *ctx, unsigned int crc_size, unsigned int data_size) -{ - ctx->crc_size = crc_size; - ctx->data_size = data_size; - ctx->syn_start = 0; - - return 0; -} - -int -FC_check_crc(FC_CTX *ctx, unsigned char *input_bits, unsigned char *control_data) -{ - int j,error_count = 0, error_index = 0, success_flag = 0, syn_index = 0; - unsigned int i; - - ctx->syn_start = 0; - // reset the syndrome register - memset(ctx->syndrome_reg, 0, sizeof ctx->syndrome_reg); - - // shift in the data bits - for (i=0; i < ctx->data_size; i++) { - error_count = FC_syndrome_shift(ctx, input_bits[i]); - control_data[i] = input_bits[i]; - } - - // shift in the crc bits - for (i=0; i < ctx->crc_size; i++) { - error_count = FC_syndrome_shift(ctx, 1-input_bits[i+ctx->data_size]); - } - - // Find position of error burst - if (error_count == 0) { - error_index = 0; - } - else { - error_index = 1; - error_count = FC_syndrome_shift(ctx, 0); - error_index += 1; - while (error_index < (ctx->data_size + ctx->crc_size) ) { - error_count = FC_syndrome_shift(ctx, 0); - error_index += 1; - if ( error_count == 0 ) break; - } - } - - // Test for correctable errors - //printf("error_index %d\n",error_index); - if (error_index == 224) success_flag = 0; - else { - - // correct index depending on the position of the error - if (error_index == 0) syn_index = error_index; - else syn_index = error_index - 1; - - // error burst lies within data bits - if (error_index < 184) { - //printf("error < bit 184,%d\n",error_index); - j = error_index; - while ( j < (error_index+12) ) { - if (j < 184) { - control_data[j] = control_data[j] ^ - ctx->syndrome_reg[REM(ctx->syn_start+39-j+syn_index,40)]; - } - else break; - j = j + 1; - } - } - else if ( error_index > 212 ) { - //printf("error > bit 212,%d\n",error_index); - j = 0; - while ( j < (error_index - 212) ) { - control_data[j] = control_data[j] ^ - ctx->syndrome_reg[REM(ctx->syn_start+39-j-224+syn_index,40)]; - j = j + 1; - } - } - // for 183 < error_index < 213 error in parity alone so ignore - success_flag = 1; - } - return success_flag; -} - -static int -FC_syndrome_shift(FC_CTX *ctx, unsigned int bit) -{ - int error_count = 0; - unsigned int i; - - if (ctx->syn_start == 0) - ctx->syn_start = 39; - else ctx->syn_start -= 1; - - int temp_syndrome_reg[sizeof ctx->syndrome_reg]; - - memcpy(temp_syndrome_reg, ctx->syndrome_reg, sizeof temp_syndrome_reg); - - temp_syndrome_reg[REM(ctx->syn_start+3,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+3,40)] ^ - ctx->syndrome_reg[ctx->syn_start]; - temp_syndrome_reg[REM(ctx->syn_start+17,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+17,40)] ^ - ctx->syndrome_reg[ctx->syn_start]; - temp_syndrome_reg[REM(ctx->syn_start+23,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+23,40)] ^ - ctx->syndrome_reg[ctx->syn_start]; - temp_syndrome_reg[REM(ctx->syn_start+26,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+26,40)] ^ - ctx->syndrome_reg[ctx->syn_start]; - - temp_syndrome_reg[REM(ctx->syn_start+4,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+4,40)] ^ bit; - temp_syndrome_reg[REM(ctx->syn_start+6,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+6,40)] ^ bit; - temp_syndrome_reg[REM(ctx->syn_start+10,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+10,40)] ^ bit; - temp_syndrome_reg[REM(ctx->syn_start+16,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+16,40)] ^ bit; - temp_syndrome_reg[REM(ctx->syn_start+27,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+27,40)] ^ bit; - temp_syndrome_reg[REM(ctx->syn_start+29,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+29,40)] ^ bit; - temp_syndrome_reg[REM(ctx->syn_start+33,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+33,40)] ^ bit; - temp_syndrome_reg[REM(ctx->syn_start+39,40)] = - ctx->syndrome_reg[REM(ctx->syn_start+39,40)] ^ bit; - - temp_syndrome_reg[ctx->syn_start] = ctx->syndrome_reg[ctx->syn_start] ^ bit; - - memcpy(ctx->syndrome_reg, temp_syndrome_reg, sizeof ctx->syndrome_reg); - - for (i = 0; i < 28; i++) { - error_count = error_count + ctx->syndrome_reg[REM(ctx->syn_start+i,40)]; - } - return error_count; -} - - diff --git a/src/lib/decoder/fire_crc.h b/src/lib/decoder/fire_crc.h deleted file mode 100644 index aa6319c..0000000 --- a/src/lib/decoder/fire_crc.h +++ /dev/null @@ -1,47 +0,0 @@ -//TODO: this file shouldn't be part of the GSM Receiver -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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 2, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef INCLUDED_FIRE_CRC_H -#define INCLUDED_FIRE_CRC_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - unsigned int crc_size; - unsigned int data_size; - unsigned int syn_start; - int syndrome_reg[40]; -} FC_CTX; - -int FC_init(FC_CTX *ctx, unsigned int crc_size, unsigned int data_size); -int FC_check_crc(FC_CTX *ctx, unsigned char *input_bits, unsigned char *control_data); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/lib/decoder/gsmstack.c b/src/lib/decoder/gsmstack.c deleted file mode 100644 index c3f1921..0000000 --- a/src/lib/decoder/gsmstack.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Invoke gsmstack() with any kind of burst. Automaticly decode and retrieve - * information. - */ -#include "system.h" -#include -#include -#include -#include -#include "gsmstack.h" -//#include "gsm_constants.h" -#include "interleave.h" -//#include "sch.h" -#include "cch.h" - -static const int USEFUL_BITS = 142; - -//#include "out_pcap.h" -enum BURST_TYPE { - UNKNOWN, - FCCH, - PARTIAL_SCH, //successful correlation, but missing data ^ - SCH, - CTS_SCH, - COMPACT_SCH, - NORMAL, - DUMMY, - ACCESS -}; -static void out_gsmdecode(char type, int arfcn, int ts, int fn, char *data, int len); - -/* encode a decoded burst (1 bit per byte) into 8-bit-per-byte */ -static void burst_octify(unsigned char *dest, - const unsigned char *data, int length) -{ - int bitpos = 0; - - while (bitpos < USEFUL_BITS) { - unsigned char tbyte; - int i; - - tbyte = 0; - for (i = 0; (i < 8) && (bitpos < length); i++) { - tbyte <<= 1; - tbyte |= data[bitpos++]; - } - if (i < 8) - tbyte <<= 8 - i; - *dest++ = tbyte; - } -} - - -#if 0 -static void -diff_decode(char *dst, char *src, int len) -{ - const char *end = src + len; - unsigned char last; - - src += 3; - last = 0; - memset(dst, 0, 3); - dst += 3; - - while (src < end) - { - *dst = !*src ^ last; - last = *dst; - src++; - dst++; - } -} -#endif - -/* - * Initialize a new GSMSTACK context. - */ -int -GS_new(GS_CTX *ctx) -{ - memset(ctx, 0, sizeof *ctx); - interleave_init(&ctx->interleave_ctx, 456, 114); - ctx->fn = -1; - ctx->bsic = -1; - - ctx->tun_fd = mktun("gsm", ctx->ether_addr); - if (ctx->tun_fd < 0) - fprintf(stderr, "cannot open 'gsm' tun device, did you create it?\n"); - - ctx->pcap_fd = open_pcap_file("gsm-receiver.pcap"); - if (ctx->pcap_fd < 0) - fprintf(stderr, "cannot open PCAP file: %s\n", strerror(errno)); - - ctx->burst_pcap_fd = open_pcap_file("gsm-receiver-burst.pcap"); - if (ctx->burst_pcap_fd < 0) - fprintf(stderr, "cannot open burst PCAP file: %s\n", strerror(errno)); - - return 0; -} - -#define BURST_BYTES ((USEFUL_BITS/8)+1) -/* - * 142 bit - */ -int -GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src, int fn) -{ -// int fn; - int bsic; - int ret; - unsigned char *data; - int len; - struct gs_ts_ctx *ts_ctx = &ctx->ts_ctx[ts]; - unsigned char octified[BURST_BYTES]; - - memset(ctx->msg, 0, sizeof(ctx->msg)); - - /* write burst to burst PCAP file */ - burst_octify(octified, src, USEFUL_BITS); - write_pcap_packet(ctx->burst_pcap_fd, 0 /* arfcn */, ts, ctx->fn, - 1, type, octified, BURST_BYTES); - -#if 0 - if (ts != 0) { - /* non-0 timeslots should end up in PCAP */ - data = decode_cch(ctx, ctx->burst, &len); - if (data == NULL) - return -1; -// write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn, data, len); - return; - } -#endif - -/* if (ts == 0) { - if (type == SCH) { -// ret = decode_sch(src, &fn, &bsic); - if (ret != 0) - return 0; - if ((ctx->bsic > 0) && (bsic != ctx->bsic)) - fprintf(stderr, "WARN: BSIC changed.\n"); - //DEBUGF("FN %d, BSIC %d\n", fn, bsic); - ctx->fn = fn; - ctx->bsic = bsic; - /* Reset message concatenator */ -// ts_ctx->burst_count = 0; -// return 0; -// } - - /* If we did not get Frame Number yet then return */ -// if (ctx->fn < 0) -// return 0; - -// ctx->fn++; -// } - ctx->fn = fn; - if (type == NORMAL) { - /* Interested in these frame numbers (cch) - * 2-5, 12-15, 22-25, 23-35, 42-45 - * 6-9, 16-19, 26-29, 36-39, 46-49 - */ - /* Copy content data into new array */ - //DEBUGF("burst count %d\n", ctx->burst_count); - memcpy(ts_ctx->burst + (116 * ts_ctx->burst_count), src, 58); - memcpy(ts_ctx->burst + (116 * ts_ctx->burst_count) + 58, src + 58 + 26, 58); - ts_ctx->burst_count++; - /* Return if not enough bursts for a full gsm message */ - if (ts_ctx->burst_count < 4) - return 0; - - ts_ctx->burst_count = 0; - data = decode_cch(ctx, ts_ctx->burst, &len); - if (data == NULL) { - DEBUGF("cannot decode fnr=0x%08x ts=%d\n", ctx->fn, ts); - return -1; - } - //DEBUGF("OK TS %d, len %d\n", ts, len); - - out_gsmdecode(0, 0, ts, ctx->fn - 4, data, len); - write_interface(ctx->tun_fd, data+1, len-1, ctx->ether_addr); - write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn, - 0, NORMAL, data, len); -#if 0 - if (ctx->fn % 51 != 0) && ( (((ctx->fn % 51 + 5) % 10 == 0) || (((ctx->fn % 51) + 1) % 10 ==0) ) ) - ready = 1; -#endif - - return 0; - } -} - - -/* - * Output data so that it can be parsed from gsmdeocde. - */ -static void -out_gsmdecode(char type, int arfcn, int ts, int fn, char *data, int len) -{ - char *end = data + len; - - /* FIXME: speed this up by first printing into an array */ - while (data < end) - printf(" %02.2x", (unsigned char)*data++); - printf("\n"); - fflush(stdout); -} diff --git a/src/lib/decoder/gsmstack.h b/src/lib/decoder/gsmstack.h deleted file mode 100644 index 9355785..0000000 --- a/src/lib/decoder/gsmstack.h +++ /dev/null @@ -1,43 +0,0 @@ -//TODO: this file shouldn't be part of the GSM Receiver -#ifndef __GSMSTACK_H__ -#define __GSMSTACK_H__ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "interleave.h" - -struct gs_ts_ctx { - /* FIXME: later do this per each ts per each arfcn */ - unsigned char burst[4 * 58 * 2]; - int burst_count; -}; - -typedef struct -{ - int flags; - int fn; - int bsic; - char msg[23]; /* last decoded message */ - - INTERLEAVE_CTX interleave_ctx; - - struct gs_ts_ctx ts_ctx[8]; - - int tun_fd; - unsigned char ether_addr[ETH_ALEN]; - - int pcap_fd; - int burst_pcap_fd; -} GS_CTX; - -int GS_new(GS_CTX *ctx); -int GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src, int fn); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/lib/decoder/gsmtap.h b/src/lib/decoder/gsmtap.h deleted file mode 100644 index 1022194..0000000 --- a/src/lib/decoder/gsmtap.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _GSMTAP_H -#define _GSMTAP_H - -/* gsmtap header, pseudo-header in front of the actua GSM payload*/ - -#include - -#define GSMTAP_VERSION 0x01 - -#define GSMTAP_TYPE_UM 0x01 -#define GSMTAP_TYPE_ABIS 0x02 -#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */ - -#define GSMTAP_BURST_UNKNOWN 0x00 -#define GSMTAP_BURST_FCCH 0x01 -#define GSMTAP_BURST_PARTIAL_SCH 0x02 -#define GSMTAP_BURST_SCH 0x03 -#define GSMTAP_BURST_CTS_SCH 0x04 -#define GSMTAP_BURST_COMPACT_SCH 0x05 -#define GSMTAP_BURST_NORMAL 0x06 -#define GSMTAP_BURST_DUMMY 0x07 -#define GSMTAP_BURST_ACCESS 0x08 - -struct gsmtap_hdr { - u_int8_t version; /* version, set to 0x01 currently */ - u_int8_t hdr_len; /* length in number of 32bit words */ - u_int8_t type; /* see GSMTAP_TYPE_* */ - u_int8_t timeslot; /* timeslot (0..7 on Um) */ - - u_int16_t arfcn; /* ARFCN (frequency) */ - u_int8_t noise_db; /* noise figure in dB */ - u_int8_t signal_db; /* signal level in dB */ - - u_int32_t frame_number; /* GSM Frame Number (FN) */ - - u_int8_t burst_type; /* Type of burst, see above */ - u_int8_t antenna_nr; /* Antenna Number */ - u_int16_t res; /* reserved for future use (RFU) */ - -} __attribute__((packed)); -#endif /* _GSMTAP_H */ diff --git a/src/lib/decoder/interleave.c b/src/lib/decoder/interleave.c deleted file mode 100644 index 7b45927..0000000 --- a/src/lib/decoder/interleave.c +++ /dev/null @@ -1,47 +0,0 @@ -//TODO: this file shouldn't be part of the GSM Receiver -#include -#include -#include "interleave.h" - -int -interleave_init(INTERLEAVE_CTX *ictx, int size, int block_size) -{ - ictx->trans_size = size; - ictx->trans = (unsigned short *)malloc(size * sizeof *ictx->trans); - -// DEBUGF("size: %d\n", size); -// DEBUGF("Block size: %d\n", block_size); - int j, k, B; - for (k = 0; k < size; k++) - { - B = k % 4; - j = 2 * ((49 * k) % 57) + ((k % 8) / 4); - ictx->trans[k] = B * block_size + j; - /* Mapping: pos1 goes to pos2: pos1 -> pos2 */ -// DEBUGF("%d -> %d\n", ictx->trans[k], k); - } -// exit(0); - return 0; -} - -int -interleave_deinit(INTERLEAVE_CTX *ictx) -{ - if (ictx->trans != NULL) - { - free(ictx->trans); - ictx->trans = NULL; - } - - return 0; -} - -void -interleave_decode(INTERLEAVE_CTX *ictx, unsigned char *dst, unsigned char *src) -{ - - int k; - for (k = 0; k < ictx->trans_size; k++) - dst[k] = src[ictx->trans[k]]; -} - diff --git a/src/lib/decoder/interleave.h b/src/lib/decoder/interleave.h deleted file mode 100644 index fa1912f..0000000 --- a/src/lib/decoder/interleave.h +++ /dev/null @@ -1,19 +0,0 @@ -//TODO: this file shouldn't be part of the GSM Receiver -/* - * $Id:$ - */ - -#ifndef __GSMSP_INTERLEAVE_H__ -#define __GSMSP_INTERLEAVE_H__ 1 - -typedef struct _interleave_ctx -{ - unsigned short *trans; - int trans_size; -} INTERLEAVE_CTX; - -int interleave_init(INTERLEAVE_CTX *ictx, int size, int block_size); -int interleave_deinit(INTERLEAVE_CTX *ictx); -void interleave_decode(INTERLEAVE_CTX *ictx, unsigned char *dst, unsigned char *src); - -#endif diff --git a/src/lib/decoder/openbtsstuff/AUTHORS b/src/lib/decoder/openbtsstuff/AUTHORS deleted file mode 100644 index 8075492..0000000 --- a/src/lib/decoder/openbtsstuff/AUTHORS +++ /dev/null @@ -1,173 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# - -David A. Burgess, dburgess@kestrelsp.com: - CommonLibs/Assert.h - CommonLibs/BitVector.cpp - CommonLibs/BitVectorTest.cpp - CommonLibs/Interthread.h - CommonLibs/InterthreadTest.cpp - CommonLibs/LinkedLists.cpp - CommonLibs/LinkedLists.h - CommonLibs/Sockets.cpp - CommonLibs/Sockets.h - CommonLibs/SocketsTest.cpp - CommonLibs/Threads.cpp - CommonLibs/Threads.h - CommonLibs/Timeval.cpp - CommonLibs/Timeval.h - CommonLibs/TimevalTest.cpp - CommonLibs/Vector.h - CommonLibs/VectorTest.cpp - Control/CallControl.cpp - Control/ControlCommon.cpp - Control/ControlCommon.h - Control/FACCHDispatch.cpp - Control/MobilityManagement.cpp - Control/PagerTest.cpp - Control/RadioResource.cpp - Control/SDCCHDispatch.cpp - GSM/GSM610Tables.cpp - GSM/GSM610Tables.h - GSM/GSMCommon.cpp - GSM/GSMCommon.h - GSM/GSMConfig.h - GSM/GSML1FEC.cpp - GSM/GSML1FEC.h - GSM/GSML2LAPDm.cpp - GSM/GSML2LAPDm.h - GSM/GSML3CCElements.cpp - GSM/GSML3CCElements.h - GSM/GSML3CCMessages.cpp - GSM/GSML3CCMessages.h - GSM/GSML3CommonElements.cpp - GSM/GSML3CommonElements.h - GSM/GSML3MMElements.cpp - GSM/GSML3MMElements.h - GSM/GSML3MMMessages.cpp - GSM/GSML3MMMessages.h - GSM/GSML3Message.cpp - GSM/GSML3Message.h - GSM/GSML3RRElements.cpp - GSM/GSML3RRElements.h - GSM/GSML3RRMessages.cpp - GSM/GSML3RRMessages.h - GSM/GSMLogicalChannel.h - GSM/GSMTDMA.cpp - GSM/GSMTDMA.h - GSM/GSMTransfer.cpp - GSM/GSMTransfer.h - LICENSEBLOCK - SIP/SIPEngine.h - SIP/SIPInterface.h - TRXManager/TRXManager.cpp - Transceiver/Complex.h - apps/OpenBTS900.cpp - tests/AGCHTest.cpp - tests/BeaconTest.cpp - tests/CallTest.cpp - tests/CallTest2.cpp - tests/LAPDmTest.cpp - tests/LoopbackTest.cpp - tests/RegistrationTest.cpp - tests/TRXSimulator.cpp - -Harvind S. Samra, hssamra@kestrelsp.com: - Control/PagerTest.cpp - Control/RadioResource.cpp - GSM/GSMConfig.h - GSM/GSMTransfer.h - LICENSEBLOCK - Transceiver/ComplexTest.cpp - Transceiver/Transceiver.cpp - Transceiver/Transceiver.h - Transceiver/USRPDevice.cpp - Transceiver/USRPDevice.h - Transceiver/USRPping.cpp - Transceiver/radioInterface.cpp - Transceiver/radioInterface.h - Transceiver/rcvLPF_651.h - Transceiver/runTransceiver.cpp - Transceiver/sendLPF_961.h - Transceiver/sigProcLib.cpp - Transceiver/sigProcLib.h - Transceiver/sigProcLibTest.cpp - Transceiver/sweepGenerator.cpp - Transceiver/testRadio.cpp - -Raffi Sevlian, raffisev@gmail.com: - Control/CallControl.cpp - Control/ControlCommon.cpp - Control/ControlCommon.h - Control/FACCHDispatch.cpp - Control/MobilityManagement.cpp - Control/PagerTest.cpp - Control/RadioResource.cpp - GSM/GSMCommon.h - GSM/GSMConfig.h - GSM/GSML1FEC.h - GSM/GSML3CCElements.cpp - GSM/GSML3CCElements.h - GSM/GSML3CCMessages.cpp - GSM/GSML3CCMessages.h - GSM/GSML3CommonElements.cpp - GSM/GSML3CommonElements.h - GSM/GSML3MMElements.cpp - GSM/GSML3MMElements.h - GSM/GSML3MMMessages.cpp - GSM/GSML3MMMessages.h - GSM/GSML3Message.cpp - GSM/GSML3Message.h - GSM/GSML3RRElements.cpp - GSM/GSML3RRElements.h - GSM/GSML3RRMessages.cpp - GSM/GSML3RRMessages.h - GSM/GSMLogicalChannel.h - GSM/GSMSAPMux.cpp - GSM/GSMSAPMux.h - GSM/GSMTransfer.h - LICENSEBLOCK - SIP/SIPEngine.cpp - SIP/SIPInterface.cpp - SIP/SIPInterface.h - SIP/SIPMessage.cpp - SIP/SIPMessage.h - SIP/SIPUtility.cpp - SIP/SIPUtility.h - SMS/CMMessage.cpp - SMS/CMMessage.h - SMS/CMProcessor.cpp - SMS/CMProcessor.h - SMS/CMTest.cpp - SMS/RLMessage.cpp - SMS/RLMessage.h - SMS/RLProcessor.cpp - SMS/RLProcessor.h - SMS/SMSMessages.cpp - SMS/SMSMessages.h - SMS/SMSProcessors.cpp - SMS/SMSProcessors.h - SMS/SMSTransfer.cpp - SMS/SMSTransfer.h - SMS/TLMessage.cpp - SMS/TLMessage.h - SMS/TLProcessor.cpp - SMS/TLProcessor.h - TRXManager/TRXManager.h diff --git a/src/lib/decoder/openbtsstuff/Assert.h b/src/lib/decoder/openbtsstuff/Assert.h deleted file mode 100644 index 00ad07d..0000000 --- a/src/lib/decoder/openbtsstuff/Assert.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 . - -*/ - - -#ifndef ASSERT_H -#define ASSERT_H - -#include "stdio.h" - -/** This is thrown by assert() so that gdb can catch it. */ -class Assertion { - - public: - - Assertion() - { - fprintf(stderr,"Try setting a breakpoint @ %s:%u.\n",__FILE__,__LINE__); - return; - } - -}; - -#ifdef NDEBUG -#define assert(EXPR) {}; -#else -/** This replaces the regular assert() with a C++ exception. */ -#include "stdio.h" -#define assert(E) { if (!(E)) { fprintf(stderr,"%s:%u failed assertion '%s'\n",__FILE__,__LINE__,#E); throw Assertion(); } } -#endif - -#endif diff --git a/src/lib/decoder/openbtsstuff/BitVector.cpp b/src/lib/decoder/openbtsstuff/BitVector.cpp deleted file mode 100644 index 89d8d19..0000000 --- a/src/lib/decoder/openbtsstuff/BitVector.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 "BitVector.h" -#include - -using namespace std; - - -/** - Apply a Galois polymonial to a binary seqeunce. - @param val The input sequence. - @param poly The polynomial. - @param order The order of the polynomial. - @return Single-bit result. -*/ -unsigned applyPoly(uint64_t val, uint64_t poly, unsigned order) -{ - uint64_t prod = val & poly; - unsigned sum = prod; - for (unsigned i=1; i>i; - return sum & 0x01; -} - - - - - - -BitVector::BitVector(const char *valString) - :Vector(strlen(valString)) -{ - uint32_t accum = 0; - for (size_t i=0; i=dpBase) { - *dp-- = value & 0x01; - value >>= 1; - } -} - -void BitVector::writeField(size_t& writeIndex, uint64_t value, unsigned length) -{ - fillField(writeIndex,value,length); - writeIndex += length; -} - - -void BitVector::invert() -{ - for (size_t i=0; i=8); - - char tmp0 = mStart[0]; - mStart[0] = mStart[7]; - mStart[7] = tmp0; - - char tmp1 = mStart[1]; - mStart[1] = mStart[6]; - mStart[6] = tmp1; - - char tmp2 = mStart[2]; - mStart[2] = mStart[5]; - mStart[5] = tmp2; - - char tmp3 = mStart[3]; - mStart[3] = mStart[4]; - mStart[4] = tmp3; -} - - - -void BitVector::LSB8MSB() -{ - size_t size8 = 8*(size()/8); - size_t iTop = size8 - 8; - for (size_t i=0; i<=iTop; i+=8) segment(i,8).reverse8(); -} - - - -uint64_t BitVector::syndrome(Generator& gen) const -{ - gen.clear(); - const char *dp = mStart; - while (dpiState) << 1; // input state for 0 - const uint32_t iState1 = iState0 | 0x01; // input state for 1 - const uint32_t oStateShifted = (sp->oState) << mIRate; // shifted output - const float cost = sp->cost; - sp++; - // 0 input extension - mCandidates[i].cost = cost; - mCandidates[i].oState = oStateShifted | mGeneratorTable[iState0 & mCMask]; - mCandidates[i].iState = iState0; - // 1 input extension - mCandidates[i+1].cost = cost; - mCandidates[i+1].oState = oStateShifted | mGeneratorTable[iState1 & mCMask]; - mCandidates[i+1].iState = iState1; - } -} - - -void ViterbiR2O4::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) -{ - const float *cTab[2] = {matchCost,mismatchCost}; - for (unsigned i=0; i>1)&0x01][0]; - } -} - - -void ViterbiR2O4::pruneCandidates() -{ - const vCand* c1 = mCandidates; // 0-prefix - const vCand* c2 = mCandidates + mIStates; // 1-prefix - for (unsigned i=0; i=minCost) continue; - minCost = thisCost; - minIndex=i; - } - return mSurvivors[minIndex]; -} - - -const ViterbiR2O4::vCand& ViterbiR2O4::step(uint32_t inSample, const float *probs, const float *iprobs) -{ - branchCandidates(); - getSoftCostMetrics(inSample,probs,iprobs); - pruneCandidates(); - return minCost(); -} - - -uint64_t Parity::syndrome(const BitVector& receivedCodeword) -{ - return receivedCodeword.syndrome(*this); -} - - -void Parity::writeParityWord(const BitVector& data, BitVector& parityTarget, bool invert) -{ - uint64_t pWord = data.parity(*this); - if (invert) pWord = ~pWord; - parityTarget.fillField(0,pWord,size()); -} - - - - - - - - - -SoftVector::SoftVector(const BitVector& source) -{ - resize(source.size()); - for (size_t i=0; i0.5F) newSig[i]=1; - else newSig[i] = 0; - } - return newSig; -} - - - -void SoftVector::decode(ViterbiR2O4 &decoder, BitVector& target) const -{ - const size_t sz = size(); - const unsigned deferral = decoder.deferral(); - const size_t ctsz = sz + deferral; - assert(sz <= decoder.iRate()*target.size()); - - // Build a "history" array where each element contains the full history. - uint32_t history[ctsz]; - { - BitVector bits = sliced(); - uint32_t accum = 0; - for (size_t i=0; i0.5F) pVal = 1.0F-pVal; - float ipVal = 1.0F-pVal; - // This is a cheap approximation to an ideal cost function. - if (pVal<0.01F) pVal = 0.01; - if (ipVal<0.01F) ipVal = 0.01; - matchCostTable[i] = 0.25F/ipVal; - mismatchCostTable[i] = 0.25F/pVal; - } - - // pad end of table with unknowns - for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral); - oCount++; - } - } -} - - - - -ostream& operator<<(ostream& os, const SoftVector& sv) -{ - for (size_t i=0; i0.75) os << "1"; - else os << "-"; - } - return os; -} - - - -void BitVector::pack(unsigned char* targ) const -{ - // Assumes MSB-first packing. - unsigned bytes = size()/8; - for (unsigned i=0; i. - -*/ - - -#ifndef FECVECTORS_H -#define FECVECTORS_H - -#include "Vector.h" -#include - - -class BitVector; -class SoftVector; - - - -/** Shift-register (LFSR) generator. */ -class Generator { - - private: - - uint64_t mCoeff; ///< polynomial coefficients. LSB is zero exponent. - uint64_t mState; ///< shift register state. LSB is most recent. - uint64_t mMask; ///< mask for reading state - unsigned mLen; ///< number of bits used in shift register - unsigned mLen_1; ///< mLen - 1 - - public: - - Generator(uint64_t wCoeff, unsigned wLen) - :mCoeff(wCoeff),mState(0), - mMask((1ULL<>(mLen_1)) & 0x01; - mState = (mState<<1) ^ (inBit & 0x01); - if (fb) mState ^= mCoeff; - } - - /** - Update the generator state by one cycle. - This is in the .h for inlining. - */ - void encoderShift(unsigned inBit) - { - const unsigned fb = ((mState>>(mLen_1)) ^ inBit) & 0x01; - mState <<= 1; - if (fb) mState ^= mCoeff; - } - - -}; - - - - -/** Parity (CRC-type) generator and checker based on a Generator. */ -class Parity : public Generator { - - protected: - - unsigned mCodewordSize; - - public: - - Parity(uint64_t wCoefficients, unsigned wParitySize, unsigned wCodewordSize) - :Generator(wCoefficients, wParitySize), - mCodewordSize(wCodewordSize) - { } - - /** Compute the parity word and write it into the target segment. */ - void writeParityWord(const BitVector& data, BitVector& parityWordTarget, bool invert=true); - - /** Compute the syndrome of a received sequence. */ - uint64_t syndrome(const BitVector& receivedCodeword); -}; - - - - -/** - Class to represent convolutional coders/decoders of rate 1/2, memory length 4. - This is the "workhorse" coder for most GSM channels. -*/ -class ViterbiR2O4 { - - private: - /**name Lots of precomputed elements so the compiler can optimize like hell. */ - //@{ - /**@name Core values. */ - //@{ - static const unsigned mIRate = 2; ///< reciprocal of rate - static const unsigned mOrder = 4; ///< memory length of generators - //@} - /**@name Derived values. */ - //@{ - static const unsigned mIStates = 0x01 << mOrder; ///< number of states, number of survivors - static const uint32_t mSMask = mIStates-1; ///< survivor mask - static const uint32_t mCMask = (mSMask<<1) | 0x01; ///< candidate mask - static const uint32_t mOMask = (0x01< { - - - public: - - /**@name Constructors. */ - //@{ - - /**@name Casts of Vector constructors. */ - //@{ - BitVector(char* wData, char* wStart, char* wEnd) - :Vector(wData,wStart,wEnd) - { } - BitVector(size_t len=0):Vector(len) {} - BitVector(const Vector& source):Vector(source) {} - BitVector(Vector& source):Vector(source) {} - BitVector(const Vector& source1, const Vector source2):Vector(source1,source2) {} - //@} - - /** Construct from a string of "0" and "1". */ - BitVector(const char* valString); - //@} - - /** Index a single bit. */ - bool bit(size_t index) const - { - // We put this code in .h for fast inlining. - const char *dp = mStart+index; - assert(dp::segment(start,span)); } - - BitVector head(size_t span) { return segment(0,span); } - const BitVector head(size_t span) const { return segment(0,span); } - BitVector tail(size_t start) { return segment(start,size()-start); } - const BitVector tail(size_t start) const { return segment(start,size()-start); } - //@} - - - void zero() { fill(0); } - - /**@name FEC operations. */ - //@{ - /** Calculate the syndrome of the vector with the given Generator. */ - uint64_t syndrome(Generator& gen) const; - /** Calculate the parity word for the vector with the given Generator. */ - uint64_t parity(Generator& gen) const; - /** Encode the signal with the GSM rate 1/2 convolutional encoder. */ - void encode(const ViterbiR2O4& encoder, BitVector& target); - //@} - - - /** Invert 0<->1. */ - void invert(); - - /**@name Byte-wise operations. */ - //@{ - /** Reverse an 8-bit vector. */ - void reverse8(); - /** Reverse groups of 8 within the vector (byte reversal). */ - void LSB8MSB(); - //@} - - /**@name Serialization and deserialization. */ - //@{ - uint64_t peekField(size_t readIndex, unsigned length) const; - uint64_t readField(size_t& readIndex, unsigned length) const; - void fillField(size_t writeIndex, uint64_t value, unsigned length); - void writeField(size_t& writeIndex, uint64_t value, unsigned length); - //@} - - /** Sum of bits. */ - unsigned sum() const; - - /** Reorder bits, dest[i] = this[map[i]]. */ - void map(const unsigned *map, size_t mapSize, BitVector& dest) const; - - /** Reorder bits, dest[map[i]] = this[i]. */ - void unmap(const unsigned *map, size_t mapSize, BitVector& dest) const; - - /** Pack into a char array. */ - void pack(unsigned char*) const; - - /** Unopack from a char array. */ - void unpack(const unsigned char*); - -}; - - - -std::ostream& operator<<(std::ostream&, const BitVector&); - - - - - - -/** - The SoftVector class is used to represent a soft-decision signal. - Values 0..1 represent probabilities that a bit is "true". - */ -class SoftVector: public Vector { - - public: - - /** Build a SoftVector of a given length. */ - SoftVector(size_t wSize=0):Vector(wSize) {} - - /** Construct a SoftVector from a C string of "0", "1", and "X". */ - SoftVector(const char* valString); - - /** Construct a SoftVector from a BitVector. */ - SoftVector(const BitVector& source); - - /** - Wrap a SoftVector around a block of floats. - The block will be delete[]ed upon desctuction. - */ - SoftVector(float *wData, unsigned length) - :Vector(wData,length) - {} - - SoftVector(float* wData, float* wStart, float* wEnd) - :Vector(wData,wStart,wEnd) - { } - - /** - Casting from a Vector. - Note that this is NOT pass-by-reference. - */ - SoftVector(Vector source) - :Vector(source) - {} - - - /**@name Casts and overrides of Vector operators. */ - //@{ - SoftVector segment(size_t start, size_t span) - { - float* wStart = mStart + start; - float* wEnd = wStart + span; - assert(wEnd<=mEnd); - return SoftVector(NULL,wStart,wEnd); - } - - SoftVector alias() - { return segment(0,size()); } - - const SoftVector segment(size_t start, size_t span) const - { return (SoftVector)(Vector::segment(start,span)); } - - SoftVector head(size_t span) { return segment(0,span); } - const SoftVector head(size_t span) const { return segment(0,span); } - SoftVector tail(size_t start) { return segment(start,size()-start); } - const SoftVector tail(size_t start) const { return segment(start,size()-start); } - //@} - - /** Decode soft symbols with the GSM rate-1/2 Viterbi decoder. */ - void decode(ViterbiR2O4 &decoder, BitVector& target) const; - - /** Fill with "unknown" values. */ - void unknown() { fill(0.5F); } - - /** Return a hard bit value from a given index by slicing. */ - bool bit(size_t index) const - { - const float *dp = mStart+index; - assert(dp0.5F; - } - - /** Slice the whole signal into bits. */ - BitVector sliced() const; - -}; - - - -std::ostream& operator<<(std::ostream&, const SoftVector&); - - - - - - -#endif -// vim: ts=4 sw=4 diff --git a/src/lib/decoder/openbtsstuff/GSM610Tables.cpp b/src/lib/decoder/openbtsstuff/GSM610Tables.cpp deleted file mode 100644 index 38f643f..0000000 --- a/src/lib/decoder/openbtsstuff/GSM610Tables.cpp +++ /dev/null @@ -1,492 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 "GSM610Tables.h" - - -/* -RFC 3551 RTP A/V Profile July 2003 - - - Octet Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 - _____________________________________________________________________ - 0 1 1 0 1 LARc0.0 LARc0.1 LARc0.2 LARc0.3 - 1 LARc0.4 LARc0.5 LARc1.0 LARc1.1 LARc1.2 LARc1.3 LARc1.4 LARc1.5 - 2 LARc2.0 LARc2.1 LARc2.2 LARc2.3 LARc2.4 LARc3.0 LARc3.1 LARc3.2 - 3 LARc3.3 LARc3.4 LARc4.0 LARc4.1 LARc4.2 LARc4.3 LARc5.0 LARc5.1 - 4 LARc5.2 LARc5.3 LARc6.0 LARc6.1 LARc6.2 LARc7.0 LARc7.1 LARc7.2 - 5 Nc0.0 Nc0.1 Nc0.2 Nc0.3 Nc0.4 Nc0.5 Nc0.6 bc0.0 - 6 bc0.1 Mc0.0 Mc0.1 xmaxc00 xmaxc01 xmaxc02 xmaxc03 xmaxc04 - 7 xmaxc05 xmc0.0 xmc0.1 xmc0.2 xmc1.0 xmc1.1 xmc1.2 xmc2.0 - 8 xmc2.1 xmc2.2 xmc3.0 xmc3.1 xmc3.2 xmc4.0 xmc4.1 xmc4.2 - 9 xmc5.0 xmc5.1 xmc5.2 xmc6.0 xmc6.1 xmc6.2 xmc7.0 xmc7.1 - 10 xmc7.2 xmc8.0 xmc8.1 xmc8.2 xmc9.0 xmc9.1 xmc9.2 xmc10.0 - 11 xmc10.1 xmc10.2 xmc11.0 xmc11.1 xmc11.2 xmc12.0 xmc12.1 xcm12.2 - 12 Nc1.0 Nc1.1 Nc1.2 Nc1.3 Nc1.4 Nc1.5 Nc1.6 bc1.0 - 13 bc1.1 Mc1.0 Mc1.1 xmaxc10 xmaxc11 xmaxc12 xmaxc13 xmaxc14 - 14 xmax15 xmc13.0 xmc13.1 xmc13.2 xmc14.0 xmc14.1 xmc14.2 xmc15.0 - 15 xmc15.1 xmc15.2 xmc16.0 xmc16.1 xmc16.2 xmc17.0 xmc17.1 xmc17.2 - 16 xmc18.0 xmc18.1 xmc18.2 xmc19.0 xmc19.1 xmc19.2 xmc20.0 xmc20.1 - 17 xmc20.2 xmc21.0 xmc21.1 xmc21.2 xmc22.0 xmc22.1 xmc22.2 xmc23.0 - 18 xmc23.1 xmc23.2 xmc24.0 xmc24.1 xmc24.2 xmc25.0 xmc25.1 xmc25.2 - 19 Nc2.0 Nc2.1 Nc2.2 Nc2.3 Nc2.4 Nc2.5 Nc2.6 bc2.0 - 20 bc2.1 Mc2.0 Mc2.1 xmaxc20 xmaxc21 xmaxc22 xmaxc23 xmaxc24 - 21 xmaxc25 xmc26.0 xmc26.1 xmc26.2 xmc27.0 xmc27.1 xmc27.2 xmc28.0 - 22 xmc28.1 xmc28.2 xmc29.0 xmc29.1 xmc29.2 xmc30.0 xmc30.1 xmc30.2 - 23 xmc31.0 xmc31.1 xmc31.2 xmc32.0 xmc32.1 xmc32.2 xmc33.0 xmc33.1 - 24 xmc33.2 xmc34.0 xmc34.1 xmc34.2 xmc35.0 xmc35.1 xmc35.2 xmc36.0 - 25 Xmc36.1 xmc36.2 xmc37.0 xmc37.1 xmc37.2 xmc38.0 xmc38.1 xmc38.2 - 26 Nc3.0 Nc3.1 Nc3.2 Nc3.3 Nc3.4 Nc3.5 Nc3.6 bc3.0 - 27 bc3.1 Mc3.0 Mc3.1 xmaxc30 xmaxc31 xmaxc32 xmaxc33 xmaxc34 - 28 xmaxc35 xmc39.0 xmc39.1 xmc39.2 xmc40.0 xmc40.1 xmc40.2 xmc41.0 - 29 xmc41.1 xmc41.2 xmc42.0 xmc42.1 xmc42.2 xmc43.0 xmc43.1 xmc43.2 - 30 xmc44.0 xmc44.1 xmc44.2 xmc45.0 xmc45.1 xmc45.2 xmc46.0 xmc46.1 - 31 xmc46.2 xmc47.0 xmc47.1 xmc47.2 xmc48.0 xmc48.1 xmc48.2 xmc49.0 - 32 xmc49.1 xmc49.2 xmc50.0 xmc50.1 xmc50.2 xmc51.0 xmc51.1 xmc51.2 - - Table 3: GSM payload format -*/ - - -/* - This file encodes a mapping between - GSM 05.03 Table 2 and RFC-3551 Table 3. -*/ - -/* - Naming convention: - xxx_p position (bit index) - xxx_l length (bit field length) - LAR log area ratio - N LTP lag - b LTP gain - M grid - Xmax block amplitude - x RPE pulses -*/ - - -/**@name Lengths of GSM 06.10 fields */ -//@{ -const unsigned int LAR1_l=6; ///< log area ratio -const unsigned int LAR2_l=6; ///< log area ratio -const unsigned int LAR3_l=5; ///< log area ratio -const unsigned int LAR4_l=5; ///< log area ratio -const unsigned int LAR5_l=4; ///< log area ratio -const unsigned int LAR6_l=4; ///< log area ratio -const unsigned int LAR7_l=3; ///< log area ratio -const unsigned int LAR8_l=3; ///< log area ratio -const unsigned int N_l=7; ///< LTP lag -const unsigned int b_l=2; ///< LTP gain -const unsigned int M_l=2; ///< grid position -const unsigned int Xmax_l=6; ///< block amplitude -const unsigned int x_l=3; ///< RPE pulses -//@} - - - -/*@name Indecies of GSM 06.10 fields as they appear in RFC-3551 Table 3. */ -//@{ - -/**@name Log area ratios, apply to whole frame. */ -//@{ -const unsigned int LAR1_p = 0; -const unsigned int LAR2_p = LAR1_p + LAR1_l; -const unsigned int LAR3_p = LAR2_p + LAR2_l; -const unsigned int LAR4_p = LAR3_p + LAR3_l; -const unsigned int LAR5_p = LAR4_p + LAR4_l; -const unsigned int LAR6_p = LAR5_p + LAR5_l; -const unsigned int LAR7_p = LAR6_p + LAR6_l; -const unsigned int LAR8_p = LAR7_p + LAR7_l; -//@} -/**@name Subframe 1 */ -//@{ -const unsigned int N1_p = LAR8_p + LAR8_l; -const unsigned int b1_p = N1_p + N_l; -const unsigned int M1_p = b1_p + b_l; -const unsigned int Xmax1_p = M1_p + M_l; -const unsigned int x1_0_p = Xmax1_p + Xmax_l; -const unsigned int x1_1_p = x1_0_p + x_l; -const unsigned int x1_2_p = x1_1_p + x_l; -const unsigned int x1_3_p = x1_2_p + x_l; -const unsigned int x1_4_p = x1_3_p + x_l; -const unsigned int x1_5_p = x1_4_p + x_l; -const unsigned int x1_6_p = x1_5_p + x_l; -const unsigned int x1_7_p = x1_6_p + x_l; -const unsigned int x1_8_p = x1_7_p + x_l; -const unsigned int x1_9_p = x1_8_p + x_l; -const unsigned int x1_10_p = x1_9_p + x_l; -const unsigned int x1_11_p = x1_10_p + x_l; -const unsigned int x1_12_p = x1_11_p + x_l; -//@} -/**@name Subframe 2 */ -//@{ -const unsigned int N2_p = x1_12_p + x_l; -const unsigned int b2_p = N2_p + N_l; -const unsigned int M2_p = b2_p + b_l; -const unsigned int Xmax2_p = M2_p + M_l; -const unsigned int x2_0_p = Xmax2_p + Xmax_l; -const unsigned int x2_1_p = x2_0_p + x_l; -const unsigned int x2_2_p = x2_1_p + x_l; -const unsigned int x2_3_p = x2_2_p + x_l; -const unsigned int x2_4_p = x2_3_p + x_l; -const unsigned int x2_5_p = x2_4_p + x_l; -const unsigned int x2_6_p = x2_5_p + x_l; -const unsigned int x2_7_p = x2_6_p + x_l; -const unsigned int x2_8_p = x2_7_p + x_l; -const unsigned int x2_9_p = x2_8_p + x_l; -const unsigned int x2_10_p = x2_9_p + x_l; -const unsigned int x2_11_p = x2_10_p + x_l; -const unsigned int x2_12_p = x2_11_p + x_l; -//@} -/**@mame Subframe 3 */ -//@{ -const unsigned int N3_p = x2_12_p + x_l; -const unsigned int b3_p = N3_p + N_l; -const unsigned int M3_p = b3_p + b_l; -const unsigned int Xmax3_p = M3_p + M_l; -const unsigned int x3_0_p = Xmax3_p + Xmax_l; -const unsigned int x3_1_p = x3_0_p + x_l; -const unsigned int x3_2_p = x3_1_p + x_l; -const unsigned int x3_3_p = x3_2_p + x_l; -const unsigned int x3_4_p = x3_3_p + x_l; -const unsigned int x3_5_p = x3_4_p + x_l; -const unsigned int x3_6_p = x3_5_p + x_l; -const unsigned int x3_7_p = x3_6_p + x_l; -const unsigned int x3_8_p = x3_7_p + x_l; -const unsigned int x3_9_p = x3_8_p + x_l; -const unsigned int x3_10_p = x3_9_p + x_l; -const unsigned int x3_11_p = x3_10_p + x_l; -const unsigned int x3_12_p = x3_11_p + x_l; -//@} -/**@name Subframe 4 */ -//@{ -const unsigned int N4_p = x3_12_p + x_l; -const unsigned int b4_p = N4_p + N_l; -const unsigned int M4_p = b4_p + b_l; -const unsigned int Xmax4_p = M4_p + M_l; -const unsigned int x4_0_p = Xmax4_p + Xmax_l; -const unsigned int x4_1_p = x4_0_p + x_l; -const unsigned int x4_2_p = x4_1_p + x_l; -const unsigned int x4_3_p = x4_2_p + x_l; -const unsigned int x4_4_p = x4_3_p + x_l; -const unsigned int x4_5_p = x4_4_p + x_l; -const unsigned int x4_6_p = x4_5_p + x_l; -const unsigned int x4_7_p = x4_6_p + x_l; -const unsigned int x4_8_p = x4_7_p + x_l; -const unsigned int x4_9_p = x4_8_p + x_l; -const unsigned int x4_10_p = x4_9_p + x_l; -const unsigned int x4_11_p = x4_10_p + x_l; -const unsigned int x4_12_p = x4_11_p + x_l; -//@} -//@} - - -/* - This array encodes GSM 05.03 Table 2. - It's also GSM 06.10 Table A2.1a. - This is the order of bits as they appear in - the d[] bits of the GSM TCH/F. - RTP[4+g610BitOrder[i]] <=> GSM[i] -*/ -unsigned int GSM::g610BitOrder[260] = { -/**@name importance class 1 */ -//@{ -/** LAR1:5 */ LAR1_p+LAR1_l-1-5, /* bit 0 */ -/** Xmax1:5 */ Xmax1_p+Xmax_l-1-5, -/** Xmax2:5 */ Xmax2_p+Xmax_l-1-5, -/** Xmax3:5 */ Xmax3_p+Xmax_l-1-5, -/** Xmax4:5 */ Xmax4_p+Xmax_l-1-5, -//@} -/**@name importance class 2 */ -//@{ -/** LAR1:4 */ LAR1_p+LAR1_l-1-4, -/** LAR2:5 */ LAR2_p+LAR2_l-1-5, -/** LAR3:4 */ LAR3_p+LAR3_l-1-4, -//@} -/**@name importance class 3 */ -//@{ -/** LAR1:3 */ LAR1_p+LAR1_l-1-3, -/** LAR2:4 */ LAR2_p+LAR2_l-1-4, -/** LAR3:3 */ LAR3_p+LAR3_l-1-3, /* bit 10 */ -/** LAR4:4 */ LAR4_p+LAR4_l-1-4, -/** N1:6 */ N1_p+N_l-1-6, -/** N2:6 */ N2_p+N_l-1-6, -/** N3:6 */ N3_p+N_l-1-6, -/** N4:6 */ N4_p+N_l-1-6, -/** Xmax1:4 */ Xmax1_p+Xmax_l-1-4, -/** Xmax2:4 */ Xmax2_p+Xmax_l-1-4, -/** Xmax3:4 */ Xmax3_p+Xmax_l-1-4, -/** Xmax4:4 */ Xmax4_p+Xmax_l-1-4, -/** LAR2:3 */ LAR2_p+LAR2_l-1-3, /* bit 20 */ -/** LAR5:3 */ LAR5_p+LAR5_l-1-3, -/** LAR6:3 */ LAR6_p+LAR6_l-1-3, -/** N1:5 */ N1_p+N_l-1-5, -/** N2:5 */ N2_p+N_l-1-5, -/** N3:5 */ N3_p+N_l-1-5, -/** N4:5 */ N4_p+N_l-1-5, -/** N1:4 */ N1_p+N_l-1-4, -/** N2:4 */ N2_p+N_l-1-4, -/** N3:4 */ N3_p+N_l-1-4, -/** N4:4 */ N4_p+N_l-1-4, /* bit 30 */ -/** N1:3 */ N1_p+N_l-1-3, -/** N2:3 */ N2_p+N_l-1-3, -/** N3:3 */ N3_p+N_l-1-3, -/** N4:3 */ N4_p+N_l-1-3, -/** N1:2 */ N1_p+N_l-1-2, -/** N2:2 */ N2_p+N_l-1-2, -/** N3:2 */ N3_p+N_l-1-2, -/** N4:2 */ N4_p+N_l-1-2, -//@} -/**@name importance class 4 */ -//@{ -/** Xmax1:3 */ Xmax1_p+Xmax_l-1-3, -/** Xmax2:3 */ Xmax2_p+Xmax_l-1-3, /* bit 40 */ -/** Xmax3:3 */ Xmax3_p+Xmax_l-1-3, -/** Xmax4:3 */ Xmax4_p+Xmax_l-1-3, -/** LAR1:2 */ LAR1_p+LAR1_l-1-2, -/** LAR4:3 */ LAR4_p+LAR4_l-1-3, -/** LAR7:2 */ LAR7_p+LAR7_l-1-2, -/** N1:1 */ N1_p+N_l-1-1, -/** N2:1 */ N2_p+N_l-1-1, -/** N3:1 */ N3_p+N_l-1-1, -/** N4:1 */ N4_p+N_l-1-1, -/** LAR5:2 */ LAR5_p+LAR5_l-1-2, /* bit 50 */ -/** LAR6:2 */ LAR6_p+LAR6_l-1-2, -/** b1:1 */ b1_p+b_l-1-1, -/** b2:1 */ b2_p+b_l-1-1, -/** b3:1 */ b3_p+b_l-1-1, -/** b4:1 */ b4_p+b_l-1-1, -/** N1:0 */ N1_p+N_l-1-0, -/** N2:0 */ N2_p+N_l-1-0, -/** N3:0 */ N3_p+N_l-1-0, -/** N4:0 */ N4_p+N_l-1-0, -/** M1:1 */ M1_p+M_l-1-1, /* bit 60 */ -/** M2:1 */ M2_p+M_l-1-1, -/** M3:1 */ M3_p+M_l-1-1, -/** M4:1 */ M4_p+M_l-1-1, -//@} -/**@name importance class 5 */ -//@{ -/** LAR1:1 */ LAR1_p+LAR1_l-1-1, -/** LAR2:2 */ LAR2_p+LAR2_l-1-2, -/** LAR3:2 */ LAR3_p+LAR3_l-1-2, -/** LAR8:2 */ LAR8_p+LAR8_l-1-2, -/** LAR4:2 */ LAR4_p+LAR4_l-1-2, -/** LAR5:1 */ LAR5_p+LAR5_l-1-1, -/** LAR7:1 */ LAR7_p+LAR7_l-1-1, /* bit 70 */ -/** b1:0 */ b1_p+b_l-1-0, -/** b2:0 */ b2_p+b_l-1-0, -/** b3:0 */ b3_p+b_l-1-0, -/** b4:0 */ b4_p+b_l-1-0, -/** Xmax1:2 */ Xmax1_p+Xmax_l-1-2, -/** Xmax2:2 */ Xmax2_p+Xmax_l-1-2, -/** Xmax3:2 */ Xmax3_p+Xmax_l-1-2, -/** Xmax4:2 */ Xmax4_p+Xmax_l-1-2, -/** x1_0:2 */ x1_0_p+x_l-1-2, -/** x1_1:2 */ x1_1_p+x_l-1-2, /* bit 80 */ -/** x1_2:2 */ x1_2_p+x_l-1-2, -/** x1_3:2 */ x1_3_p+x_l-1-2, -/** x1_4:2 */ x1_4_p+x_l-1-2, -/** x1_5:2 */ x1_5_p+x_l-1-2, -/** x1_6:2 */ x1_6_p+x_l-1-2, -/** x1_7:2 */ x1_7_p+x_l-1-2, -/** x1_8:2 */ x1_8_p+x_l-1-2, -/** x1_9:2 */ x1_9_p+x_l-1-2, -/** x1_10:2 */ x1_10_p+x_l-1-2, -/** x1_11:2 */ x1_11_p+x_l-1-2, /* bit 90 */ -/** x1_12:2 */ x1_12_p+x_l-1-2, -/** x2_0:2 */ x2_0_p+x_l-1-2, -/** x2_1:2 */ x2_1_p+x_l-1-2, -/** x2_2:2 */ x2_2_p+x_l-1-2, -/** x2_3:2 */ x2_3_p+x_l-1-2, -/** x2_4:2 */ x2_4_p+x_l-1-2, -/** x2_5:2 */ x2_5_p+x_l-1-2, -/** x2_6:2 */ x2_6_p+x_l-1-2, -/** x2_7:2 */ x2_7_p+x_l-1-2, -/** x2_8:2 */ x2_8_p+x_l-1-2, /* bit 100 */ -/** x2_9:2 */ x2_9_p+x_l-1-2, -/** x2_10:2 */ x2_10_p+x_l-1-2, -/** x2_11:2 */ x2_11_p+x_l-1-2, -/** x2_12:2 */ x2_12_p+x_l-1-2, -/** x3_0:2 */ x3_0_p+x_l-1-2, -/** x3_1:2 */ x3_1_p+x_l-1-2, -/** x3_2:2 */ x3_2_p+x_l-1-2, -/** x3_3:2 */ x3_3_p+x_l-1-2, -/** x3_4:2 */ x3_4_p+x_l-1-2, -/** x3_5:2 */ x3_5_p+x_l-1-2, /* bit 110 */ -/** x3_6:2 */ x3_6_p+x_l-1-2, -/** x3_7:2 */ x3_7_p+x_l-1-2, -/** x3_8:2 */ x3_8_p+x_l-1-2, -/** x3_9:2 */ x3_9_p+x_l-1-2, -/** x3_10:2 */ x3_10_p+x_l-1-2, -/** x3_11:2 */ x3_11_p+x_l-1-2, -/** x3_12:2 */ x3_12_p+x_l-1-2, -/** x4_0:2 */ x4_0_p+x_l-1-2, -/** x4_1:2 */ x4_1_p+x_l-1-2, -/** x4_2:2 */ x4_2_p+x_l-1-2, /* bit 120 */ -/** x4_3:2 */ x4_3_p+x_l-1-2, -/** x4_4:2 */ x4_4_p+x_l-1-2, -/** x4_5:2 */ x4_5_p+x_l-1-2, -/** x4_6:2 */ x4_6_p+x_l-1-2, -/** x4_7:2 */ x4_7_p+x_l-1-2, -/** x4_8:2 */ x4_8_p+x_l-1-2, -/** x4_9:2 */ x4_9_p+x_l-1-2, -/** x4_10:2 */ x4_10_p+x_l-1-2, -/** x4_11:2 */ x4_11_p+x_l-1-2, -/** x4_12:2 */ x4_12_p+x_l-1-2, /* bit 130 */ -/** M1:0 */ M1_p+M_l-1-0, -/** M2:0 */ M2_p+M_l-1-0, -/** M3:0 */ M3_p+M_l-1-0, -/** M4:0 */ M4_p+M_l-1-0, -/** Xmax1:1 */ Xmax1_p+Xmax_l-1-1, -/** Xmax2:1 */ Xmax2_p+Xmax_l-1-1, -/** Xmax3:1 */ Xmax3_p+Xmax_l-1-1, -/** Xmax4:1 */ Xmax4_p+Xmax_l-1-1, -/** x1_0:1 */ x1_0_p+x_l-1-1, -/** x1_1:1 */ x1_1_p+x_l-1-1, /* bit 140 */ -/** x1_2:1 */ x1_2_p+x_l-1-1, -/** x1_3:1 */ x1_3_p+x_l-1-1, -/** x1_4:1 */ x1_4_p+x_l-1-1, -/** x1_5:1 */ x1_5_p+x_l-1-1, -/** x1_6:1 */ x1_6_p+x_l-1-1, -/** x1_7:1 */ x1_7_p+x_l-1-1, -/** x1_8:1 */ x1_8_p+x_l-1-1, -/** x1_9:1 */ x1_9_p+x_l-1-1, -/** x1_10:1 */ x1_10_p+x_l-1-1, -/** x1_11:1 */ x1_11_p+x_l-1-1, /* bit 150 */ -/** x1_12:1 */ x1_12_p+x_l-1-1, -/** x2_0:1 */ x2_0_p+x_l-1-1, -/** x2_1:1 */ x2_1_p+x_l-1-1, -/** x2_2:1 */ x2_2_p+x_l-1-1, -/** x2_3:1 */ x2_3_p+x_l-1-1, -/** x2_4:1 */ x2_4_p+x_l-1-1, -/** x2_5:1 */ x2_5_p+x_l-1-1, -/** x2_6:1 */ x2_6_p+x_l-1-1, -/** x2_7:1 */ x2_7_p+x_l-1-1, -/** x2_8:1 */ x2_8_p+x_l-1-1, /* bit 160 */ -/** x2_9:1 */ x2_9_p+x_l-1-1, -/** x2_10:1 */ x2_10_p+x_l-1-1, -/** x2_11:1 */ x2_11_p+x_l-1-1, -/** x2_12:1 */ x2_12_p+x_l-1-1, -/** x3_0:1 */ x3_0_p+x_l-1-1, -/** x3_1:1 */ x3_1_p+x_l-1-1, -/** x3_2:1 */ x3_2_p+x_l-1-1, -/** x3_3:1 */ x3_3_p+x_l-1-1, -/** x3_4:1 */ x3_4_p+x_l-1-1, -/** x3_5:1 */ x3_5_p+x_l-1-1, /* bit 170 */ -/** x3_6:1 */ x3_6_p+x_l-1-1, -/** x3_7:1 */ x3_7_p+x_l-1-1, -/** x3_8:1 */ x3_8_p+x_l-1-1, -/** x3_9:1 */ x3_9_p+x_l-1-1, -/** x3_10:1 */ x3_10_p+x_l-1-1, -/** x3_11:1 */ x3_11_p+x_l-1-1, -/** x3_12:1 */ x3_12_p+x_l-1-1, -/** x4_0:1 */ x4_0_p+x_l-1-1, -/** x4_1:1 */ x4_1_p+x_l-1-1, -/** x4_2:1 */ x4_2_p+x_l-1-1, /* bit 180 */ -/** x4_3:1 */ x4_3_p+x_l-1-1, -//@} -/**@name importance class 6 */ -//@{ -/** x4_4:1 */ x4_4_p+x_l-1-1, -/** x4_5:1 */ x4_5_p+x_l-1-1, -/** x4_6:1 */ x4_6_p+x_l-1-1, -/** x4_7:1 */ x4_7_p+x_l-1-1, -/** x4_8:1 */ x4_8_p+x_l-1-1, -/** x4_9:1 */ x4_9_p+x_l-1-1, -/** x4_10:1 */ x4_10_p+x_l-1-1, -/** x4_11:1 */ x4_11_p+x_l-1-1, -/** x4_12:1 */ x4_12_p+x_l-1-1, /* bit 190 */ -/** LAR1:0 */ LAR1_p+LAR1_l-1-0, -/** LAR2:1 */ LAR2_p+LAR2_l-1-1, -/** LAR3:1 */ LAR3_p+LAR3_l-1-1, -/** LAR6:1 */ LAR6_p+LAR6_l-1-1, -/** LAR7:0 */ LAR7_p+LAR7_l-1-0, -/** LAR8:1 */ LAR8_p+LAR8_l-1-1, -/** LAR8:0 */ LAR8_p+LAR8_l-1-0, -/** LAR3:0 */ LAR3_p+LAR3_l-1-0, -/** LAR4:1 */ LAR4_p+LAR4_l-1-1, -/** LAR4:0 */ LAR4_p+LAR4_l-1-0, -/** LAR5:0 */ LAR5_p+LAR5_l-1-0, -/** Xmax1:0 */ Xmax1_p+Xmax_l-1-0, -/** Xmax2:0 */ Xmax2_p+Xmax_l-1-0, -/** Xmax3:0 */ Xmax3_p+Xmax_l-1-0, -/** Xmax4:0 */ Xmax4_p+Xmax_l-1-0, -/** x1_0:0 */ x1_0_p+x_l-1-0, -/** x1_1:0 */ x1_1_p+x_l-1-0, -/** x1_2:0 */ x1_2_p+x_l-1-0, -/** x1_3:0 */ x1_3_p+x_l-1-0, -/** x1_4:0 */ x1_4_p+x_l-1-0, -/** x1_5:0 */ x1_5_p+x_l-1-0, -/** x1_6:0 */ x1_6_p+x_l-1-0, -/** x1_7:0 */ x1_7_p+x_l-1-0, -/** x1_8:0 */ x1_8_p+x_l-1-0, -/** x1_9:0 */ x1_9_p+x_l-1-0, -/** x1_10:0 */ x1_10_p+x_l-1-0, -/** x1_11:0 */ x1_11_p+x_l-1-0, -/** x1_12:0 */ x1_12_p+x_l-1-0, -/** x2_0:0 */ x2_0_p+x_l-1-0, -/** x2_1:0 */ x2_1_p+x_l-1-0, -/** x2_2:0 */ x2_2_p+x_l-1-0, -/** x2_3:0 */ x2_3_p+x_l-1-0, -/** x2_4:0 */ x2_4_p+x_l-1-0, -/** x2_5:0 */ x2_5_p+x_l-1-0, -/** x2_6:0 */ x2_6_p+x_l-1-0, -/** x2_7:0 */ x2_7_p+x_l-1-0, -/** x2_8:0 */ x2_8_p+x_l-1-0, -/** x2_9:0 */ x2_9_p+x_l-1-0, -/** x2_10:0 */ x2_10_p+x_l-1-0, -/** x2_11:0 */ x2_11_p+x_l-1-0, -/** x2_12:0 */ x2_12_p+x_l-1-0, -/** x3_0:0 */ x3_0_p+x_l-1-0, -/** x3_1:0 */ x3_1_p+x_l-1-0, -/** x3_2:0 */ x3_2_p+x_l-1-0, -/** x3_3:0 */ x3_3_p+x_l-1-0, -/** x3_4:0 */ x3_4_p+x_l-1-0, -/** x3_5:0 */ x3_5_p+x_l-1-0, -/** x3_6:0 */ x3_6_p+x_l-1-0, -/** x3_7:0 */ x3_7_p+x_l-1-0, -/** x3_8:0 */ x3_8_p+x_l-1-0, -/** x3_9:0 */ x3_9_p+x_l-1-0, -/** x3_10:0 */ x3_10_p+x_l-1-0, -/** x3_11:0 */ x3_11_p+x_l-1-0, -/** x3_12:0 */ x3_12_p+x_l-1-0, -/** x4_0:0 */ x4_0_p+x_l-1-0, -/** x4_1:0 */ x4_1_p+x_l-1-0, -/** x4_2:0 */ x4_2_p+x_l-1-0, -/** x4_3:0 */ x4_3_p+x_l-1-0, -/** x4_4:0 */ x4_4_p+x_l-1-0, -/** x4_5:0 */ x4_5_p+x_l-1-0, -/** x4_6:0 */ x4_6_p+x_l-1-0, -/** x4_7:0 */ x4_7_p+x_l-1-0, -/** x4_8:0 */ x4_8_p+x_l-1-0, -/** x4_9:0 */ x4_9_p+x_l-1-0, -/** x4_10:0 */ x4_10_p+x_l-1-0, -/** x4_11:0 */ x4_11_p+x_l-1-0, -/** x4_12:0 */ x4_12_p+x_l-1-0, -/** LAR2:0 */ LAR2_p+LAR2_l-1-0, -/** LAR6:0 */ LAR6_p+LAR6_l-1-0 -//@} -}; - diff --git a/src/lib/decoder/openbtsstuff/GSM610Tables.h b/src/lib/decoder/openbtsstuff/GSM610Tables.h deleted file mode 100644 index 53a8e1c..0000000 --- a/src/lib/decoder/openbtsstuff/GSM610Tables.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 . - -*/ - - - -#ifndef GSM610TABLES_H -#define GSM610TABLES_H - - - -namespace GSM { - -/** Table #2 from GSM 05.03 */ -extern unsigned int g610BitOrder[260]; - -} - - -#endif diff --git a/src/lib/decoder/openbtsstuff/GSMCommon.cpp b/src/lib/decoder/openbtsstuff/GSMCommon.cpp deleted file mode 100644 index 0bec812..0000000 --- a/src/lib/decoder/openbtsstuff/GSMCommon.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 "GSMCommon.h" - -using namespace GSM; -using namespace std; - - -ostream& GSM::operator<<(ostream& os, L3PD val) -{ - switch (val) { - case L3CallControlPD: os << "Call Control"; break; - case L3MobilityManagementPD: os << "Mobility Management"; break; - case L3RadioResourcePD: os << "Radio Resource"; break; - default: os << hex << "0x" << (int)val << dec; - } - return os; -} - - -const BitVector GSM::gTrainingSequence[] = { - BitVector("00100101110000100010010111"), - BitVector("00101101110111100010110111"), - BitVector("01000011101110100100001110"), - BitVector("01000111101101000100011110"), - BitVector("00011010111001000001101011"), - BitVector("01001110101100000100111010"), - BitVector("10100111110110001010011111"), - BitVector("11101111000100101110111100"), -}; - -const BitVector GSM::gDummyBurst("0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000"); - -const BitVector GSM::gRACHSynchSequence("01001011011111111001100110101010001111000"); - - - -char encodeGSMChar(char ascii) -{ - // Given an ASCII char, return the corresponding GSM char. - static char reverseTable[256]={0}; - static bool init = false; - if (!init) { - for (size_t i=0; i='0') && (ascii<='9')) return ascii-'0'; - switch (ascii) { - case '.': return 11; - case '*': return 11; - case '#': return 12; - case 'a': return 13; - case 'b': return 14; - case 'c': return 15; - default: return 15; - } -} - - - - -unsigned GSM::uplinkFreqKHz(GSMBand band, unsigned ARFCN) -{ - switch (band) { - case GSM850: - assert((ARFCN<252)&&(ARFCN>129)); - return 824200+200*(ARFCN-128); - case EGSM900: - if (ARFCN<=124) return 890000+200*ARFCN; - assert((ARFCN>974)&&(ARFCN<1024)); - return 890000+200*(ARFCN-1024); - case DCS1800: - assert((ARFCN>511)&&(ARFCN<886)); - return 1710200+200*(ARFCN-512); - case PCS1900: - assert((ARFCN>511)&&(ARFCN<811)); - return 1850200+200*(ARFCN-512); - default: - abort(); - } -} - - -unsigned GSM::downlinkFreqKHz(GSMBand band, unsigned ARFCN) -{ - static unsigned uplinkOffset[] = { - 45000, // 850 - 45000, // 900 - 95000, // 1800 - 80000 // 1900 - }; - return uplinkFreqKHz(band,ARFCN) + uplinkOffset[band]; -} - - - - -int32_t GSM::FNDelta(int32_t v1, int32_t v2) -{ - static const int64_t halfModulus = gHyperframe/2; - int32_t delta = v1-v2; - if (delta>halfModulus) delta -= gHyperframe; - else if (delta<-halfModulus) delta += gHyperframe; - return (int32_t) delta; -} - -int GSM::FNCompare(int32_t v1, int32_t v2) -{ - int32_t delta = FNDelta(v1,v2); - if (delta==0) return 0; - else if (delta>0) return 1; - else return -1; -} - - - - -ostream& GSM::operator<<(ostream& os, const Time& t) -{ - os << t.TN() << ":" << t.FN(); - return os; -} - - - - -void Clock::set(const Time& when) -{ - mLock.lock(); - mBaseTime = Timeval(0); - mBaseFN = when.FN(); - mLock.unlock(); -} - - -int32_t Clock::FN() const -{ - mLock.lock(); - Timeval now; - int deltaSec = now.sec() - mBaseTime.sec(); - int deltaUSec = now.usec() - mBaseTime.usec(); - int elapsedUSec = 1000000*deltaSec + deltaUSec; - int elapsedFrames = elapsedUSec / gFrameMicroseconds; - int32_t currentFN = (mBaseFN + elapsedFrames) % gHyperframe; - mLock.unlock(); - return currentFN; -} - - -void Clock::wait(const Time& when) const -{ - int32_t now = FN(); - int32_t target = when.FN(); - int32_t delta = FNDelta(target,now); - if (delta<1) return; - const int32_t maxSleep = 51*26; - if (delta>maxSleep) delta=maxSleep; - sleepFrames(delta); -} - - - - - - - -ostream& GSM::operator<<(ostream& os, TypeOfNumber type) -{ - switch (type) { - case UnknownTypeOfNumber: os << "unknown"; break; - case InternationalNumber: os << "international"; break; - case NationalNumber: os << "national"; break; - case NetworkSpecificNumber: os << "network-specific"; break; - case ShortCodeNumber: os << "short code"; break; - default: os << "?" << type << "?"; - } - return os; -} - - -ostream& GSM::operator<<(ostream& os, NumberingPlan plan) -{ - switch (plan) { - case UnknownPlan: os << "unknown"; break; - case E164Plan: os << "E.164/ISDN"; break; - case X121Plan: os << "X.121/data"; break; - case F69Plan: os << "F.69/Telex"; break; - case NationalPlan: os << "national"; break; - case PrivatePlan: os << "private"; break; - default: os << "?" << (int)plan << "?"; - } - return os; -} - -ostream& GSM::operator<<(ostream& os, MobileIDType wID) -{ - switch (wID) { - case NoIDType: os << "None"; break; - case IMSIType: os << "IMSI"; break; - case IMEIType: os << "IMEI"; break; - case TMSIType: os << "TMSI"; break; - case IMEISVType: os << "IMEISV"; break; - default: os << "?" << (int)wID << "?"; - } - return os; -} - - -ostream& GSM::operator<<(ostream& os, TypeAndOffset tao) -{ - switch (tao) { - case TDMA_MISC: os << "(misc)"; break; - case TCHF_0: os << "TCH/F"; break; - case TCHH_0: os << "TCH/H-0"; break; - case TCHH_1: os << "TCH/H-1"; break; - case SDCCH_4_0: os << "SDCCH/4-0"; break; - case SDCCH_4_1: os << "SDCCH/4-1"; break; - case SDCCH_4_2: os << "SDCCH/4-2"; break; - case SDCCH_4_3: os << "SDCCH/4-3"; break; - case SDCCH_8_0: os << "SDCCH/8-0"; break; - case SDCCH_8_1: os << "SDCCH/8-1"; break; - case SDCCH_8_2: os << "SDCCH/8-2"; break; - case SDCCH_8_3: os << "SDCCH/8-3"; break; - case SDCCH_8_4: os << "SDCCH/8-4"; break; - case SDCCH_8_5: os << "SDCCH/8-5"; break; - case SDCCH_8_6: os << "SDCCH/8-6"; break; - case SDCCH_8_7: os << "SDCCH/8-7"; break; - case TDMA_BEACON: os << "(beacon)"; break; - default: os << "?" << (int)tao << "?"; - } - return os; -} - -ostream& GSM::operator<<(ostream& os, ChannelType val) -{ - switch (val) { - case UndefinedCHType: os << "undefined"; return os; - case SCHType: os << "SCH"; break; - case FCCHType: os << "FCCH"; break; - case BCCHType: os << "BCCH"; break; - case RACHType: os << "RACH"; break; - case SDCCHType: os << "SDCCH"; break; - case FACCHType: os << "FACCH"; break; - case CCCHType: os << "CCCH"; break; - case SACCHType: os << "SACCH"; break; - case TCHFType: os << "TCH/F"; break; - case TCHHType: os << "TCH/H"; break; - case AnyTCHType: os << "any TCH"; break; - case LoopbackFullType: os << "Loopback Full"; break; - case LoopbackHalfType: os << "Loopback Half"; break; - case AnyDCCHType: os << "any DCCH"; break; - default: os << "?" << (int)val << "?"; - } - return os; -} - - - - -bool Z100Timer::expired() const -{ - // A non-active timer does not expire. - if (!mActive) return false; - return mEndTime.passed(); -} - -void Z100Timer::set() -{ - mEndTime = Timeval(mLimitTime); - mActive=true; -} - -long Z100Timer::remaining() const -{ - if (!mActive) return 0; - long rem = mEndTime.remaining(); - if (rem<0) rem=0; - return rem; -} - -void Z100Timer::wait() const -{ - while (!expired()) msleep(remaining()); -} - -// vim: ts=4 sw=4 diff --git a/src/lib/decoder/openbtsstuff/GSMCommon.h b/src/lib/decoder/openbtsstuff/GSMCommon.h deleted file mode 100644 index 9dc1c95..0000000 --- a/src/lib/decoder/openbtsstuff/GSMCommon.h +++ /dev/null @@ -1,537 +0,0 @@ -/**@file Common-use GSM declarations, most from the GSM 04.xx and 05.xx series. */ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 . - -*/ - - - -#ifndef GSMCOMMON_H -#define GSMCOMMON_H - -#include -#include -#include -#include - -#include -#include -#include - - - - -namespace GSM { - -/**@namespace GSM This namespace covers L1 FEC, L2 and L3 message translation. */ - - -/* forward references */ -class L1FEC; -class L2LAPDm; -class L3Processor; -class LogicalChannel; -class L2Header; - - -/** A base class for GSM exceptions. */ -class GSMError {}; - -/** Duration ofa GSM frame, in microseconds. */ -const unsigned gFrameMicroseconds = 4615; - - -/** Sleep for a given number of GSM frame periods. */ -inline void sleepFrames(unsigned frames) - { usleep(frames*gFrameMicroseconds); } - -/** Sleep for 1 GSM frame period. */ -inline void sleepFrame() - { usleep(gFrameMicroseconds); } - - - -/** GSM Training sequences from GSM 05.02 5.2.3. */ -extern const BitVector gTrainingSequence[]; - -/** C0T0 filler burst, GSM 05.02, 5.2.6 */ -extern const BitVector gDummyBurst; - -/** Random access burst synch. sequence */ -extern const BitVector gRACHSynchSequence; - - -/**@name Support for GSM 7-bit alphabet, GSM 03.38 6.2.1. */ -//@{ -/** Indexed by GSM 7-bit, returns ASCII. */ -static const char gGSMAlphabet[] = "@\243$\245\350\351\371\354\362\347\n\330\370\r\305\345D_FGLOPCSTZ \306\346\337\311 !\"#\244%&\'()*+,-./0123456789:;<=>?\241ABCDEFGHIJKLMNOPQRSTUVWXYZ\304\326\321\334\247\277abcdefghijklmnopqrstuvwxyz\344\366\361\374\341"; -char encodeGSMChar(char ascii); -inline char decodeGSMChar(char sms) { return gGSMAlphabet[(unsigned)sms]; } -//@} - - -/**@name BCD-ASCII mapping, GMS 04.08 Table 10.5.118. */ -//@{ -/** Indexed by BCD, returns ASCII. */ -static const char gBCDAlphabet[] = "0123456789.#abc"; -char encodeBCDChar(char ascii); -inline char decodeBCDChar(char bcd) { return gBCDAlphabet[(unsigned)bcd]; } -//@} - - -/**@name Globally-fixed GSM timeout values (all in ms). */ -//@{ -/**@name GSM LAPDm timeouts, GSM 04.06 5.8, ITU-T Q.921 5.9 */ -//@{ -const unsigned T200ms = 900; ///< LAPDm ACK timeout, set for typical turnaround time -//@} -/**@name GSM timeouts for radio resource management, GSM 04.08 11.1. */ -//@{ -const unsigned T3101ms = 4000; ///< L1 timeout for SDCCH assignment -const unsigned T3107ms = 3000; ///< L1 timeout for TCH/FACCH assignment -const unsigned T3109ms = 10000; ///< L1 timeout for an existing channel -const unsigned T3111ms = 2*T200ms; ///< L1 timeout for reassignment of a channel -const unsigned T3113ms = 10000; ///< timeout for paging response -const unsigned T3122ms = 2000; ///< RR access holdoff time (GSM 04.08 3.3.1.1.3.2) -//@} -/**@name GSM timeouts for mobility management, GSM 04.08 11.2. */ -//@{ -const unsigned T3212ms = 8*360000; ///< location updating period (in 6-min increments, 0-255) -//const unsigned T3212ms = 0; ///< location updating period (in 6-min increments, 0-255), 0 disables -//@} -//@} - - - - -/** GSM 04.08 Table 10.5.118 */ -enum TypeOfNumber { - UnknownTypeOfNumber = 0, - InternationalNumber = 1, - NationalNumber = 2, - NetworkSpecificNumber = 3, - ShortCodeNumber = 4 -}; - -std::ostream& operator<<(std::ostream&, TypeOfNumber); - - -/** GSM 04.08 Table 10.5.118 */ -enum NumberingPlan { - UnknownPlan = 0, - E164Plan = 1, - X121Plan = 3, - F69Plan = 4, - NationalPlan = 8, - PrivatePlan = 9 -}; - -std::ostream& operator<<(std::ostream&, NumberingPlan); - - - -/** Codes for GSM band types, GSM 05.05 2. */ -enum GSMBand { - GSM850=0, ///< US cellular - EGSM900, ///< extended GSM - DCS1800, ///< worldwide DCS band - PCS1900 ///< US PCS band -}; - - -/**@name Actual radio carrier frequencies, in kHz, GSM 05.05 2 */ -//@{ -unsigned uplinkFreqKHz(GSMBand wBand, unsigned wARFCN); -unsigned downlinkFreqKHz(GSMBand wBand, unsigned wARFCN); -//@} - - - -/**@name GSM Logical channel (LCH) types. */ -//@{ -/** Codes for logical channel types. */ -enum ChannelType { - ///@name Non-dedicated control channels. - //@{ - SCHType, ///< sync - FCCHType, ///< frequency correction - BCCHType, ///< broadcast control - CCCHType, ///< common control, a combination of several sub-types - RACHType, ///< random access - SACCHType, ///< slow associated control (acutally dedicated, but...) - //@} - ///@name Dedicated control channels (DCCHs). - //@{ - SDCCHType, ///< standalone dedicated control - FACCHType, ///< fast associated control - //@} - ///@name Traffic channels - //@{ - TCHFType, ///< full-rate traffic - TCHHType, ///< half-rate traffic - AnyTCHType, ///< any TCH type - //@} - ///@name Special internal channel types. - //@{ - LoopbackFullType, ///< loopback testing - LoopbackHalfType, ///< loopback testing - AnyDCCHType, ///< any dedicated control channel - UndefinedCHType, ///< undefined - //@} -}; - - -/** Print channel type name to a stream. */ -std::ostream& operator<<(std::ostream& os, ChannelType val); - - -//@} - - - -/** Mobile identity types, GSM 04.08 10.5.1.4 */ -enum MobileIDType { - NoIDType = 0, - IMSIType = 1, - IMEIType = 2, - IMEISVType = 3, - TMSIType = 4 -}; - -std::ostream& operator<<(std::ostream& os, MobileIDType); - - -/** Type and TDMA offset of a logical channel, from GSM 04.08 10.5.2.5 */ -enum TypeAndOffset { - TDMA_MISC=0, - TCHF_0=1, - TCHH_0=2, TCHH_1=3, - SDCCH_4_0=4, SDCCH_4_1=5, SDCCH_4_2=6, SDCCH_4_3=7, - SDCCH_8_0=8, SDCCH_8_1=9, SDCCH_8_2=10, SDCCH_8_3=11, - SDCCH_8_4=12, SDCCH_8_5=13, SDCCH_8_6=14, SDCCH_8_7=15, - /// An extra one for our internal use. - TDMA_BEACON=255 -}; - -std::ostream& operator<<(std::ostream& os, TypeAndOffset); - - - - - - - - -/** - L3 Protocol Discriminator, GSM 04.08 10.2, GSM 04.07 11.2.3.1.1. -*/ -enum L3PD { - L3GroupCallControlPD=0x00, - L3BroadcastCallControlPD=0x01, - L3PDSS1PD=0x02, - L3CallControlPD=0x03, - L3PDSS2PD=0x04, - L3MobilityManagementPD=0x05, - L3RadioResourcePD=0x06, - L3MobilityManagementGPRSPD=0x08, - L3SMSPD=0x09, - L3GPRSSessionManagementPD=0x0a, - L3NonCallSSPD=0x0b, - L3LocationPD=0x0c, - L3ExtendedPD=0x0e, - L3TestProcedurePD=0x0f, - L3UndefinedPD=-1 -}; - - - -std::ostream& operator<<(std::ostream& os, L3PD val); - - - - -/**@name Modulus operations for frame numbers. */ -//@{ -/** The GSM hyperframe is largest time period in the GSM system, GSM 05.02 4.3.3. */ -const int32_t gHyperframe = 2048UL * 26UL * 51UL; - -/** Get a clock difference, within the modulus. */ -int32_t FNDelta(int32_t v1, int32_t v2); - -/** - Compare two frame clock values. - @return 1 if v1>v2, -1 if v1(const Time& other) const - { - if (mFN==other.mFN) return (mTN>other.mTN); - return FNCompare(mFN,other.mFN)>0; - } - - bool operator<=(const Time& other) const - { - if (mFN==other.mFN) return (mTN<=other.mTN); - return FNCompare(mFN,other.mFN)<=0; - } - - bool operator>=(const Time& other) const - { - if (mFN==other.mFN) return (mTN>=other.mTN); - return FNCompare(mFN,other.mFN)>=0; - } - - bool operator==(const Time& other) const - { - return (mFN == other.mFN) && (mTN==other.mTN); - } - - //@} - - - - /**@name Standard derivations. */ - //@{ - - unsigned SFN() const { return mFN / (26*51); } - - unsigned T1() const { return SFN() % 2048; } - - unsigned T2() const { return mFN % 26; } - - unsigned T3() const { return mFN % 51; } - - /** GSM 05.02 3.3.2.2.1. */ - unsigned T3p() const { return (T3()-1)/10; } - - /** GSM 05.02 6.3.1.3. */ - unsigned TC() const { return (FN()/51) % 8; } - - /** GSM 04.08 10.5.2.30. */ - unsigned T1p() const { return SFN() % 32; } - - /** GSM 05.02 6.2.3 */ - unsigned T1R() const { return T1() % 64; } - - //@} -}; - - -std::ostream& operator<<(std::ostream& os, const Time& ts); - - - - - - -/** - A class for calculating the current GSM frame number. -*/ -class Clock { - - private: - - mutable Mutex mLock; - int32_t mBaseFN; - Timeval mBaseTime; - - public: - - Clock(const Time& when = Time(0)) - :mBaseFN(when.FN()) - {} - - /** Set the clock to a value. */ - void set(const Time&); - - /** Read the clock. */ - int32_t FN() const; - - /** Read the clock. */ - Time get() const { return Time(FN()); } - - /** Block until the clock passes a given time. */ - void wait(const Time&) const; -}; - - - - - - - - -/** - CCITT Z.100 activity timer, as described in GSM 04.06 5.1. - All times are in milliseconds. -*/ -class Z100Timer { - - private: - - Timeval mEndTime; ///< the time at which this timer will expire - long mLimitTime; ///< timeout in milliseconds - bool mActive; ///< true if timer is active - - public: - - /** Create a timer with a given timeout in milliseconds. */ - Z100Timer(long wLimitTime) - :mLimitTime(wLimitTime), - mActive(false) - {} - - /** True if the timer is active and expired. */ - bool expired() const; - - /** Start or restart the timer. */ - void set(); - - /** Stop the timer. */ - void reset() { mActive = false; } - - /** Returns true if the timer is active. */ - bool active() const { return mActive; } - - /** - Remaining time until expiration, in milliseconds. - Returns zero if the timer has expired. - */ - long remaining() const; - - /** - Block until the timer expires. - Returns immediately if the timer is not running. - */ - void wait() const; -}; - - - - - -}; // namespace GSM - - -#endif - -// vim: ts=4 sw=4 diff --git a/src/lib/decoder/openbtsstuff/GSML1FEC.cpp b/src/lib/decoder/openbtsstuff/GSML1FEC.cpp deleted file mode 100644 index 1c99a0f..0000000 --- a/src/lib/decoder/openbtsstuff/GSML1FEC.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 . - -*/ - - -#define NDEBUG - - -#include "GSML1FEC.h" -#include "GSMCommon.h" -#include "RxBurst.h" -//#include "GSMSAPMux.h" -//#include "GSMConfig.h" -#include "GSMTDMA.h" -#include "GSM610Tables.h" -#include "Assert.h" - - -using namespace std; -using namespace GSM; - -/* - Compilation flags: - NOCONTROL Compile without referencing control layer functions. -*/ - - -/* - - Notes on reading the GSM specifications. - - Every FEC section in GSM 05.03 uses standard names for the bits at - different stages of the encoding/decoding process. - - This is all described formally in GSM 05.03 2.2. - - "d" -- data bits. The actual payloads from L2 and the vocoders. - "p" -- parity bits. These are calculated from d. - "u" -- uncoded bits. A concatenation of d, p and inner tail bits. - "c" -- coded bits. These are the convolutionally encoded from u. - "i" -- interleaved bits. These are the output of the interleaver. - "e" -- "encrypted" bits. These are the channel bits in the radio bursts. - - The "e" bits are call "encrypted" even when encryption is not used. - - The encoding process is: - - L2 -> d -> -> calc p -> u -> c -> i -> e -> radio bursts - - The decoding process is: - - radio bursts -> e -> i -> c -> u -> check p -> d -> L2 - - Bit ordering in d is LSB-first in each octet. - Bit ordering everywhere else in the OpenBTS code is MSB-first - in every field to give contiguous fields across byte boundaries. - We use the BitVector::LSB8MSB() method to translate. - -*/ - -TCHFACCHL1Decoder::TCHFACCHL1Decoder(const TDMAMapping& wMapping) - : mTCHU(189), mTCHD(260), mC(456), - mClass1_c(mC.head(378)), mClass1A_d(mTCHD.head(50)), mClass2_c(mC.segment(378, 78)), - mTCHParity(0x0b, 3, 50), mMapping(wMapping) -{ - for (int i = 0; i < 8; i++) { - mI[i] = SoftVector(114); - } -} - - -void TCHFACCHL1Decoder::writeLowSide(const RxBurst& inBurst) -{ - OBJDCOUT("TCHFACCHL1Decoder::writeLowSide " << inBurst); - // If the channel is closed, ignore the burst. -// if (!active()) { -// OBJDCOUT("TCHFACCHL1Decoder::writeLowSide not active, ignoring input"); -// return; -// } - processBurst(inBurst); -} - -bool TCHFACCHL1Decoder::processBurst( const RxBurst& inBurst) -{ - // Accept the burst into the deinterleaving buffer. - // Return true if we are ready to interleave. - - // TODO -- One quick test of burst validity is to look at the tail bits. - // We could do that as a double-check against putting garbage into - // the interleaver or accepting bad parameters. - - // Get the physical parameters of the burst. - // RSSI is dB wrt full scale. -// mRSSI = inBurst.RSSI(); - // Timing error is a float in symbol intervals. -// mTimingError = inBurst.timingError(); - // This flag is used as a half-ass semaphore. - // It is cleared when the new value is read. -// mPhyNew = true; - - // The reverse index runs 0..3 as the bursts arrive. - // It is the "B" index of GSM 05.03 3.1.3 and 3.1.4. - int B = mMapping.reverseMapping(inBurst.time().FN()) % 8; - // A negative value means that the demux is misconfigured. - assert(B >= 0); - OBJDCOUT("TCHFACCHL1Decoder::processBurst B=" << B << " " << inBurst); - - // Pull the data fields (e-bits) out of the burst and put them into i[B][]. - // GSM 05.03 3.1.4 - inBurst.data1().copyToSegment(mI[B], 0); - inBurst.data2().copyToSegment(mI[B], 57); - - // Every 4th frame is the start of a new block. - // So if this isn't a "4th" frame, return now. - if (B % 4 != 3) return false; - - // Deinterleave according to the diagonal "phase" of B. - // See GSM 05.03 3.1.3. - // Deinterleaves i[] to c[] - if (B == 3) deinterleave(4); - else deinterleave(0); - - // See if this was the end of a stolen frame, GSM 05.03 4.2.5. - bool stolen = inBurst.Hl(); - OBJDCOUT("TCHFACCHL!Decoder::processBurst Hl=" << inBurst.Hl() << " Hu=" << inBurst.Hu()); - /* if (stolen) { - if (decode()) { - OBJDCOUT("TCHFACCHL1Decoder::processBurst good FACCH frame"); - countGoodFrame(); - handleGoodFrame(); - } else { - OBJDCOUT("TCHFACCHL1Decoder::processBurst bad FACCH frame"); - countBadFrame(); - } - }*/ - - // Always feed the traffic channel, even on a stolen frame. - // decodeTCH will handle the GSM 06.11 bad frmae processing. - bool traffic = decodeTCH(stolen); -// if (traffic) { - OBJDCOUT("TCHFACCHL1Decoder::processBurst good TCH frame"); -// countGoodFrame(); - // Don't let the channel timeout. - // mLock.lock(); - // mT3109.set(); - // mLock.unlock(); -// } -// else countBadFrame(); - - return traffic; -} - -void TCHFACCHL1Decoder::deinterleave(int blockOffset ) -{ - OBJDCOUT("TCHFACCHL1Decoder::deinterleave blockOffset=" << blockOffset); - for (int k = 0; k < 456; k++) { - int B = ( k + blockOffset ) % 8; - int j = 2 * ((49 * k) % 57) + ((k % 8) / 4); - mC[k] = mI[B][j]; - mI[B][j] = 0.5F; - //OBJDCOUT("deinterleave k="< - - - -namespace GSM -{ - - -//class SAPMux; - class L1FEC; - class L1Decoder; - - - - /* - Naming convention for bit vectors follows GSM 05.03 Section 2.2. - d[k] data - u[k] data bits after first encoding step - c[k] data bits after second encoding step - i[B][k] interleaved data bits - e[B][k] bits in a burst - */ - - - - - /** L1 decoder used for full rate TCH and FACCH -- mostly from GSM 05.03 3.1 and 4.2 */ -//: public XCCHL1Decoder - class TCHFACCHL1Decoder - { - - protected: - SoftVector mI[8]; ///< deinterleaving history, 8 blocks instead of 4 - SoftVector mC; ///< c[], as per GSM 05.03 2.2 - BitVector mTCHU; ///< u[] (uncoded) in the spec - BitVector mTCHD; ///< d[] (data) in the spec - SoftVector mClass1_c; ///< the class 1 part of c[] - BitVector mClass1A_d; ///< the class 1A part of d[] - SoftVector mClass2_c; ///< the class 2 part of c[] - ViterbiR2O4 mVCoder; - - VocoderFrame mVFrame; ///< unpacking buffer for vocoder frame - unsigned char mPrevGoodFrame[33]; ///< previous good frame. - - Parity mTCHParity; - const TDMAMapping& mMapping; ///< multiplexing description - -// InterthreadQueue mSpeechQ; ///< output queue for speech frames - - static const unsigned mMaxQSize = 3; - - - public: - - TCHFACCHL1Decoder( const TDMAMapping& wMapping ); - - ChannelType channelType() const { - return FACCHType; - } - - - /** TCH/FACCH has a special-case writeLowSide. */ - void writeLowSide(const RxBurst& inBurst); - - /** - Unlike other DCCHs, TCH/FACCH process burst calls - deinterleave, decode, handleGoodFrame. - */ - bool processBurst( const RxBurst& ); - - /** Deinterleave i[] to c[]. */ - void deinterleave(int blockOffset ); - - void replaceFACCH( int blockOffset ); - - /** - Decode a traffic frame from TCHI[] and enqueue it. - Return true if there's a good frame. - */ - bool decodeTCH(bool stolen); - - unsigned char * get_voice_frame(){ - return mPrevGoodFrame; - } - /** - Receive a traffic frame. - Non-blocking. Returns NULL if queue is dry. - Caller is responsible for deleting the returned array. - */ -// unsigned char *recvTCH() { return mSpeechQ.read(0); } - - /** Return count of internally-queued traffic frames. */ -// unsigned queueSize() const { return mSpeechQ.size(); } - - }; - - - - - - -}; // namespace GSM - - - - - -#endif - -// vim: ts=4 sw=4 diff --git a/src/lib/decoder/openbtsstuff/GSMTDMA.cpp b/src/lib/decoder/openbtsstuff/GSMTDMA.cpp deleted file mode 100644 index 27ebe0e..0000000 --- a/src/lib/decoder/openbtsstuff/GSMTDMA.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 "GSMTDMA.h" - - -using namespace GSM; - - - - -TDMAMapping::TDMAMapping(TypeAndOffset - wTypeAndOffset, bool wDownlink, bool wUplink, char wAllowedSlots, bool wC0Only, - unsigned wRepeatLength, unsigned wNumFrames, const unsigned *wFrameMapping) - :mTypeAndOffset(wTypeAndOffset), - mDownlink(wDownlink),mUplink(wUplink),mAllowedSlots(wAllowedSlots),mC0Only(wC0Only), - mRepeatLength(wRepeatLength),mNumFrames(wNumFrames),mFrameMapping(wFrameMapping) -{ - // Sanity check. - assert(mRepeatLength<=mMaxRepeatLength); - - // Default, -1, means a non-occupied position. - for (unsigned i=0; i. - -*/ - - - -#ifndef GSMTDMA_H -#define GSMTDMA_H - - -#include "GSMCommon.h" - - -namespace GSM { - - -/** - A description of a channel's multiplexing pattern. - From GSM 05.02 Clause 7. - This object encodes a line from tables 1-4 in the spec. - The columns of interest in this encoding are: - - 1, Channel Designation - - 2, Subchannel - - 3, Direction - - 4, Allowable Time Slot Assignments - - 5, Allowable RF Channel Assignments - - 7, Repeat Length in TDMA Frames - - 8, Interleaved Block TDMA Frame Mapping - - Col 6, Burst Type, is implied by 1 & 2 and encoded into the transcevier source code. -*/ -class TDMAMapping { - - public: - - /// The longest "repeat length" of any channel we support is 104 for the SACCH/TF. - static const unsigned mMaxRepeatLength = 104; - - private: - - TypeAndOffset mTypeAndOffset; ///< col 1, 2, encoded as per GSM 04.08 10.5.2.5 - bool mDownlink; ///< col 3, true for downlink channels - bool mUplink; ///< col 3, true for uplink channels - char mAllowedSlots; ///< col 4, an 8-bit mask - bool mC0Only; ///< col 5, true if channel is limited to C0 - unsigned mRepeatLength; ///< col 7 - unsigned mNumFrames; ///< number of occupied frames in col 8 - const unsigned *mFrameMapping; ///< col 8 - unsigned mReverseMapping[mMaxRepeatLength]; ///< index reversal of mapping, -1 means unused - - - public: - - - /** - Construct a TDMAMapping, encoding one line of GSM 05.02 Clause 7 Tables 1-4. - @param wTypeAndOffset Encoding of "Channel designnation". See GSM 04.08 10.5.2.5. - @param wDownlink True for downlink and bidirectional hannels - @param wUplink True for uplink and bidirectional channels - @param wRepeatLength "Repeat Length in TDMA Frames" - @param wNumFrames Number of occupied TDMA frames in frame mapping. - @param wFrameMapping "Interleaved Block TDMA Frame Mapping" -- MUST PERSIST!! - */ - TDMAMapping(TypeAndOffset wTypeAndOffset, - bool wDownlink, bool wUplink, char wAllowedSlots, bool wC0Only, - unsigned wRepeatLength, unsigned wNumFrames, const unsigned *wFrameMapping); - - /** Given a count of frames sent, return the corresponding frame number. */ - unsigned frameMapping(unsigned count) const - { return mFrameMapping[count % mNumFrames]; } - - /** Given a frame number, return the corresponding count, modulo patten length. */ - int reverseMapping(unsigned FN) const - { return mReverseMapping[FN % mRepeatLength]; } - - /**@name Simple accessors. */ - //@{ - unsigned numFrames() const { return mNumFrames; } - - unsigned repeatLength() const { return mRepeatLength; } - - TypeAndOffset typeAndOffset() const { return mTypeAndOffset; } - - bool uplink() const { return mUplink; } - - bool downlink() const { return mDownlink; } - - bool C0Only() const { return mC0Only; } - //@} - - ///< Return true if this channel is allowed on this slot. - bool allowedSlot(unsigned slot) const - { return mAllowedSlots & (1<. - -*/ - - - - -#include "Threads.h" -#include "Timeval.h" - - -using namespace std; - - - - -Mutex gStreamLock; ///< Global lock to control access to cout and cerr. - -void lockCout() -{ - gStreamLock.lock(); - Timeval entryTime; - cout << entryTime << " " << pthread_self() << ": "; -} - - -void unlockCout() -{ - cout << dec << endl << flush; - gStreamLock.unlock(); -} - - -void lockCerr() -{ - gStreamLock.lock(); - Timeval entryTime; - cerr << entryTime << " " << pthread_self() << ": "; -} - -void unlockCerr() -{ - cerr << dec << endl << flush; - gStreamLock.unlock(); -} - - - - - - - -Mutex::Mutex() -{ - assert(!pthread_mutexattr_init(&mAttribs)); - assert(!pthread_mutexattr_settype(&mAttribs,PTHREAD_MUTEX_RECURSIVE)); - assert(!pthread_mutex_init(&mMutex,&mAttribs)); -} - - -Mutex::~Mutex() -{ - pthread_mutex_destroy(&mMutex); - assert(!pthread_mutexattr_destroy(&mAttribs)); -} - - - - -/** Block for the signal up to the cancellation timeout. */ -void Signal::wait(Mutex& wMutex, unsigned timeout) const -{ - struct timespec waitTime = Timeval(timeout).timespec(); - // FIXME -- With -O3 optimzation in OS X this doesn't block. See bug #320. - pthread_cond_timedwait(&mSignal,&wMutex.mMutex,&waitTime); -} - - -void Thread::start(void *(*task)(void*), void *arg) -{ - assert(mThread==((pthread_t)0)); - assert(!pthread_attr_init(&mAttrib)); - assert(!pthread_attr_setstacksize(&mAttrib, mStackSize)); - assert(!pthread_create(&mThread, &mAttrib, task, arg)); -} - - - -// vim: ts=4 sw=4 diff --git a/src/lib/decoder/openbtsstuff/Threads.h b/src/lib/decoder/openbtsstuff/Threads.h deleted file mode 100644 index 14cff04..0000000 --- a/src/lib/decoder/openbtsstuff/Threads.h +++ /dev/null @@ -1,150 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 . - -*/ - - -#ifndef THREADS_H -#define THREADS_H - - -#include -#include -#include "Assert.h" - -class Mutex; - - -/**@name Multithreaded access for standard streams. */ -//@{ - -/**@name Functions for gStreamLock. */ -//@{ -extern Mutex gStreamLock; ///< global lock for cout and cerr -void lockCerr(); ///< call prior to writing cerr -void unlockCerr(); ///< call after writing cerr -void lockCout(); ///< call prior to writing cout -void unlockCout(); ///< call after writing cout -//@} - -/**@name Macros for standard messages. */ -//@{ -#define COUT(text) { lockCout(); std::cout << text; unlockCout(); } -#define CERR(text) { lockCerr(); std::cerr << __FILE__ << ":" << __LINE__ << ": " << text; unlockCerr(); } -#ifdef NDEBUG -#define DCOUT(text) {} -#define OBJDCOUT(text) {} -#else -#define DCOUT(text) { COUT(__FILE__ << ":" << __LINE__ << " " << text); } -#define OBJDCOUT(text) { DCOUT(this << " " << text); } -#endif -//@} -//@} - - - -/**@defgroup C++ wrappers for pthread mechanisms. */ -//@{ - -/** A class for recursive mutexes based on pthread_mutex. */ -class Mutex { - - private: - - pthread_mutex_t mMutex; - pthread_mutexattr_t mAttribs; - - public: - - Mutex(); - - ~Mutex(); - - void lock() { pthread_mutex_lock(&mMutex); } - - void unlock() { pthread_mutex_unlock(&mMutex); } - - friend class Signal; - -}; - - - -/** A C++ interthread signal based on pthread condition variables. */ -class Signal { - - private: - - mutable pthread_cond_t mSignal; - - public: - - Signal() { assert(!pthread_cond_init(&mSignal,NULL)); } - - ~Signal() { pthread_cond_destroy(&mSignal); } - - /** Block for the signal up to the cancellation timeout. */ - void wait(Mutex& wMutex, unsigned timeout=1000000000) const; - - void signal() { pthread_cond_signal(&mSignal); } - - void broadcast() { pthread_cond_broadcast(&mSignal); } - -}; - - - -#define START_THREAD(thread,function,argument) \ - thread.start((void *(*)(void*))function, (void*)argument); - -/** A C++ wrapper for pthread threads. */ -class Thread { - - private: - - pthread_t mThread; - pthread_attr_t mAttrib; - const static size_t mStackSize=4*65536; - - - public: - - /** Create a thread in a non-running state. */ - Thread():mThread((pthread_t)0) { } - - /** - Destroy the Thread. - It should be stopped and joined. - */ - ~Thread() { assert(!pthread_attr_destroy(&mAttrib)); } - - - /** Start the thread on a task. */ - void start(void *(*task)(void*), void *arg); - - /** Join a thread that will stop on its own. */ - void join() { assert(!pthread_join(mThread,NULL)); } - -}; - - - - -#endif -// vim: ts=4 sw=4 diff --git a/src/lib/decoder/openbtsstuff/Timeval.cpp b/src/lib/decoder/openbtsstuff/Timeval.cpp deleted file mode 100644 index e7590cb..0000000 --- a/src/lib/decoder/openbtsstuff/Timeval.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 "Timeval.h" - -using namespace std; - -void Timeval::future(unsigned offset) -{ - now(); - unsigned sec = offset/1000; - unsigned msec = offset%1000; - mTimeval.tv_usec += msec*1000; - mTimeval.tv_sec += sec; - if (mTimeval.tv_usec>1000000) { - mTimeval.tv_usec -= 1000000; - mTimeval.tv_sec += 1; - } -} - - -struct timespec Timeval::timespec() const -{ - struct timespec retVal; - retVal.tv_sec = mTimeval.tv_sec; - retVal.tv_nsec = 1000 * (long)mTimeval.tv_usec; - return retVal; -} - - -bool Timeval::passed() const -{ - Timeval nowTime; - if (nowTime.mTimeval.tv_sec < mTimeval.tv_sec) return false; - if (nowTime.mTimeval.tv_sec > mTimeval.tv_sec) return true; - if (nowTime.mTimeval.tv_usec > mTimeval.tv_usec) return true; - return false; -} - -double Timeval::seconds() const -{ - return ((double)mTimeval.tv_sec) + 1e-6*((double)mTimeval.tv_usec); -} - - - -long Timeval::delta(const Timeval& other) const -{ - long deltaS = other.sec() - sec(); - long deltaUs = other.usec() - usec(); - return 1000*deltaS + deltaUs/1000; -} - - - - -ostream& operator<<(ostream& os, const Timeval& tv) -{ - os.setf( ios::fixed, ios::floatfield ); - os << tv.seconds(); - return os; -} - - -ostream& operator<<(ostream& os, const struct timespec& ts) -{ - os << ts.tv_sec << "," << ts.tv_nsec; - return os; -} - - - -// vim: ts=4 sw=4 diff --git a/src/lib/decoder/openbtsstuff/Timeval.h b/src/lib/decoder/openbtsstuff/Timeval.h deleted file mode 100644 index 44618bc..0000000 --- a/src/lib/decoder/openbtsstuff/Timeval.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 . - -*/ - - -#ifndef TIMEVAL_H -#define TIMEVAL_H - -#include "sys/time.h" -#include - - - -inline void msleep(long v) { usleep((v+500)/1000); } - - -/** A C++ wrapper for struct timeval. */ -class Timeval { - - private: - - struct timeval mTimeval; - - public: - - /** Set the value to gettimeofday. */ - void now() { gettimeofday(&mTimeval,NULL); } - - /** Set the value to gettimeofday plus an offset. */ - void future(unsigned offset); - - //@{ - Timeval(unsigned sec, unsigned usec) - { - mTimeval.tv_sec = sec; - mTimeval.tv_usec = usec; - } - - Timeval(const struct timeval& wTimeval) - :mTimeval(wTimeval) - {} - - /** - Create a Timeval offset into the future. - @param offset milliseconds - */ - Timeval(unsigned offset=0) { future(offset); } - //@} - - /** Convert to a struct timespec. */ - struct timespec timespec() const; - - /** Return total seconds. */ - double seconds() const; - - uint32_t sec() const { return mTimeval.tv_sec; } - uint32_t usec() const { return mTimeval.tv_usec; } - - /** Return differnce from other (other-self), in ms. */ - long delta(const Timeval& other) const; - - /** Elapsed time in ms. */ - long elapsed() const { return delta(Timeval()); } - - /** Remaining time in ms. */ - long remaining() const { return -elapsed(); } - - /** Return true if the time has passed, as per gettimeofday. */ - bool passed() const; - -}; - -std::ostream& operator<<(std::ostream& os, const Timeval&); - -std::ostream& operator<<(std::ostream& os, const struct timespec&); - - -#endif -// vim: ts=4 sw=4 diff --git a/src/lib/decoder/openbtsstuff/Vector.h b/src/lib/decoder/openbtsstuff/Vector.h deleted file mode 100644 index cec278a..0000000 --- a/src/lib/decoder/openbtsstuff/Vector.h +++ /dev/null @@ -1,257 +0,0 @@ -/**@file Simplified Vector template with aliases. */ -/* -* Copyright 2008 Free Software Foundation, Inc. -* -* This software is distributed under the terms of the GNU Public License. -* See the COPYING file in the main directory for details. - - 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 . - -*/ - - - - -#ifndef VECTOR_H -#define VECTOR_H - -#include -#include -#include "Assert.h" - - -/** - A simplified Vector template with aliases. - Unlike std::vector, this class does not support dynamic resizing. - Unlike std::vector, this class does support "aliases" and subvectors. -*/ -template class Vector { - - // TODO -- Replace memcpy calls with for-loops. - - public: - - /**@name Iterator types. */ - //@{ - typedef T* iterator; - typedef const T* const_iterator; - //@} - - protected: - - T* mData; ///< allocated data block, if any - T* mStart; ///< start of useful data - T* mEnd; ///< end of useful data + 1 - - public: - - /** Return the size of the Vector. */ - size_t size() const - { - assert(mStart>=mData); - assert(mEnd>=mStart); - return mEnd - mStart; - } - - /** Return size in bytes. */ - size_t bytes() const { return size()*sizeof(T); } - - /** Change the size of the Vector, discarding content. */ - void resize(size_t newSize) - { - if (mData!=NULL) delete[] mData; - if (newSize==0) mData=NULL; - else mData = new T[newSize]; - mStart = mData; - mEnd = mStart + newSize; - } - - /** Release memory and clear pointers. */ - void clear() { resize(0); } - - - /** Copy data from another vector. */ - void clone(const Vector& other) - { - resize(other.size()); - memcpy(mData,other.mStart,other.bytes()); - } - - - - - //@{ - - /** Build an empty Vector of a given size. */ - Vector(size_t wSize=0):mData(NULL) { resize(wSize); } - - /** Build a Vector by shifting the data block. */ - Vector(Vector& other) - :mData(other.mData),mStart(other.mStart),mEnd(other.mEnd) - { other.mData=NULL; } - - /** Build a Vector by copying another. */ - Vector(const Vector& other):mData(NULL) { clone(other); } - - /** Build a Vector with explicit values. */ - Vector(T* wData, T* wStart, T* wEnd) - :mData(wData),mStart(wStart),mEnd(wEnd) - { } - - /** Build a vector from an existing block, NOT to be deleted upon destruction. */ - Vector(T* wStart, size_t span) - :mData(NULL),mStart(wStart),mEnd(wStart+span) - { } - - /** Build a Vector by concatenation. */ - Vector(const Vector& other1, const Vector& other2) - :mData(NULL) - { - resize(other1.size()+other2.size()); - memcpy(mStart, other1.mStart, other1.bytes()); - memcpy(mStart+other1.size(), other2.mStart, other2.bytes()); - } - - //@} - - /** Destroy a Vector, deleting held memory. */ - ~Vector() { clear(); } - - - - - //@{ - - /** Assign from another Vector, shifting ownership. */ - void operator=(Vector& other) - { - clear(); - mData=other.mData; - mStart=other.mStart; - mEnd=other.mEnd; - other.mData=NULL; - } - - /** Assign from another Vector, copying. */ - void operator=(const Vector& other) { clone(other); } - - //@} - - - //@{ - - /** Return an alias to a segment of this Vector. */ - Vector segment(size_t start, size_t span) - { - T* wStart = mStart + start; - T* wEnd = wStart + span; - assert(wEnd<=mEnd); - return Vector(NULL,wStart,wEnd); - } - - /** Return an alias to a segment of this Vector. */ - const Vector segment(size_t start, size_t span) const - { - T* wStart = mStart + start; - T* wEnd = wStart + span; - assert(wEnd<=mEnd); - return Vector(NULL,wStart,wEnd); - } - - Vector head(size_t span) { return segment(0,span); } - const Vector head(size_t span) const { return segment(0,span); } - Vector tail(size_t start) { return segment(start,size()-start); } - const Vector tail(size_t start) const { return segment(start,size()-start); } - - /** - Copy part of this Vector to a segment of another Vector. - @param other The other vector. - @param start The start point in the other vector. - @param span The number of elements to copy. - */ - void copyToSegment(Vector& other, size_t start, size_t span) const - { - T* base = other.mStart + start; - assert(base+span<=other.mEnd); - assert(mStart+span<=mEnd); - memcpy(base,mStart,span*sizeof(T)); - } - - /** Copy all of this Vector to a segment of another Vector. */ - void copyToSegment(Vector& other, size_t start=0) const { copyToSegment(other,start,size()); } - - void copyTo(Vector& other) const { copyToSegment(other,0,size()); } - - /** - Copy a segment of this vector into another. - @param other The other vector (to copt into starting at 0.) - @param start The start point in this vector. - @param span The number of elements to copy. - */ - void segmentCopyTo(Vector& other, size_t start, size_t span) - { - T* base = mStart + start; - assert(base+span<=mEnd); - assert(other.mStart+span<=other.mEnd); - memcpy(other.mStart,base,span*sizeof(T)); - } - - void fill(const T& val) - { - T* dp=mStart; - while (dp -std::ostream& operator<<(std::ostream& os, const Vector& v) -{ - for (unsigned i=0; i - */ - -#include -#include -#include -#include -#include -#include - -#include "out_pcap.h" -#include "gsmtap.h" - -#ifndef LINKTYPE_GSMTAP -#define LINKTYPE_GSMTAP 2342 -#endif - -#define TCPDUMP_MAGIC 0xa1b2c3d4 - -struct pcap_timeval { - int32_t tv_sec; - int32_t tv_usec; -}; - -struct pcap_sf_pkthdr { - struct pcap_timeval ts; /* time stamp */ - u_int32_t caplen; /* lenght of portion present */ - u_int32_t len; /* length of this packet */ -}; - -static int write_pcap_file_header(int fd) -{ - struct pcap_file_header pfh; - - pfh.magic = TCPDUMP_MAGIC; - pfh.version_major = PCAP_VERSION_MAJOR; - pfh.version_minor = PCAP_VERSION_MINOR; - pfh.thiszone = timezone; - pfh.sigfigs = 0; - pfh.snaplen = 1024; /* FIXME */ - pfh.linktype = LINKTYPE_GSMTAP; - - if (write(fd, &pfh, sizeof(pfh)) < sizeof(pfh)) - return -1; - - return 0; -} - -/* open pcap file and write header */ -int open_pcap_file(char *fname) -{ - int fd; - int rc; - - fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0660); - if (fd < 0) - return fd; - - rc = write_pcap_file_header(fd); - if (rc < 0) { - close(fd); - fd = -EIO; - } - - return fd; -} - -int write_pcap_packet(int fd, int arfcn, int ts, int fn, - int burst, int burst_type, - const unsigned char *data, unsigned int len) -{ - unsigned char buf[8192]; - struct pcap_sf_pkthdr *ph; - struct gsmtap_hdr *gh; - struct timeval tv; - int rc; - - if (fd < 0) - return -EINVAL; - - ph = (struct pcap_sf_pkthdr *) &buf[0]; - gh = (struct gsmtap_hdr *) &buf[sizeof(struct pcap_sf_pkthdr)]; - - gettimeofday(&tv, NULL); - - ph->ts.tv_sec = tv.tv_sec; - ph->ts.tv_usec = tv.tv_usec; - ph->caplen = ph->len = len + sizeof(struct gsmtap_hdr); - - gh->version = GSMTAP_VERSION; - gh->hdr_len = sizeof(struct gsmtap_hdr)>>2; - if (burst) - gh->type = GSMTAP_TYPE_UM_BURST; - else - gh->type = GSMTAP_TYPE_UM; - gh->timeslot = ts; - gh->arfcn = htons(arfcn); - /* we don't support signal/noise yet */ - gh->noise_db = gh->signal_db = 0; - gh->frame_number = htonl(fn); - gh->burst_type = burst_type & 0xff; - - memcpy(buf + sizeof(*ph) + sizeof(*gh), data, len); - - rc = write(fd, buf, sizeof(*ph) + sizeof(*gh) + len); - - //fsync(fd); - - return rc; -} diff --git a/src/lib/decoder/out_pcap.h b/src/lib/decoder/out_pcap.h deleted file mode 100644 index 5ae5e3c..0000000 --- a/src/lib/decoder/out_pcap.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _PCAP_IF_H -#define _PCAP_IF_H - -extern int open_pcap_file(char *fname); - -int write_pcap_packet(int fd, int arfcn, int ts, int fn, - int burst, int burst_type, - const unsigned char *data, unsigned int len); -#endif diff --git a/src/lib/decoder/sch.c b/src/lib/decoder/sch.c deleted file mode 100644 index 6f141dd..0000000 --- a/src/lib/decoder/sch.c +++ /dev/null @@ -1,333 +0,0 @@ -#include "system.h" -#include -#include -#include -#include -#include "gsm_constants.h" - -/* - * Synchronization channel. - * - * Timeslot Repeat length Frame Number (mod repeat length) - * 0 51 1, 11, 21, 31, 41 - */ - -/* - * Parity (FIRE) for the GSM SCH. - * - * g(x) = x^10 + x^8 + x^6 + x^5 + x^4 + x^2 + 1 - */ -#define DATA_BLOCK_SIZE 25 -#define PARITY_SIZE 10 -#define TAIL_BITS_SIZE 4 -#define PARITY_OUTPUT_SIZE (DATA_BLOCK_SIZE + PARITY_SIZE + TAIL_BITS_SIZE) - -static const unsigned char parity_polynomial[PARITY_SIZE + 1] = { - 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 -}; - -static const unsigned char parity_remainder[PARITY_SIZE] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -}; - - -static void parity_encode(unsigned char *d, unsigned char *p) -{ - - unsigned int i; - unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q; - - memcpy(buf, d, DATA_BLOCK_SIZE); - memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE); - - for (q = buf; q < buf + DATA_BLOCK_SIZE; q++) - if (*q) - for (i = 0; i < PARITY_SIZE + 1; i++) - q[i] ^= parity_polynomial[i]; - for (i = 0; i < PARITY_SIZE; i++) - p[i] = !buf[DATA_BLOCK_SIZE + i]; -} - - -static int parity_check(unsigned char *d) -{ - - unsigned int i; - unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q; - - memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE); - - for (q = buf; q < buf + DATA_BLOCK_SIZE; q++) - if (*q) - for (i = 0; i < PARITY_SIZE + 1; i++) - q[i] ^= parity_polynomial[i]; - return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE); -} - - -/* - * Convolutional encoding and Viterbi decoding for the GSM SCH. - * (Equivalent to the GSM SACCH.) - * - * G_0 = 1 + x^3 + x^4 - * G_1 = 1 + x + x^3 + x^4 - * - * i.e., - * - * c_{2k} = u_k + u_{k - 3} + u_{k - 4} - * c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4} - */ -#define CONV_INPUT_SIZE PARITY_OUTPUT_SIZE -#define CONV_SIZE (2 * CONV_INPUT_SIZE) -#define K 5 -#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1) - - -/* - * Given the current state and input bit, what are the output bits? - * - * encode[current_state][input_bit] - */ -static const unsigned int encode[1 << (K - 1)][2] = { - {0, 3}, {3, 0}, {3, 0}, {0, 3}, - {0, 3}, {3, 0}, {3, 0}, {0, 3}, - {1, 2}, {2, 1}, {2, 1}, {1, 2}, - {1, 2}, {2, 1}, {2, 1}, {1, 2} -}; - - -/* - * Given the current state and input bit, what is the next state? - * - * next_state[current_state][input_bit] - */ -static const unsigned int next_state[1 << (K - 1)][2] = { - {0, 8}, {0, 8}, {1, 9}, {1, 9}, - {2, 10}, {2, 10}, {3, 11}, {3, 11}, - {4, 12}, {4, 12}, {5, 13}, {5, 13}, - {6, 14}, {6, 14}, {7, 15}, {7, 15} -}; - - -/* - * Given the previous state and the current state, what input bit caused - * the transition? If it is impossible to transition between the two - * states, the value is 2. - * - * prev_next_state[previous_state][current_state] - */ -static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = { - { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2}, - { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2}, - { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2}, - { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2}, - { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2}, - { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2}, - { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2}, - { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2}, - { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2}, - { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2}, - { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2}, - { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2}, - { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2}, - { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2}, - { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}, - { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1} -}; - - -static inline unsigned int hamming_distance2(unsigned int w) -{ - - return (w & 1) + !!(w & 2); -} - - -static void conv_encode(unsigned char *data, unsigned char *output) -{ - - unsigned int i, state = 0, o; - - // encode data - for (i = 0; i < CONV_INPUT_SIZE; i++) { - o = encode[state][data[i]]; - state = next_state[state][data[i]]; - *output++ = !!(o & 2); - *output++ = o & 1; - } -} - - -static int conv_decode(unsigned char *data, unsigned char *output) -{ - - int i, t; - unsigned int rdata, state, nstate, b, o, distance, accumulated_error, - min_state, min_error, cur_state; - - unsigned int ae[1 << (K - 1)]; - unsigned int nae[1 << (K - 1)]; // next accumulated error - unsigned int state_history[1 << (K - 1)][CONV_INPUT_SIZE + 1]; - - // initialize accumulated error, assume starting state is 0 - for (i = 0; i < (1 << (K - 1)); i++) - ae[i] = nae[i] = MAX_ERROR; - ae[0] = 0; - - // build trellis - for (t = 0; t < CONV_INPUT_SIZE; t++) { - - // get received data symbol - rdata = (data[2 * t] << 1) | data[2 * t + 1]; - - // for each state - for (state = 0; state < (1 << (K - 1)); state++) { - - // make sure this state is possible - if (ae[state] >= MAX_ERROR) - continue; - - // find all states we lead to - for (b = 0; b < 2; b++) { - - // get next state given input bit b - nstate = next_state[state][b]; - - // find output for this transition - o = encode[state][b]; - - // calculate distance from received data - distance = hamming_distance2(rdata ^ o); - - // choose surviving path - accumulated_error = ae[state] + distance; - if (accumulated_error < nae[nstate]) { - - // save error for surviving state - nae[nstate] = accumulated_error; - - // update state history - state_history[nstate][t + 1] = state; - } - } - } - - // get accumulated error ready for next time slice - for (i = 0; i < (1 << (K - 1)); i++) { - ae[i] = nae[i]; - nae[i] = MAX_ERROR; - } - } - - // the final state is the state with the fewest errors - min_state = (unsigned int) - 1; - min_error = MAX_ERROR; - for (i = 0; i < (1 << (K - 1)); i++) { - if (ae[i] < min_error) { - min_state = i; - min_error = ae[i]; - } - } - - // trace the path - cur_state = min_state; - for (t = CONV_INPUT_SIZE; t >= 1; t--) { - min_state = cur_state; - cur_state = state_history[cur_state][t]; // get previous - output[t - 1] = prev_next_state[cur_state][min_state]; - } - - // return the number of errors detected (hard-decision) - return min_error; -} - - -int decode_sch(const unsigned char *buf, int * t1_o, int * t2_o, int * t3_o, int * ncc_o, int * bcc_o) -{ - - int errors, t1, t2, t3p, t3, ncc, bcc; - unsigned char data[CONV_SIZE], decoded_data[PARITY_OUTPUT_SIZE]; - - // extract encoded data from synchronization burst - /* buf, 39 bit */ - /* buf + 39 + 64 = 103, 39 */ - memcpy(data, buf, SCH_DATA_LEN); - memcpy(data + SCH_DATA_LEN, buf + SCH_DATA_LEN + N_SYNC_BITS, SCH_DATA_LEN); - - // Viterbi decode - if (errors = conv_decode(data, decoded_data)) { - // fprintf(stderr, "error: sch: conv_decode (%d)\n", errors); - DEBUGF("ERR: conv_decode %d\n", errors); - return errors; - } - - // check parity - if (parity_check(decoded_data)) { - // fprintf(stderr, "error: sch: parity failed\n"); - DEBUGF("ERR: parity_check failed\n"); - return 1; - } - - // Synchronization channel information, 44.018 page 171. (V7.2.0) - ncc = - (decoded_data[ 7] << 2) | - (decoded_data[ 6] << 1) | - (decoded_data[ 5] << 0); - bcc = - (decoded_data[ 4] << 2) | - (decoded_data[ 3] << 1) | - (decoded_data[ 2] << 0); - t1 = - (decoded_data[ 1] << 10) | - (decoded_data[ 0] << 9) | - (decoded_data[15] << 8) | - (decoded_data[14] << 7) | - (decoded_data[13] << 6) | - (decoded_data[12] << 5) | - (decoded_data[11] << 4) | - (decoded_data[10] << 3) | - (decoded_data[ 9] << 2) | - (decoded_data[ 8] << 1) | - (decoded_data[23] << 0); - t2 = - (decoded_data[22] << 4) | - (decoded_data[21] << 3) | - (decoded_data[20] << 2) | - (decoded_data[19] << 1) | - (decoded_data[18] << 0); - t3p = - (decoded_data[17] << 2) | - (decoded_data[16] << 1) | - (decoded_data[24] << 0); - - t3 = 10 * t3p + 1; - - // modulo arithmetic t3 - t2 mod 26 -// tt = ((t3 + 26) - t2) % 26; - -// fn = (51 * 26 * t1) + (51 * tt) + t3; - - /* - * BSIC: Base Station Identification Code - * BCC: Base station Color Code - * NCC: Network Color Code - * - * FN: Frame Number - */ - -// printf("bsic: %x (bcc: %u; ncc: %u)\tFN: %u\n", bsic, bsic & 7, -// (bsic >> 3) & 7, fn); - -// if (fn_o) -// *fn_o = fn; -// if (bsic_o) - if (t1_o && t2_o && t3_o && ncc_o && bcc_o) { - *t1_o = t1; - *t2_o = t2; - *t3_o = t3; - *bcc_o = bcc; - *ncc_o = ncc; - } - - return 0; -} diff --git a/src/lib/decoder/sch.h b/src/lib/decoder/sch.h deleted file mode 100644 index 4d47eb5..0000000 --- a/src/lib/decoder/sch.h +++ /dev/null @@ -1,17 +0,0 @@ - -#ifndef __SCH_H__ -#define __SCH_H__ 1 - -#ifdef __cplusplus -extern "C" -{ -#endif - - int decode_sch(const unsigned char *buf, int * t1_o, int * t2_o, int * t3_o, int * ncc, int * bcc); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/lib/decoder/system.h b/src/lib/decoder/system.h deleted file mode 100644 index 414730a..0000000 --- a/src/lib/decoder/system.h +++ /dev/null @@ -1,11 +0,0 @@ - -#ifndef __GSMTVOID_SYSTEM_H__ -#define __GSMTVOID_SYSTEM_H__ 1 - -#define DEBUGF(a...) { \ - fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ - fprintf(stderr, a); \ -} while (0) - -#endif - diff --git a/src/lib/decoder/tun.c b/src/lib/decoder/tun.c deleted file mode 100644 index 2abda90..0000000 --- a/src/lib/decoder/tun.c +++ /dev/null @@ -1,125 +0,0 @@ -// $Id: tun.cc,v 1.2 2007-07-07 16:31:42 jl Exp $ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int mktun(const char *chan_name, unsigned char *ether_addr) { - - struct ifreq ifr; - // struct ifreq ifw; - char if_name[IFNAMSIZ]; - int fd, one = 1; - // int sd; - - // construct TUN interface - if((fd = open("/dev/net/tun", O_RDWR)) == -1) { - perror("open"); - return -1; - } - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", chan_name); - if(ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) { - perror("TUNSETIFF"); - close(fd); - return -1; - } - - // save actual name - memcpy(if_name, ifr.ifr_name, IFNAMSIZ); - - // get ether addr - memset(&ifr, 0, sizeof(ifr)); - memcpy(ifr.ifr_name, if_name, IFNAMSIZ); - if(ioctl(fd, SIOCGIFHWADDR, (void *)&ifr) == -1) { - perror("SIOCGIFHWADDR"); - close(fd); - return -1; - } - memcpy(ether_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - // set persistent - if(ioctl(fd, TUNSETPERSIST, (void *)&one) == -1) { - perror("TUNSETPERSIST"); - close(fd); - return -1; - } - - // set interface up - /* XXX must be root - if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - perror("socket"); - close(fd); - return -1; - } - - // get current flags - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1); - if(ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) { - perror("SIOCGIFFLAGS"); - close(sd); - close(fd); - return -1; - } - - // set up - memset(&ifw, 0, sizeof(ifw)); - strncpy(ifw.ifr_name, if_name, IFNAMSIZ - 1); - ifw.ifr_flags = ifr.ifr_flags | IFF_UP | IFF_RUNNING; - if(ioctl(sd, SIOCSIFFLAGS, &ifw) == -1) { - perror("SIOCSIFFLAGS"); - close(sd); - close(fd); - return -1; - } - close(sd); - */ - - return fd; -} - - -static inline int min(int a, int b) { - - return (a < b)? a : b; -} - - -static const unsigned int DEFAULT_MTU = 1500; -static const unsigned short ether_type = 0xfed5; // current dtap ethertype - -int write_interface(int fd, unsigned char *data, unsigned int data_len, - unsigned char *ether_addr) { - - unsigned char frame[DEFAULT_MTU]; // XXX buffer overflow? - struct ethhdr eh; - - if(fd < 0) - return data_len; - - memcpy(eh.h_dest, ether_addr, ETH_ALEN); - memcpy(eh.h_source, ether_addr, ETH_ALEN); - eh.h_proto = htons(ether_type); - - memcpy(frame, &eh, sizeof(eh)); - memcpy(frame + sizeof(eh), data, - min(data_len, sizeof(frame) - sizeof(eh))); - - if(write(fd, frame, sizeof(eh) + data_len) == -1) { - perror("write"); - return -1; - } - - return data_len; -} diff --git a/src/lib/decoder/tun.h b/src/lib/decoder/tun.h deleted file mode 100644 index a7868c4..0000000 --- a/src/lib/decoder/tun.h +++ /dev/null @@ -1,4 +0,0 @@ -// $Id: tun.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $ - -int mktun(const char *, unsigned char *); -int write_interface(int, unsigned char *, unsigned int, unsigned char *); diff --git a/src/lib/gsm.i b/src/lib/gsm.i deleted file mode 100644 index 3a5c561..0000000 --- a/src/lib/gsm.i +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author Piotr Krysik - * @section LICENSE - * - * 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, 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -%feature("autodoc", "1"); // generate python docstrings - -%include "exception.i" -%import "gnuradio.i" // the common stuff - -/* %include "gsm_constants.h" */ - -%{ -#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix -#include "gsm_receiver_cf.h" -#include -/* #include "gsm_constants.h" */ -%} - -// ---------------------------------------------------------------- - -GR_SWIG_BLOCK_MAGIC(gsm,receiver_cf); - -gsm_receiver_cf_sptr gsm_make_receiver_cf ( gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key); - -class gsm_receiver_cf : public gr_block -{ -private: - gsm_receiver_cf ( gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr); -}; - -// ---------------------------------------------------------------- diff --git a/src/lib/gsm_constants.h b/src/lib/gsm_constants.h deleted file mode 100644 index 939099d..0000000 --- a/src/lib/gsm_constants.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef INCLUDED_GSM_CONSTANTS_H -#define INCLUDED_GSM_CONSTANTS_H - -#define GSM_SYMBOL_RATE (1625000.0/6.0) //symbols per second -#define GSM_SYMBOL_PERIOD (1.0/GSM_SYMBOL_RATE) //seconds per symbol - -//Burst timing -#define TAIL_BITS 3 -#define GUARD_BITS 8 -#define GUARD_FRACTIONAL 0.25 //fractional part of guard period -#define GUARD_PERIOD GUARD_BITS + GUARD_FRACTIONAL -#define DATA_BITS 57 //size of 1 data block in normal burst -#define STEALING_BIT 1 -#define N_TRAIN_BITS 26 -#define N_SYNC_BITS 64 -#define USEFUL_BITS 142 //(2*(DATA_BITS+STEALING_BIT) + N_TRAIN_BITS ) -#define FCCH_BITS USEFUL_BITS -#define BURST_SIZE (USEFUL_BITS+2*TAIL_BITS) - -#define SCH_DATA_LEN 39 -#define TS_BITS (TAIL_BITS+USEFUL_BITS+TAIL_BITS+GUARD_BITS) //a full TS (156 bits) -#define TS_PER_FRAME 8 -#define FRAME_BITS (TS_PER_FRAME * TS_BITS + 2) // 156.25 * 8 -#define FCCH_POS TAIL_BITS -#define SYNC_POS 39 -#define TRAIN_POS ( TAIL_BITS + (DATA_BITS+STEALING_BIT) + 5) //first 5 bits of a training sequence - //aren't used for channel impulse response estimation -#define TRAIN_BEGINNING 5 -#define SAFETY_MARGIN 6 // - -#define FCCH_HITS_NEEDED (USEFUL_BITS - 4) -#define FCCH_MAX_MISSES 1 -#define FCCH_MAX_FREQ_OFFSET 100 - -#define CHAN_IMP_RESP_LENGTH 5 - -#define MAX_SCH_ERRORS 5 //maximum number of subsequent sch errors after which gsm receiver goes to find_next_fcch state - -typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy, dummy_or_normal} burst_type; -typedef enum {unknown, multiframe_26, multiframe_51} multiframe_type; - -static const unsigned char SYNC_BITS[] = { - 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, - 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1 -}; - -const unsigned FCCH_FRAMES[] = {0, 10, 20, 30, 40}; -const unsigned SCH_FRAMES[] = {1, 11, 21, 31, 41}; - -const unsigned BCCH_FRAMES[] = {2, 3, 4, 5}; //!!the receiver shouldn't care about logical - //!!channels so this will be removed from this header -const unsigned TEST_CCH_FRAMES[] = {2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 49}; -const unsigned TRAFFIC_CHANNEL_F[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; -const unsigned TEST51[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50}; - - -#define TSC0 0 -#define TSC1 1 -#define TSC2 2 -#define TSC3 3 -#define TSC4 4 -#define TSC5 5 -#define TSC6 6 -#define TSC7 7 -#define TS_DUMMY 8 - -#define TRAIN_SEQ_NUM 9 - -#define TIMESLOT0 0 -#define TIMESLOT1 1 -#define TIMESLOT2 2 -#define TIMESLOT3 3 -#define TIMESLOT4 4 -#define TIMESLOT5 5 -#define TIMESLOT6 6 -#define TIMESLOT7 7 - - -static const unsigned char train_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS] = { - {0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, - {0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, - {0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0}, - {0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0}, - {0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1}, - {0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0}, - {1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1}, - {1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0}, - {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1} // DUMMY -}; - - -//Dummy burst 0xFB 76 0A 4E 09 10 1F 1C 5C 5C 57 4A 33 39 E9 F1 2F A8 -static const unsigned char dummy_burst[] = { - 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, - 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, - 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, - 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 0, 0, - - 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, - 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, - 0, 0, 0, 1, 0, 1, - - 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, - 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, - 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, - 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, - 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, - 1, 1, 1, 0, 1, 0, 1, 0 -}; - - -/* - * The frequency correction burst is used for frequency synchronization - * of the mobile. This is broadcast in TS0 together with the SCH and - * BCCH. - * - * Modulating the bits below causes a spike at 62.5kHz above (below for - * COMPACT) the center frequency. One can use this spike with a narrow - * band filter to accurately determine the center of the channel. - */ -static const unsigned char fc_fb[] = { //I don't use this tables, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //I copied this here from burst_types.h because - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //the description is very informative - p.krysik - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char fc_compact_fb[] = { - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 -}; - - -#endif /* INCLUDED_GSM_CONSTANTS_H */ diff --git a/src/lib/gsm_receiver_cf.cc b/src/lib/gsm_receiver_cf.cc deleted file mode 100644 index 4742b33..0000000 --- a/src/lib/gsm_receiver_cf.cc +++ /dev/null @@ -1,853 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author Piotr Krysik - * @section LICENSE - * - * 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, 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "RxBurst.h" -#include "GSMCommon.h" - -#define SYNC_SEARCH_RANGE 30 -// #define TRAIN_SEARCH_RANGE 40 -//FIXME: decide to use this define or not - -//TODO: this shouldn't be here - remove it when gsm receiver's interface will be ready -void decrypt(const unsigned char * burst_binary, byte * KC, float * decrypted_data, unsigned FN) -{ - byte AtoB[2*DATA_BITS]; - - keysetup(KC, FN); - runA51(AtoB); - - for (int i = 0; i < 148; i++) { - decrypted_data[i] = burst_binary[i]; - } - - for (int i = 0; i < 57; i++) { - decrypted_data[i+3] = AtoB[i] ^ burst_binary[i+3]; - } - - for (int i = 0; i < 57; i++) { - decrypted_data[i+88] = AtoB[i+57] ^ burst_binary[i+88]; - } -} - -void gsm_receiver_cf::read_key(std::string key) -{ - int i; - int b; - for (i = 0;i < 8;i++) { - b = d_hex_to_int[(char)key[(i)*2]]*16 + d_hex_to_int[(char)key[i*2+1]]; - d_KC[i] = (byte)b; - } -} - -void gsm_receiver_cf::process_normal_burst(burst_counter burst_nr, const unsigned char * burst_binary) -{ -// static byte KC[] = { 0xAD, 0x6A, 0x3E, 0xC2, 0xB4, 0x42, 0xE4, 0x00 }; -// static byte KC[] = { 0x2B, 0x08, 0x74, 0x9F, 0xDD, 0x0D, 0x9C, 0x00 }; -// printf("%x", KC[0]); - float decrypted_data[148]; - unsigned char * voice_frame; - -// if (burst_nr.get_timeslot_nr() == 7) { - if (burst_nr.get_timeslot_nr() >= 1 && burst_nr.get_timeslot_nr() <= 7) { - decrypt(burst_binary, d_KC, decrypted_data, burst_nr.get_frame_nr_mod()); - - GSM::Time time(burst_nr.get_frame_nr(), burst_nr.get_timeslot_nr()); - GSM::RxBurst rxbrst(decrypted_data, time); - switch (burst_nr.get_timeslot_nr()) { - case 1: - if ( d_tch_decoder1.processBurst( rxbrst ) == true) { - fwrite(d_tch_decoder1.get_voice_frame(), 1 , 33, d_gsm_file); - } - break; - case 2: - if ( d_tch_decoder2.processBurst( rxbrst ) == true) { - fwrite(d_tch_decoder2.get_voice_frame(), 1 , 33, d_gsm_file); - } - break; - case 3: - if ( d_tch_decoder3.processBurst( rxbrst ) == true) { - fwrite(d_tch_decoder3.get_voice_frame(), 1 , 33, d_gsm_file); - } - break; - case 4: - if ( d_tch_decoder4.processBurst( rxbrst ) == true) { - fwrite(d_tch_decoder4.get_voice_frame(), 1 , 33, d_gsm_file); - } - break; - case 5: - if ( d_tch_decoder5.processBurst( rxbrst ) == true) { - fwrite(d_tch_decoder5.get_voice_frame(), 1 , 33, d_gsm_file); - } - break; - case 6: - if ( d_tch_decoder6.processBurst( rxbrst ) == true) { - fwrite(d_tch_decoder6.get_voice_frame(), 1 , 33, d_gsm_file); - } - break; - case 7: - if ( d_tch_decoder7.processBurst( rxbrst ) == true) { - fwrite(d_tch_decoder7.get_voice_frame(), 1 , 33, d_gsm_file); - } - break; - } - } - - if (burst_nr.get_timeslot_nr() == 0) { - GS_process(&d_gs_ctx, TIMESLOT0, 6, &burst_binary[3], burst_nr.get_frame_nr()); - } -} -//TODO: this shouldn't be here also - the same reason -void gsm_receiver_cf::configure_receiver() -{ - d_channel_conf.set_multiframe_type(TSC0, multiframe_51); - - d_channel_conf.set_burst_types(TSC0, TEST_CCH_FRAMES, sizeof(TEST_CCH_FRAMES) / sizeof(unsigned), normal_burst); - d_channel_conf.set_burst_types(TSC0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst); - - d_channel_conf.set_multiframe_type(TIMESLOT1, multiframe_26); - d_channel_conf.set_burst_types(TIMESLOT1, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - d_channel_conf.set_multiframe_type(TIMESLOT2, multiframe_26); - d_channel_conf.set_burst_types(TIMESLOT2, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - - d_channel_conf.set_multiframe_type(TIMESLOT3, multiframe_26); - d_channel_conf.set_burst_types(TIMESLOT3, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - d_channel_conf.set_multiframe_type(TIMESLOT4, multiframe_26); - d_channel_conf.set_burst_types(TIMESLOT4, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - - d_channel_conf.set_multiframe_type(TIMESLOT5, multiframe_26); - d_channel_conf.set_burst_types(TIMESLOT5, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - d_channel_conf.set_multiframe_type(TIMESLOT6, multiframe_26); - d_channel_conf.set_burst_types(TIMESLOT6, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - - d_channel_conf.set_multiframe_type(TIMESLOT7, multiframe_26); - d_channel_conf.set_burst_types(TIMESLOT7, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - -} - - -typedef std::list list_float; -typedef std::vector vector_float; - -typedef boost::circular_buffer circular_buffer_float; - -gsm_receiver_cf_sptr -gsm_make_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key) -{ - return gsm_receiver_cf_sptr(new gsm_receiver_cf(tuner, synchronizer, osr, key)); -} - -static const int MIN_IN = 1; // mininum number of input streams -static const int MAX_IN = 1; // maximum number of input streams -static const int MIN_OUT = 0; // minimum number of output streams -static const int MAX_OUT = 1; // maximum number of output streams - -/* - * The private constructor - */ -gsm_receiver_cf::gsm_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key) - : gr_block("gsm_receiver", - gr_make_io_signature(MIN_IN, MAX_IN, sizeof(gr_complex)), - gr_make_io_signature(MIN_OUT, MAX_OUT, 142 * sizeof(float))), - d_OSR(osr), - d_chan_imp_length(CHAN_IMP_RESP_LENGTH), - d_tuner(tuner), - d_counter(0), - d_fcch_start_pos(0), - d_freq_offset(0), - d_state(first_fcch_search), - d_burst_nr(osr), - d_failed_sch(0), - d_tch_decoder1( GSM::gFACCH_TCHFMapping ), - d_tch_decoder2( GSM::gFACCH_TCHFMapping ), - d_tch_decoder3( GSM::gFACCH_TCHFMapping ), - d_tch_decoder4( GSM::gFACCH_TCHFMapping ), - d_tch_decoder5( GSM::gFACCH_TCHFMapping ), - d_tch_decoder6( GSM::gFACCH_TCHFMapping ), - d_tch_decoder7( GSM::gFACCH_TCHFMapping ) -{ - int i; - gmsk_mapper(SYNC_BITS, N_SYNC_BITS, d_sch_training_seq, gr_complex(0.0, -1.0)); - for (i = 0; i < TRAIN_SEQ_NUM; i++) { - gr_complex startpoint; - if (i == 6) { //this is nasty hack - startpoint = gr_complex(-1.0, 0.0); //if I don't change it here all bits of normal bursts for BTSes with bcc=6 will have reversed values - } else { - startpoint = gr_complex(1.0, 0.0); //I've checked this hack for bcc==0,1,2,3,4,6 - } //I don't know what about bcc==5 and 7 yet - //TODO:find source of this situation - this is purely mathematical problem I guess - - gmsk_mapper(train_seq[i], N_TRAIN_BITS, d_norm_training_seq[i], startpoint); - } - d_gsm_file = fopen( "speech.gsm", "wb" ); - - d_hex_to_int['0'] = 0; - d_hex_to_int['4'] = 4; - d_hex_to_int['8'] = 8; - d_hex_to_int['c'] = 0xc; - d_hex_to_int['1'] = 1; - d_hex_to_int['5'] = 5; - d_hex_to_int['9'] = 9; - d_hex_to_int['d'] = 0xd; - d_hex_to_int['2'] = 2; - d_hex_to_int['6'] = 6; - d_hex_to_int['a'] = 0xa; - d_hex_to_int['e'] = 0xe; - d_hex_to_int['3'] = 3; - d_hex_to_int['7'] = 7; - d_hex_to_int['b'] = 0xb; - d_hex_to_int['f'] = 0xf; - read_key(key); - /* Initialize GSM Stack */ - GS_new(&d_gs_ctx); //TODO: remove it! it's not a right place for a decoder -} - -/* - * Virtual destructor. - */ -gsm_receiver_cf::~gsm_receiver_cf() -{ -} - -void gsm_receiver_cf::forecast(int noutput_items, gr_vector_int &nitems_items_required) -{ - nitems_items_required[0] = noutput_items * floor((TS_BITS + 2 * GUARD_PERIOD) * d_OSR); -} - -int -gsm_receiver_cf::general_work(int noutput_items, - gr_vector_int &nitems_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *input = (const gr_complex *) input_items[0]; - //float *out = (float *) output_items[0]; - int produced_out = 0; //how many output elements were produced - this isn't used yet - //probably the gsm receiver will be changed into sink so this variable won't be necessary - - switch (d_state) { - //bootstrapping - case first_fcch_search: - if (find_fcch_burst(input, nitems_items[0])) { //find frequency correction burst in the input buffer - set_frequency(d_freq_offset); //if fcch search is successful set frequency offset - //produced_out = 0; - d_state = next_fcch_search; - } else { - //produced_out = 0; - d_state = first_fcch_search; - } - break; - - case next_fcch_search: { //this state is used because it takes some time (a bunch of buffered samples) - float prev_freq_offset = d_freq_offset; //before previous set_frequqency cause change - if (find_fcch_burst(input, nitems_items[0])) { - if (abs(prev_freq_offset - d_freq_offset) > FCCH_MAX_FREQ_OFFSET) { - set_frequency(d_freq_offset); //call set_frequncy only frequency offset change is greater than some value - } - //produced_out = 0; - d_state = sch_search; - } else { - //produced_out = 0; - d_state = next_fcch_search; - } - break; - } - - case sch_search: { - vector_complex channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR); - int t1, t2, t3; - int burst_start = 0; - unsigned char output_binary[BURST_SIZE]; - - if (reach_sch_burst(nitems_items[0])) { //wait for a SCH burst - burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response from it - detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //detect bits using MLSE detection - if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) { //decode SCH burst - DCOUT("sch burst_start: " << burst_start); - DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3); - d_burst_nr.set(t1, t2, t3, 0); //set counter of bursts value - - //configure the receiver - tell him where to find which burst type - d_channel_conf.set_multiframe_type(TIMESLOT0, multiframe_51); //in the timeslot nr.0 bursts changes according to t3 counter - configure_receiver();//TODO: this shouldn't be here - remove it when gsm receiver's interface will be ready - d_channel_conf.set_burst_types(TIMESLOT0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst); //tell where to find fcch bursts - d_channel_conf.set_burst_types(TIMESLOT0, SCH_FRAMES, sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst); //sch bursts - d_channel_conf.set_burst_types(TIMESLOT0, BCCH_FRAMES, sizeof(BCCH_FRAMES) / sizeof(unsigned), normal_burst);//!and maybe normal bursts of the BCCH logical channel - d_burst_nr++; - - consume_each(burst_start + BURST_SIZE * d_OSR); //consume samples up to next guard period - d_state = synchronized; - } else { - d_state = next_fcch_search; //if there is error in the sch burst go back to fcch search phase - } - } else { - d_state = sch_search; - } - break; - } - //in this state receiver is synchronized and it processes bursts according to burst type for given burst number - case synchronized: { - vector_complex channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR); - int burst_start; - int offset = 0; - int to_consume = 0; - unsigned char output_binary[BURST_SIZE]; - - burst_type b_type = d_channel_conf.get_burst_type(d_burst_nr); //get burst type for given burst number - - switch (b_type) { - case fcch_burst: { //if it's FCCH burst - const unsigned first_sample = ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1; - const unsigned last_sample = first_sample + USEFUL_BITS * d_OSR - TAIL_BITS * d_OSR; - double freq_offset = compute_freq_offset(input, first_sample, last_sample); //extract frequency offset from it - - d_freq_offset_vals.push_front(freq_offset); - - if (d_freq_offset_vals.size() >= 10) { - double sum = std::accumulate(d_freq_offset_vals.begin(), d_freq_offset_vals.end(), 0); - double mean_offset = sum / d_freq_offset_vals.size(); //compute mean - d_freq_offset_vals.clear(); - if (abs(mean_offset) > FCCH_MAX_FREQ_OFFSET) { - d_freq_offset -= mean_offset; //and adjust frequency if it have changed beyond - set_frequency(d_freq_offset); //some limit - DCOUT("mean_offset: " << mean_offset); - DCOUT("Adjusting frequency, new frequency offset: " << d_freq_offset << "\n"); - } - } - } - break; - case sch_burst: { //if it's SCH burst - int t1, t2, t3, d_ncc, d_bcc; - burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response - detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //MLSE detection of bits - if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) { //and decode SCH data - // d_burst_nr.set(t1, t2, t3, 0); //but only to check if burst_start value is correct - d_failed_sch = 0; - DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3); - offset = burst_start - floor((GUARD_PERIOD) * d_OSR); //compute offset from burst_start - burst should start after a guard period - DCOUT(offset); - to_consume += offset; //adjust with offset number of samples to be consumed - } else { - d_failed_sch++; - if (d_failed_sch >= MAX_SCH_ERRORS) { -// d_state = next_fcch_search; //TODO: this isn't good, the receiver is going wild when it goes back to next_fcch_search from here -// d_freq_offset_vals.clear(); - DCOUT("many sch decoding errors"); - } - } - } - break; - - case normal_burst: //if it's normal burst - burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], d_bcc); //get channel impulse response for given training sequence number - d_bcc - detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //MLSE detection of bits - process_normal_burst(d_burst_nr, output_binary); //TODO: this shouldn't be here - remove it when gsm receiver's interface will be ready - break; - - case dummy_or_normal: { - burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], TS_DUMMY); - detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); - - std::vector v(20); - std::vector::iterator it; - it = std::set_difference(output_binary + TRAIN_POS, output_binary + TRAIN_POS + 16, &train_seq[TS_DUMMY][5], &train_seq[TS_DUMMY][21], v.begin()); - int different_bits = (it - v.begin()); - - if (different_bits > 2) { - burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], d_bcc); - detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); - if (!output_binary[0] && !output_binary[1] && !output_binary[2]) { - process_normal_burst(d_burst_nr, output_binary); //TODO: this shouldn't be here - remove it when gsm receiver's interface will be ready - } - } - } - case rach_burst: - //implementation of this channel isn't possible in current gsm_receiver - //it would take some realtime processing, counter of samples from USRP to - //stay synchronized with this device and possibility to switch frequency from uplink - //to C0 (where sch is) back and forth - - break; - case dummy: //if it's dummy - burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], TS_DUMMY); //read dummy - detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); // but as far as I know it's pointless - break; - case empty: //if it's empty burst - break; //do nothing - } - - d_burst_nr++; //go to next burst - - to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset(); //consume samples of the burst up to next guard period - //and add offset which is introduced by - //0.25 fractional part of a guard period - //burst_number computes this offset - //but choice of this class to do this was random - consume_each(to_consume); - } - break; - } - - return produced_out; -} - -bool gsm_receiver_cf::find_fcch_burst(const gr_complex *input, const int nitems) -{ - circular_buffer_float phase_diff_buffer(FCCH_HITS_NEEDED * d_OSR); //circular buffer used to scan throug signal to find - //best match for FCCH burst - float phase_diff = 0; - gr_complex conjprod; - int start_pos = -1; - int hit_count = 0; - int miss_count = 0; - float min_phase_diff; - float max_phase_diff; - double best_sum = 0; - float lowest_max_min_diff = 99999; - - int to_consume = 0; - int sample_number = 0; - bool end = false; - bool result = false; - circular_buffer_float::iterator buffer_iter; - - /**@name Possible states of FCCH search algorithm*/ - //@{ - enum states { - init, ///< initialize variables - search, ///< search for positive samples - found_something, ///< search for FCCH and the best position of it - fcch_found, ///< when FCCH was found - search_fail ///< when there is no FCCH in the input vector - } fcch_search_state; - //@} - - fcch_search_state = init; - - while (!end) { - switch (fcch_search_state) { - - case init: //initialize variables - hit_count = 0; - miss_count = 0; - start_pos = -1; - lowest_max_min_diff = 99999; - phase_diff_buffer.clear(); - fcch_search_state = search; - - break; - - case search: // search for positive samples - sample_number++; - - if (sample_number > nitems - FCCH_HITS_NEEDED * d_OSR) { //if it isn't possible to find FCCH because - //there's too few samples left to look into, - to_consume = sample_number; //don't do anything with those samples which are left - //and consume only those which were checked - fcch_search_state = search_fail; - } else { - phase_diff = compute_phase_diff(input[sample_number], input[sample_number-1]); - - if (phase_diff > 0) { //if a positive phase difference was found - to_consume = sample_number; - fcch_search_state = found_something; //switch to state in which searches for FCCH - } else { - fcch_search_state = search; - } - } - - break; - - case found_something: {// search for FCCH and the best position of it - if (phase_diff > 0) { - hit_count++; //positive phase differencies increases hits_count - } else { - miss_count++; //negative increases miss_count - } - - if ((miss_count >= FCCH_MAX_MISSES * d_OSR) && (hit_count <= FCCH_HITS_NEEDED * d_OSR)) { - //if miss_count exceeds limit before hit_count - fcch_search_state = init; //go to init - continue; - } else if (((miss_count >= FCCH_MAX_MISSES * d_OSR) && (hit_count > FCCH_HITS_NEEDED * d_OSR)) || (hit_count > 2 * FCCH_HITS_NEEDED * d_OSR)) { - //if hit_count and miss_count exceeds limit then FCCH was found - fcch_search_state = fcch_found; - continue; - } else if ((miss_count < FCCH_MAX_MISSES * d_OSR) && (hit_count > FCCH_HITS_NEEDED * d_OSR)) { - //find difference between minimal and maximal element in the buffer - //for FCCH this value should be low - //this part is searching for a region where this value is lowest - min_phase_diff = * (min_element(phase_diff_buffer.begin(), phase_diff_buffer.end())); - max_phase_diff = * (max_element(phase_diff_buffer.begin(), phase_diff_buffer.end())); - - if (lowest_max_min_diff > max_phase_diff - min_phase_diff) { - lowest_max_min_diff = max_phase_diff - min_phase_diff; - start_pos = sample_number - FCCH_HITS_NEEDED * d_OSR - FCCH_MAX_MISSES * d_OSR; //store start pos - best_sum = 0; - - for (buffer_iter = phase_diff_buffer.begin(); - buffer_iter != (phase_diff_buffer.end()); - buffer_iter++) { - best_sum += *buffer_iter - (M_PI / 2) / d_OSR; //store best value of phase offset sum - } - } - } - - sample_number++; - - if (sample_number >= nitems) { //if there's no single sample left to check - fcch_search_state = search_fail;//FCCH search failed - continue; - } - - phase_diff = compute_phase_diff(input[sample_number], input[sample_number-1]); - phase_diff_buffer.push_back(phase_diff); - fcch_search_state = found_something; - } - break; - - case fcch_found: { - DCOUT("fcch found on position: " << d_counter + start_pos); - to_consume = start_pos + FCCH_HITS_NEEDED * d_OSR + 1; //consume one FCCH burst - - d_fcch_start_pos = d_counter + start_pos; - - //compute frequency offset - double phase_offset = best_sum / FCCH_HITS_NEEDED; - double freq_offset = phase_offset * 1625000.0 / (12.0 * M_PI); - d_freq_offset -= freq_offset; - DCOUT("freq_offset: " << d_freq_offset); - - end = true; - result = true; - break; - } - - case search_fail: - end = true; - result = false; - break; - } - } - - d_counter += to_consume; - consume_each(to_consume); - - return result; -} - -double gsm_receiver_cf::compute_freq_offset(const gr_complex * input, unsigned first_sample, unsigned last_sample) -{ - double phase_sum = 0; - unsigned ii; - - for (ii = first_sample; ii < last_sample; ii++) { - double phase_diff = compute_phase_diff(input[ii], input[ii-1]) - (M_PI / 2) / d_OSR; - phase_sum += phase_diff; - } - - double phase_offset = phase_sum / (last_sample - first_sample); - double freq_offset = phase_offset * 1625000.0 / (12.0 * M_PI); - return freq_offset; -} - -void gsm_receiver_cf::set_frequency(double freq_offset) -{ - d_tuner->calleval(freq_offset); -} - -inline float gsm_receiver_cf::compute_phase_diff(gr_complex val1, gr_complex val2) -{ - gr_complex conjprod = val1 * conj(val2); - return gr_fast_atan2f(imag(conjprod), real(conjprod)); -} - -bool gsm_receiver_cf::reach_sch_burst(const int nitems) -{ - //it just consumes samples to get near to a SCH burst - int to_consume = 0; - bool result = false; - unsigned sample_nr_near_sch_start = d_fcch_start_pos + (FRAME_BITS - SAFETY_MARGIN) * d_OSR; - - //consume samples until d_counter will be equal to sample_nr_near_sch_start - if (d_counter < sample_nr_near_sch_start) { - if (d_counter + nitems >= sample_nr_near_sch_start) { - to_consume = sample_nr_near_sch_start - d_counter; - } else { - to_consume = nitems; - } - result = false; - } else { - to_consume = 0; - result = true; - } - - d_counter += to_consume; - consume_each(to_consume); - return result; -} - -int gsm_receiver_cf::get_sch_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp) -{ - vector_complex correlation_buffer; - vector_float power_buffer; - vector_float window_energy_buffer; - - int strongest_window_nr; - int burst_start = 0; - int chan_imp_resp_center = 0; - float max_correlation = 0; - float energy = 0; - - for (int ii = SYNC_POS * d_OSR; ii < (SYNC_POS + SYNC_SEARCH_RANGE) *d_OSR; ii++) { - gr_complex correlation = correlate_sequence(&d_sch_training_seq[5], N_SYNC_BITS - 10, &input[ii]); - correlation_buffer.push_back(correlation); - power_buffer.push_back(pow(abs(correlation), 2)); - } - - //compute window energies - vector_float::iterator iter = power_buffer.begin(); - bool loop_end = false; - while (iter != power_buffer.end()) { - vector_float::iterator iter_ii = iter; - energy = 0; - - for (int ii = 0; ii < (d_chan_imp_length) *d_OSR; ii++, iter_ii++) { - if (iter_ii == power_buffer.end()) { - loop_end = true; - break; - } - energy += (*iter_ii); - } - if (loop_end) { - break; - } - iter++; - window_energy_buffer.push_back(energy); - } - - strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin(); -// d_channel_imp_resp.clear(); - - max_correlation = 0; - for (int ii = 0; ii < (d_chan_imp_length) *d_OSR; ii++) { - gr_complex correlation = correlation_buffer[strongest_window_nr + ii]; - if (abs(correlation) > max_correlation) { - chan_imp_resp_center = ii; - max_correlation = abs(correlation); - } -// d_channel_imp_resp.push_back(correlation); - chan_imp_resp[ii] = correlation; - } - - burst_start = strongest_window_nr + chan_imp_resp_center - 48 * d_OSR - 2 * d_OSR + 2 + SYNC_POS * d_OSR; - return burst_start; -} - -void gsm_receiver_cf::detect_burst(const gr_complex * input, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary) -{ - float output[BURST_SIZE]; - gr_complex rhh_temp[CHAN_IMP_RESP_LENGTH*d_OSR]; - gr_complex rhh[CHAN_IMP_RESP_LENGTH]; - gr_complex filtered_burst[BURST_SIZE]; - int start_state = 3; - unsigned int stop_states[2] = {4, 12}; - - autocorrelation(chan_imp_resp, rhh_temp, d_chan_imp_length*d_OSR); - for (int ii = 0; ii < (d_chan_imp_length); ii++) { - rhh[ii] = conj(rhh_temp[ii*d_OSR]); - } - - mafi(&input[burst_start], BURST_SIZE, chan_imp_resp, d_chan_imp_length*d_OSR, filtered_burst); - - viterbi_detector(filtered_burst, BURST_SIZE, rhh, start_state, stop_states, 2, output); - - for (int i = 0; i < BURST_SIZE ; i++) { - output_binary[i] = (output[i] > 0); - } -} - -//TODO consider placing this funtion in a separate class for signal processing -void gsm_receiver_cf::gmsk_mapper(const unsigned char * input, int nitems, gr_complex * gmsk_output, gr_complex start_point) -{ - gr_complex j = gr_complex(0.0, 1.0); - - int current_symbol; - int encoded_symbol; - int previous_symbol = 2 * input[0] - 1; - gmsk_output[0] = start_point; - - for (int i = 1; i < nitems; i++) { - //change bits representation to NRZ - current_symbol = 2 * input[i] - 1; - //differentially encode - encoded_symbol = current_symbol * previous_symbol; - //and do gmsk mapping - gmsk_output[i] = j * gr_complex(encoded_symbol, 0.0) * gmsk_output[i-1]; - previous_symbol = current_symbol; - } -} - -//TODO consider use of some generalized function for correlation and placing it in a separate class for signal processing -gr_complex gsm_receiver_cf::correlate_sequence(const gr_complex * sequence, int length, const gr_complex * input) -{ - gr_complex result(0.0, 0.0); - int sample_number = 0; - - for (int ii = 0; ii < length; ii++) { - sample_number = (ii * d_OSR) ; - result += sequence[ii] * conj(input[sample_number]); - } - - result = result / gr_complex(length, 0); - return result; -} - -//computes autocorrelation for positive arguments -//TODO consider placing this funtion in a separate class for signal processing -inline void gsm_receiver_cf::autocorrelation(const gr_complex * input, gr_complex * out, int nitems) -{ - int i, k; - for (k = nitems - 1; k >= 0; k--) { - out[k] = gr_complex(0, 0); - for (i = k; i < nitems; i++) { - out[k] += input[i] * conj(input[i-k]); - } - } -} - -//TODO consider use of some generalized function for filtering and placing it in a separate class for signal processing -inline void gsm_receiver_cf::mafi(const gr_complex * input, int nitems, gr_complex * filter, int filter_length, gr_complex * output) -{ - int ii = 0, n, a; - - for (n = 0; n < nitems; n++) { - a = n * d_OSR; - output[n] = 0; - ii = 0; - - while (ii < filter_length) { - if ((a + ii) >= nitems*d_OSR) - break; - output[n] += input[a+ii] * filter[ii]; - ii++; - } - } -} - -//TODO: get_norm_chan_imp_resp is similar to get_sch_chan_imp_resp - consider joining this two functions -//TODO: this is place where most errors are introduced and can be corrected by improvements to this fuction -//especially computations of strongest_window_nr -int gsm_receiver_cf::get_norm_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp, int bcc) -{ - vector_complex correlation_buffer; - vector_float power_buffer; - vector_float window_energy_buffer; - - int strongest_window_nr; - int burst_start = 0; - int chan_imp_resp_center = 0; - float max_correlation = 0; - float energy = 0; - - int search_center = (int)((TRAIN_POS + GUARD_PERIOD) * d_OSR); - int search_start_pos = search_center + 1; -// int search_start_pos = search_center - d_chan_imp_length * d_OSR; - int search_stop_pos = search_center + d_chan_imp_length * d_OSR + 2 * d_OSR; - - for (int ii = search_start_pos; ii < search_stop_pos; ii++) { - gr_complex correlation = correlate_sequence(&d_norm_training_seq[bcc][TRAIN_BEGINNING], N_TRAIN_BITS - 10, &input[ii]); - - correlation_buffer.push_back(correlation); - power_buffer.push_back(pow(abs(correlation), 2)); - } - - //compute window energies - vector_float::iterator iter = power_buffer.begin(); - bool loop_end = false; - while (iter != power_buffer.end()) { - vector_float::iterator iter_ii = iter; - energy = 0; - - for (int ii = 0; ii < (d_chan_imp_length - 2)*d_OSR; ii++, iter_ii++) { -// for (int ii = 0; ii < (d_chan_imp_length)*d_OSR; ii++, iter_ii++) { - if (iter_ii == power_buffer.end()) { - loop_end = true; - break; - } - energy += (*iter_ii); - } - if (loop_end) { - break; - } - iter++; - - window_energy_buffer.push_back(energy); - } - //!why doesn't this work - strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin(); - strongest_window_nr = 3; //! so I have to override it here - - max_correlation = 0; - for (int ii = 0; ii < (d_chan_imp_length)*d_OSR; ii++) { - gr_complex correlation = correlation_buffer[strongest_window_nr + ii]; - if (abs(correlation) > max_correlation) { - chan_imp_resp_center = ii; - max_correlation = abs(correlation); - } -// d_channel_imp_resp.push_back(correlation); - chan_imp_resp[ii] = correlation; - } - // We want to use the first sample of the impulseresponse, and the - // corresponding samples of the received signal. - // the variable sync_w should contain the beginning of the used part of - // training sequence, which is 3+57+1+6=67 bits into the burst. That is - // we have that sync_t16 equals first sample in bit number 67. - - burst_start = search_start_pos + chan_imp_resp_center + strongest_window_nr - TRAIN_POS * d_OSR; - - // GMSK modulator introduces ISI - each bit is expanded for 3*Tb - // and it's maximum value is in the last bit period, so burst starts - // 2*Tb earlier - burst_start -= 2 * d_OSR; - burst_start += 2; - //std::cout << " burst_start: " << burst_start << " center: " << ((float)(search_start_pos + strongest_window_nr + chan_imp_resp_center)) / d_OSR << " stronegest window nr: " << strongest_window_nr << "\n"; - - return burst_start; -} - diff --git a/src/lib/gsm_receiver_cf.h b/src/lib/gsm_receiver_cf.h deleted file mode 100644 index 21cb1ff..0000000 --- a/src/lib/gsm_receiver_cf.h +++ /dev/null @@ -1,254 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author Piotr Krysik - * @section LICENSE - * - * 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, 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GSM_RECEIVER_CF_H -#define INCLUDED_GSM_RECEIVER_CF_H - -#include -#include -#include -#include -#include -#include -#include - -#include //TODO: remember to remove this line in the future! -#include "GSML1FEC.h" //!! -#include //!! -#include //!! -#include //!! - -class gsm_receiver_cf; - -typedef boost::shared_ptr gsm_receiver_cf_sptr; -typedef std::vector vector_complex; - -gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key); - -/** GSM Receiver GNU Radio block - * - * GSM Receiver class supports frequency correction, synchronisation and - * MLSE (Maximum Likelihood Sequence Estimation) estimation of synchronisation - * bursts and normal bursts. - * \ingroup block - */ - -class gsm_receiver_cf : public gr_block -{ - private: - std::map d_hex_to_int; - FILE * d_gsm_file; //!! - byte d_KC[8]; //!! - GSM::TCHFACCHL1Decoder d_tch_decoder1; //!! - GSM::TCHFACCHL1Decoder d_tch_decoder2; //!! - GSM::TCHFACCHL1Decoder d_tch_decoder3; //!! - GSM::TCHFACCHL1Decoder d_tch_decoder4; //!! - GSM::TCHFACCHL1Decoder d_tch_decoder5; //!! - GSM::TCHFACCHL1Decoder d_tch_decoder6; //!! - GSM::TCHFACCHL1Decoder d_tch_decoder7; //!! - /**@name Configuration of the receiver */ - //@{ - const int d_OSR; ///< oversampling ratio - const int d_chan_imp_length; ///< channel impulse length - //@} - - gr_complex d_sch_training_seq[N_SYNC_BITS]; /// d_freq_offset_vals; - - /**@name Identifiers of the BTS extracted from the SCH burst */ - //@{ - int d_ncc; ///< network color code - int d_bcc; ///< base station color code - //@} - - /**@name Internal state of the gsm receiver */ - //@{ - enum states { - first_fcch_search, next_fcch_search, sch_search, // synchronization search part - synchronized // receiver is synchronized in this state - } d_state; - //@} - - /**@name Variables which make internal state in the "synchronized" state */ - //@{ - burst_counter d_burst_nr; ///< frame number and timeslot number - channel_configuration d_channel_conf; ///< mapping of burst_counter to burst_type - //@} - - unsigned d_failed_sch; ///< number of subsequent erroneous SCH bursts - - // GSM Stack - GS_CTX d_gs_ctx;//TODO: remove it! it'a not right place for a decoder - - friend gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key); - gsm_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key); - - /** Function whis is used to search a FCCH burst and to compute frequency offset before - * "synchronized" state of the receiver - * - * TODO: Describe the FCCH search algorithm in the documentation - * @param input vector with input signal - * @param nitems number of samples in the input vector - * @return - */ - bool find_fcch_burst(const gr_complex *input, const int nitems); - - /** Computes frequency offset from FCCH burst samples - * - * @param input vector with input samples - * @param first_sample number of the first sample of the FCCH busrt - * @param last_sample number of the last sample of the FCCH busrt - * @return frequency offset - */ - double compute_freq_offset(const gr_complex * input, unsigned first_sample, unsigned last_sample); - - /** Calls d_tuner's method to set frequency offset from Python level - * - * @param freq_offset absolute frequency offset of the received signal - */ - void set_frequency(double freq_offset); - - /** Computes angle between two complex numbers - * - * @param val1 first complex number - * @param val2 second complex number - * @return - */ - inline float compute_phase_diff(gr_complex val1, gr_complex val2); - - /** Function whis is used to get near to SCH burst - * - * @param nitems number of samples in the gsm_receiver's buffer - * @return true if SCH burst is near, false otherwise - */ - bool reach_sch_burst(const int nitems); - - /** Extracts channel impulse response from a SCH burst and computes first sample number of this burst - * - * @param input vector with input samples - * @param chan_imp_resp complex vector where channel impulse response will be stored - * @return number of first sample of the burst - */ - int get_sch_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp); - - /** MLSE detection of a burst bits - * - * Detects bits of burst using viterbi algorithm. - * @param input vector with input samples - * @param chan_imp_resp vector with the channel impulse response - * @param burst_start number of the first sample of the burst - * @param output_binary vector with output bits - */ - void detect_burst(const gr_complex * input, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary); - - /** Encodes differentially input bits and maps them into MSK states - * - * @param input vector with input bits - * @param nitems number of samples in the "input" vector - * @param gmsk_output bits mapped into MSK states - * @param start_point first state - */ - void gmsk_mapper(const unsigned char * input, int nitems, gr_complex * gmsk_output, gr_complex start_point); - - /** Correlates MSK mapped sequence with input signal - * - * @param sequence MKS mapped sequence - * @param length length of the sequence - * @param input_signal vector with input samples - * @return correlation value - */ - gr_complex correlate_sequence(const gr_complex * sequence, int length, const gr_complex * input); - - /** Computes autocorrelation of input vector for positive arguments - * - * @param input vector with input samples - * @param out output vector - * @param nitems length of the input vector - */ - inline void autocorrelation(const gr_complex * input, gr_complex * out, int nitems); - - /** Filters input signal through channel impulse response - * - * @param input vector with input samples - * @param nitems number of samples to pass through filter - * @param filter filter taps - channel impulse response - * @param filter_length nember of filter taps - * @param output vector with filtered samples - */ - inline void mafi(const gr_complex * input, int nitems, gr_complex * filter, int filter_length, gr_complex * output); - - /** Extracts channel impulse response from a normal burst and computes first sample number of this burst - * - * @param input vector with input samples - * @param chan_imp_resp complex vector where channel impulse response will be stored - * @param search_range possible absolute offset of a channel impulse response start - * @param bcc base station color code - number of a training sequence - * @return first sample number of normal burst - */ - int get_norm_chan_imp_resp(const gr_complex * input, gr_complex * chan_imp_resp, int bcc); - - - /** - * - */ - void read_key(std::string key); - - /** - * - */ - void process_normal_burst(burst_counter burst_nr, const unsigned char * burst_binary); - - /** - * - */ - void configure_receiver(); - - - - public: - ~gsm_receiver_cf(); - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GSM_RECEIVER_CF_H */ diff --git a/src/lib/gsm_receiver_config.cc b/src/lib/gsm_receiver_config.cc deleted file mode 100644 index 44344f7..0000000 --- a/src/lib/gsm_receiver_config.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author Piotr Krysik - * @section LICENSE - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - * - * @section DESCRIPTION - * This file contains classes which define gsm_receiver configuration - * and the burst_counter which is used to store internal state of the receiver - * when it's synchronized - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -burst_counter & burst_counter::operator++(int) -{ - d_timeslot_nr++; - if (d_timeslot_nr == TS_PER_FRAME) { - d_timeslot_nr = 0; - - if ((d_t2 == 25) && (d_t3 == 50)) { - d_t1 = (d_t1 + 1) % (1 << 11); - } - - d_t2 = (d_t2 + 1) % 26; - d_t3 = (d_t3 + 1) % 51; - } - - //update offset - this is integer for d_OSR which is multiple of four - d_offset_fractional += GUARD_FRACTIONAL * d_OSR; - d_offset_integer = floor(d_offset_fractional); - d_offset_fractional = d_offset_fractional - d_offset_integer; - return (*this); -} - -void burst_counter::set(uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr) -{ - d_t1 = t1; - d_t2 = t2; - d_t3 = t3; - d_timeslot_nr = timeslot_nr; - double first_sample_position = (get_frame_nr() * 8 + timeslot_nr) * TS_BITS; - d_offset_fractional = first_sample_position - floor(first_sample_position); - d_offset_integer = 0; -} - -burst_type channel_configuration::get_burst_type(burst_counter burst_nr) -{ - uint32_t timeslot_nr = burst_nr.get_timeslot_nr(); - multiframe_type m_type = d_timeslots_descriptions[timeslot_nr].get_type(); - uint32_t nr; - - switch (m_type) { - case multiframe_26: - nr = burst_nr.get_t2(); - break; - case multiframe_51: - nr = burst_nr.get_t3(); - break; - default: - nr = 0; - break; - } - - return d_timeslots_descriptions[timeslot_nr].get_burst_type(nr); -} diff --git a/src/lib/gsm_receiver_config.h b/src/lib/gsm_receiver_config.h deleted file mode 100644 index b7ba43a..0000000 --- a/src/lib/gsm_receiver_config.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author Piotr Krysik - * @section LICENSE - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - * - * @section DESCRIPTION - * This file contains classes which define gsm_receiver configuration - * and the burst_counter which is used to store internal state of the receiver - * when it's synchronized - */ -#ifndef INCLUDED_GSM_RECEIVER_CONFIG_H -#define INCLUDED_GSM_RECEIVER_CONFIG_H - -#include -#include -#include -#include -#include - -class multiframe_configuration -{ - private: - multiframe_type d_type; - std::vector d_burst_types; - public: - multiframe_configuration() { - d_type = unknown; - fill(d_burst_types.begin(), d_burst_types.end(), empty); - } - - ~multiframe_configuration() {} - - void set_type(multiframe_type type) { - if (type == multiframe_26) { - d_burst_types.resize(26); - } else { - d_burst_types.resize(51); - } - - d_type = type; - } - - void set_burst_type(int nr, burst_type type) { - d_burst_types[nr] = type; - } - - multiframe_type get_type() { - return d_type; - } - - burst_type get_burst_type(int nr) { - return d_burst_types[nr]; - } -}; - -class burst_counter -{ - private: - const int d_OSR; - uint32_t d_t1, d_t2, d_t3, d_timeslot_nr; - double d_offset_fractional; - double d_offset_integer; - public: - burst_counter(int osr): - d_OSR(osr), - d_t1(0), - d_t2(0), - d_t3(0), - d_timeslot_nr(0), - d_offset_fractional(0.0), - d_offset_integer(0.0) { - } - - burst_counter(int osr, uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr): - d_OSR(osr), - d_t1(t1), - d_t2(t2), - d_t3(t3), - d_timeslot_nr(timeslot_nr), - d_offset_fractional(0.0), - d_offset_integer(0.0) { - double first_sample_position = (get_frame_nr() * 8 + timeslot_nr) * TS_BITS; - d_offset_integer = floor(first_sample_position); - d_offset_fractional = first_sample_position - floor(first_sample_position); - } - - burst_counter & operator++(int); - void set(uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr); - - uint32_t get_t1() { - return d_t1; - } - - uint32_t get_t2() { - return d_t2; - } - - uint32_t get_t3() { - return d_t3; - } - - uint32_t get_timeslot_nr() { - return d_timeslot_nr; - } - - uint32_t get_frame_nr() { - return (51 * 26 * d_t1) + (51 * (((d_t3 + 26) - d_t2) % 26)) + d_t3; - } - - uint32_t get_frame_nr_mod() { - return (d_t1 << 11) + (d_t3 << 5) + d_t2; - } - - unsigned get_offset() { - return (unsigned)d_offset_integer; - } -}; - -class channel_configuration -{ - private: - multiframe_configuration d_timeslots_descriptions[TS_PER_FRAME]; - public: - channel_configuration() { - for (int i = 0; i < TS_PER_FRAME; i++) { - d_timeslots_descriptions[i].set_type(unknown); - } - } - - void set_multiframe_type(int timeslot_nr, multiframe_type type) { - d_timeslots_descriptions[timeslot_nr].set_type(type); - } - - void set_burst_types(int timeslot_nr, const unsigned mapping[], unsigned mapping_size, burst_type b_type) { - unsigned i; - for (i = 0; i < mapping_size; i++) { - d_timeslots_descriptions[timeslot_nr].set_burst_type(mapping[i], b_type); - } - } - - void set_single_burst_type(int timeslot_nr, int burst_nr, burst_type b_type) { - d_timeslots_descriptions[timeslot_nr].set_burst_type(burst_nr, b_type); - } - - burst_type get_burst_type(burst_counter burst_nr); -}; - -#endif /* INCLUDED_GSM_RECEIVER_CONFIG_H */ diff --git a/src/lib/viterbi_detector.cc b/src/lib/viterbi_detector.cc deleted file mode 100644 index f3445cf..0000000 --- a/src/lib/viterbi_detector.cc +++ /dev/null @@ -1,554 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author Piotr Krysik - * @section LICENSE - * - * 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, 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * viterbi_detector: - * This part does the detection of received sequnece. - * Employed algorithm is viterbi Maximum Likehood Sequence Estimation. - * At this moment it gives hard decisions on the output, but - * it was designed with soft decisions in mind. - * - * SYNTAX: void viterbi_detector( - * const gr_complex * input, - * unsigned int samples_num, - * gr_complex * rhh, - * unsigned int start_state, - * const unsigned int * stop_states, - * unsigned int stops_num, - * float * output) - * - * INPUT: input: Complex received signal afted matched filtering. - * samples_num: Number of samples in the input table. - * rhh: The autocorrelation of the estimated channel - * impulse response. - * start_state: Number of the start point. In GSM each burst - * starts with sequence of three bits (0,0,0) which - * indicates start point of the algorithm. - * stop_states: Table with numbers of possible stop states. - * stops_num: Number of possible stop states - * - * - * OUTPUT: output: Differentially decoded hard output of the algorithm: - * -1 for logical "0" and 1 for logical "1" - * - * SUB_FUNC: none - * - * TEST(S): Tested with real world normal burst. - */ - -#include -#include -#define PATHS_NUM (1 << (CHAN_IMP_RESP_LENGTH-1)) - -void viterbi_detector(const gr_complex * input, unsigned int samples_num, gr_complex * rhh, unsigned int start_state, const unsigned int * stop_states, unsigned int stops_num, float * output) -{ - float increment[8]; - float path_metrics1[16]; - float path_metrics2[16]; - float * new_path_metrics; - float * old_path_metrics; - float * tmp; - float trans_table[BURST_SIZE][16]; - float pm_candidate1, pm_candidate2; - bool real_imag; - float input_symbol_real, input_symbol_imag; - unsigned int i, sample_nr; - -/* -* Setup first path metrics, so only state pointed by start_state is possible. -* Start_state metric is equal to zero, the rest is written with some very low value, -* which makes them practically impossible to occur. -*/ - for(i=0; i pm_candidate2){ -* new_path_metrics[0] = pm_candidate1; -* trans_table[sample_nr][0] = -1.0; -* } -* else{ -* new_path_metrics[0] = pm_candidate2; -* trans_table[sample_nr][0] = 1.0; -* } -* This is very good point for optimisations (SIMD or OpenMP) as it's most time -* consuming part of this function. -*/ - sample_nr=0; - old_path_metrics=path_metrics1; - new_path_metrics=path_metrics2; - while(sample_nr pm_candidate2){ - new_path_metrics[0] = pm_candidate1; - trans_table[sample_nr][0] = -1.0; - } - else{ - new_path_metrics[0] = pm_candidate2; - trans_table[sample_nr][0] = 1.0; - } - - pm_candidate1 = old_path_metrics[0] - input_symbol_imag + increment[2]; - pm_candidate2 = old_path_metrics[8] - input_symbol_imag - increment[5]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[1] = pm_candidate1; - trans_table[sample_nr][1] = -1.0; - } - else{ - new_path_metrics[1] = pm_candidate2; - trans_table[sample_nr][1] = 1.0; - } - - pm_candidate1 = old_path_metrics[1] + input_symbol_imag - increment[3]; - pm_candidate2 = old_path_metrics[9] + input_symbol_imag + increment[4]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[2] = pm_candidate1; - trans_table[sample_nr][2] = -1.0; - } - else{ - new_path_metrics[2] = pm_candidate2; - trans_table[sample_nr][2] = 1.0; - } - - pm_candidate1 = old_path_metrics[1] - input_symbol_imag + increment[3]; - pm_candidate2 = old_path_metrics[9] - input_symbol_imag - increment[4]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[3] = pm_candidate1; - trans_table[sample_nr][3] = -1.0; - } - else{ - new_path_metrics[3] = pm_candidate2; - trans_table[sample_nr][3] = 1.0; - } - - pm_candidate1 = old_path_metrics[2] + input_symbol_imag - increment[0]; - pm_candidate2 = old_path_metrics[10] + input_symbol_imag + increment[7]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[4] = pm_candidate1; - trans_table[sample_nr][4] = -1.0; - } - else{ - new_path_metrics[4] = pm_candidate2; - trans_table[sample_nr][4] = 1.0; - } - - pm_candidate1 = old_path_metrics[2] - input_symbol_imag + increment[0]; - pm_candidate2 = old_path_metrics[10] - input_symbol_imag - increment[7]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[5] = pm_candidate1; - trans_table[sample_nr][5] = -1.0; - } - else{ - new_path_metrics[5] = pm_candidate2; - trans_table[sample_nr][5] = 1.0; - } - - pm_candidate1 = old_path_metrics[3] + input_symbol_imag - increment[1]; - pm_candidate2 = old_path_metrics[11] + input_symbol_imag + increment[6]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[6] = pm_candidate1; - trans_table[sample_nr][6] = -1.0; - } - else{ - new_path_metrics[6] = pm_candidate2; - trans_table[sample_nr][6] = 1.0; - } - - pm_candidate1 = old_path_metrics[3] - input_symbol_imag + increment[1]; - pm_candidate2 = old_path_metrics[11] - input_symbol_imag - increment[6]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[7] = pm_candidate1; - trans_table[sample_nr][7] = -1.0; - } - else{ - new_path_metrics[7] = pm_candidate2; - trans_table[sample_nr][7] = 1.0; - } - - pm_candidate1 = old_path_metrics[4] + input_symbol_imag - increment[6]; - pm_candidate2 = old_path_metrics[12] + input_symbol_imag + increment[1]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[8] = pm_candidate1; - trans_table[sample_nr][8] = -1.0; - } - else{ - new_path_metrics[8] = pm_candidate2; - trans_table[sample_nr][8] = 1.0; - } - - pm_candidate1 = old_path_metrics[4] - input_symbol_imag + increment[6]; - pm_candidate2 = old_path_metrics[12] - input_symbol_imag - increment[1]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[9] = pm_candidate1; - trans_table[sample_nr][9] = -1.0; - } - else{ - new_path_metrics[9] = pm_candidate2; - trans_table[sample_nr][9] = 1.0; - } - - pm_candidate1 = old_path_metrics[5] + input_symbol_imag - increment[7]; - pm_candidate2 = old_path_metrics[13] + input_symbol_imag + increment[0]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[10] = pm_candidate1; - trans_table[sample_nr][10] = -1.0; - } - else{ - new_path_metrics[10] = pm_candidate2; - trans_table[sample_nr][10] = 1.0; - } - - pm_candidate1 = old_path_metrics[5] - input_symbol_imag + increment[7]; - pm_candidate2 = old_path_metrics[13] - input_symbol_imag - increment[0]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[11] = pm_candidate1; - trans_table[sample_nr][11] = -1.0; - } - else{ - new_path_metrics[11] = pm_candidate2; - trans_table[sample_nr][11] = 1.0; - } - - pm_candidate1 = old_path_metrics[6] + input_symbol_imag - increment[4]; - pm_candidate2 = old_path_metrics[14] + input_symbol_imag + increment[3]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[12] = pm_candidate1; - trans_table[sample_nr][12] = -1.0; - } - else{ - new_path_metrics[12] = pm_candidate2; - trans_table[sample_nr][12] = 1.0; - } - - pm_candidate1 = old_path_metrics[6] - input_symbol_imag + increment[4]; - pm_candidate2 = old_path_metrics[14] - input_symbol_imag - increment[3]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[13] = pm_candidate1; - trans_table[sample_nr][13] = -1.0; - } - else{ - new_path_metrics[13] = pm_candidate2; - trans_table[sample_nr][13] = 1.0; - } - - pm_candidate1 = old_path_metrics[7] + input_symbol_imag - increment[5]; - pm_candidate2 = old_path_metrics[15] + input_symbol_imag + increment[2]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[14] = pm_candidate1; - trans_table[sample_nr][14] = -1.0; - } - else{ - new_path_metrics[14] = pm_candidate2; - trans_table[sample_nr][14] = 1.0; - } - - pm_candidate1 = old_path_metrics[7] - input_symbol_imag + increment[5]; - pm_candidate2 = old_path_metrics[15] - input_symbol_imag - increment[2]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[15] = pm_candidate1; - trans_table[sample_nr][15] = -1.0; - } - else{ - new_path_metrics[15] = pm_candidate2; - trans_table[sample_nr][15] = 1.0; - } - tmp=old_path_metrics; - old_path_metrics=new_path_metrics; - new_path_metrics=tmp; - - sample_nr++; - if(sample_nr==samples_num) - break; - - //Processing real states - real_imag=0; - input_symbol_real = input[sample_nr].real(); - - pm_candidate1 = old_path_metrics[0] - input_symbol_real - increment[7]; - pm_candidate2 = old_path_metrics[8] - input_symbol_real + increment[0]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[0] = pm_candidate1; - trans_table[sample_nr][0] = -1.0; - } - else{ - new_path_metrics[0] = pm_candidate2; - trans_table[sample_nr][0] = 1.0; - } - - pm_candidate1 = old_path_metrics[0] + input_symbol_real + increment[7]; - pm_candidate2 = old_path_metrics[8] + input_symbol_real - increment[0]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[1] = pm_candidate1; - trans_table[sample_nr][1] = -1.0; - } - else{ - new_path_metrics[1] = pm_candidate2; - trans_table[sample_nr][1] = 1.0; - } - - pm_candidate1 = old_path_metrics[1] - input_symbol_real - increment[6]; - pm_candidate2 = old_path_metrics[9] - input_symbol_real + increment[1]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[2] = pm_candidate1; - trans_table[sample_nr][2] = -1.0; - } - else{ - new_path_metrics[2] = pm_candidate2; - trans_table[sample_nr][2] = 1.0; - } - - pm_candidate1 = old_path_metrics[1] + input_symbol_real + increment[6]; - pm_candidate2 = old_path_metrics[9] + input_symbol_real - increment[1]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[3] = pm_candidate1; - trans_table[sample_nr][3] = -1.0; - } - else{ - new_path_metrics[3] = pm_candidate2; - trans_table[sample_nr][3] = 1.0; - } - - pm_candidate1 = old_path_metrics[2] - input_symbol_real - increment[5]; - pm_candidate2 = old_path_metrics[10] - input_symbol_real + increment[2]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[4] = pm_candidate1; - trans_table[sample_nr][4] = -1.0; - } - else{ - new_path_metrics[4] = pm_candidate2; - trans_table[sample_nr][4] = 1.0; - } - - pm_candidate1 = old_path_metrics[2] + input_symbol_real + increment[5]; - pm_candidate2 = old_path_metrics[10] + input_symbol_real - increment[2]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[5] = pm_candidate1; - trans_table[sample_nr][5] = -1.0; - } - else{ - new_path_metrics[5] = pm_candidate2; - trans_table[sample_nr][5] = 1.0; - } - - pm_candidate1 = old_path_metrics[3] - input_symbol_real - increment[4]; - pm_candidate2 = old_path_metrics[11] - input_symbol_real + increment[3]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[6] = pm_candidate1; - trans_table[sample_nr][6] = -1.0; - } - else{ - new_path_metrics[6] = pm_candidate2; - trans_table[sample_nr][6] = 1.0; - } - - pm_candidate1 = old_path_metrics[3] + input_symbol_real + increment[4]; - pm_candidate2 = old_path_metrics[11] + input_symbol_real - increment[3]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[7] = pm_candidate1; - trans_table[sample_nr][7] = -1.0; - } - else{ - new_path_metrics[7] = pm_candidate2; - trans_table[sample_nr][7] = 1.0; - } - - pm_candidate1 = old_path_metrics[4] - input_symbol_real - increment[3]; - pm_candidate2 = old_path_metrics[12] - input_symbol_real + increment[4]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[8] = pm_candidate1; - trans_table[sample_nr][8] = -1.0; - } - else{ - new_path_metrics[8] = pm_candidate2; - trans_table[sample_nr][8] = 1.0; - } - - pm_candidate1 = old_path_metrics[4] + input_symbol_real + increment[3]; - pm_candidate2 = old_path_metrics[12] + input_symbol_real - increment[4]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[9] = pm_candidate1; - trans_table[sample_nr][9] = -1.0; - } - else{ - new_path_metrics[9] = pm_candidate2; - trans_table[sample_nr][9] = 1.0; - } - - pm_candidate1 = old_path_metrics[5] - input_symbol_real - increment[2]; - pm_candidate2 = old_path_metrics[13] - input_symbol_real + increment[5]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[10] = pm_candidate1; - trans_table[sample_nr][10] = -1.0; - } - else{ - new_path_metrics[10] = pm_candidate2; - trans_table[sample_nr][10] = 1.0; - } - - pm_candidate1 = old_path_metrics[5] + input_symbol_real + increment[2]; - pm_candidate2 = old_path_metrics[13] + input_symbol_real - increment[5]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[11] = pm_candidate1; - trans_table[sample_nr][11] = -1.0; - } - else{ - new_path_metrics[11] = pm_candidate2; - trans_table[sample_nr][11] = 1.0; - } - - pm_candidate1 = old_path_metrics[6] - input_symbol_real - increment[1]; - pm_candidate2 = old_path_metrics[14] - input_symbol_real + increment[6]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[12] = pm_candidate1; - trans_table[sample_nr][12] = -1.0; - } - else{ - new_path_metrics[12] = pm_candidate2; - trans_table[sample_nr][12] = 1.0; - } - - pm_candidate1 = old_path_metrics[6] + input_symbol_real + increment[1]; - pm_candidate2 = old_path_metrics[14] + input_symbol_real - increment[6]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[13] = pm_candidate1; - trans_table[sample_nr][13] = -1.0; - } - else{ - new_path_metrics[13] = pm_candidate2; - trans_table[sample_nr][13] = 1.0; - } - - pm_candidate1 = old_path_metrics[7] - input_symbol_real - increment[0]; - pm_candidate2 = old_path_metrics[15] - input_symbol_real + increment[7]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[14] = pm_candidate1; - trans_table[sample_nr][14] = -1.0; - } - else{ - new_path_metrics[14] = pm_candidate2; - trans_table[sample_nr][14] = 1.0; - } - - pm_candidate1 = old_path_metrics[7] + input_symbol_real + increment[0]; - pm_candidate2 = old_path_metrics[15] + input_symbol_real - increment[7]; - if(pm_candidate1 > pm_candidate2){ - new_path_metrics[15] = pm_candidate1; - trans_table[sample_nr][15] = -1.0; - } - else{ - new_path_metrics[15] = pm_candidate2; - trans_table[sample_nr][15] = 1.0; - } - tmp=old_path_metrics; - old_path_metrics=new_path_metrics; - new_path_metrics=tmp; - - sample_nr++; - } - -/* -* Find the best from the stop states by comparing their path metrics. -* Not every stop state is always possible, so we are searching in -* a subset of them. -*/ - unsigned int best_stop_state; - float stop_state_metric, max_stop_state_metric; - best_stop_state = stop_states[0]; - max_stop_state_metric = old_path_metrics[best_stop_state]; - for(i=1; i< stops_num; i++){ - stop_state_metric = old_path_metrics[stop_states[i]]; - if(stop_state_metric > max_stop_state_metric){ - max_stop_state_metric = stop_state_metric; - best_stop_state = stop_states[i]; - } - } - -/* -* This table was generated with hope that it gives a litle speedup during -* traceback stage. -* Received bit is related to the number of state in the trellis. -* I've numbered states so their parity (number of ones) is related -* to a received bit. -*/ - static const unsigned int parity_table[PATHS_NUM] = { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, }; - -/* -* Table of previous states in the trellis diagram. -* For GMSK modulation every state has two previous states. -* Example: -* previous_state_nr1 = prev_table[current_state_nr][0] -* previous_state_nr2 = prev_table[current_state_nr][1] -*/ - static const unsigned int prev_table[PATHS_NUM][2] = { {0,8}, {0,8}, {1,9}, {1,9}, {2,10}, {2,10}, {3,11}, {3,11}, {4,12}, {4,12}, {5,13}, {5,13}, {6,14}, {6,14}, {7,15}, {7,15}, }; - -/* -* Traceback and differential decoding of received sequence. -* Decisions stored in trans_table are used to restore best path in the trellis. -*/ - sample_nr=samples_num; - unsigned int state_nr=best_stop_state; - unsigned int decision; - bool out_bit=0; - - while(sample_nr>0){ - sample_nr--; - decision = (trans_table[sample_nr][state_nr]>0); - - if(decision != out_bit) - output[sample_nr]=-trans_table[sample_nr][state_nr]; - else - output[sample_nr]=trans_table[sample_nr][state_nr]; - - out_bit = out_bit ^ real_imag ^ parity_table[state_nr]; - state_nr = prev_table[state_nr][decision]; - real_imag = !real_imag; - } -} diff --git a/src/lib/viterbi_detector.h b/src/lib/viterbi_detector.h deleted file mode 100644 index 0360f83..0000000 --- a/src/lib/viterbi_detector.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author Piotr Krysik - * @section LICENSE - * - * 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, 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * viterbi_detector: - * This part does the detection of received sequnece. - * Employed algorithm is viterbi Maximum Likehood Sequence Estimation. - * At this moment it gives hard decisions on the output, but - * it was designed with soft decisions in mind. - * - * SYNTAX: void viterbi_detector( - * const gr_complex * input, - * unsigned int samples_num, - * gr_complex * rhh, - * unsigned int start_state, - * const unsigned int * stop_states, - * unsigned int stops_num, - * float * output) - * - * INPUT: input: Complex received signal afted matched filtering. - * samples_num: Number of samples in the input table. - * rhh: The autocorrelation of the estimated channel - * impulse response. - * start_state: Number of the start point. In GSM each burst - * starts with sequence of three bits (0,0,0) which - * indicates start point of the algorithm. - * stop_states: Table with numbers of possible stop states. - * stops_num: Number of possible stop states - * - * - * OUTPUT: output: Differentially decoded hard output of the algorithm: - * -1 for logical "0" and 1 for logical "1" - * - * SUB_FUNC: none - * - * TEST(S): Tested with real world normal burst. - */ - -#ifndef INCLUDED_VITERBI_DETECTOR_H -#define INCLUDED_VITERBI_DETECTOR_H - -void viterbi_detector(const gr_complex * input, unsigned int samples_num, gr_complex * rhh, unsigned int start_state, const unsigned int * stop_states, unsigned int stops_num, float * output); - -#endif /* INCLUDED_VITERBI_DETECTOR_H */ -- cgit v1.2.3