File: time_core_3000.cpp

package info (click to toggle)
uhd 4.3.0.0%2Bds1-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 175,384 kB
  • sloc: cpp: 271,145; ansic: 103,960; python: 95,906; vhdl: 55,838; tcl: 14,117; xml: 8,535; makefile: 2,706; sh: 2,432; pascal: 230; javascript: 120; csh: 94; asm: 20; perl: 11
file content (120 lines) | stat: -rw-r--r-- 3,883 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//
// Copyright 2013-2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#include <uhd/utils/log.hpp>
#include <uhd/utils/safe_call.hpp>
#include <uhdlib/usrp/cores/time_core_3000.hpp>
#include <chrono>
#include <thread>

#define REG_TIME_HI _base + 0
#define REG_TIME_LO _base + 4
#define REG_TIME_CTRL _base + 8

#define CTRL_LATCH_TIME_NOW (1 << 0)
#define CTRL_LATCH_TIME_PPS (1 << 1)
#define CTRL_LATCH_TIME_SYNC (1 << 2)

using namespace uhd;

time_core_3000::~time_core_3000(void)
{
    /* NOP */
}

struct time_core_3000_impl : time_core_3000
{
    time_core_3000_impl(wb_iface::sptr iface,
        const size_t base,
        const readback_bases_type& readback_bases)
        : _iface(iface), _base(base), _readback_bases(readback_bases)
    {
        this->set_tick_rate(1); // init to non zero
    }

    ~time_core_3000_impl(void) override
    {
        UHD_SAFE_CALL(; // NOP
        )
    }

    void set_tick_rate(const double rate) override
    {
        _tick_rate = rate;
    }

    void self_test(void) override
    {
        const size_t sleep_millis = 100;
        UHD_LOGGER_DEBUG("CORES") << "Performing timer loopback test... ";
        const time_spec_t time0 = this->get_time_now();
        std::this_thread::sleep_for(std::chrono::milliseconds(sleep_millis));
        const time_spec_t time1  = this->get_time_now();
        const double approx_secs = (time1 - time0).get_real_secs();
        const bool test_fail     = (approx_secs > 0.15) or (approx_secs < 0.05);
        if (test_fail) {
            UHD_LOG_WARNING("CORES", "Timer loopback test failed!");
        } else {
            UHD_LOG_DEBUG("CORES", "Timer loopback test passed.");
        }

        // useful warning for debugging actual rate
        const size_t ticks_elapsed = size_t(_tick_rate * approx_secs);
        const size_t approx_rate   = size_t(ticks_elapsed / (sleep_millis / 1e3));
        if (test_fail)
            UHD_LOGGER_WARNING("CORES")
                << "Expecting clock rate: " << (_tick_rate / 1e6) << " MHz\n"
                << "Approximate clock rate: " << (approx_rate / 1e6) << " MHz\n";
    }

    uhd::time_spec_t get_time_now(void) override
    {
        const uint64_t ticks = _iface->peek64(_readback_bases.rb_now);
        return time_spec_t::from_ticks(ticks, _tick_rate);
    }

    uhd::time_spec_t get_time_last_pps(void) override
    {
        const uint64_t ticks = _iface->peek64(_readback_bases.rb_pps);
        return time_spec_t::from_ticks(ticks, _tick_rate);
    }

    void set_time_now(const uhd::time_spec_t& time) override
    {
        const uint64_t ticks = time.to_ticks(_tick_rate);
        _iface->poke32(REG_TIME_HI, uint32_t(ticks >> 32));
        _iface->poke32(REG_TIME_LO, uint32_t(ticks >> 0));
        _iface->poke32(REG_TIME_CTRL, CTRL_LATCH_TIME_NOW);
    }

    void set_time_sync(const uhd::time_spec_t& time) override
    {
        const uint64_t ticks = time.to_ticks(_tick_rate);
        _iface->poke32(REG_TIME_HI, uint32_t(ticks >> 32));
        _iface->poke32(REG_TIME_LO, uint32_t(ticks >> 0));
        _iface->poke32(REG_TIME_CTRL, CTRL_LATCH_TIME_SYNC);
    }

    void set_time_next_pps(const uhd::time_spec_t& time) override
    {
        const uint64_t ticks = time.to_ticks(_tick_rate);
        _iface->poke32(REG_TIME_HI, uint32_t(ticks >> 32));
        _iface->poke32(REG_TIME_LO, uint32_t(ticks >> 0));
        _iface->poke32(REG_TIME_CTRL, CTRL_LATCH_TIME_PPS);
    }

    wb_iface::sptr _iface;
    const size_t _base;
    const readback_bases_type _readback_bases;
    double _tick_rate;
};

time_core_3000::sptr time_core_3000::make(
    wb_iface::sptr iface, const size_t base, const readback_bases_type& readback_bases)
{
    return time_core_3000::sptr(new time_core_3000_impl(iface, base, readback_bases));
}