blob: 2773f33f23bfb54816a394243163908020aac03f [file] [log] [blame]
Piotr Krysik34ce7a02017-10-31 11:30:59 +01001/* -*- c++ -*- */
2/* @file
3 * @author Piotr Krysik <ptrkrysik@gmail.com>
4 * @author Vadim Yanitskiy <axilirator@gmail.com>
5 * @section LICENSE
6 *
7 * Gr-gsm is free software; you can redistribute it and/or modify
8 * 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.
11 *
12 * Gr-gsm is distributed in the hope that it will be useful,
13 * 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.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with gr-gsm; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include <grgsm/misc_utils/fn_time.h>
Piotr Krysik6e41d062017-11-03 09:56:49 +010025#include <grgsm/misc_utils/time_spec.h>
Piotr Krysik34ce7a02017-10-31 11:30:59 +010026#include <math.h>
Piotr Krysik34ce7a02017-10-31 11:30:59 +010027
Piotr Krysik6e41d062017-11-03 09:56:49 +010028#define GSM_HYPER_FRAME (26 * 51 * 2048)
29#define GSM_SYM_RATE (13.0e6 / 48.0)
Piotr Krysik34ce7a02017-10-31 11:30:59 +010030
Piotr Krysik6e41d062017-11-03 09:56:49 +010031#define GSM_TS_PERIOD (156.25 / GSM_SYM_RATE)
32#define GSM_FN_PERIOD (8 * GSM_TS_PERIOD)
Piotr Krysik34ce7a02017-10-31 11:30:59 +010033
34namespace gr {
35 namespace gsm {
Piotr Krysik6e41d062017-11-03 09:56:49 +010036 /**
37 * Computes difference between two frame numbers modulo
38 * GSM_HYPER_FRAME / 2. The result is correct if difference
39 * between the frame numbers is not bigger than GSM_HYPER_FRAME / 2.
40 * @param fn1 first frame number
41 * @param fn2 second frame number
42 * @return computed difference
43 */
44 static int fnmod_delta(uint32_t fn1, uint32_t fn2)
Piotr Krysik34ce7a02017-10-31 11:30:59 +010045 {
Piotr Krysik6e41d062017-11-03 09:56:49 +010046 int delta, h2;
Piotr Krysik34ce7a02017-10-31 11:30:59 +010047
48 delta = (fn1 % GSM_HYPER_FRAME) - (fn2 % GSM_HYPER_FRAME);
Piotr Krysik6e41d062017-11-03 09:56:49 +010049
Piotr Krysik34ce7a02017-10-31 11:30:59 +010050 h2 = GSM_HYPER_FRAME / 2;
51
Piotr Krysik6e41d062017-11-03 09:56:49 +010052 if (delta >= h2) {
53 delta -= GSM_HYPER_FRAME;
54 } else if(delta < -h2) {
55 delta += GSM_HYPER_FRAME;
56 }
Piotr Krysik34ce7a02017-10-31 11:30:59 +010057
58 return delta;
59 }
60
61 static int fn_time_diff_delta(uint32_t fn, uint32_t fn_ref,
62 time_spec_t time_diff_hint)
63 {
64 int frames_diff, fn_delta;
Piotr Krysik34ce7a02017-10-31 11:30:59 +010065 frames_diff = int(round(time_diff_hint.get_real_secs() / GSM_FN_PERIOD));
66 fn_delta = fnmod_delta(fn, fn_ref + frames_diff) + frames_diff;
67
68 return fn_delta;
69 }
70
71 /**
72 * Computes difference between reference frame number
73 * and a second frame number.
74 * @param fn_ref reference frame number modulo GSM_HYPER_FRAME
75 * @param fn second frame number modulo GSM_HYPER_FRAME
76 * @param time_ref precise timestamp of the first sample in the fn_ref
77 * @param time_hint coarse time for fn that is used as a hint to avoid
78 * ambiguities caused by modulo operation applied to
79 * frame numbers
80 * @return difference between fn_ref and fn
81 */
Piotr Krysik6e41d062017-11-03 09:56:49 +010082 time_format fn_time_delta_cpp(uint32_t fn_ref, time_format time_ref, uint32_t fn_x,
83 time_format time_hint, uint32_t ts_num, uint32_t ts_ref)
Piotr Krysik34ce7a02017-10-31 11:30:59 +010084 {
Piotr Krysik6e41d062017-11-03 09:56:49 +010085 time_spec_t time_diff_hint = time_spec_t(time_hint.first, time_hint.second) - time_spec_t(time_ref.first, time_ref.second);
86 int fn_delta = fn_time_diff_delta(fn_x, fn_ref, time_diff_hint);
87 time_spec_t time_x_precise = fn_delta * GSM_FN_PERIOD + time_spec_t(time_ref.first, time_ref.second) + (static_cast<int>(ts_num) - static_cast<int>(ts_ref)) * GSM_TS_PERIOD;
88
89 return time_format(time_x_precise.get_full_secs(), time_x_precise.get_frac_secs());
Piotr Krysik34ce7a02017-10-31 11:30:59 +010090 }
Piotr Krysik6e41d062017-11-03 09:56:49 +010091
Piotr Krysik34ce7a02017-10-31 11:30:59 +010092 } /* namespace gsm */
93} /* namespace gr */
94