From faacc72413cb64544b8e46beded071ff91826d82 Mon Sep 17 00:00:00 2001 From: piotr Date: Sun, 20 Jul 2014 23:48:32 +0200 Subject: Added typical signalization channels (CCCH, BCCH, SDCCH) decoder and demapper for BCCH. The implementation is quite dirty at this moment. --- lib/CMakeLists.txt | 6 +- lib/burst_printer/bursts_printer_impl.cc | 4 +- lib/decoding/cch.c | 553 ++++++++++++++++++++++++++ lib/decoding/cch.h | 59 +++ lib/decoding/control_channels_decoder_impl.cc | 147 +++++++ lib/decoding/control_channels_decoder_impl.h | 48 +++ lib/decoding/fire_crc.c | 179 +++++++++ lib/decoding/fire_crc.h | 47 +++ lib/decoding/interleave.c | 71 ++++ lib/decoding/interleave.h | 28 ++ lib/demapping/get_bcch_or_ccch_bursts_impl.cc | 100 +++++ lib/demapping/get_bcch_or_ccch_bursts_impl.h | 44 ++ lib/receiver/gsmtap.h | 72 ---- lib/receiver/receiver_impl.h | 2 +- 14 files changed, 1284 insertions(+), 76 deletions(-) create mode 100644 lib/decoding/cch.c create mode 100644 lib/decoding/cch.h create mode 100644 lib/decoding/control_channels_decoder_impl.cc create mode 100644 lib/decoding/control_channels_decoder_impl.h create mode 100644 lib/decoding/fire_crc.c create mode 100644 lib/decoding/fire_crc.h create mode 100644 lib/decoding/interleave.c create mode 100644 lib/decoding/interleave.h create mode 100644 lib/demapping/get_bcch_or_ccch_bursts_impl.cc create mode 100644 lib/demapping/get_bcch_or_ccch_bursts_impl.h delete mode 100644 lib/receiver/gsmtap.h (limited to 'lib') diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 931e0c1..79fa57a 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -30,7 +30,11 @@ list(APPEND gsm_sources receiver/viterbi_detector.cc receiver/sch.c burst_printer/bursts_printer_impl.cc - ) + demapping/get_bcch_or_ccch_bursts_impl.cc + decoding/control_channels_decoder_impl.cc + decoding/cch.c + decoding/fire_crc.c +) add_library(gnuradio-gsm SHARED ${gsm_sources}) target_link_libraries(gnuradio-gsm ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} diff --git a/lib/burst_printer/bursts_printer_impl.cc b/lib/burst_printer/bursts_printer_impl.cc index dbb7023..c37838b 100644 --- a/lib/burst_printer/bursts_printer_impl.cc +++ b/lib/burst_printer/bursts_printer_impl.cc @@ -23,10 +23,10 @@ #endif #include -#include "bursts_printer_impl.h" -#include +#include #include #include +#include "bursts_printer_impl.h" namespace gr { namespace gsm { diff --git a/lib/decoding/cch.c b/lib/decoding/cch.c new file mode 100644 index 0000000..16db5eb --- /dev/null +++ b/lib/decoding/cch.c @@ -0,0 +1,553 @@ +//#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]; +} + */ + + +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 new file mode 100644 index 0000000..efd5615 --- /dev/null +++ b/lib/decoding/cch.h @@ -0,0 +1,59 @@ +//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) + +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 new file mode 100644 index 0000000..544e6bb --- /dev/null +++ b/lib/decoding/control_channels_decoder_impl.cc @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 <+YOU OR YOUR COMPANY+>. + * + * This 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, + * 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 + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "control_channels_decoder_impl.h" + +namespace gr { + namespace gsm { + + control_channels_decoder::sptr + control_channels_decoder::make() + { + return gnuradio::get_initial_sptr + (new control_channels_decoder_impl()); + } + + /* + * The private constructor + */ + control_channels_decoder_impl::control_channels_decoder_impl() + : gr::block("control_channels_decoder", + gr::io_signature::make(0, 0, 0), + 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 + } + + FC_init(&fc_ctx, 40, 184); + message_port_register_in(pmt::mp("bursts")); + set_msg_handler(pmt::mp("bursts"), boost::bind(&control_channels_decoder_impl::decode, this, _1)); +// message_port_register_out(pmt::mp("")); + } + + /* + * Our virtual destructor. + */ + control_channels_decoder_impl::~control_channels_decoder_impl() + { + } + + 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]; + d_bursts[d_collected_bursts_num] = msg; + d_collected_bursts_num++; + //get convecutive bursts + pmt::pmt_t header_blob = pmt::car(msg); + gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_blob); + + if(d_collected_bursts_num==4) + { + d_collected_bursts_num=0; + //reorganize data + for(int ii = 0; ii < 4; ii++) + { + pmt::pmt_t burst_content = pmt::cdr(d_bursts[ii]); + int8_t * burst_bits = (int8_t *)pmt::blob_data(burst_content); + + 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 + } + } + //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. + + 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; + } 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[27]; + 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; + } + + //printf("%6d %d:", (0 + 1), 0); + int jj=0; + while (jj < 23){ + printf(" %02x", outmsg[jj]);//decoded_data[jj]); + jj++; + } + printf("\n"); + fflush(stdout); + } + return; + } + } /* namespace gsm */ +} /* namespace gr */ + diff --git a/lib/decoding/control_channels_decoder_impl.h b/lib/decoding/control_channels_decoder_impl.h new file mode 100644 index 0000000..41404fa --- /dev/null +++ b/lib/decoding/control_channels_decoder_impl.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 <+YOU OR YOUR COMPANY+>. + * + * This 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, + * 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 + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GSM_CONTROL_CHANNELS_DECODER_IMPL_H +#define INCLUDED_GSM_CONTROL_CHANNELS_DECODER_IMPL_H + +#include +#include "fire_crc.h" +#include "cch.h" + +namespace gr { + namespace gsm { + + class control_channels_decoder_impl : public control_channels_decoder + { + 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); + public: + control_channels_decoder_impl(); + ~control_channels_decoder_impl(); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_CONTROL_CHANNELS_DECODER_IMPL_H */ + diff --git a/lib/decoding/fire_crc.c b/lib/decoding/fire_crc.c new file mode 100644 index 0000000..7cdfc0b --- /dev/null +++ b/lib/decoding/fire_crc.c @@ -0,0 +1,179 @@ +//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/lib/decoding/fire_crc.h b/lib/decoding/fire_crc.h new file mode 100644 index 0000000..aa6319c --- /dev/null +++ b/lib/decoding/fire_crc.h @@ -0,0 +1,47 @@ +//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/lib/decoding/interleave.c b/lib/decoding/interleave.c new file mode 100644 index 0000000..8388a6f --- /dev/null +++ b/lib/decoding/interleave.c @@ -0,0 +1,71 @@ +//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 */ + //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 new file mode 100644 index 0000000..a50434a --- /dev/null +++ b/lib/decoding/interleave.h @@ -0,0 +1,28 @@ +//TODO: this file shouldn't be part of the GSM Receiver +/* + * $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/demapping/get_bcch_or_ccch_bursts_impl.cc b/lib/demapping/get_bcch_or_ccch_bursts_impl.cc new file mode 100644 index 0000000..4e8d369 --- /dev/null +++ b/lib/demapping/get_bcch_or_ccch_bursts_impl.cc @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 <+YOU OR YOUR COMPANY+>. + * + * This 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, + * 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 + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "get_bcch_or_ccch_bursts_impl.h" + +namespace gr { + namespace gsm { + + get_bcch_or_ccch_bursts::sptr + get_bcch_or_ccch_bursts::make() + { + return gnuradio::get_initial_sptr + (new get_bcch_or_ccch_bursts_impl()); + } + + /* + * The private constructor + */ + get_bcch_or_ccch_bursts_impl::get_bcch_or_ccch_bursts_impl() + : gr::block("get_bcch_or_ccch_bursts", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) + { + message_port_register_in(pmt::mp("bursts")); + set_msg_handler(pmt::mp("bursts"), boost::bind(&get_bcch_or_ccch_bursts_impl::filter_ccch, this, _1)); + message_port_register_out(pmt::mp("bursts")); + } + + /* + * Our virtual destructor. + */ + get_bcch_or_ccch_bursts_impl::~get_bcch_or_ccch_bursts_impl() + { + } + + void get_bcch_or_ccch_bursts_impl::filter_ccch(pmt::pmt_t msg) + { + pmt::pmt_t header_blob = pmt::car(msg); + pmt::pmt_t content = pmt::cdr(msg); + gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_blob); + uint32_t frame_nr = header->frame_number; + + uint32_t fn_mod51 = header->frame_number % 51; + const int fn51_start = 6; + const int fn51_stop = 9; + + if(header->timeslot==0){ + if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop){ + uint32_t ii = fn_mod51-fn51_start; + d_frame_numbers[ii]=header->frame_number; + d_bursts[ii] = msg; + } + + if(fn_mod51==fn51_stop){ + //check for a situation where some BCCH bursts were lost + //in this situation frame numbers won't be consecutive + bool frames_are_consecutive = true; + for(int jj=1; jj<4; jj++) + { + if((d_frame_numbers[jj]-d_frame_numbers[jj-1])!=1){ + frames_are_consecutive = false; + } + } + if(frames_are_consecutive) + { + //send bursts to the output + for(int jj=0; jj<4; jj++) + { + message_port_pub(pmt::mp("bursts"), d_bursts[jj]); + } + } + } + } + } + } /* namespace gsm */ +} /* namespace gr */ + diff --git a/lib/demapping/get_bcch_or_ccch_bursts_impl.h b/lib/demapping/get_bcch_or_ccch_bursts_impl.h new file mode 100644 index 0000000..c3c4c59 --- /dev/null +++ b/lib/demapping/get_bcch_or_ccch_bursts_impl.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 <+YOU OR YOUR COMPANY+>. + * + * This 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, + * 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 + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GSM_GET_BCCH_OR_CCCH_BURSTS_IMPL_H +#define INCLUDED_GSM_GET_BCCH_OR_CCCH_BURSTS_IMPL_H + +#include + +namespace gr { + namespace gsm { + + class get_bcch_or_ccch_bursts_impl : public get_bcch_or_ccch_bursts + { + private: + uint32_t d_frame_numbers[4]; + pmt::pmt_t d_bursts[4]; + public: + get_bcch_or_ccch_bursts_impl(); + ~get_bcch_or_ccch_bursts_impl(); + void filter_ccch(pmt::pmt_t msg); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_GET_BCCH_OR_CCCH_BURSTS_IMPL_H */ + diff --git a/lib/receiver/gsmtap.h b/lib/receiver/gsmtap.h deleted file mode 100644 index bf8226b..0000000 --- a/lib/receiver/gsmtap.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _GSMTAP_H -#define _GSMTAP_H - -/* gsmtap header, pseudo-header in front of the actua GSM payload */ - -/* GSMTAP is a generic header format for GSM protocol captures, - * it uses the IANA-assigned UDP port number 4729 and carries - * payload in various formats of GSM interfaces such as Um MAC - * blocks or Um bursts. - * - * Example programs generating GSMTAP data are airprobe - * (http://airprobe.org/) or OsmocomBB (http://bb.osmocom.org/) - */ - -#include - -#define GSMTAP_VERSION 0x02 - -#define GSMTAP_TYPE_UM 0x01 /* A Layer 2 MAC block (23 bytes) */ -#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 -#define GSMTAP_BURST_NONE 0x09 - -#define GSMTAP_CHANNEL_UNKNOWN 0x00 -#define GSMTAP_CHANNEL_BCCH 0x01 -#define GSMTAP_CHANNEL_CCCH 0x02 -#define GSMTAP_CHANNEL_RACH 0x03 -#define GSMTAP_CHANNEL_AGCH 0x04 -#define GSMTAP_CHANNEL_PCH 0x05 -#define GSMTAP_CHANNEL_SDCCH 0x06 -#define GSMTAP_CHANNEL_SDCCH4 0x07 -#define GSMTAP_CHANNEL_SDCCH8 0x08 -#define GSMTAP_CHANNEL_TCH_F 0x09 -#define GSMTAP_CHANNEL_TCH_H 0x0a -#define GSMTAP_CHANNEL_ACCH 0x80 - -#define GSMTAP_ARFCN_F_PCS 0x8000 -#define GSMTAP_ARFCN_F_UPLINK 0x4000 -#define GSMTAP_ARFCN_MASK 0x3fff - -#define GSMTAP_UDP_PORT 4729 /* officially registered with IANA */ - -struct gsmtap_hdr { - uint8_t version; /* version, set to GSMTAP_VERSION */ - uint8_t hdr_len; /* length in number of 32bit words */ - uint8_t type; /* see GSMTAP_TYPE_* */ - uint8_t timeslot; /* timeslot (0..7 on Um) */ - - uint16_t arfcn; /* ARFCN (frequency) */ - int8_t signal_dbm; /* signal level in dBm */ - int8_t snr_db; /* signal/noise ratio in dB */ - - uint32_t frame_number; /* GSM Frame Number (FN) */ - - uint8_t sub_type; /* Type of burst/channel, see above */ - uint8_t antenna_nr; /* Antenna Number */ - uint8_t sub_slot; /* sub-slot within timeslot */ - uint8_t res; /* reserved for future use (RFU) */ - -} __attribute__((packed)); - -#endif /* _GSMTAP_H */ diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h index 42e6d01..200a951 100644 --- a/lib/receiver/receiver_impl.h +++ b/lib/receiver/receiver_impl.h @@ -22,9 +22,9 @@ #define INCLUDED_GSM_RECEIVER_IMPL_H #include +#include #include #include -#include namespace gr { namespace gsm { -- cgit v1.2.3