blob: c7119285832698e03048cb6297bf5a81745a3b3d [file] [log] [blame]
ptrkrysik6dded652014-11-19 11:32:05 +01001/* -*- 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
ptrkrysik6dded652014-11-19 11:32:05 +01008 * 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,
ptrkrysik6dded652014-11-19 11:32:05 +010013 * 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 *
ptrkrysik6dded652014-11-19 11:32:05 +010017 * 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
ptrkrysik6dded652014-11-19 11:32:05 +010019 * 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>
28#include "universal_ctrl_chans_demapper_impl.h"
ptrkrysik3be74a72014-12-13 10:11:00 +010029#include <grgsm/endian.h>
30#include <grgsm/gsmtap.h>
ptrkrysik42411c62015-07-08 10:50:41 +020031#include <set>
ptrkrysik6dded652014-11-19 11:32:05 +010032
iZsh66987932015-08-16 14:42:18 +020033#define BURST_SIZE 148
34
ptrkrysik6dded652014-11-19 11:32:05 +010035namespace gr {
36 namespace gsm {
37
38 universal_ctrl_chans_demapper::sptr
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010039 universal_ctrl_chans_demapper::make(unsigned int timeslot_nr, const std::vector<int> &starts_fn_mod51, const std::vector<int> &channel_types)
ptrkrysik6dded652014-11-19 11:32:05 +010040 {
41 return gnuradio::get_initial_sptr
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010042 (new universal_ctrl_chans_demapper_impl(timeslot_nr, starts_fn_mod51, channel_types));
ptrkrysik6dded652014-11-19 11:32:05 +010043 }
44
45 /*
46 * The private constructor
47 */
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010048 universal_ctrl_chans_demapper_impl::universal_ctrl_chans_demapper_impl(unsigned int timeslot_nr, const std::vector<int> &starts_fn_mod51, const std::vector<int> &channel_types)
ptrkrysik6dded652014-11-19 11:32:05 +010049 : gr::block("universal_ctrl_chans_demapper",
50 gr::io_signature::make(0, 0, 0),
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010051 gr::io_signature::make(0, 0, 0)),
52 d_timeslot(timeslot_nr)
53
ptrkrysik6dded652014-11-19 11:32:05 +010054 {
55
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010056
ptrkrysik6dded652014-11-19 11:32:05 +010057 for(int ii=0; ii<51; ii++)
58 {
59 d_starts_fn_mod51[ii]=0;
60 d_channel_types[ii]=0;
Roman Khassrafe571e962015-04-12 15:35:41 +020061 d_subslots[ii] = 0;
62 d_subslots[ii+51] = 0;
ptrkrysik6dded652014-11-19 11:32:05 +010063 }
64
65 std::vector<int>::const_iterator s;
66 std::vector<int>::const_iterator ch_type;
67
68 for(s=starts_fn_mod51.begin(), ch_type=channel_types.begin();s != starts_fn_mod51.end(); s++)
69 {
Roman Khassraf939edef2015-04-12 15:20:38 +020070 if((*s >= 0) and (*s <= (51-4)))
ptrkrysik6dded652014-11-19 11:32:05 +010071 {
72 for(int ii=0; ii<4; ii++){
73 d_starts_fn_mod51[*s+ii] = *s;
74 if(ch_type!=channel_types.end())
75 {
76 d_channel_types[*s+ii] = *ch_type;
77 }
78 }
79 if(ch_type!=channel_types.end())
80 {
81 ch_type++;
82 }
83 }
84 }
85
Roman Khassrafe571e962015-04-12 15:35:41 +020086 std::set<int> distinct_channels(channel_types.begin(), channel_types.end());
87 std::set<int>::iterator it;
88 unsigned int subslot;
89
90 for (it=distinct_channels.begin(); it != distinct_channels.end(); it++)
91 {
92 subslot = 0;
93 for(s=starts_fn_mod51.begin();s != starts_fn_mod51.end(); s++)
94 {
95 if ((d_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
96 {
97 for(int ii=0; ii<4; ii++)
98 {
99 d_subslots[*s+ii] = subslot;
100 d_subslots[*s+ii+51] = subslot;
101 }
102 subslot++;
103 }
104 }
105
106 if (*it == GSMTAP_CHANNEL_ACCH or
107 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or
108 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or
109 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or
110 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or
111 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H)
112 )
113 {
114 for(s=starts_fn_mod51.begin();s != starts_fn_mod51.end(); s++)
115 {
116 if ((d_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
117 {
118 for(int ii=0; ii<4; ii++)
119 {
120 d_subslots[*s+ii+51] = subslot;
121 }
122 subslot++;
123 }
124 }
125 }
126 }
127
ptrkrysik6dded652014-11-19 11:32:05 +0100128
129 message_port_register_in(pmt::mp("bursts"));
130 set_msg_handler(pmt::mp("bursts"), boost::bind(&universal_ctrl_chans_demapper_impl::filter_ctrl_chans, this, _1));
131 message_port_register_out(pmt::mp("bursts"));
132 }
133
134 /*
135 * Our virtual destructor.
136 */
137 universal_ctrl_chans_demapper_impl::~universal_ctrl_chans_demapper_impl()
138 {
139 }
140
141 void universal_ctrl_chans_demapper_impl::filter_ctrl_chans(pmt::pmt_t msg)
142 {
ptrkrysik617ba032014-11-21 10:11:05 +0100143 pmt::pmt_t header_plus_burst = pmt::cdr(msg);
144 gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
iZsh66987932015-08-16 14:42:18 +0200145
ptrkrysik617ba032014-11-21 10:11:05 +0100146 uint32_t frame_nr = be32toh(header->frame_number);
ptrkrysik6dded652014-11-19 11:32:05 +0100147 uint32_t fn_mod51 = frame_nr % 51;
148 uint32_t fn51_start = d_starts_fn_mod51[fn_mod51];
149 uint32_t fn51_stop = fn51_start + 3;
150 uint32_t ch_type = d_channel_types[fn_mod51];
Roman Khassraf275a0872015-04-12 15:17:47 +0200151
ptrkrysik6dded652014-11-19 11:32:05 +0100152 if(header->timeslot==d_timeslot){
iZsh66987932015-08-16 14:42:18 +0200153 int8_t new_msg[sizeof(gsmtap_hdr)+BURST_SIZE];
154 gsmtap_hdr * new_hdr = (gsmtap_hdr*)new_msg;
155 memcpy(new_msg, header, sizeof(gsmtap_hdr)+BURST_SIZE);
156 new_hdr->sub_type = ch_type;
157 new_hdr->sub_slot = d_subslots[fn_mod51 + (51 * (frame_nr % 2))];
158 pmt::pmt_t msg_binary_blob = pmt::make_blob(new_msg,sizeof(gsmtap_hdr)+BURST_SIZE);
159 pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob);
Roman Khassraf275a0872015-04-12 15:17:47 +0200160
ptrkrysik6dded652014-11-19 11:32:05 +0100161 if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop)
162 {
163 uint32_t ii = fn_mod51 - fn51_start;
164 d_frame_numbers[ii] = frame_nr;
iZsh66987932015-08-16 14:42:18 +0200165 d_bursts[ii] = msg_out;
ptrkrysik6dded652014-11-19 11:32:05 +0100166 }
167
168 if(fn_mod51==fn51_stop)
169 {
170 //check for a situation where some bursts were lost
171 //in this situation frame numbers won't be consecutive
172 bool frames_are_consecutive = true;
173 for(int jj=1; jj<4; jj++)
174 {
175 if((d_frame_numbers[jj]-d_frame_numbers[jj-1])!=1)
176 {
177 frames_are_consecutive = false;
178 }
179 }
180 if(frames_are_consecutive)
181 {
182 //send bursts to the output
183 for(int jj=0; jj<4; jj++)
184 {
185 message_port_pub(pmt::mp("bursts"), d_bursts[jj]);
186 }
187 }
188 }
189 }
190 }
191 } /* namespace gsm */
192} /* namespace gr */
193