blob: 205508d6c2fdc1fd6566a313fd25dd0298fce00a [file] [log] [blame]
Piotr Krysikdf978692017-09-27 21:58:24 +02001//
2// Copyright 2011-2013 Ettus Research LLC
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//
17
18#include "time_spec.h"
19
20namespace gr {
21 namespace gsm {
22
23 /***********************************************************************
24 * Time spec system time
25 **********************************************************************/
26
27 #ifdef HAVE_CLOCK_GETTIME
28 #include <time.h>
29 time_spec_t time_spec_t::get_system_time(void){
30 timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);
31 return time_spec_t(ts.tv_sec, ts.tv_nsec, 1e9);
32 }
33 #endif /* HAVE_CLOCK_GETTIME */
34
35
36 #ifdef HAVE_MACH_ABSOLUTE_TIME
37 #include <mach/mach_time.h>
38 time_spec_t time_spec_t::get_system_time(void){
39 mach_timebase_info_data_t info; mach_timebase_info(&info);
40 intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom;
41 return time_spec_t::from_ticks(nanosecs, 1e9);
42 }
43 #endif /* HAVE_MACH_ABSOLUTE_TIME */
44
45
46 #ifdef HAVE_QUERY_PERFORMANCE_COUNTER
47 #include <Windows.h>
48 time_spec_t time_spec_t::get_system_time(void){
49 LARGE_INTEGER counts, freq;
50 QueryPerformanceCounter(&counts);
51 QueryPerformanceFrequency(&freq);
52 return time_spec_t::from_ticks(counts.QuadPart, double(freq.QuadPart));
53 }
54 #endif /* HAVE_QUERY_PERFORMANCE_COUNTER */
55
56
57 #ifdef HAVE_MICROSEC_CLOCK
58 #include <boost/date_time/posix_time/posix_time.hpp>
59 namespace pt = boost::posix_time;
60 time_spec_t time_spec_t::get_system_time(void){
61 pt::ptime time_now = pt::microsec_clock::universal_time();
62 pt::time_duration time_dur = time_now - pt::from_time_t(0);
63 return time_spec_t(
64 time_t(time_dur.total_seconds()),
65 long(time_dur.fractional_seconds()),
66 double(pt::time_duration::ticks_per_second())
67 );
68 }
69 #endif /* HAVE_MICROSEC_CLOCK */
70
71 /***********************************************************************
72 * Time spec constructors
73 **********************************************************************/
74 #define time_spec_init(full, frac) { \
75 const time_t _full = time_t(full); \
76 const double _frac = double(frac); \
77 const int _frac_int = int(_frac); \
78 _full_secs = _full + _frac_int; \
79 _frac_secs = _frac - _frac_int; \
80 if (_frac_secs < 0) {\
81 _full_secs -= 1; \
82 _frac_secs += 1; \
83 } \
84 }
85
86 inline long long fast_llround(const double x){
87 return (long long)(x + 0.5); // assumption of non-negativity
88 }
89
90 time_spec_t::time_spec_t(const time_spec_t & spec){
91 time_spec_init(spec.get_full_secs(), spec.get_frac_secs());
92 }
93
94 time_spec_t::time_spec_t(double secs){
95 time_spec_init(0, secs);
96 }
97
98 time_spec_t::time_spec_t(time_t full_secs, double frac_secs){
99 time_spec_init(full_secs, frac_secs);
100 }
101
102 time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate){
103 const double frac_secs = tick_count/tick_rate;
104 time_spec_init(full_secs, frac_secs);
105 }
106
107 time_spec_t time_spec_t::from_ticks(long long ticks, double tick_rate){
108 const long long rate_i = (long long)(tick_rate);
109 const double rate_f = tick_rate - rate_i;
110 const time_t secs_full = time_t(ticks/rate_i);
111 const long long ticks_error = ticks - (secs_full*rate_i);
112 const double ticks_frac = ticks_error - secs_full*rate_f;
113 return time_spec_t(secs_full, ticks_frac/tick_rate);
114 }
115
116 /***********************************************************************
117 * Time spec accessors
118 **********************************************************************/
119 long time_spec_t::get_tick_count(double tick_rate) const{
120 return long(fast_llround(this->get_frac_secs()*tick_rate));
121 }
122
123 long long time_spec_t::to_ticks(double tick_rate) const{
124 const long long rate_i = (long long)(tick_rate);
125 const double rate_f = tick_rate - rate_i;
126 const long long ticks_full = this->get_full_secs()*rate_i;
127 const double ticks_error = this->get_full_secs()*rate_f;
128 const double ticks_frac = this->get_frac_secs()*tick_rate;
129 return ticks_full + fast_llround(ticks_error + ticks_frac);
130 }
131
132 double time_spec_t::get_real_secs(void) const{
133 return this->get_full_secs() + this->get_frac_secs();
134 }
135
136 /***********************************************************************
137 * Time spec math overloads
138 **********************************************************************/
139 time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){
140 time_spec_init(
141 this->get_full_secs() + rhs.get_full_secs(),
142 this->get_frac_secs() + rhs.get_frac_secs()
143 );
144 return *this;
145 }
146
147 time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){
148 time_spec_init(
149 this->get_full_secs() - rhs.get_full_secs(),
150 this->get_frac_secs() - rhs.get_frac_secs()
151 );
152 return *this;
153 }
154
155 bool operator==(const time_spec_t &lhs, const time_spec_t &rhs){
156 return
157 lhs.get_full_secs() == rhs.get_full_secs() and
158 lhs.get_frac_secs() == rhs.get_frac_secs()
159 ;
160 }
161
162 bool operator<(const time_spec_t &lhs, const time_spec_t &rhs){
163 return (
164 (lhs.get_full_secs() < rhs.get_full_secs()) or (
165 (lhs.get_full_secs() == rhs.get_full_secs()) and
166 (lhs.get_frac_secs() < rhs.get_frac_secs())
167 ));
168 }
169 }
170}