/* * Set the time of day clock based on the value of the struct timespec arg. * Return 0 on success, an error number otherwise. */ int mc146818_settime(device_t dev, struct timespec *ts) { struct mc146818_softc *sc; struct clocktime ct; int cent, year; sc = device_get_softc(dev); /* Accuracy is only one second. */ if (ts->tv_nsec >= 500000000) ts->tv_sec++; ts->tv_nsec = 0; clock_ts_to_ct(ts, &ct); mtx_lock_spin(&sc->sc_mtx); /* Disable RTC updates and interrupts (if enabled). */ (*sc->sc_mcwrite)(dev, MC_REGB, ((sc->sc_regb & (MC_REGB_BINARY | MC_REGB_24HR)) | MC_REGB_SET)); #define TOREG(x) ((sc->sc_flag & MC146818_BCD) ? TOBCD(x) : (x)) (*sc->sc_mcwrite)(dev, MC_SEC, TOREG(ct.sec)); (*sc->sc_mcwrite)(dev, MC_MIN, TOREG(ct.min)); (*sc->sc_mcwrite)(dev, MC_HOUR, TOREG(ct.hour)); /* Map dow from 0 - 6 to 1 - 7. */ (*sc->sc_mcwrite)(dev, MC_DOW, TOREG(ct.dow + 1)); (*sc->sc_mcwrite)(dev, MC_DOM, TOREG(ct.day)); (*sc->sc_mcwrite)(dev, MC_MONTH, TOREG(ct.mon)); year = ct.year - sc->sc_year0; if (sc->sc_flag & MC146818_NO_CENT_ADJUST) { cent = year / 100; (*sc->sc_setcent)(dev, cent); year -= cent * 100; } else if (year > 99) year -= 100; (*sc->sc_mcwrite)(dev, MC_YEAR, TOREG(year)); /* Reenable RTC updates and interrupts. */ (*sc->sc_mcwrite)(dev, MC_REGB, sc->sc_regb); mtx_unlock_spin(&sc->sc_mtx); #undef TOREG return (0); }
void x300_impl::synchronize_dacs(const std::vector<radio_perifs_t*>& radios) { if (radios.size() < 2) return; //Nothing to synchronize //**PRECONDITION** //This function assumes that all the VITA times in "radios" are synchronized //to a common reference. Currently, this function is called in get_tx_stream //which also has the same precondition. //Reinitialize and resync all DACs for (size_t i = 0; i < radios.size(); i++) { radios[i]->dac->reset_and_resync(); } //Get a rough estimate of the cumulative command latency boost::posix_time::ptime t_start = boost::posix_time::microsec_clock::local_time(); for (size_t i = 0; i < radios.size(); i++) { radios[i]->ctrl->peek64(RB64_TIME_NOW); //Discard value. We are just timing the call } boost::posix_time::time_duration t_elapsed = boost::posix_time::microsec_clock::local_time() - t_start; //Add 100% of headroom + uncertaintly to the command time boost::uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 13000 /*Scheduler latency*/; //Pick radios[0] as the time reference. uhd::time_spec_t sync_time = radios[0]->time64->get_time_now() + uhd::time_spec_t(((double)t_sync_us)/1e6); //Send the sync command for (size_t i = 0; i < radios.size(); i++) { radios[i]->ctrl->set_time(sync_time); radios[i]->ctrl->poke32(TOREG(SR_DACSYNC), 0x1); //Arm FRAMEP/N sync pulse radios[i]->ctrl->set_time(uhd::time_spec_t(0.0)); //Clear command time } //Wait and check status boost::this_thread::sleep(boost::posix_time::microseconds(t_sync_us)); for (size_t i = 0; i < radios.size(); i++) { radios[i]->dac->verify_sync(); } }