blob: cbbbc32cb6d90b689d70375d03ce8e2c1c013cea [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
Piotr Krysik9f723fd2015-08-06 10:23:52 +020039 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 +010040 {
41 return gnuradio::get_initial_sptr
Piotr Krysik9f723fd2015-08-06 10:23:52 +020042 (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 +010043 }
44
45 /*
46 * The private constructor
47 */
Piotr Krysik9f723fd2015-08-06 10:23:52 +020048 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 +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 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +020059 d_downlink_starts_fn_mod51[ii]=0;
60 d_downlink_channel_types[ii]=0;
61 d_downlink_subslots[ii] = 0;
62 d_downlink_subslots[ii+51] = 0;
63
64 d_uplink_starts_fn_mod51[ii]=0;
65 d_uplink_channel_types[ii]=0;
66 d_uplink_subslots[ii] = 0;
67 d_uplink_subslots[ii+51] = 0;
ptrkrysik6dded652014-11-19 11:32:05 +010068 }
69
70 std::vector<int>::const_iterator s;
71 std::vector<int>::const_iterator ch_type;
72
Piotr Krysik9f723fd2015-08-06 10:23:52 +020073 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 +010074 {
Roman Khassraf939edef2015-04-12 15:20:38 +020075 if((*s >= 0) and (*s <= (51-4)))
ptrkrysik6dded652014-11-19 11:32:05 +010076 {
77 for(int ii=0; ii<4; ii++){
Piotr Krysik9f723fd2015-08-06 10:23:52 +020078 d_downlink_starts_fn_mod51[*s+ii] = *s;
79 if(ch_type!=downlink_channel_types.end())
ptrkrysik6dded652014-11-19 11:32:05 +010080 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +020081 d_downlink_channel_types[*s+ii] = *ch_type;
ptrkrysik6dded652014-11-19 11:32:05 +010082 }
83 }
Piotr Krysik9f723fd2015-08-06 10:23:52 +020084 if(ch_type!=downlink_channel_types.end())
ptrkrysik6dded652014-11-19 11:32:05 +010085 {
86 ch_type++;
87 }
88 }
89 }
90
Piotr Krysik9f723fd2015-08-06 10:23:52 +020091 for(s=uplink_starts_fn_mod51.begin(), ch_type=uplink_channel_types.begin();s != uplink_starts_fn_mod51.end(); s++)
92 {
93 if((*s >= 0) and (*s <= (51-4)))
94 {
95 for(int ii=0; ii<4; ii++){
96 d_uplink_starts_fn_mod51[*s+ii] = *s;
97 if(ch_type!=uplink_channel_types.end())
98 {
99 d_uplink_channel_types[*s+ii] = *ch_type;
100 }
101 }
102 if(ch_type!=uplink_channel_types.end())
103 {
104 ch_type++;
105 }
106 }
107 }
Roman Khassrafe571e962015-04-12 15:35:41 +0200108
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200109 std::set<int> distinct_downlink_channels(downlink_channel_types.begin(), downlink_channel_types.end());
110 std::set<int>::iterator it;
111 unsigned int subslot;
112
113 for (it=distinct_downlink_channels.begin(); it != distinct_downlink_channels.end(); it++)
114 {
115 subslot = 0;
116 for(s=downlink_starts_fn_mod51.begin();s != downlink_starts_fn_mod51.end(); s++)
117 {
118 if ((d_downlink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
119 {
120 for(int ii=0; ii<4; ii++)
121 {
122 d_downlink_subslots[*s+ii] = subslot;
123 d_downlink_subslots[*s+ii+51] = subslot;
124 }
125 subslot++;
126 }
127 }
128
129 if (*it == GSMTAP_CHANNEL_ACCH or
130 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or
131 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or
132 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or
133 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or
134 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H)
135 )
136 {
137 for(s=downlink_starts_fn_mod51.begin();s != downlink_starts_fn_mod51.end(); s++)
138 {
139 if ((d_downlink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
140 {
141 for(int ii=0; ii<4; ii++)
142 {
143 d_downlink_subslots[*s+ii+51] = subslot;
144 }
145 subslot++;
146 }
147 }
148 }
149 }
150
151 std::set<int> distinct_uplink_channels(uplink_channel_types.begin(), uplink_channel_types.end());
152 for (it=distinct_uplink_channels.begin(); it != distinct_uplink_channels.end(); it++)
153 {
154 subslot = 0;
155 for(s=uplink_starts_fn_mod51.begin();s != uplink_starts_fn_mod51.end(); s++)
156 {
157 if ((d_uplink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
158 {
159 for(int ii=0; ii<4; ii++)
160 {
161 d_uplink_subslots[*s+ii] = subslot;
162 d_uplink_subslots[*s+ii+51] = subslot;
163 }
164 subslot++;
165 }
166 }
167
168 if (*it == GSMTAP_CHANNEL_ACCH or
169 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or
170 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or
171 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or
172 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or
173 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H)
174 )
175 {
176 for(s=uplink_starts_fn_mod51.begin();s != uplink_starts_fn_mod51.end(); s++)
177 {
178 if ((d_uplink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
179 {
180 for(int ii=0; ii<4; ii++)
181 {
182 d_uplink_subslots[*s+ii+51] = subslot;
183 }
184 subslot++;
185 }
186 }
187 }
188 }
189
ptrkrysik6dded652014-11-19 11:32:05 +0100190
191 message_port_register_in(pmt::mp("bursts"));
192 set_msg_handler(pmt::mp("bursts"), boost::bind(&universal_ctrl_chans_demapper_impl::filter_ctrl_chans, this, _1));
193 message_port_register_out(pmt::mp("bursts"));
194 }
195
196 /*
197 * Our virtual destructor.
198 */
199 universal_ctrl_chans_demapper_impl::~universal_ctrl_chans_demapper_impl()
200 {
201 }
202
203 void universal_ctrl_chans_demapper_impl::filter_ctrl_chans(pmt::pmt_t msg)
204 {
ptrkrysik617ba032014-11-21 10:11:05 +0100205 pmt::pmt_t header_plus_burst = pmt::cdr(msg);
206 gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
ptrkrysik6dded652014-11-19 11:32:05 +0100207
ptrkrysik617ba032014-11-21 10:11:05 +0100208 uint32_t frame_nr = be32toh(header->frame_number);
ptrkrysik6dded652014-11-19 11:32:05 +0100209 uint32_t fn_mod51 = frame_nr % 51;
Roman Khassraf275a0872015-04-12 15:17:47 +0200210
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200211 bool uplink_burst = (be16toh(header->arfcn) & 0x4000) ? true : false;
212
ptrkrysik6dded652014-11-19 11:32:05 +0100213 if(header->timeslot==d_timeslot){
iZsh66987932015-08-16 14:42:18 +0200214 int8_t new_msg[sizeof(gsmtap_hdr)+BURST_SIZE];
215 gsmtap_hdr * new_hdr = (gsmtap_hdr*)new_msg;
216 memcpy(new_msg, header, sizeof(gsmtap_hdr)+BURST_SIZE);
iZsh66987932015-08-16 14:42:18 +0200217 pmt::pmt_t msg_binary_blob = pmt::make_blob(new_msg,sizeof(gsmtap_hdr)+BURST_SIZE);
218 pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob);
Roman Khassraf275a0872015-04-12 15:17:47 +0200219
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200220 if(uplink_burst)
ptrkrysik6dded652014-11-19 11:32:05 +0100221 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200222 uint32_t fn51_start = d_uplink_starts_fn_mod51[fn_mod51];
223 uint32_t fn51_stop = fn51_start + 3;
224 uint32_t ch_type = d_uplink_channel_types[fn_mod51];
225
226 if(ch_type != 0)
ptrkrysik6dded652014-11-19 11:32:05 +0100227 {
Piotr Krysik8630fac2016-05-14 19:37:14 +0200228 new_hdr->sub_type = ch_type;
ptrkrysik6dded652014-11-19 11:32:05 +0100229 }
Piotr Krysik8630fac2016-05-14 19:37:14 +0200230 new_hdr->sub_slot = d_uplink_subslots[fn_mod51 + (51 * (frame_nr % 2))];
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200231
232 if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop)
ptrkrysik6dded652014-11-19 11:32:05 +0100233 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200234 uint32_t ii = fn_mod51 - fn51_start;
235 d_uplink_frame_numbers[ii] = frame_nr;
Piotr Krysik8630fac2016-05-14 19:37:14 +0200236 d_uplink_bursts[ii] = msg_out;
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200237 }
238
239 if(fn_mod51==fn51_stop)
240 {
241 //check for a situation where some bursts were lost
242 //in this situation frame numbers won't be consecutive
243 bool frames_are_consecutive = true;
244 for(int jj=1; jj<4; jj++)
ptrkrysik6dded652014-11-19 11:32:05 +0100245 {
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200246 if((d_uplink_frame_numbers[jj]-d_uplink_frame_numbers[jj-1])!=1)
247 {
248 frames_are_consecutive = false;
249 }
ptrkrysik6dded652014-11-19 11:32:05 +0100250 }
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200251 if(frames_are_consecutive)
252 {
253 //send bursts to the output
254 for(int jj=0; jj<4; jj++)
255 {
256 message_port_pub(pmt::mp("bursts"), d_uplink_bursts[jj]);
257 }
258 }
259 }
260 }
261 else
262 {
263 uint32_t fn51_start = d_downlink_starts_fn_mod51[fn_mod51];
264 uint32_t fn51_stop = fn51_start + 3;
265 uint32_t ch_type = d_downlink_channel_types[fn_mod51];
266
267 if(ch_type != 0)
268 {
Piotr Krysik8630fac2016-05-14 19:37:14 +0200269 new_hdr->sub_type = ch_type;
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200270 }
Piotr Krysik8630fac2016-05-14 19:37:14 +0200271 new_hdr->sub_slot = d_downlink_subslots[fn_mod51 + (51 * (frame_nr % 2))];
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200272
273 if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop)
274 {
275 uint32_t ii = fn_mod51 - fn51_start;
276 d_downlink_frame_numbers[ii] = frame_nr;
Piotr Krysik8630fac2016-05-14 19:37:14 +0200277 d_downlink_bursts[ii] = msg_out;
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200278 }
279
280 if(fn_mod51==fn51_stop)
281 {
282 //check for a situation where some bursts were lost
283 //in this situation frame numbers won't be consecutive
284 bool frames_are_consecutive = true;
285 for(int jj=1; jj<4; jj++)
286 {
287 if((d_downlink_frame_numbers[jj]-d_downlink_frame_numbers[jj-1])!=1)
288 {
289 frames_are_consecutive = false;
290 }
291 }
292 if(frames_are_consecutive)
293 {
294 //send bursts to the output
295 for(int jj=0; jj<4; jj++)
296 {
297 message_port_pub(pmt::mp("bursts"), d_downlink_bursts[jj]);
298 }
299 }
300 }
ptrkrysik6dded652014-11-19 11:32:05 +0100301 }
302 }
303 }
304 } /* namespace gsm */
305} /* namespace gr */