aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPiotr Krysik <ptrkrysik@gmail.com>2016-10-02 18:51:43 +0200
committerPiotr Krysik <ptrkrysik@gmail.com>2016-10-02 18:51:43 +0200
commit61696edd01ae4b124b8b94bf2ddb3642572c24e0 (patch)
tree54a5774f4dd0885c55dadfbd672cd7cd7d2e18eb /lib
parent5878225d8a0c24e428c6497f1969637cda726f8f (diff)
SCH decoding with libosmocore
Diffstat (limited to 'lib')
-rw-r--r--lib/receiver/sch.c299
-rw-r--r--lib/receiver/sch.h21
2 files changed, 67 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) |
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