diff options
author | Piotr Krysik <ptrkrysik@gmail.com> | 2016-10-02 18:51:43 +0200 |
---|---|---|
committer | Piotr Krysik <ptrkrysik@gmail.com> | 2016-10-02 18:51:43 +0200 |
commit | 61696edd01ae4b124b8b94bf2ddb3642572c24e0 (patch) | |
tree | 54a5774f4dd0885c55dadfbd672cd7cd7d2e18eb /lib/receiver/sch.c | |
parent | 5878225d8a0c24e428c6497f1969637cda726f8f (diff) |
SCH decoding with libosmocore
Diffstat (limited to 'lib/receiver/sch.c')
-rw-r--r-- | lib/receiver/sch.c | 299 |
1 files changed, 46 insertions, 253 deletions
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> -#include <string.h> -#include "gsm_constants.h" - -#define DEBUGF(a...) { \ - fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ - fprintf(stderr, a); \ -} while (0) - - - +/* -*- c++ -*- */ /* - * Synchronization channel. + * @file + * @author Piotr Krysik <ptrkrysik@gmail.com> + * @section LICENSE * - * Timeslot Repeat length Frame Number (mod repeat length) - * 0 51 1, 11, 21, 31, 41 - */ - -/* - * Parity (FIRE) for the GSM SCH. + * 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. * - * g(x) = x^10 + x^8 + x^6 + x^5 + x^4 + x^2 + 1 - */ -#define DATA_BLOCK_SIZE 25 -#define PARITY_SIZE 10 -#define TAIL_BITS_SIZE 4 -#define PARITY_OUTPUT_SIZE (DATA_BLOCK_SIZE + PARITY_SIZE + TAIL_BITS_SIZE) - -static const unsigned char parity_polynomial[PARITY_SIZE + 1] = { - 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 -}; - -static const unsigned char parity_remainder[PARITY_SIZE] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -}; - - -static void parity_encode(unsigned char *d, unsigned char *p) -{ - - unsigned int i; - unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q; - - memcpy(buf, d, DATA_BLOCK_SIZE); - memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE); - - for (q = buf; q < buf + DATA_BLOCK_SIZE; q++) - if (*q) - for (i = 0; i < PARITY_SIZE + 1; i++) - q[i] ^= parity_polynomial[i]; - for (i = 0; i < PARITY_SIZE; i++) - p[i] = !buf[DATA_BLOCK_SIZE + i]; -} - - -static int parity_check(unsigned char *d) -{ - - unsigned int i; - unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q; - - memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE); - - for (q = buf; q < buf + DATA_BLOCK_SIZE; q++) - if (*q) - for (i = 0; i < PARITY_SIZE + 1; i++) - q[i] ^= parity_polynomial[i]; - return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE); -} - - -/* - * Convolutional encoding and Viterbi decoding for the GSM SCH. - * (Equivalent to the GSM SACCH.) - * - * G_0 = 1 + x^3 + x^4 - * G_1 = 1 + x + x^3 + x^4 - * - * i.e., - * - * c_{2k} = u_k + u_{k - 3} + u_{k - 4} - * c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4} - */ -#define CONV_INPUT_SIZE PARITY_OUTPUT_SIZE -#define CONV_SIZE (2 * CONV_INPUT_SIZE) -#define K 5 -#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1) - - -/* - * Given the current state and input bit, what are the output bits? - * - * encode[current_state][input_bit] - */ -static const unsigned int encode[1 << (K - 1)][2] = { - {0, 3}, {3, 0}, {3, 0}, {0, 3}, - {0, 3}, {3, 0}, {3, 0}, {0, 3}, - {1, 2}, {2, 1}, {2, 1}, {1, 2}, - {1, 2}, {2, 1}, {2, 1}, {1, 2} -}; - - -/* - * Given the current state and input bit, what is the next state? - * - * next_state[current_state][input_bit] - */ -static const unsigned int next_state[1 << (K - 1)][2] = { - {0, 8}, {0, 8}, {1, 9}, {1, 9}, - {2, 10}, {2, 10}, {3, 11}, {3, 11}, - {4, 12}, {4, 12}, {5, 13}, {5, 13}, - {6, 14}, {6, 14}, {7, 15}, {7, 15} -}; - - -/* - * Given the previous state and the current state, what input bit caused - * the transition? If it is impossible to transition between the two - * states, the value is 2. + * 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. * - * prev_next_state[previous_state][current_state] + * 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. */ -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; - } -} +#include <string.h> +#include "gsm_constants.h" +#include <osmocom/coding/gsm0503_coding.h> +#include <osmocom/core/utils.h> -static int conv_decode(unsigned char *data, unsigned char *output) +static int ubits2sbits(ubit_t *ubits, sbit_t *sbits, int count) { - - 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; - } - } + int i; + + 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) | |