blob: b67cb158c53d218700253f79cb4ce4c6bd410916 [file] [log] [blame]
rpp4f0f3b52015-06-10 10:23:30 +02001/* -*- c++ -*- */
2/* @file
3 * @author Piotr Krysik <ptrkrysik@gmail.com>
4 * @section LICENSE
Martin Jesper Low Madsenf3105d92015-06-24 13:33:56 +02005 *
rpp4f0f3b52015-06-10 10:23:30 +02006 * Gr-gsm is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
9 * any later version.
Martin Jesper Low Madsenf3105d92015-06-24 13:33:56 +020010 *
rpp4f0f3b52015-06-10 10:23:30 +020011 * Gr-gsm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Martin Jesper Low Madsenf3105d92015-06-24 13:33:56 +020015 *
rpp4f0f3b52015-06-10 10:23:30 +020016 * You should have received a copy of the GNU General Public License
17 * along with gr-gsm; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street,
19 * Boston, MA 02110-1301, USA.
Martin Jesper Low Madsenf3105d92015-06-24 13:33:56 +020020 *
rpp4f0f3b52015-06-10 10:23:30 +020021 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <gnuradio/io_signature.h>
rpp267214a2015-06-10 11:49:55 +020028#include <grgsm/gsmtap.h>
Martin Jesper Low Madsenf3105d92015-06-24 13:33:56 +020029#include <grgsm/endian.h>
rpp4f0f3b52015-06-10 10:23:30 +020030#include "cx_channel_hopper_impl.h"
31
32namespace gr {
33 namespace gsm {
34
35 cx_channel_hopper::sptr
rpp267214a2015-06-10 11:49:55 +020036 cx_channel_hopper::make(const std::vector<int> &ma, int maio, int hsn)
rpp4f0f3b52015-06-10 10:23:30 +020037 {
rpp267214a2015-06-10 11:49:55 +020038 return gnuradio::get_initial_sptr
39 (new cx_channel_hopper_impl(ma, maio, hsn));
rpp4f0f3b52015-06-10 10:23:30 +020040 }
41
42 /*
43 * The private constructor
44 */
rpp267214a2015-06-10 11:49:55 +020045 cx_channel_hopper_impl::cx_channel_hopper_impl(const std::vector<int> &ma, int maio, int hsn)
46 : gr::block("cx_channel_hopper",
47 gr::io_signature::make(0, 0, 0),
48 gr::io_signature::make(0, 0, 0)),
49 d_ma(ma),
50 d_maio(maio),
51 d_hsn(hsn)
rpp4f0f3b52015-06-10 10:23:30 +020052 {
rpp267214a2015-06-10 11:49:55 +020053 d_narfcn = ma.size();
rpp4f0f3b52015-06-10 10:23:30 +020054
rpp267214a2015-06-10 11:49:55 +020055 message_port_register_in(pmt::mp("CX"));
56 set_msg_handler(pmt::mp("CX"), boost::bind(&cx_channel_hopper_impl::assemble_bursts, this, _1));
57 message_port_register_out(pmt::mp("bursts"));
rpp4f0f3b52015-06-10 10:23:30 +020058 }
59
60 /*
61 * Our virtual destructor.
62 */
63 cx_channel_hopper_impl::~cx_channel_hopper_impl()
64 {
65 }
66
rpp267214a2015-06-10 11:49:55 +020067 /**
Martin Jesper Low Madsenf3105d92015-06-24 13:33:56 +020068 * Random number table used for calculating the
rpp267214a2015-06-10 11:49:55 +020069 * hopping sequence. Defined in GSM 05.02.
70 */
71 unsigned char RNTABLE[114] = {
72 48, 98, 63, 1, 36, 95, 78, 102, 94, 73, \
73 0, 64, 25, 81, 76, 59, 124, 23, 104, 100, \
74 101, 47, 118, 85, 18, 56, 96, 86, 54, 2, \
75 80, 34, 127, 13, 6, 89, 57, 103, 12, 74, \
76 55, 111, 75, 38, 109, 71, 112, 29, 11, 88, \
77 87, 19, 3, 68, 110, 26, 33, 31, 8, 45, \
78 82, 58, 40, 107, 32, 5, 106, 92, 62, 67, \
79 77, 108, 122, 37, 60, 66, 121, 42, 51, 126, \
80 117, 114, 4, 90, 43, 52, 53, 113, 120, 72, \
81 16, 49, 7, 79, 119, 61, 22, 84, 9, 97, \
82 91, 15, 21, 24, 46, 39, 93, 105, 65, 70, \
83 125, 99, 17, 123 \
84 };
85
86 /*
87 * Slow Frequency Hopping (SFH) MAI calculation based
88 * on airprobe-hopping by Bogdan Diaconescu.
89 */
90 int cx_channel_hopper_impl::calculate_ma_sfh(int maio, int hsn, int n, int fn)
91 {
92 int mai = 0;
93 int s = 0;
94 int nbin = floor(log2(n) + 1);
95 int t1 = fn / 1326;
96 int t2 = fn % 26;
97 int t3 = fn % 51;
98
99 if (hsn == 0)
100 mai = (fn + maio) % n;
101 else {
102 int t1r = t1 % 64;
103 int m = t2 + RNTABLE[(hsn ^ t1r) + t3];
104 int mprim = m % (1 << nbin);
105 int tprim = t3 % (1 << nbin);
106
107 if (mprim < n)
108 s = mprim;
109 else
110 s = (mprim + tprim) % n;
111
112 mai = (s + maio) % n;
113 }
114
115 return (mai);
116 }
117
118 /**
119 * Given MA, MAIO, HSN, and FN, decide which frames
120 * to forward to the demapper.
121 */
122 void cx_channel_hopper_impl::assemble_bursts(pmt::pmt_t msg)
123 {
124 pmt::pmt_t header_plus_burst = pmt::cdr(msg);
125 gsmtap_hdr *header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
126
127 uint32_t frame_nr = be32toh(header->frame_number);
128 uint16_t frame_ca = be16toh(header->arfcn);
129 int mai = calculate_ma_sfh(d_maio, d_hsn, d_narfcn, frame_nr);
130
131 if(d_ma[mai] == frame_ca) {
132 message_port_pub(pmt::mp("bursts"), msg);
133 }
134 }
135
rpp4f0f3b52015-06-10 10:23:30 +0200136 } /* namespace gsm */
137} /* namespace gr */