blob: 8a6bfb5a8c7b35ee0ae23796838d702fe84ebe86 [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
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010037 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 +010038 {
39 return gnuradio::get_initial_sptr
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010040 (new universal_ctrl_chans_demapper_impl(timeslot_nr, starts_fn_mod51, channel_types));
ptrkrysik6dded652014-11-19 11:32:05 +010041 }
42
43 /*
44 * The private constructor
45 */
ptrkrysikd8d4fbc2015-02-07 19:37:42 +010046 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 +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 {
57 d_starts_fn_mod51[ii]=0;
58 d_channel_types[ii]=0;
Roman Khassrafe571e962015-04-12 15:35:41 +020059 d_subslots[ii] = 0;
60 d_subslots[ii+51] = 0;
ptrkrysik6dded652014-11-19 11:32:05 +010061 }
62
63 std::vector<int>::const_iterator s;
64 std::vector<int>::const_iterator ch_type;
65
66 for(s=starts_fn_mod51.begin(), ch_type=channel_types.begin();s != starts_fn_mod51.end(); s++)
67 {
Roman Khassraf939edef2015-04-12 15:20:38 +020068 if((*s >= 0) and (*s <= (51-4)))
ptrkrysik6dded652014-11-19 11:32:05 +010069 {
70 for(int ii=0; ii<4; ii++){
71 d_starts_fn_mod51[*s+ii] = *s;
72 if(ch_type!=channel_types.end())
73 {
74 d_channel_types[*s+ii] = *ch_type;
75 }
76 }
77 if(ch_type!=channel_types.end())
78 {
79 ch_type++;
80 }
81 }
82 }
83
Roman Khassrafe571e962015-04-12 15:35:41 +020084 std::set<int> distinct_channels(channel_types.begin(), channel_types.end());
85 std::set<int>::iterator it;
86 unsigned int subslot;
87
88 for (it=distinct_channels.begin(); it != distinct_channels.end(); it++)
89 {
90 subslot = 0;
91 for(s=starts_fn_mod51.begin();s != starts_fn_mod51.end(); s++)
92 {
93 if ((d_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
94 {
95 for(int ii=0; ii<4; ii++)
96 {
97 d_subslots[*s+ii] = subslot;
98 d_subslots[*s+ii+51] = subslot;
99 }
100 subslot++;
101 }
102 }
103
104 if (*it == GSMTAP_CHANNEL_ACCH or
105 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or
106 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or
107 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or
108 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or
109 *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H)
110 )
111 {
112 for(s=starts_fn_mod51.begin();s != starts_fn_mod51.end(); s++)
113 {
114 if ((d_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4)))
115 {
116 for(int ii=0; ii<4; ii++)
117 {
118 d_subslots[*s+ii+51] = subslot;
119 }
120 subslot++;
121 }
122 }
123 }
124 }
125
ptrkrysik6dded652014-11-19 11:32:05 +0100126
127 message_port_register_in(pmt::mp("bursts"));
128 set_msg_handler(pmt::mp("bursts"), boost::bind(&universal_ctrl_chans_demapper_impl::filter_ctrl_chans, this, _1));
129 message_port_register_out(pmt::mp("bursts"));
130 }
131
132 /*
133 * Our virtual destructor.
134 */
135 universal_ctrl_chans_demapper_impl::~universal_ctrl_chans_demapper_impl()
136 {
137 }
138
139 void universal_ctrl_chans_demapper_impl::filter_ctrl_chans(pmt::pmt_t msg)
140 {
ptrkrysik617ba032014-11-21 10:11:05 +0100141 pmt::pmt_t header_plus_burst = pmt::cdr(msg);
142 gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
ptrkrysik6dded652014-11-19 11:32:05 +0100143
ptrkrysik617ba032014-11-21 10:11:05 +0100144 uint32_t frame_nr = be32toh(header->frame_number);
ptrkrysik6dded652014-11-19 11:32:05 +0100145 uint32_t fn_mod51 = frame_nr % 51;
146 uint32_t fn51_start = d_starts_fn_mod51[fn_mod51];
147 uint32_t fn51_stop = fn51_start + 3;
148 uint32_t ch_type = d_channel_types[fn_mod51];
Roman Khassraf275a0872015-04-12 15:17:47 +0200149
ptrkrysik6dded652014-11-19 11:32:05 +0100150 if(header->timeslot==d_timeslot){
Roman Khassraf275a0872015-04-12 15:17:47 +0200151 header->sub_type = ch_type;
Roman Khassrafe571e962015-04-12 15:35:41 +0200152 header->sub_slot = d_subslots[fn_mod51 + (51 * (frame_nr % 2))];
Roman Khassraf275a0872015-04-12 15:17:47 +0200153
ptrkrysik6dded652014-11-19 11:32:05 +0100154 if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop)
155 {
156 uint32_t ii = fn_mod51 - fn51_start;
157 d_frame_numbers[ii] = frame_nr;
158 d_bursts[ii] = msg;
159 }
160
161 if(fn_mod51==fn51_stop)
162 {
163 //check for a situation where some bursts were lost
164 //in this situation frame numbers won't be consecutive
165 bool frames_are_consecutive = true;
166 for(int jj=1; jj<4; jj++)
167 {
168 if((d_frame_numbers[jj]-d_frame_numbers[jj-1])!=1)
169 {
170 frames_are_consecutive = false;
171 }
172 }
173 if(frames_are_consecutive)
174 {
175 //send bursts to the output
176 for(int jj=0; jj<4; jj++)
177 {
178 message_port_pub(pmt::mp("bursts"), d_bursts[jj]);
179 }
180 }
181 }
182 }
183 }
184 } /* namespace gsm */
185} /* namespace gr */
186