File: time64_core_200.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 (153 lines) | stat: -rw-r--r-- 5,074 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//
// Copyright 2011,2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#include <uhd/exception.hpp>
#include <uhd/utils/assert_has.hpp>
#include <uhdlib/usrp/cores/time64_core_200.hpp>
#include <boost/math/special_functions/round.hpp>

#define REG_TIME64_TICKS_HI _base + 0
#define REG_TIME64_TICKS_LO _base + 4
#define REG_TIME64_FLAGS _base + 8
#define REG_TIME64_IMM _base + 12
#define REG_TIME64_MIMO_SYNC _base + 20 // lower byte is delay cycles

// pps flags (see above)
#define FLAG_TIME64_PPS_NEGEDGE (0 << 0)
#define FLAG_TIME64_PPS_POSEDGE (1 << 0)
#define FLAG_TIME64_PPS_SMA (0 << 1)
#define FLAG_TIME64_PPS_MIMO (1 << 1) // apparently not used

#define FLAG_TIME64_LATCH_NOW 1
#define FLAG_TIME64_LATCH_NEXT_PPS 0

#define FLAG_TIME64_MIMO_SYNC (1 << 8)

using namespace uhd;

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

class time64_core_200_impl : public time64_core_200
{
public:
    time64_core_200_impl(wb_iface::sptr iface,
        const size_t base,
        const readback_bases_type& readback_bases,
        const size_t mimo_delay_cycles)
        : _iface(iface)
        , _base(base)
        , _readback_bases(readback_bases)
        , _tick_rate(0.0)
        , _mimo_delay_cycles(mimo_delay_cycles)
    {
        _sources.push_back("none");
        _sources.push_back("external");
        _sources.push_back("_external_");
        if (_mimo_delay_cycles != 0)
            _sources.push_back("mimo");
    }

    void enable_gpsdo(void) override
    {
        _sources.push_back("gpsdo");
    }

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

    uhd::time_spec_t get_time_now(void) override
    {
        for (size_t i = 0; i < 3;
             i++) { // special algorithm because we cant read 64 bits synchronously
            const uint32_t ticks_hi = _iface->peek32(_readback_bases.rb_hi_now);
            const uint32_t ticks_lo = _iface->peek32(_readback_bases.rb_lo_now);
            if (ticks_hi != _iface->peek32(_readback_bases.rb_hi_now))
                continue;
            const uint64_t ticks = (uint64_t(ticks_hi) << 32) | ticks_lo;
            return time_spec_t::from_ticks(ticks, _tick_rate);
        }
        throw uhd::runtime_error("time64_core_200: get time now timeout");
    }

    uhd::time_spec_t get_time_last_pps(void) override
    {
        for (size_t i = 0; i < 3;
             i++) { // special algorithm because we cant read 64 bits synchronously
            const uint32_t ticks_hi = _iface->peek32(_readback_bases.rb_hi_pps);
            const uint32_t ticks_lo = _iface->peek32(_readback_bases.rb_lo_pps);
            if (ticks_hi != _iface->peek32(_readback_bases.rb_hi_pps))
                continue;
            const uint64_t ticks = (uint64_t(ticks_hi) << 32) | ticks_lo;
            return time_spec_t::from_ticks(ticks, _tick_rate);
        }
        throw uhd::runtime_error("time64_core_200: get time last pps timeout");
    }

    void set_time_now(const uhd::time_spec_t& time) override
    {
        const uint64_t ticks = time.to_ticks(_tick_rate);
        _iface->poke32(REG_TIME64_TICKS_LO, uint32_t(ticks >> 0));
        _iface->poke32(REG_TIME64_IMM, FLAG_TIME64_LATCH_NOW);
        _iface->poke32(REG_TIME64_TICKS_HI, uint32_t(ticks >> 32)); // latches all 3
    }

    void set_time_next_pps(const uhd::time_spec_t& time) override
    {
        const uint64_t ticks = time.to_ticks(_tick_rate);
        _iface->poke32(REG_TIME64_TICKS_LO, uint32_t(ticks >> 0));
        _iface->poke32(REG_TIME64_IMM, FLAG_TIME64_LATCH_NEXT_PPS);
        _iface->poke32(REG_TIME64_TICKS_HI, uint32_t(ticks >> 32)); // latches all 3
    }

    void set_time_source(const std::string& source) override
    {
        assert_has(_sources, source, "time source");

        // setup pps flags
        if (source == "external" or source == "gpsdo") {
            _iface->poke32(
                REG_TIME64_FLAGS, FLAG_TIME64_PPS_SMA | FLAG_TIME64_PPS_POSEDGE);
        } else if (source == "_external_") {
            _iface->poke32(
                REG_TIME64_FLAGS, FLAG_TIME64_PPS_SMA | FLAG_TIME64_PPS_NEGEDGE);
        }

        // setup mimo flags
        if (source == "mimo") {
            _iface->poke32(REG_TIME64_MIMO_SYNC,
                FLAG_TIME64_MIMO_SYNC | (_mimo_delay_cycles & 0xff));
        } else {
            _iface->poke32(REG_TIME64_MIMO_SYNC, 0);
        }
    }

    std::vector<std::string> get_time_sources(void) override
    {
        return _sources;
    }

private:
    wb_iface::sptr _iface;
    const size_t _base;
    const readback_bases_type _readback_bases;
    double _tick_rate;
    const size_t _mimo_delay_cycles;
    std::vector<std::string> _sources;
};

time64_core_200::sptr time64_core_200::make(wb_iface::sptr iface,
    const size_t base,
    const readback_bases_type& readback_bases,
    const size_t mimo_delay_cycles)
{
    return sptr(new time64_core_200_impl(iface, base, readback_bases, mimo_delay_cycles));
}