// // Copyright 2011,2014 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include "time64_core_200.hpp" #include #include #include #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){ _sources.push_back("gpsdo"); } void set_tick_rate(const double rate){ _tick_rate = rate; } uhd::time_spec_t get_time_now(void){ 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){ 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){ 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){ 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){ 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 get_time_sources(void){ 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 _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)); }