Merge branch '213-3digit-mnc' of https://github.com/romankh/gr-gsm into libosmocore_integration
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5832d42..11d589d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -107,6 +107,7 @@
 find_package(CppUnit)
 find_package(Doxygen)
 find_package(Libosmocore)
+find_package(Libosmocoding)
 
 if(NOT GNURADIO_RUNTIME_FOUND)
     message(FATAL_ERROR "GnuRadio Runtime required to compile gr-gsm")
@@ -120,6 +121,9 @@
 if(NOT LIBOSMOCORE_FOUND)
     message(FATAL_ERROR "Libosmocore required to compile gr-gsm")
 endif()
+if(NOT LIBOSMOCODING_FOUND)
+    message(FATAL_ERROR "Libosmocoding required to compile gr-gsm")
+endif()
 
 ########################################################################
 # Setup doxygen option
diff --git a/apps/README b/apps/README
index e811c06..e9de333 100644
--- a/apps/README
+++ b/apps/README
@@ -10,8 +10,8 @@
 
 There are following helper programs for grgsm_decode program:
 
-* grgsm_capture    (old name: airprobe_rtlsdr_capture.py) - program for capturing GSM signal to a file 
+* grgsm_capture.py    (old name: airprobe_rtlsdr_capture.py) - program for capturing GSM signal to a file 
                     that can be later processed by grgsm_decode,
-* grgsm_channelize (old name: gsm_channelize.py) - splits wideband capture file into multiple files - each contain 
+* grgsm_channelize.py (old name: gsm_channelize.py) - splits wideband capture file into multiple files - each contain 
                   single GSM channel.
 
diff --git a/apps/grgsm_livemon b/apps/grgsm_livemon
index d4376e4..c51485c 100755
--- a/apps/grgsm_livemon
+++ b/apps/grgsm_livemon
@@ -1,5 +1,25 @@
 #!/usr/bin/env python2
 # -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+#
 ##################################################
 # GNU Radio Python Flow Graph
 # Title: Gr-gsm Livemon
diff --git a/cmake/Modules/FindLibosmocoding.cmake b/cmake/Modules/FindLibosmocoding.cmake
new file mode 100644
index 0000000..c3e4cbb
--- /dev/null
+++ b/cmake/Modules/FindLibosmocoding.cmake
@@ -0,0 +1,32 @@
+find_package(PkgConfig)
+pkg_check_modules(PC_libosmocoding libosmocoding)
+set(LIBOSMOCODING_DEFINITIONS ${PC_LIBOSMOCODING_CFLAGS_OTHER})
+
+find_path(
+        LIBOSMOCODING_INCLUDE_DIR
+        NAMES   osmocom/coding/gsm0503_coding.h
+        HINTS   ${PC_libosmocoding_INCLUDEDIR}
+                ${PC_libosmocoding_INCLUDE_DIRS}
+                ${CMAKE_INSTALL_PREFIX}/include
+        PATHS   /usr/local/include
+                /usr/include
+)
+
+find_library(
+        LIBOSMOCODING_LIBRARY
+        NAMES   libosmocoding osmocoding
+        HINTS   ${PC_libosmocoding_LIBDIR}
+                ${PC_libosmocoding_LIBRARY_DIRS}
+                ${CMAKE_INSTALL_PREFIX}/lib/
+                ${CMAKE_INSTALL_PREFIX}/lib64/
+        PATHS   /usr/local/lib
+                /usr/lib
+)
+
+
+set(LIBOSMOCODING_LIBRARIES ${LIBOSMOCODING_LIBRARY})
+set(LIBOSMOCODING_INCLUDE_DIRS ${LIBOSMOCODING_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(libosmocoding  DEFAULT_MSG LIBOSMOCODING_LIBRARY LIBOSMOCODING_INCLUDE_DIR)
+mark_as_advanced(LIBOSMOCODING_INCLUDE_DIR LIBOSMOCODING_LIBRARY )
diff --git a/cmake/Modules/FindLibosmocore.cmake b/cmake/Modules/FindLibosmocore.cmake
index 9eff233..1704bf6 100644
--- a/cmake/Modules/FindLibosmocore.cmake
+++ b/cmake/Modules/FindLibosmocore.cmake
@@ -1,5 +1,6 @@
 find_package(PkgConfig)
 pkg_check_modules(PC_libosmocore libosmocore)
+pkg_check_modules(PC_libosmogsm libosmogsm)
 set(LIBOSMOCORE_DEFINITIONS ${PC_LIBOSMOCORE_CFLAGS_OTHER})
 
 find_path(
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 660bbfd..4c18c18 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -34,8 +34,6 @@
     demapping/universal_ctrl_chans_demapper_impl.cc
     demapping/tch_f_chans_demapper_impl.cc
     decoding/control_channels_decoder_impl.cc
-    decoding/cch.c
-    decoding/fire_crc.c
     decoding/tch_f_decoder_impl.cc
     decoding/AmrCoder.cpp
     decoding/BitVector.cpp
@@ -71,7 +69,7 @@
 
 
 add_library(grgsm SHARED ${grgsm_sources})
-target_link_libraries(grgsm ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${VOLK_LIBRARIES} ${LIBOSMOCORE_LIBRARIES}
+target_link_libraries(grgsm ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${VOLK_LIBRARIES} ${LIBOSMOCORE_LIBRARIES} ${LIBOSMOCODING_LIBRARIES} 
 # libraries required by plotting.h - have troubles to be installed by pybombs
 #    boost_iostreams
 #    boost_system
diff --git a/lib/decoding/cch.c b/lib/decoding/cch.c
deleted file mode 100644
index df83d3e..0000000
--- a/lib/decoding/cch.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
-   The Hacker's Choice - http://www.thc.org
-   Part of THC's GSM SCANNER PROJECT
-*/
-
-//#include "system.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-
-//#include <exception>
-//#include <stdexcept>
-#include <math.h>
-//#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];
-}
- */
-
-
-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;
-	}
-}
- */
-
-
-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)]; // accumulated error
-	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);*/
-
-/*	// check parity*/
-/*	// If parity check error detected try to fix it.*/
-/*	if (parity_check(decoded_data))*/
-/*	{*/
-/*		unsigned char crc_result[224];*/
-/*		if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0)*/
-/*		{*/
-/*			errors = -1;*/
-/*			//DEBUGF("error: sacch: parity error (%d fn=%d)\n",*/
-/*			//	errors, ctx->fn);*/
-/*			return NULL;*/
-/*		} else {*/
-/*			//DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n",*/
-/*			//	errors, ctx->fn);*/
-/*			memcpy(decoded_data, crc_result, sizeof crc_result);*/
-/*			errors = 0;*/
-/*		}*/
-/*	}*/
-
-/*	if (errors)*/
-/*		printf("WRN: errors=%d fn=%d\n", errors, ctx->fn);*/
-
-/*	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
-
-/*unsigned char *decode_facch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen, int offset) {*/
-
-/*	int errors, len, data_size;*/
-/*	unsigned char conv_data[CONV_SIZE], iBLOCK[BLOCKS * 2][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);*/
-/*	decode_burstmap(iBLOCK[4], burst + 116 * 4, &hl, &hn);*/
-/*	decode_burstmap(iBLOCK[5], burst + 116 * 5, &hl, &hn);*/
-/*	decode_burstmap(iBLOCK[6], burst + 116 * 6, &hl, &hn);*/
-/*	decode_burstmap(iBLOCK[7], burst + 116 * 7, &hl, &hn);*/
-
-/*	// remove interleave*/
-/*	if (offset == 0)*/
-/*		interleave_decode(&ctx->interleave_facch_f1_ctx, conv_data, (unsigned char *)iBLOCK);*/
-/*	else*/
-/*		interleave_decode(&ctx->interleave_facch_f2_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);*/
-
-/*	// 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)*/
-/*		{*/
-/*			//DEBUGF("error: sacch: parity error (errors=%d fn=%d)\n", errors, ctx->fn);*/
-/*			errors = -1;*/
-/*			return NULL;*/
-/*		} else {*/
-/*			//DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n", errors, ctx->fn);*/
-/*			memcpy(decoded_data, crc_result, sizeof crc_result);*/
-/*			errors = 0;*/
-/*		}*/
-/*	}*/
-
-/*	if (errors)*/
-/*		fprintf(stderr, "WRN: errors=%d fn=%d\n", errors, ctx->fn);*/
-
-/*	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;*/
-/*}*/
diff --git a/lib/decoding/cch.h b/lib/decoding/cch.h
deleted file mode 100644
index e371213..0000000
--- a/lib/decoding/cch.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-   The Hacker's Choice - http://www.thc.org
-   Part of THC's GSM SCANNER PROJECT
-*/
-
-#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)
-
-int conv_decode(unsigned char *output, unsigned char *data);
-int parity_check(unsigned char *d);
-//unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *len);
-//unsigned char *decode_facch(GS_CTX *ctx, unsigned char *burst, unsigned int *len, int offset);
-//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/lib/decoding/control_channels_decoder_impl.cc b/lib/decoding/control_channels_decoder_impl.cc
index 532e255..71695e2 100644
--- a/lib/decoding/control_channels_decoder_impl.cc
+++ b/lib/decoding/control_channels_decoder_impl.cc
@@ -33,6 +33,25 @@
 namespace gr {
   namespace gsm {
 
+    static int ubits2sbits(ubit_t *ubits, sbit_t *sbits, int count)
+    {
+	    int i;
+
+	    for (i = 0; i < count; i++) {
+		    if (*ubits == 0x23) {
+			    ubits++;
+			    sbits++;
+			    continue;
+		    }
+		    if ((*ubits++) & 1)
+			    *sbits++ = -127;
+		    else
+			    *sbits++ = 127;
+	    }
+
+	    return count;
+    }
+
     control_channels_decoder::sptr
     control_channels_decoder::make()
     {
@@ -49,18 +68,6 @@
               gr::io_signature::make(0, 0, 0)),
               d_collected_bursts_num(0)
     {
-        //initialize de/interleaver
-        int j, k, B;
-        for (k = 0; k < CONV_SIZE; k++)
-        {
-            B = k % 4;
-            j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
-            interleave_trans[k] = B * 114 + j; //114=57 + 57
-        }
-        
-        //initialize decoder
-        FC_init(&fc_ctx, 40, 184);
-        
         //setup input/output ports
         message_port_register_in(pmt::mp("bursts"));
         set_msg_handler(pmt::mp("bursts"), boost::bind(&control_channels_decoder_impl::decode, this, _1));
@@ -73,78 +80,44 @@
 
     void control_channels_decoder_impl::decode(pmt::pmt_t msg)
     {
-        unsigned char iBLOCK[BLOCKS*iBLOCK_SIZE], hl, hn, conv_data[CONV_SIZE], decoded_data[PARITY_OUTPUT_SIZE];
+        ubit_t bursts_u[116 * 4];
+        sbit_t bursts_s[116 * 4];
+        uint8_t result[23];
+        int n_errors, n_bits_total;
+        int8_t header_plus_data[sizeof(gsmtap_hdr)+DATA_BYTES];
+
         d_bursts[d_collected_bursts_num] = msg;
         d_collected_bursts_num++;
+
         //get convecutive bursts
-        
         if(d_collected_bursts_num==4)
         {
             d_collected_bursts_num=0;
-            //reorganize data
+            //reorganize data from input bursts
             for(int ii = 0; ii < 4; ii++)
             {
                 pmt::pmt_t header_plus_burst = pmt::cdr(d_bursts[ii]);
                 int8_t * burst_bits = (int8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr);
 
-                for(int jj = 0; jj < 57; jj++)
-                {
-                    iBLOCK[ii*iBLOCK_SIZE+jj] = burst_bits[jj + 3];
-                    iBLOCK[ii*iBLOCK_SIZE+jj+57] = burst_bits[jj + 88]; //88 = 3+57+1+26+1
-                }
+                memcpy(&bursts_u[ii*116], &burst_bits[3],58);
+                memcpy(&bursts_u[ii*116+58], &burst_bits[3+57+1+26],58);
             }
-            //deinterleave
-            for (int k = 0; k < CONV_SIZE; k++)
-            {
-                conv_data[k] = iBLOCK[interleave_trans[k]];
-            }
-            //convolutional code decode
-            int errors = conv_decode(decoded_data, conv_data);
-            //std::cout << "Errors:" << errors << " " << parity_check(decoded_data) << std::endl;
-            // check parity
-            // If parity check error detected try to fix it.
+            //convert to soft bits
+            ubits2sbits(bursts_u, bursts_s, 116 * 4);
+            //decode
+            gsm0503_xcch_decode(result, bursts_s, &n_errors, &n_bits_total);
 
-            if (parity_check(decoded_data))
-            {
-                FC_init(&fc_ctx, 40, 184);
-                unsigned char crc_result[PARITY_OUTPUT_SIZE];
-                if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0)
-                {
-                    //("error: sacch: parity error (errors=%d fn=%d)\n", errors, ctx->fn);
-                    //std::cout << "Uncorrectable errors!" << std::endl;
-                    errors = -1;
-                    return;
-                } else {
-                    //DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n", errors, ctx->fn);
-                    //std::cout << "Corrected some errors" << std::endl;
-                    memcpy(decoded_data, crc_result, PARITY_OUTPUT_SIZE);
-                    errors = 0;
-                }
-            } else {
-                //std::cout << "Everything correct" << std::endl;
-            }
-           //compress bits
-           unsigned char outmsg[28];
-           unsigned char sbuf_len=224;
-           int i, j, c, pos=0;
-           for(i = 0; i < sbuf_len; i += 8) {
-                for(j = 0, c = 0; (j < 8) && (i + j < sbuf_len); j++){
-                    c |= (!!decoded_data[i + j]) << j;
-                }
-                outmsg[pos++] = c & 0xff;
-           }
-
-           //send message with header of the first burst
+            //extract header of the first burst of the four bursts
             pmt::pmt_t first_header_plus_burst = pmt::cdr(d_bursts[0]);
             gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(first_header_plus_burst);
-            int8_t header_plus_data[sizeof(gsmtap_hdr)+DATA_BYTES];
+            //copy header and data
             memcpy(header_plus_data, header, sizeof(gsmtap_hdr));
-            memcpy(header_plus_data+sizeof(gsmtap_hdr), outmsg, DATA_BYTES);
+            memcpy(header_plus_data+sizeof(gsmtap_hdr), result, DATA_BYTES);
+            //set data type in the header
             ((gsmtap_hdr*)header_plus_data)->type = GSMTAP_TYPE_UM;
-            
-            pmt::pmt_t msg_binary_blob = pmt::make_blob(header_plus_data,DATA_BYTES+sizeof(gsmtap_hdr));
-            pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob);
-            
+            //prepare message
+            pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, pmt::make_blob(header_plus_data,DATA_BYTES+sizeof(gsmtap_hdr)));
+            //send message to the output
             message_port_pub(pmt::mp("msgs"), msg_out);
         }
         return;
diff --git a/lib/decoding/control_channels_decoder_impl.h b/lib/decoding/control_channels_decoder_impl.h
index 2fa3dce..f2261a2 100644
--- a/lib/decoding/control_channels_decoder_impl.h
+++ b/lib/decoding/control_channels_decoder_impl.h
@@ -24,8 +24,9 @@
 #define INCLUDED_GSM_CONTROL_CHANNELS_DECODER_IMPL_H
 
 #include <grgsm/decoding/control_channels_decoder.h>
-#include "fire_crc.h"
-#include "cch.h"
+extern "C" {
+    #include <osmocom/coding/gsm0503_coding.h>
+}
 
 namespace gr {
   namespace gsm {
@@ -35,9 +36,8 @@
      private:
       unsigned int d_collected_bursts_num;
       pmt::pmt_t d_bursts[4];
-      unsigned short interleave_trans[CONV_SIZE];      
-      FC_CTX fc_ctx;      
-      void decode(pmt::pmt_t msg);
+     
+      void decode(pmt::pmt_t msg);      
      public:
       control_channels_decoder_impl();
       ~control_channels_decoder_impl();
diff --git a/lib/decoding/fire_crc.c b/lib/decoding/fire_crc.c
deleted file mode 100644
index 5800517..0000000
--- a/lib/decoding/fire_crc.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-   The Hacker's Choice - http://www.thc.org
-   Part of THC's GSM SCANNER PROJECT
-*/
-
-
-#include "fire_crc.h"
-#include <stdio.h>
-#include <string.h>
-
-#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");
-	return 0;
-}
-
-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/lib/decoding/fire_crc.h b/lib/decoding/fire_crc.h
deleted file mode 100644
index d02021e..0000000
--- a/lib/decoding/fire_crc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-   The Hacker's Choice - http://www.thc.org
-   Part of THC's GSM SCANNER PROJECT
-*/
-
-
-
-#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/lib/decoding/interleave.c b/lib/decoding/interleave.c
deleted file mode 100644
index c6304db..0000000
--- a/lib/decoding/interleave.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-   The Hacker's Choice - http://www.thc.org
-   Part of THC's GSM SCANNER PROJECT
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#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 */
-		//printf("%d -> %d\n", ictx->trans[k], k);
-	}
-//	exit(0);
-	return 0;
-}
-
-int
-interleave_init_facch_f(INTERLEAVE_CTX *ictx, int size, int block_size, int block_offset)
-{
-	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 + block_offset) % 8;
-		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)
-{
-    printf("Lol\n");
-	int k;
-	for (k = 0; k < ictx->trans_size; k++)
-	{
-		printf("k=%d, ictx->trans[k]=%d\n", k, ictx->trans[k]);
-		dst[k] = src[ictx->trans[k]];
-    }
-}
-
diff --git a/lib/decoding/interleave.h b/lib/decoding/interleave.h
deleted file mode 100644
index aba1dfd..0000000
--- a/lib/decoding/interleave.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-   The Hacker's Choice - http://www.thc.org
-   Part of THC's GSM SCANNER PROJECT
-*/
-
-/*
- * $Id:$
- */
-
-#ifndef __GSMSP_INTERLEAVE_H__
-#define __GSMSP_INTERLEAVE_H__ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-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_init_facch_f(INTERLEAVE_CTX *ictx, int size, int block_size, int block_offset);
-int interleave_deinit(INTERLEAVE_CTX *ictx);
-void interleave_decode(INTERLEAVE_CTX *ictx, unsigned char *dst, unsigned char *src);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/lib/decoding/tch_f_decoder_impl.cc b/lib/decoding/tch_f_decoder_impl.cc
index 41e5f53..a84c47c 100644
--- a/lib/decoding/tch_f_decoder_impl.cc
+++ b/lib/decoding/tch_f_decoder_impl.cc
@@ -29,11 +29,34 @@
 #include "stdio.h"
 #include "tch_f_decoder_impl.h"
 
+extern "C" {
+    #include <osmocom/coding/gsm0503_coding.h>
+}
+
 #define DATA_BYTES 23
 
 namespace gr {
   namespace gsm {
 
+    static int ubits2sbits(ubit_t *ubits, sbit_t *sbits, int count)
+    {
+	    int i;
+
+	    for (i = 0; i < count; i++) {
+		    if (*ubits == 0x23) {
+			    ubits++;
+			    sbits++;
+			    continue;
+		    }
+		    if ((*ubits++) & 1)
+			    *sbits++ = -127;
+		    else
+			    *sbits++ = 127;
+	    }
+
+	    return count;
+    }
+
     tch_f_decoder::sptr
     tch_f_decoder::make(tch_mode mode, bool boundary_check)
     {
@@ -107,6 +130,7 @@
 
         if (d_collected_bursts_num == 8)
         {
+        	ubit_t bursts_u[116 * 8];
             d_collected_bursts_num = 0;
 
             // reorganize data
@@ -115,6 +139,9 @@
                 pmt::pmt_t header_plus_burst = pmt::cdr(d_bursts[ii]);
                 int8_t * burst_bits = (int8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr);
 
+                memcpy(&bursts_u[ii*116], &burst_bits[3],58);
+                memcpy(&bursts_u[ii*116+58], &burst_bits[3+57+1+26],58);
+
                 for (int jj = 0; jj < 57; jj++)
                 {
                     iBLOCK[ii*114+jj] = burst_bits[jj + 3];
@@ -269,65 +296,26 @@
                 unsigned tail = mTCHU.peekField(185, 4);
                 bool good = (sentParity == calcParity) && (tail == 0);
 
+                
                 if (good)
                 {
-                    unsigned char frameBuffer[33];
+                    uint8_t frameBuffer[33];
+                	sbit_t bursts_s[116 * 8];
+	                int n_errors, n_bits_total;
                     unsigned int  mTCHFrameLength;
 
+                	ubits2sbits(bursts_u, bursts_s, 116 * 8);                    
+
                     if (d_tch_mode == TCH_FS) // GSM-FR
                     {
-                        unsigned char mFrameHeader = 0x0d;
                         mTCHFrameLength = 33;
-
-                        // Undo Um's importance-sorted bit ordering.
-                        // See GSM 05.03 3.1 and Table 2.
-                        BitVector frFrame(260 + 4); // FR has a frameheader of 4 bits only
-                        frFrame.fillField(0, mFrameHeader, 4);
-                        BitVector payload = frFrame.tail(4);
-
-                        mTCHD.unmap(GSM::g610BitOrder, 260, payload);
-                        frFrame.pack(frameBuffer);
-
+                        gsm0503_tch_fr_decode(frameBuffer, bursts_s, 1, 0, &n_errors, &n_bits_total);
+                        std::cout << "Errors: " << n_errors << std::endl;
                     }
                     else if (d_tch_mode == TCH_EFR) // GSM-EFR
                     {
-                        unsigned char mFrameHeader = 0x3c;
-
-                        // AMR Frame, consisting of a 8 bit frame header, plus the payload from decoding
-                        BitVector amrFrame(244 + 8); // Same output length as AMR 12.2
-                        BitVector payload = amrFrame.tail(8);
-
-                        BitVector TCHW(260), EFRBits(244);
-
-                        // write frame header
-                        amrFrame.fillField(0, mFrameHeader, 8);
-
-                        // Undo Um's EFR bit ordering.
-                        mTCHD.unmap(GSM::g660BitOrder, 260, TCHW);
-
-                        // Remove repeating bits and CRC to get raw EFR frame (244 bits)
-                        for (unsigned k=0; k<71; k++)
-                          EFRBits[k] = TCHW[k] & 1;
-
-                        for (unsigned k=73; k<123; k++)
-                          EFRBits[k-2] = TCHW[k] & 1;
-
-                        for (unsigned k=125; k<178; k++)
-                          EFRBits[k-4] = TCHW[k] & 1;
-
-                        for (unsigned k=180; k<230; k++)
-                          EFRBits[k-6] = TCHW[k] & 1;
-
-                        for (unsigned k=232; k<252; k++)
-                          EFRBits[k-8] = TCHW[k] & 1;
-
-                        // Map bits as AMR 12.2k
-                        EFRBits.map(GSM::gAMRBitOrderTCH_AFS12_2, 244, payload);
-
-                        // Put the whole frame (hdr + payload)
                         mTCHFrameLength = 32;
-                        amrFrame.pack(frameBuffer);
-
+                        gsm0503_tch_fr_decode(frameBuffer, bursts_s, 1, 1, &n_errors, &n_bits_total);
                     }
                     message_port_pub(pmt::mp("voice"), pmt::cons(pmt::PMT_NIL, pmt::make_blob(frameBuffer,mTCHFrameLength)));
                 }
diff --git a/lib/decryption/decryption_impl.cc b/lib/decryption/decryption_impl.cc
index 9e6112b..5fa0c03 100644
--- a/lib/decryption/decryption_impl.cc
+++ b/lib/decryption/decryption_impl.cc
@@ -1,19 +1,22 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * @file
+ * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @section LICENSE
  *
- * This is free software; you can redistribute it and/or modify
+ * Gr-gsm 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 software is distributed in the hope that it will be useful,
+ * Gr-gsm 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 software; see the file COPYING.  If not, write to
+ * along with gr-gsm; see the file COPYING.  If not, write to
  * the Free Software Foundation, Inc., 51 Franklin Street,
  * Boston, MA 02110-1301, USA.
  */
@@ -57,7 +60,6 @@
         set_a5_version(a5_version);
         validate_k_c();
 
-//        std::cout << "Be careful with decryption block - it wasn't tested yet!" << std::endl;
         message_port_register_in(pmt::mp("bursts"));
         set_msg_handler(pmt::mp("bursts"), boost::bind(&decryption_impl::decrypt, this, _1));
         message_port_register_out(pmt::mp("bursts"));
@@ -138,7 +140,7 @@
             for (int i = 0; i < 3; i++) {
                 decrypted_data[i] = burst_binary[i];
             }
-            //encrypt first part of the burst
+            //decrypt first part of the burst
             for (int i = 0; i < 57; i++) {
                 decrypted_data[i+3] = keystream[i] ^ burst_binary[i+3];
             }
@@ -146,7 +148,7 @@
             for (int i = 60; i < 88; i++) {
                 decrypted_data[i] = burst_binary[i];
             }
-            //encrypt second part of the burst
+            //decrypt second part of the burst
             for (int i = 0; i < 57; i++) {
                 decrypted_data[i+88] = keystream[i+57] ^ burst_binary[i+88];
             }
diff --git a/lib/decryption/decryption_impl.h b/lib/decryption/decryption_impl.h
index 68fbb9c..d5332d4 100644
--- a/lib/decryption/decryption_impl.h
+++ b/lib/decryption/decryption_impl.h
@@ -1,19 +1,21 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * @file
+ * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @section LICENSE
  *
- * This is free software; you can redistribute it and/or modify
+ * Gr-gsm 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 software is distributed in the hope that it will be useful,
+ * Gr-gsm 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 software; see the file COPYING.  If not, write to
+ * along with gr-gsm; see the file COPYING.  If not, write to
  * the Free Software Foundation, Inc., 51 Franklin Street,
  * Boston, MA 02110-1301, USA.
  */
diff --git a/lib/receiver/clock_offset_control_impl.cc b/lib/receiver/clock_offset_control_impl.cc
index 7fef8fa..4b9a921 100644
--- a/lib/receiver/clock_offset_control_impl.cc
+++ b/lib/receiver/clock_offset_control_impl.cc
@@ -1,4 +1,3 @@
-
 /* -*- c++ -*- */
 /*
  * @file
diff --git a/lib/receiver/sch.c b/lib/receiver/sch.c
index 3273237..a75673f 100644
--- a/lib/receiver/sch.c
+++ b/lib/receiver/sch.c
@@ -1,280 +1,73 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @section LICENSE
+ *
+ * Gr-gsm 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.
+ *
+ * Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #include <string.h>
 #include "gsm_constants.h"
 
-#define DEBUGF(a...)	{ \
-    fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
-    fprintf(stderr, a); \
-} while (0)
+#include <osmocom/coding/gsm0503_coding.h>
+#include <osmocom/core/utils.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)
+static int ubits2sbits(ubit_t *ubits, sbit_t *sbits, int count)
 {
+    int i;
 
-  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;
-        }
-      }
+    for (i = 0; i < count; i++) {
+	    if (*ubits == 0x23) {
+		    ubits++;
+		    sbits++;
+		    continue;
+	    }
+	    if ((*ubits++) & 1)
+		    *sbits++ = -127;
+	    else
+		    *sbits++ = 127;
     }
 
-    // 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;
+    return count;
 }
 
-
 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];
+  int t1, t2, t3p, t3, ncc, bcc;
+
+  uint8_t result[4];
+  ubit_t bursts_u[SCH_DATA_LEN*2];
+  sbit_t bursts_s[SCH_DATA_LEN*2];
 
   // 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);
+  memcpy(bursts_u, buf, SCH_DATA_LEN);
+  memcpy(bursts_u + 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");
+  ubits2sbits(bursts_u, bursts_s, SCH_DATA_LEN*2);
+  if(gsm0503_sch_decode(result, bursts_s)==-1){
     return 1;
   }
-
+  
   // Synchronization channel information, 44.018 page 171. (V7.2.0)
+  uint8_t decoded_data[25];
+  osmo_pbit2ubit_ext(decoded_data, 0, result, 0, 25, 1);
   ncc =
     (decoded_data[ 7] << 2)  |
     (decoded_data[ 6] << 1)  |
diff --git a/lib/receiver/sch.h b/lib/receiver/sch.h
index 7b5a657..5164c89 100644
--- a/lib/receiver/sch.h
+++ b/lib/receiver/sch.h
@@ -1,3 +1,24 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @section LICENSE
+ *
+ * Gr-gsm 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.
+ *
+ * Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
 
 #ifndef __SCH_H__
 #define __SCH_H__ 1
diff --git a/python/demapping/gsm_bcch_ccch_demapper.py b/python/demapping/gsm_bcch_ccch_demapper.py
index d7b5218..e3ae041 100644
--- a/python/demapping/gsm_bcch_ccch_demapper.py
+++ b/python/demapping/gsm_bcch_ccch_demapper.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
 # -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
 ##################################################
 # GNU Radio Python Flow Graph
 # Title: BCCH + CCCH demapper
diff --git a/python/demapping/gsm_bcch_ccch_sdcch4_demapper.py b/python/demapping/gsm_bcch_ccch_sdcch4_demapper.py
index 9234408..79841d2 100644
--- a/python/demapping/gsm_bcch_ccch_sdcch4_demapper.py
+++ b/python/demapping/gsm_bcch_ccch_sdcch4_demapper.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
 # -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
 ##################################################
 # GNU Radio Python Flow Graph
 # Title: BCCH + CCCH + SDCCH/4 demapper
diff --git a/python/demapping/gsm_sdcch8_demapper.py b/python/demapping/gsm_sdcch8_demapper.py
index 9c1e485..f3e360f 100644
--- a/python/demapping/gsm_sdcch8_demapper.py
+++ b/python/demapping/gsm_sdcch8_demapper.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
 # -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
 ##################################################
 # GNU Radio Python Flow Graph
 # Title: SDCCH/8 demapper
diff --git a/python/misc_utils/clock_offset_corrector_tagged.py b/python/misc_utils/clock_offset_corrector_tagged.py
index bf4b455..ae8d22c 100644
--- a/python/misc_utils/clock_offset_corrector_tagged.py
+++ b/python/misc_utils/clock_offset_corrector_tagged.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
 # -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
 ##################################################
 # GNU Radio Python Flow Graph
 # Title: Clock Offset Corrector Tagged
diff --git a/python/misc_utils/hier_block.py b/python/misc_utils/hier_block.py
index a3ca1e6..189165d 100644
--- a/python/misc_utils/hier_block.py
+++ b/python/misc_utils/hier_block.py
@@ -1,3 +1,25 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
 from gnuradio import gr
 from distutils.version import LooseVersion as version
 
diff --git a/python/receiver/fcch_detector.py b/python/receiver/fcch_detector.py
index 2f2a4ab..06a1257 100644
--- a/python/receiver/fcch_detector.py
+++ b/python/receiver/fcch_detector.py
@@ -1,4 +1,24 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
 ##################################################
 # Gnuradio Python Flow Graph
 # Title: FCCH Bursts Detector
diff --git a/python/receiver/gsm_input.py b/python/receiver/gsm_input.py
index af5d4c3..8442eee 100644
--- a/python/receiver/gsm_input.py
+++ b/python/receiver/gsm_input.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
 # -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
 ##################################################
 # GNU Radio Python Flow Graph
 # Title: GSM input adaptor
diff --git a/python/receiver/gsm_wideband_input.py b/python/receiver/gsm_wideband_input.py
index 962d7b0..633ead2 100644
--- a/python/receiver/gsm_wideband_input.py
+++ b/python/receiver/gsm_wideband_input.py
@@ -1,4 +1,24 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm 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.
+#
+# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
 ##################################################
 # Gnuradio Python Flow Graph
 # Title: GSM wideband input adaptor