blob: 98bcc9c9b1a7f50fedbbec719649868b2f971233 [file] [log] [blame]
ptrkrysik6dded652014-11-19 11:32:05 +01001/* -*- c++ -*- */
ptrkrysik529895b2014-12-02 18:07:38 +01002/*
3 * @file
Piotr Krysika6268a52017-08-23 16:02:19 +02004 * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
ptrkrysik529895b2014-12-02 18:07:38 +01005 * @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 Krysik773a1942016-05-20 12:45:54 +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> &downlink_subslots, const std::vector<int> &uplink_starts_fn_mod51, const std::vector<int> &uplink_channel_types, const std::vector<int> &uplink_subslots)
40 {
ptrkrysik6dded652014-11-19 11:32:05 +010041 return gnuradio::get_initial_sptr
Piotr Krysik773a1942016-05-20 12:45:54 +020042 (new universal_ctrl_chans_demapper_impl(timeslot_nr, downlink_starts_fn_mod51, downlink_channel_types, downlink_subslots, uplink_starts_fn_mod51, uplink_channel_types, uplink_subslots));
ptrkrysik6dded652014-11-19 11:32:05 +010043 }
44
45 /*
46 * The private constructor
47 */
Piotr Krysik773a1942016-05-20 12:45:54 +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> &downlink_subslots, const std::vector<int> &uplink_starts_fn_mod51, const std::vector<int> &uplink_channel_types, const std::vector<int> &uplink_subslots)
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)),
Piotr Krysik773a1942016-05-20 12:45:54 +020052 d_timeslot_nr(timeslot_nr),
53 d_downlink_starts_fn_mod51(51, 0),
54 d_downlink_channel_types(51, 0),
55 d_downlink_subslots(102, 0),
56 d_uplink_starts_fn_mod51(51, 0),
57 d_uplink_channel_types(51, 0),
58 d_uplink_subslots(102, 0)
ptrkrysik6dded652014-11-19 11:32:05 +010059 {
Piotr Krysikf517bea2016-05-21 09:02:12 +020060 if(downlink_starts_fn_mod51.size() != 51 ||
61 downlink_channel_types.size() != 51 ||
62 downlink_subslots.size() != 102 ||
63 uplink_starts_fn_mod51.size() != 51 ||
64 uplink_channel_types.size() != 51 ||
65 uplink_subslots.size() != 102 )
66 {
67 std::cout << "Check lengths of the vectors passed to the universal demapper - _starts_fn_mod15 and _sublots should have 51 elements, _subslots should have 102 elements" << std::endl;
68 std::runtime_error("Check lengths of the vectors passed to the universal demapper - _starts_fn_mod15 and _sublots should have 51 elements, _subslots should have 102 elements");
69 }
Piotr Krysik773a1942016-05-20 12:45:54 +020070 std::copy(downlink_starts_fn_mod51.begin(), downlink_starts_fn_mod51.end(), d_downlink_starts_fn_mod51.begin());
71 std::copy(downlink_channel_types.begin(), downlink_channel_types.end(), d_downlink_channel_types.begin());
72 std::copy(downlink_subslots.begin(), downlink_subslots.end(), d_downlink_subslots.begin());
73 std::copy(uplink_starts_fn_mod51.begin(), uplink_starts_fn_mod51.end(), d_uplink_starts_fn_mod51.begin());
74 std::copy(uplink_channel_types.begin(), uplink_channel_types.end(), d_uplink_channel_types.begin());
75 std::copy(uplink_subslots.begin(), uplink_subslots.end(), d_uplink_subslots.begin());
Piotr Krysik27085ac2016-05-22 14:07:16 +020076
ptrkrysik6dded652014-11-19 11:32:05 +010077 message_port_register_in(pmt::mp("bursts"));
78 set_msg_handler(pmt::mp("bursts"), boost::bind(&universal_ctrl_chans_demapper_impl::filter_ctrl_chans, this, _1));
79 message_port_register_out(pmt::mp("bursts"));
80 }
81
82 /*
83 * Our virtual destructor.
84 */
85 universal_ctrl_chans_demapper_impl::~universal_ctrl_chans_demapper_impl()
86 {
87 }
88
Piotr Krysik27085ac2016-05-22 14:07:16 +020089 void universal_ctrl_chans_demapper_impl::filter_ctrl_chans(pmt::pmt_t burst_in)
ptrkrysik6dded652014-11-19 11:32:05 +010090 {
Piotr Krysik27085ac2016-05-22 14:07:16 +020091 pmt::pmt_t header_plus_burst = pmt::cdr(burst_in);
92 int8_t * burst_in_int8 = (int8_t *)pmt::blob_data(header_plus_burst);
93 gsmtap_hdr * header = (gsmtap_hdr *)(burst_in_int8);
ptrkrysik6dded652014-11-19 11:32:05 +010094
Piotr Krysik773a1942016-05-20 12:45:54 +020095 if(header->timeslot==d_timeslot_nr)
96 {
97 int * starts_fn_mod51;
98 int * channel_types;
99 int * subslots;
100 uint32_t * frame_numbers;
101 pmt::pmt_t * bursts;
102
103 uint32_t frame_nr = be32toh(header->frame_number); //get frame number
104 uint32_t fn_mod51 = frame_nr % 51; //frame number modulo 51
Piotr Krysik27085ac2016-05-22 14:07:16 +0200105 uint32_t fn_mod102 = frame_nr % 102; //frame number modulo 102
Piotr Krysik773a1942016-05-20 12:45:54 +0200106
Piotr Krysik27085ac2016-05-22 14:07:16 +0200107 //create new burst
108 int8_t burst_tmp[sizeof(gsmtap_hdr)+BURST_SIZE];
109 memcpy(burst_tmp, burst_in_int8, sizeof(gsmtap_hdr)+BURST_SIZE);
110 pmt::pmt_t msg_binary_blob = pmt::make_blob(burst_tmp,sizeof(gsmtap_hdr)+BURST_SIZE);
111 pmt::pmt_t burst_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob);
112 gsmtap_hdr * new_header = (gsmtap_hdr *)pmt::blob_data(msg_binary_blob);
113
Piotr Krysik773a1942016-05-20 12:45:54 +0200114 //get information if burst is from uplink or downlink
115 bool uplink_burst = (be16toh(header->arfcn) & 0x4000) ? true : false;
116
117 //select right set of configuration and history for uplink or downlink
118 if(uplink_burst) {
119 starts_fn_mod51 = &d_uplink_starts_fn_mod51[0];
120 channel_types = &d_uplink_channel_types[0];
121 subslots = &d_uplink_subslots[0];
122 frame_numbers = d_uplink_frame_numbers;
123 bursts = d_uplink_bursts;
124 } else {
125 starts_fn_mod51 = &d_downlink_starts_fn_mod51[0];
126 channel_types = &d_downlink_channel_types[0];
127 subslots = &d_downlink_subslots[0];
128 frame_numbers = d_downlink_frame_numbers;
129 bursts = d_downlink_bursts;
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200130 }
Piotr Krysik773a1942016-05-20 12:45:54 +0200131
132 uint32_t fn51_start = starts_fn_mod51[fn_mod51];
133 uint32_t fn51_stop = fn51_start + 3;
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200134
Piotr Krysik27085ac2016-05-22 14:07:16 +0200135 //set type
136 new_header->type = GSMTAP_TYPE_UM;
137 //set type of the channel
138 uint32_t ch_type = channel_types[fn_mod51];
Piotr Krysik773a1942016-05-20 12:45:54 +0200139 if(ch_type != 0)
140 {
Piotr Krysik27085ac2016-05-22 14:07:16 +0200141 new_header->sub_type = ch_type;
Piotr Krysik773a1942016-05-20 12:45:54 +0200142 }
Piotr Krysik27085ac2016-05-22 14:07:16 +0200143 new_header->sub_slot = subslots[fn_mod51 + (51 * (frame_nr % 2))];
Piotr Krysik773a1942016-05-20 12:45:54 +0200144
145 if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop)
146 {
147 uint32_t ii = fn_mod51 - fn51_start;
148 frame_numbers[ii] = frame_nr;
Piotr Krysik27085ac2016-05-22 14:07:16 +0200149 bursts[ii] = burst_out;
Piotr Krysik773a1942016-05-20 12:45:54 +0200150 }
151
152 if(fn_mod51==fn51_stop)
153 {
154 //check for a situation where some bursts were lost
155 //in this situation frame numbers won't be consecutive
156 bool frames_are_consecutive = true;
157 for(int jj=1; jj<4; jj++)
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200158 {
Piotr Krysik773a1942016-05-20 12:45:54 +0200159 if((frame_numbers[jj] - frame_numbers[jj-1])!=1)
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200160 {
Piotr Krysik773a1942016-05-20 12:45:54 +0200161 frames_are_consecutive = false;
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200162 }
Piotr Krysik9f723fd2015-08-06 10:23:52 +0200163 }
Piotr Krysik773a1942016-05-20 12:45:54 +0200164 if(frames_are_consecutive)
165 {
166 //send bursts to the output
167 for(int jj=0; jj<4; jj++)
168 {
169 message_port_pub(pmt::mp("bursts"), bursts[jj]);
170 }
Piotr Krysik27085ac2016-05-22 14:07:16 +0200171 }
ptrkrysik6dded652014-11-19 11:32:05 +0100172 }
173 }
174 }
175 } /* namespace gsm */
176} /* namespace gr */