blob: 3e239102cfa278dc12a7af9eff4fabe3a06545b9 [file] [log] [blame]
rpp4f0f3b52015-06-10 10:23:30 +02001/* -*- c++ -*- */
2/* @file
3 * @author Piotr Krysik <ptrkrysik@gmail.com>
4 * @section LICENSE
5 *
6 * 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.
10 *
11 * 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.
15 *
16 * 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.
20 *
21 */
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>
rpp4f0f3b52015-06-10 10:23:30 +020029#include "cx_channel_hopper_impl.h"
30
31namespace gr {
32 namespace gsm {
33
34 cx_channel_hopper::sptr
rpp267214a2015-06-10 11:49:55 +020035 cx_channel_hopper::make(const std::vector<int> &ma, int maio, int hsn)
rpp4f0f3b52015-06-10 10:23:30 +020036 {
rpp267214a2015-06-10 11:49:55 +020037 return gnuradio::get_initial_sptr
38 (new cx_channel_hopper_impl(ma, maio, hsn));
rpp4f0f3b52015-06-10 10:23:30 +020039 }
40
41 /*
42 * The private constructor
43 */
rpp267214a2015-06-10 11:49:55 +020044 cx_channel_hopper_impl::cx_channel_hopper_impl(const std::vector<int> &ma, int maio, int hsn)
45 : gr::block("cx_channel_hopper",
46 gr::io_signature::make(0, 0, 0),
47 gr::io_signature::make(0, 0, 0)),
48 d_ma(ma),
49 d_maio(maio),
50 d_hsn(hsn)
rpp4f0f3b52015-06-10 10:23:30 +020051 {
rpp267214a2015-06-10 11:49:55 +020052 d_narfcn = ma.size();
rpp4f0f3b52015-06-10 10:23:30 +020053
rpp267214a2015-06-10 11:49:55 +020054 message_port_register_in(pmt::mp("CX"));
55 set_msg_handler(pmt::mp("CX"), boost::bind(&cx_channel_hopper_impl::assemble_bursts, this, _1));
56 message_port_register_out(pmt::mp("bursts"));
rpp4f0f3b52015-06-10 10:23:30 +020057 }
58
59 /*
60 * Our virtual destructor.
61 */
62 cx_channel_hopper_impl::~cx_channel_hopper_impl()
63 {
64 }
65
rpp267214a2015-06-10 11:49:55 +020066 /**
67 * Random number table used for calculating the
68 * hopping sequence. Defined in GSM 05.02.
69 */
70 unsigned char RNTABLE[114] = {
71 48, 98, 63, 1, 36, 95, 78, 102, 94, 73, \
72 0, 64, 25, 81, 76, 59, 124, 23, 104, 100, \
73 101, 47, 118, 85, 18, 56, 96, 86, 54, 2, \
74 80, 34, 127, 13, 6, 89, 57, 103, 12, 74, \
75 55, 111, 75, 38, 109, 71, 112, 29, 11, 88, \
76 87, 19, 3, 68, 110, 26, 33, 31, 8, 45, \
77 82, 58, 40, 107, 32, 5, 106, 92, 62, 67, \
78 77, 108, 122, 37, 60, 66, 121, 42, 51, 126, \
79 117, 114, 4, 90, 43, 52, 53, 113, 120, 72, \
80 16, 49, 7, 79, 119, 61, 22, 84, 9, 97, \
81 91, 15, 21, 24, 46, 39, 93, 105, 65, 70, \
82 125, 99, 17, 123 \
83 };
84
85 /*
86 * Slow Frequency Hopping (SFH) MAI calculation based
87 * on airprobe-hopping by Bogdan Diaconescu.
88 */
89 int cx_channel_hopper_impl::calculate_ma_sfh(int maio, int hsn, int n, int fn)
90 {
91 int mai = 0;
92 int s = 0;
93 int nbin = floor(log2(n) + 1);
94 int t1 = fn / 1326;
95 int t2 = fn % 26;
96 int t3 = fn % 51;
97
98 if (hsn == 0)
99 mai = (fn + maio) % n;
100 else {
101 int t1r = t1 % 64;
102 int m = t2 + RNTABLE[(hsn ^ t1r) + t3];
103 int mprim = m % (1 << nbin);
104 int tprim = t3 % (1 << nbin);
105
106 if (mprim < n)
107 s = mprim;
108 else
109 s = (mprim + tprim) % n;
110
111 mai = (s + maio) % n;
112 }
113
114 return (mai);
115 }
116
117 /**
118 * Given MA, MAIO, HSN, and FN, decide which frames
119 * to forward to the demapper.
120 */
121 void cx_channel_hopper_impl::assemble_bursts(pmt::pmt_t msg)
122 {
123 pmt::pmt_t header_plus_burst = pmt::cdr(msg);
124 gsmtap_hdr *header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
125
126 uint32_t frame_nr = be32toh(header->frame_number);
127 uint16_t frame_ca = be16toh(header->arfcn);
128 int mai = calculate_ma_sfh(d_maio, d_hsn, d_narfcn, frame_nr);
129
130 if(d_ma[mai] == frame_ca) {
131 message_port_pub(pmt::mp("bursts"), msg);
132 }
133 }
134
rpp4f0f3b52015-06-10 10:23:30 +0200135 } /* namespace gsm */
136} /* namespace gr */
137