blob: 1d2566469c0845b8bde8ec5dc3e7e58506b26d47 [file] [log] [blame]
piotrfaacc722014-07-20 23:48:32 +02001/* -*- c++ -*- */
ptrkrysik529895b2014-12-02 18:07:38 +01002/*
3 * @file
4 * @author Piotr Krysik <ptrkrysik@gmail.com>
5 * @section LICENSE
6 *
7 * Gr-gsm is free software; you can redistribute it and/or modify
piotrfaacc722014-07-20 23:48:32 +02008 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
ptrkrysik529895b2014-12-02 18:07:38 +010011 *
12 * Gr-gsm is distributed in the hope that it will be useful,
piotrfaacc722014-07-20 23:48:32 +020013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
ptrkrysik529895b2014-12-02 18:07:38 +010016 *
piotrfaacc722014-07-20 23:48:32 +020017 * You should have received a copy of the GNU General Public License
ptrkrysik529895b2014-12-02 18:07:38 +010018 * along with gr-gsm; see the file COPYING. If not, write to
piotrfaacc722014-07-20 23:48:32 +020019 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <gnuradio/io_signature.h>
ptrkrysik3be74a72014-12-13 10:11:00 +010028#include <grgsm/gsmtap.h>
piotrfaacc722014-07-20 23:48:32 +020029#include "control_channels_decoder_impl.h"
30
ptrkrysik617ba032014-11-21 10:11:05 +010031#define DATA_BYTES 23
32
piotrfaacc722014-07-20 23:48:32 +020033namespace gr {
34 namespace gsm {
35
36 control_channels_decoder::sptr
37 control_channels_decoder::make()
38 {
39 return gnuradio::get_initial_sptr
40 (new control_channels_decoder_impl());
41 }
42
43 /*
ptrkrysik7f61c642014-10-30 08:57:27 +010044 * Constructor
piotrfaacc722014-07-20 23:48:32 +020045 */
46 control_channels_decoder_impl::control_channels_decoder_impl()
47 : gr::block("control_channels_decoder",
48 gr::io_signature::make(0, 0, 0),
49 gr::io_signature::make(0, 0, 0)),
50 d_collected_bursts_num(0)
51 {
52 //initialize de/interleaver
53 int j, k, B;
54 for (k = 0; k < CONV_SIZE; k++)
55 {
56 B = k % 4;
57 j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
58 interleave_trans[k] = B * 114 + j; //114=57 + 57
59 }
ptrkrysik7f61c642014-10-30 08:57:27 +010060
61 //initialize decoder
piotrfaacc722014-07-20 23:48:32 +020062 FC_init(&fc_ctx, 40, 184);
ptrkrysik7f61c642014-10-30 08:57:27 +010063
64 //setup input/output ports
piotrfaacc722014-07-20 23:48:32 +020065 message_port_register_in(pmt::mp("bursts"));
66 set_msg_handler(pmt::mp("bursts"), boost::bind(&control_channels_decoder_impl::decode, this, _1));
piotrb529a592014-08-04 11:30:43 +020067 message_port_register_out(pmt::mp("msgs"));
piotrfaacc722014-07-20 23:48:32 +020068 }
69
piotrfaacc722014-07-20 23:48:32 +020070 control_channels_decoder_impl::~control_channels_decoder_impl()
71 {
72 }
73
74 void control_channels_decoder_impl::decode(pmt::pmt_t msg)
75 {
76 unsigned char iBLOCK[BLOCKS*iBLOCK_SIZE], hl, hn, conv_data[CONV_SIZE], decoded_data[PARITY_OUTPUT_SIZE];
77 d_bursts[d_collected_bursts_num] = msg;
78 d_collected_bursts_num++;
79 //get convecutive bursts
piotrfaacc722014-07-20 23:48:32 +020080
81 if(d_collected_bursts_num==4)
82 {
83 d_collected_bursts_num=0;
84 //reorganize data
85 for(int ii = 0; ii < 4; ii++)
86 {
ptrkrysik617ba032014-11-21 10:11:05 +010087 pmt::pmt_t header_plus_burst = pmt::cdr(d_bursts[ii]);
88 int8_t * burst_bits = (int8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr);
piotrfaacc722014-07-20 23:48:32 +020089
90 for(int jj = 0; jj < 57; jj++)
91 {
92 iBLOCK[ii*iBLOCK_SIZE+jj] = burst_bits[jj + 3];
93 iBLOCK[ii*iBLOCK_SIZE+jj+57] = burst_bits[jj + 88]; //88 = 3+57+1+26+1
94 }
95 }
96 //deinterleave
97 for (int k = 0; k < CONV_SIZE; k++)
98 {
99 conv_data[k] = iBLOCK[interleave_trans[k]];
100 }
101 //convolutional code decode
102 int errors = conv_decode(decoded_data, conv_data);
103 //std::cout << "Errors:" << errors << " " << parity_check(decoded_data) << std::endl;
104 // check parity
105 // If parity check error detected try to fix it.
106
107 if (parity_check(decoded_data))
108 {
109 FC_init(&fc_ctx, 40, 184);
110 unsigned char crc_result[PARITY_OUTPUT_SIZE];
111 if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0)
112 {
113 //("error: sacch: parity error (errors=%d fn=%d)\n", errors, ctx->fn);
piotrab663c82014-08-06 14:14:15 +0200114 //std::cout << "Uncorrectable errors!" << std::endl;
piotrfaacc722014-07-20 23:48:32 +0200115 errors = -1;
ptrkrysik18df2f32014-11-19 11:33:08 +0100116 return;
piotrfaacc722014-07-20 23:48:32 +0200117 } else {
118 //DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n", errors, ctx->fn);
119 //std::cout << "Corrected some errors" << std::endl;
120 memcpy(decoded_data, crc_result, PARITY_OUTPUT_SIZE);
121 errors = 0;
122 }
123 } else {
124 //std::cout << "Everything correct" << std::endl;
125 }
126 //compress bits
127 unsigned char outmsg[27];
128 unsigned char sbuf_len=224;
129 int i, j, c, pos=0;
130 for(i = 0; i < sbuf_len; i += 8) {
piotrab663c82014-08-06 14:14:15 +0200131 for(j = 0, c = 0; (j < 8) && (i + j < sbuf_len); j++){
132 c |= (!!decoded_data[i + j]) << j;
133 }
134 outmsg[pos++] = c & 0xff;
135 }
piotrb529a592014-08-04 11:30:43 +0200136
137 //send message with header of the first burst
ptrkrysik617ba032014-11-21 10:11:05 +0100138 pmt::pmt_t first_header_plus_burst = pmt::cdr(d_bursts[0]);
139 gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(first_header_plus_burst);
ptrkrysik617ba032014-11-21 10:11:05 +0100140 int8_t header_plus_data[sizeof(gsmtap_hdr)+DATA_BYTES];
iZsh66987932015-08-16 14:42:18 +0200141 memcpy(header_plus_data, header, sizeof(gsmtap_hdr));
ptrkrysik617ba032014-11-21 10:11:05 +0100142 memcpy(header_plus_data+sizeof(gsmtap_hdr), outmsg, DATA_BYTES);
iZsh66987932015-08-16 14:42:18 +0200143 ((gsmtap_hdr*)header_plus_data)->type = GSMTAP_TYPE_UM;
ptrkrysik617ba032014-11-21 10:11:05 +0100144
145 pmt::pmt_t msg_binary_blob = pmt::make_blob(header_plus_data,DATA_BYTES+sizeof(gsmtap_hdr));
ptrkrysik7f61c642014-10-30 08:57:27 +0100146 pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob);
147
piotrb529a592014-08-04 11:30:43 +0200148 message_port_pub(pmt::mp("msgs"), msg_out);
piotrfaacc722014-07-20 23:48:32 +0200149 }
150 return;
151 }
152 } /* namespace gsm */
153} /* namespace gr */
154