blob: 85cb0c659fd063a7982a209132fbf49d6fd6d210 [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
33namespace gr {
34 namespace gsm {
35
36 universal_ctrl_chans_demapper::sptr
Piotr Krysik9f723fd2015-08-06 10:23:52 +020037 universal_ctrl_chans_demapper::make(unsigned int timeslot_nr, const std::vector<int> &downlink_starts_fn_mod51, const std::vector<int> &downlink_channel_types, const std::vector<int> &uplink_starts_fn_mod51, const std::vector<int> &uplink_channel_types)
ptrkrysik6dded652014-11-19 11:32:05 +010038 {
39 return gnuradio::get_initial_sptr
Piotr Krysik9f723fd2015-08-06 10:23:52 +020040 (new universal_ctrl_chans_demapper_impl(timeslot_nr, downlink_starts_fn_mod51, downlink_channel_types, uplink_starts_fn_mod51, uplink_channel_types));
ptrkrysik6dded652014-11-19 11:32:05 +010041 }
42
43 /*
44 * The private constructor
45 */
Piotr Krysik9f723fd2015-08-06 10:23:52 +020046 universal_ctrl_chans_demapper_impl::universal_ctrl_chans_demapper_impl(unsigned int timeslot_nr, const std::vector<int> &downlink_starts_fn_mod51, const std::vector<int> &downlink_channel_types, const std::vector<int> &uplink_starts_fn_mod51, const std::vector<int> &uplink_channel_types)
ptrkrysik6dded652014-11-19 11:32:05 +010047 : gr::block("universal_ctrl_chans_demapper",
48 gr::io_signature::make(0, 0, 0),
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010049 gr::io_signature::make(0, 0, 0)),
50 d_timeslot(timeslot_nr)
51
ptrkrysik6dded652014-11-19 11:32:05 +010052 {
53
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010054
ptrkrysik6dded652014-11-19 11:32:05 +010055 for(int ii=0; ii<51; ii++)
56 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +020057 d_downlink_starts_fn_mod51[ii]=0;
58 d_downlink_channel_types[ii]=0;
59 d_downlink_subslots[ii] = 0;
60 d_downlink_subslots[ii+51] = 0;
61
62 d_uplink_starts_fn_mod51[ii]=0;
63 d_uplink_channel_types[ii]=0;
64 d_uplink_subslots[ii] = 0;
65 d_uplink_subslots[ii+51] = 0;
ptrkrysik6dded652014-11-19 11:32:05 +010066 }
67
68 std::vector<int>::const_iterator s;
69 std::vector<int>::const_iterator ch_type;
70
Piotr Krysik9f723fd2015-08-06 10:23:52 +020071 for(s=downlink_starts_fn_mod51.begin(), ch_type=downlink_channel_types.begin();s != downlink_starts_fn_mod51.end(); s++)
ptrkrysik6dded652014-11-19 11:32:05 +010072 {
Roman Khassraf939edef2015-04-12 15:20:38 +020073 if((*s >= 0) and (*s <= (51-4)))
ptrkrysik6dded652014-11-19 11:32:05 +010074 {
75 for(int ii=0; ii<4; ii++){
Piotr Krysik9f723fd2015-08-06 10:23:52 +020076 d_downlink_starts_fn_mod51[*s+ii] = *s;
77 if(ch_type!=downlink_channel_types.end())
ptrkrysik6dded652014-11-19 11:32:05 +010078 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +020079 d_downlink_channel_types[*s+ii] = *ch_type;
ptrkrysik6dded652014-11-19 11:32:05 +010080 }
81 }
Piotr Krysik9f723fd2015-08-06 10:23:52 +020082 if(ch_type!=downlink_channel_types.end())
ptrkrysik6dded652014-11-19 11:32:05 +010083 {
84 ch_type++;
85 }
86 }
87 }
88
Piotr Krysik9f723fd2015-08-06 10:23:52 +020089 for(s=uplink_starts_fn_mod51.begin(), ch_type=uplink_channel_types.begin();s != uplink_starts_fn_mod51.end(); s++)
90 {
91 if((*s >= 0) and (*s <= (51-4)))
92 {
93 for(int ii=0; ii<4; ii++){
94 d_uplink_starts_fn_mod51[*s+ii] = *s;
95 if(ch_type!=uplink_channel_types.end())
96 {
97 d_uplink_channel_types[*s+ii] = *ch_type;
98 }
99 }
100 if(ch_type!=uplink_channel_types.end())
101 {
102 ch_type++;
103 }
104 }
105 }
Roman Khassrafe571e962015-04-12 15:35:41 +0200106
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200107 std::set<int> distinct_downlink_channels(downlink_channel_types.begin(), downlink_channel_types.end());
108 std::set<int>::iterator it;
109 unsigned int subslot;
110
111 for (it=distinct_downlink_channels.begin(); it != distinct_downlink_channels.end(); it++)
112 {
113 subslot = 0;
114 for(s=downlink_starts_fn_mod51.begin();s != downlink_starts_fn_mod51.end(); s++)
115 {
116 if ((d_downlink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
117 {
118 for(int ii=0; ii<4; ii++)
119 {
120 d_downlink_subslots[*s+ii] = subslot;
121 d_downlink_subslots[*s+ii+51] = subslot;
122 }
123 subslot++;
124 }
125 }
126
127 if (*it == GSMTAP_CHANNEL_ACCH or
128 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or
129 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or
130 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or
131 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or
132 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H)
133 )
134 {
135 for(s=downlink_starts_fn_mod51.begin();s != downlink_starts_fn_mod51.end(); s++)
136 {
137 if ((d_downlink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
138 {
139 for(int ii=0; ii<4; ii++)
140 {
141 d_downlink_subslots[*s+ii+51] = subslot;
142 }
143 subslot++;
144 }
145 }
146 }
147 }
148
149 std::set<int> distinct_uplink_channels(uplink_channel_types.begin(), uplink_channel_types.end());
150 for (it=distinct_uplink_channels.begin(); it != distinct_uplink_channels.end(); it++)
151 {
152 subslot = 0;
153 for(s=uplink_starts_fn_mod51.begin();s != uplink_starts_fn_mod51.end(); s++)
154 {
155 if ((d_uplink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
156 {
157 for(int ii=0; ii<4; ii++)
158 {
159 d_uplink_subslots[*s+ii] = subslot;
160 d_uplink_subslots[*s+ii+51] = subslot;
161 }
162 subslot++;
163 }
164 }
165
166 if (*it == GSMTAP_CHANNEL_ACCH or
167 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or
168 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or
169 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or
170 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or
171 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H)
172 )
173 {
174 for(s=uplink_starts_fn_mod51.begin();s != uplink_starts_fn_mod51.end(); s++)
175 {
176 if ((d_uplink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
177 {
178 for(int ii=0; ii<4; ii++)
179 {
180 d_uplink_subslots[*s+ii+51] = subslot;
181 }
182 subslot++;
183 }
184 }
185 }
186 }
187
ptrkrysik6dded652014-11-19 11:32:05 +0100188
189 message_port_register_in(pmt::mp("bursts"));
190 set_msg_handler(pmt::mp("bursts"), boost::bind(&universal_ctrl_chans_demapper_impl::filter_ctrl_chans, this, _1));
191 message_port_register_out(pmt::mp("bursts"));
192 }
193
194 /*
195 * Our virtual destructor.
196 */
197 universal_ctrl_chans_demapper_impl::~universal_ctrl_chans_demapper_impl()
198 {
199 }
200
201 void universal_ctrl_chans_demapper_impl::filter_ctrl_chans(pmt::pmt_t msg)
202 {
ptrkrysik617ba032014-11-21 10:11:05 +0100203 pmt::pmt_t header_plus_burst = pmt::cdr(msg);
204 gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
ptrkrysik6dded652014-11-19 11:32:05 +0100205
ptrkrysik617ba032014-11-21 10:11:05 +0100206 uint32_t frame_nr = be32toh(header->frame_number);
ptrkrysik6dded652014-11-19 11:32:05 +0100207 uint32_t fn_mod51 = frame_nr % 51;
Roman Khassraf275a0872015-04-12 15:17:47 +0200208
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200209 bool uplink_burst = (be16toh(header->arfcn) & 0x4000) ? true : false;
210
ptrkrysik6dded652014-11-19 11:32:05 +0100211 if(header->timeslot==d_timeslot){
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200212 if(uplink_burst)
ptrkrysik6dded652014-11-19 11:32:05 +0100213 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200214 uint32_t fn51_start = d_uplink_starts_fn_mod51[fn_mod51];
215 uint32_t fn51_stop = fn51_start + 3;
216 uint32_t ch_type = d_uplink_channel_types[fn_mod51];
217
218 if(ch_type != 0)
ptrkrysik6dded652014-11-19 11:32:05 +0100219 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200220 header->sub_type = ch_type;
ptrkrysik6dded652014-11-19 11:32:05 +0100221 }
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200222 header->sub_slot = d_uplink_subslots[fn_mod51 + (51 * (frame_nr % 2))];
223
224 if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop)
ptrkrysik6dded652014-11-19 11:32:05 +0100225 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200226 uint32_t ii = fn_mod51 - fn51_start;
227 d_uplink_frame_numbers[ii] = frame_nr;
228 d_uplink_bursts[ii] = msg;
229 }
230
231 if(fn_mod51==fn51_stop)
232 {
233 //check for a situation where some bursts were lost
234 //in this situation frame numbers won't be consecutive
235 bool frames_are_consecutive = true;
236 for(int jj=1; jj<4; jj++)
ptrkrysik6dded652014-11-19 11:32:05 +0100237 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200238 if((d_uplink_frame_numbers[jj]-d_uplink_frame_numbers[jj-1])!=1)
239 {
240 frames_are_consecutive = false;
241 }
ptrkrysik6dded652014-11-19 11:32:05 +0100242 }
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200243 if(frames_are_consecutive)
244 {
245 //send bursts to the output
246 for(int jj=0; jj<4; jj++)
247 {
248 message_port_pub(pmt::mp("bursts"), d_uplink_bursts[jj]);
249 }
250 }
251 }
252 }
253 else
254 {
255 uint32_t fn51_start = d_downlink_starts_fn_mod51[fn_mod51];
256 uint32_t fn51_stop = fn51_start + 3;
257 uint32_t ch_type = d_downlink_channel_types[fn_mod51];
258
259 if(ch_type != 0)
260 {
261 header->sub_type = ch_type;
262 }
263 header->sub_slot = d_downlink_subslots[fn_mod51 + (51 * (frame_nr % 2))];
264
265 if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop)
266 {
267 uint32_t ii = fn_mod51 - fn51_start;
268 d_downlink_frame_numbers[ii] = frame_nr;
269 d_downlink_bursts[ii] = msg;
270 }
271
272 if(fn_mod51==fn51_stop)
273 {
274 //check for a situation where some bursts were lost
275 //in this situation frame numbers won't be consecutive
276 bool frames_are_consecutive = true;
277 for(int jj=1; jj<4; jj++)
278 {
279 if((d_downlink_frame_numbers[jj]-d_downlink_frame_numbers[jj-1])!=1)
280 {
281 frames_are_consecutive = false;
282 }
283 }
284 if(frames_are_consecutive)
285 {
286 //send bursts to the output
287 for(int jj=0; jj<4; jj++)
288 {
289 message_port_pub(pmt::mp("bursts"), d_downlink_bursts[jj]);
290 }
291 }
292 }
ptrkrysik6dded652014-11-19 11:32:05 +0100293 }
294 }
295 }
296 } /* namespace gsm */
297} /* namespace gr */
298