Skip to content

Commit f32cc54

Browse files
committed
Fixed slow timing drift.
1 parent 04b24f1 commit f32cc54

File tree

5 files changed

+186
-7
lines changed

5 files changed

+186
-7
lines changed

include/common.h.in

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ typedef short int16;
1414
typedef unsigned short uint16;
1515
typedef int int32;
1616
typedef unsigned int uint32;
17+
typedef long int int64;
18+
typedef unsigned long int uint64;
1719
// Prevent int8 and uint8 from printing out as characters instead of integers.
1820
inline std::ostream & operator<< (
1921
std::ostream & os,

src/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Create a library of all the shared functions.
2-
add_library(LTE_MISC capbuf.cpp constants.cpp itpp_ext.cpp macros.cpp searcher.cpp common.cpp dsp.cpp lte_lib.cpp)
2+
add_library(LTE_MISC capbuf.cpp constants.cpp itpp_ext.cpp macros.cpp searcher.cpp common.cpp dsp.cpp lte_lib.cpp from_osmocom.cpp)
33

44
SET (common_link_libs ${Boost_LIBRARIES} ${Boost_THREAD_LIBRARY} ${LAPACK_LIBRARIES} ${FFTW_LIBRARIES} ${RTLSDR_LIBRARIES} ${CURSES_LIBRARIES})
55

src/LTE-Tracker.cpp

+10-5
Original file line numberDiff line numberDiff line change
@@ -471,13 +471,13 @@ void config_usb(
471471
}
472472

473473
// Calculate the actual fs that was programmed
474-
//uint32 xtal=dev->rtl_xtal;
475-
//uint32 divider=itpp::round((xtal*pow(2.0,22.0))/fs_requested);
476-
//divider&=~3;
477-
//fs_programmed=(xtal*pow(2.0,22.0))/divider;
474+
uint32 xtal=28800000;
475+
uint32 divider=itpp::round((xtal*pow(2.0,22.0))/fs_requested);
476+
divider&=~3;
477+
fs_programmed=(xtal*pow(2.0,22.0))/divider;
478478
// Using the API will have a maximum frequency error of 1Hz... Should
479479
// be enough, right???
480-
fs_programmed=(double)rtlsdr_get_sample_rate(dev);
480+
//fs_programmed=(double)rtlsdr_get_sample_rate(dev);
481481

482482
// Center frequency
483483
if (rtlsdr_set_center_freq(dev,itpp::round(fc*correction))<0) {
@@ -790,6 +790,11 @@ int main(
790790
tracked_cell_list_t tracked_cell_list;
791791
capbuf_sync_t capbuf_sync;
792792
global_thread_data_t global_thread_data(fc_requested,fc_programmed,fs_programmed);
793+
cout << "fc_requested = " << fc_requested << endl;
794+
cout << "fc_programmed = " << fc_programmed << endl;
795+
cout << "fc_requested-fc_programmed = " << fc_requested-fc_programmed << endl;
796+
cout << "fs_programmed = " << fs_programmed << endl;
797+
cout << "fs_programmed-1.92e6 = " << fs_programmed-1.92e6 << endl;
793798
global_thread_data.main_thread_id=syscall(SYS_gettid);
794799
global_thread_data.frequency_offset(initial_freq_offset);
795800

src/capbuf.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ static void capbuf_rtlsdr_callback(
6868
// previously captured data.
6969
// Also, optionally, this function can save each set of captured data
7070
// to a file.
71+
double compute_fc_programmed(const double & fosc,const double & intended_flo);
7172
void capture_data(
7273
// Inputs
7374
const double & fc_requested,
@@ -114,7 +115,11 @@ void capture_data(
114115
ABORT(-1);
115116
}
116117
// Calculate the actual center frequency that was programmed.
117-
fc_programmed=(double)rtlsdr_get_center_freq(dev);
118+
//fc_programmed=(double)rtlsdr_get_center_freq(dev);
119+
fc_programmed=compute_fc_programmed(28.8e6,fc_requested);
120+
//FIXME!! Only for testing!!!
121+
//fc_programmed=fc_requested+(fc_requested-fc_programmed);
122+
fc_programmed=fc_programmed+58;
118123

119124
// Reset the buffer
120125
if (rtlsdr_reset_buffer(dev)<0) {

src/from_osmocom.cpp

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// Code originally came from osmocom:
2+
// http://sdr.osmocom.org/trac/wiki/rtl-sdr
3+
// From tuner_e4k.c
4+
5+
/*
6+
* Elonics E4000 tuner driver
7+
*
8+
* (C) 2011-2012 by Harald Welte <[email protected]>
9+
* (C) 2012 by Sylvain Munaut <[email protected]>
10+
* (C) 2012 by Hoernchen <[email protected]>
11+
*
12+
* All Rights Reserved
13+
*
14+
* This program is free software; you can redistribute it and/or modify
15+
* it under the terms of the GNU General Public License as published by
16+
* the Free Software Foundation; either version 2 of the License, or
17+
* (at your option) any later version.
18+
*
19+
* This program is distributed in the hope that it will be useful,
20+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+
* GNU General Public License for more details.
23+
*
24+
* You should have received a copy of the GNU General Public License
25+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
26+
*/
27+
28+
#include <stdio.h>
29+
#include <stdlib.h>
30+
#include <getopt.h>
31+
#include <unistd.h>
32+
#include <itpp/itbase.h>
33+
#include <itpp/signal/transforms.h>
34+
#include <boost/math/special_functions/gamma.hpp>
35+
#include <boost/thread.hpp>
36+
#include <boost/thread/condition.hpp>
37+
#include <list>
38+
#include <sstream>
39+
#include <queue>
40+
#include <sys/stat.h>
41+
#include <sys/syscall.h>
42+
#include <sys/types.h>
43+
#include <curses.h>
44+
#include "rtl-sdr.h"
45+
#include "common.h"
46+
47+
struct e4k_pll_params {
48+
uint32 fosc;
49+
uint32 intended_flo;
50+
uint32 flo;
51+
uint16 x;
52+
uint8 z;
53+
uint8 r;
54+
uint8 r_idx;
55+
uint8 threephase;
56+
};
57+
58+
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
59+
60+
#define KHZ(x) ((x)*1000)
61+
62+
#define E4K_PLL_Y 65536
63+
64+
struct pll_settings {
65+
uint32_t freq;
66+
uint8_t reg_synth7;
67+
uint8_t mult;
68+
};
69+
70+
static const struct pll_settings pll_vars[] = {
71+
{KHZ(72400), (1 << 3) | 7, 48},
72+
{KHZ(81200), (1 << 3) | 6, 40},
73+
{KHZ(108300), (1 << 3) | 5, 32},
74+
{KHZ(162500), (1 << 3) | 4, 24},
75+
{KHZ(216600), (1 << 3) | 3, 16},
76+
{KHZ(325000), (1 << 3) | 2, 12},
77+
{KHZ(350000), (1 << 3) | 1, 8},
78+
{KHZ(432000), (0 << 3) | 3, 8},
79+
{KHZ(667000), (0 << 3) | 2, 6},
80+
{KHZ(1200000), (0 << 3) | 1, 4}
81+
};
82+
83+
/* \brief compute Fvco based on Fosc, Z and X
84+
* \returns positive value (Fvco in Hz), 0 in case of error */
85+
static uint64_t compute_fvco(uint32_t f_osc, uint8_t z, uint16_t x)
86+
{
87+
uint64_t fvco_z, fvco_x, fvco;
88+
89+
/* We use the following transformation in order to
90+
* handle the fractional part with integer arithmetic:
91+
* Fvco = Fosc * (Z + X/Y) <=> Fvco = Fosc * Z + (Fosc * X)/Y
92+
* This avoids X/Y = 0. However, then we would overflow a 32bit
93+
* integer, as we cannot hold e.g. 26 MHz * 65536 either.
94+
*/
95+
fvco_z = (uint64_t)f_osc * z;
96+
97+
fvco_x = ((uint64_t)f_osc * x) / E4K_PLL_Y;
98+
99+
fvco = fvco_z + fvco_x;
100+
101+
return fvco;
102+
}
103+
104+
static uint32_t compute_flo(uint32_t f_osc, uint8_t z, uint16_t x, uint8_t r)
105+
{
106+
uint64_t fvco = compute_fvco(f_osc, z, x);
107+
if (fvco == 0)
108+
return -EINVAL;
109+
110+
return fvco / r;
111+
}
112+
113+
double compute_fc_programmed(const double & fosc,const double & intended_flo)
114+
{
115+
e4k_pll_params oscp_actual;
116+
e4k_pll_params * oscp=&oscp_actual;
117+
118+
uint32 i;
119+
uint8 r = 2;
120+
uint64 intended_fvco, remainder;
121+
uint64 z = 0;
122+
uint32 x;
123+
int flo;
124+
int three_phase_mixing = 0;
125+
oscp->r_idx = 0;
126+
127+
//if (!is_fosc_valid(fosc))
128+
// return 0;
129+
130+
for(i = 0; i < ARRAY_SIZE(pll_vars); ++i) {
131+
if(intended_flo < pll_vars[i].freq) {
132+
three_phase_mixing = (pll_vars[i].reg_synth7 & 0x08) ? 1 : 0;
133+
oscp->r_idx = pll_vars[i].reg_synth7;
134+
r = pll_vars[i].mult;
135+
break;
136+
}
137+
}
138+
139+
//fprintf(stderr, "[E4K] Fint=%u, R=%u\n", intended_flo, r);
140+
141+
/* flo(max) = 1700MHz, R(max) = 48, we need 64bit! */
142+
intended_fvco = (uint64)intended_flo * r;
143+
144+
/* compute integral component of multiplier */
145+
z = intended_fvco / fosc;
146+
147+
/* compute fractional part. this will not overflow,
148+
* as fosc(max) = 30MHz and z(max) = 255 */
149+
remainder = intended_fvco - (fosc * z);
150+
/* remainder(max) = 30MHz, E4K_PLL_Y = 65536 -> 64bit! */
151+
x = (remainder * E4K_PLL_Y) / fosc;
152+
/* x(max) as result of this computation is 65536 */
153+
154+
flo = compute_flo(fosc, z, x, r);
155+
156+
oscp->fosc = fosc;
157+
oscp->flo = flo;
158+
oscp->intended_flo = intended_flo;
159+
oscp->r = r;
160+
// oscp->r_idx = pll_vars[i].reg_synth7 & 0x0;
161+
oscp->threephase = three_phase_mixing;
162+
oscp->x = x;
163+
oscp->z = z;
164+
165+
return flo;
166+
}
167+

0 commit comments

Comments
 (0)