diff options
-rw-r--r-- | mpm/lib/mykonos/ad937x_device.cpp | 16 | ||||
-rw-r--r-- | mpm/lib/mykonos/adi_ctrl.cpp | 2 | ||||
-rw-r--r-- | mpm/lib/mykonos/config/ad937x_config_t.cpp | 14 | ||||
-rw-r--r-- | mpm/lib/mykonos/config/ad937x_default_config.hpp | 108 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/lmk_mg.py | 116 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/magnesium.py | 66 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/nijesdcore.py | 10 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/base.py | 2 |
8 files changed, 246 insertions, 88 deletions
diff --git a/mpm/lib/mykonos/ad937x_device.cpp b/mpm/lib/mykonos/ad937x_device.cpp index 68065e67d..0e0851f41 100644 --- a/mpm/lib/mykonos/ad937x_device.cpp +++ b/mpm/lib/mykonos/ad937x_device.cpp @@ -24,6 +24,7 @@ #include <functional> #include <iostream> +#include <thread> using namespace mpm::ad937x::device; using namespace mpm::ad937x::gpio; @@ -42,13 +43,14 @@ static const double RX_DEFAULT_FREQ = 1e9; static const double TX_DEFAULT_FREQ = 1e9; // TODO: get the actual device ID -static const uint32_t AD9371_PRODUCT_ID = 0x1F; +static const uint32_t AD9371_PRODUCT_ID = 0x1; // TODO: move this to whereever we declare the ARM binary static const size_t ARM_BINARY_SIZE = 98304; static const uint32_t INIT_CAL_TIMEOUT_MS = 10000; +// TODO: actually figure out what cals we want to run static const uint32_t INIT_CALS = TX_BB_FILTER | ADC_TUNER | @@ -96,9 +98,7 @@ void ad937x_device::_call_api_function(std::function<mykonosErr_t()> func) auto error = func(); if (error != MYKONOS_ERR_OK) { - std::cout << getMykonosErrorMessage(error); - // TODO: make UHD exception - //throw std::exception(getMykonosErrorMessage(error)); + throw mpm::runtime_error(getMykonosErrorMessage(error)); } } @@ -108,9 +108,7 @@ void ad937x_device::_call_gpio_api_function(std::function<mykonosGpioErr_t()> fu auto error = func(); if (error != MYKONOS_ERR_GPIO_OK) { - std::cout << getGpioMykonosErrorMessage(error); - // TODO: make UHD exception - //throw std::exception(getMykonosErrorMessage(error)); + throw mpm::runtime_error(getGpioMykonosErrorMessage(error)); } } @@ -217,13 +215,15 @@ void ad937x_device::begin_initialization() void ad937x_device::finish_initialization() { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); // to check status, just call the same function with a 0 instead of a 1, seems good uint8_t mcs_status = 0; _call_api_function(std::bind(MYKONOS_enableMultichipSync, mykonos_config.device, 0, &mcs_status)); if ((mcs_status & 0x0A) != 0x0A) { - throw mpm::runtime_error("Multichip sync failed!"); + throw mpm::runtime_error(str(boost::format("Multichip sync failed! Read: %X Expected: %X") + % int(mcs_status) % int(0x0A))); } _call_api_function(std::bind(MYKONOS_initSubRegisterTables, mykonos_config.device)); diff --git a/mpm/lib/mykonos/adi_ctrl.cpp b/mpm/lib/mykonos/adi_ctrl.cpp index be3fa0ddb..ac83e2a56 100644 --- a/mpm/lib/mykonos/adi_ctrl.cpp +++ b/mpm/lib/mykonos/adi_ctrl.cpp @@ -241,7 +241,7 @@ commonErr_t CMB_closeLog(void) commonErr_t CMB_writeToLog(ADI_LOGLEVEL level, uint8_t deviceIndex, uint32_t errorCode, const char *comment) { - std::cout << "[CMB_writeToLog] level==" << level << " errorCode==" << errorCode << " " << comment << std::endl; + std::cout << "[CMB_writeToLog] level==" << level << " errorCode==" << errorCode << " " << comment; return COMMONERR_OK; } commonErr_t CMB_flushLog(void) diff --git a/mpm/lib/mykonos/config/ad937x_config_t.cpp b/mpm/lib/mykonos/config/ad937x_config_t.cpp index eac294299..0e6d499e6 100644 --- a/mpm/lib/mykonos/config/ad937x_config_t.cpp +++ b/mpm/lib/mykonos/config/ad937x_config_t.cpp @@ -60,6 +60,11 @@ void ad937x_config_t::_assign_default_configuration() _orxPowerAgc = DEFAULT_ORX_POWER_AGC; _orxAgcCtrl = DEFAULT_ORX_AGC_CTRL; + // TODO: this is ridiculous + // oh, and ORX bring up requires a valid sniffer gain control + // https://github.com/EttusResearch/uhddev/blob/n3xx-master/mpm/lib/mykonos/adi/mykonos.c#L5713 + _snifferGainCtrl = DEFAULT_SNIFFER_GAIN; + _armGpio = DEFAULT_ARM_GPIO; _gpio3v3 = DEFAULT_GPIO_3V3; _gpio = DEFAULT_GPIO; @@ -110,7 +115,6 @@ void ad937x_config_t::_init_pointers() _snifferProfile.rxFir = _sniffer_rx_fir_config.fir; _obsRx.snifferGainCtrl = &_snifferGainCtrl; // sniffer has no AGC ctrl, so leave as null - _obsRx.orxAgcCtrl = nullptr; _obsRx.framer = &_orxFramer; _auxIo.gpio3v3 = &_gpio3v3; @@ -121,9 +125,9 @@ void ad937x_config_t::_init_pointers() void ad937x_config_t::_assign_firs() { // TODO: get default filters here - tx_fir_config.set_fir(6, { 32, 0 }); - rx_fir_config.set_fir( -6,{ 48, 0 }); - _orx_fir_config.set_fir( -6, { 48, 0 }); - _sniffer_rx_fir_config.set_fir( -6, { 48, 0 }); + tx_fir_config.set_fir(6, std::vector<int16_t>(48, 0)); + rx_fir_config.set_fir(-6, std::vector<int16_t>(48, 0)); + _orx_fir_config.set_fir(-6, std::vector<int16_t>(48, 0)); + _sniffer_rx_fir_config.set_fir(-6, std::vector<int16_t>(48, 0)); } diff --git a/mpm/lib/mykonos/config/ad937x_default_config.hpp b/mpm/lib/mykonos/config/ad937x_default_config.hpp index dc476a0ee..b0f254308 100644 --- a/mpm/lib/mykonos/config/ad937x_default_config.hpp +++ b/mpm/lib/mykonos/config/ad937x_default_config.hpp @@ -42,9 +42,9 @@ static const mykonosRxProfile_t DEFAULT_RX_PROFILE = 5, // Decimation of Dec5 or Dec4 filter (5,4) 1, // If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled) 1, // RX Half band 1 decimation (1 or 2) - 122880, // Rx IQ data rate in kHz + 125000, // Rx IQ data rate in kHz 100000000, // The Rx RF passband bandwidth for the profile - 100000, // Rx BBF 3dB corner in kHz + 102000, // Rx BBF 3dB corner in kHz NULL // pointer to custom ADC profile }; @@ -164,11 +164,11 @@ static const mykonosTxProfile_t DEFAULT_TX_PROFILE = 2, // Tx Halfband1 filter interpolation (1,2) 1, // Tx Halfband2 filter interpolation (1,2) 1, // TxInputHbInterpolation (1,2) - 122880, // Tx IQ data rate in kHz + 125000, // Tx IQ data rate in kHz 20000000, // Primary Signal BW - 100000000, // The Tx RF passband bandwidth for the profile - 710539, // The DAC filter 3dB corner in kHz - 50000, // Tx BBF 3dB corner in kHz + 102000000, // The Tx RF passband bandwidth for the profile + 722000, // The DAC filter 3dB corner in kHz + 51000, // Tx BBF 3dB corner in kHz 0 // Enable DPD, only valid for AD9373 }; @@ -240,18 +240,18 @@ static const mykonosORxGainControl_t DEFAULT_ORX_GAIN = static const mykonosAgcCfg_t DEFAULT_ORX_AGC_CTRL = { - 0, // agcRx1MaxGainIndex - 0, // agcRx1MinGainIndex - 0, // agcRx2MaxGainIndex - 0, // agcRx2MinGainIndex: - 0, // agcObsRxMaxGainIndex - 0, // agcObsRxMinGainIndex - 0, // agcObsRxSelect - 0, // agcPeakThresholdMode - 0, // agcLowThsPreventGainIncrease - 0, // agcGainUpdateCounter - 0, // agcSlowLoopSettlingDelay - 0, // agcPeakWaitTime + 255, // agcRx1MaxGainIndex + 195, // agcRx1MinGainIndex + 255, // agcRx2MaxGainIndex + 195, // agcRx2MinGainIndex: + 255, // agcObsRxMaxGainIndex + 203, // agcObsRxMinGainIndex + 1, // agcObsRxSelect + 1, // agcPeakThresholdMode + 1, // agcLowThsPreventGainIncrease + 30720, // agcGainUpdateCounter + 3, // agcSlowLoopSettlingDelay + 4, // agcPeakWaitTime 0, // agcResetOnRxEnable 0, // agcEnableSyncPulseForGainCounter nullptr,// *peakAgc @@ -260,40 +260,48 @@ static const mykonosAgcCfg_t DEFAULT_ORX_AGC_CTRL = static const mykonosPeakDetAgcCfg_t DEFAULT_ORX_PEAK_AGC = { - 0, // apdHighThresh: - 0, // apdLowThresh - 0, // hb2HighThresh - 0, // hb2LowThresh - 0, // hb2VeryLowThresh - 0, // apdHighThreshExceededCnt - 0, // apdLowThreshExceededCnt - 0, // hb2HighThreshExceededCnt - 0, // hb2LowThreshExceededCnt - 0, // hb2VeryLowThreshExceededCnt - 0, // apdHighGainStepAttack - 0, // apdLowGainStepRecovery - 0, // hb2HighGainStepAttack - 0, // hb2LowGainStepRecovery - 0, // hb2VeryLowGainStepRecovery - 0, // apdFastAttack - 0, // hb2FastAttack - 0, // hb2OverloadDetectEnable - 0, // hb2OverloadDurationCnt - 0 // hb2OverloadThreshCnt + 0x2A, // apdHighThresh: + 0x16, // apdLowThresh + 0xB5, // hb2HighThresh + 0x72, // hb2LowThresh + 0x40, // hb2VeryLowThresh + 0x03, // apdHighThreshExceededCnt + 0x03, // apdLowThreshExceededCnt + 0x03, // hb2HighThreshExceededCnt + 0x03, // hb2LowThreshExceededCnt + 0x03, // hb2VeryLowThreshExceededCnt + 0x4, // apdHighGainStepAttack + 0x2, // apdLowGainStepRecovery + 0x4, // hb2HighGainStepAttack + 0x2, // hb2LowGainStepRecovery + 0x4, // hb2VeryLowGainStepRecovery + 0x0, // apdFastAttack + 0x0, // hb2FastAttack + 0x1, // hb2OverloadDetectEnable + 0x1, // hb2OverloadDurationCnt + 0x1 // hb2OverloadThreshCnt }; static const mykonosPowerMeasAgcCfg_t DEFAULT_ORX_POWER_AGC = { - 0, // pmdUpperHighThresh - 0, // pmdUpperLowThresh - 0, // pmdLowerHighThresh - 0, // pmdLowerLowThresh - 0, // pmdUpperHighGainStepAttack - 0, // pmdUpperLowGainStepAttack - 0, // pmdLowerHighGainStepRecovery - 0, // pmdLowerLowGainStepRecovery - 0, // pmdMeasDuration - 0, // pmdMeasConfig + 0x01, // pmdUpperHighThresh + 0x03, // pmdUpperLowThresh + 0x0C, // pmdLowerHighThresh + 0x04, // pmdLowerLowThresh + 0x0, // pmdUpperHighGainStepAttack + 0x0, // pmdUpperLowGainStepAttack + 0x0, // pmdLowerHighGainStepRecovery + 0x0, // pmdLowerLowGainStepRecovery + 0x08, // pmdMeasDuration + 0x02 // pmdMeasConfig +}; + +static const mykonosSnifferGainControl_t DEFAULT_SNIFFER_GAIN = +{ + MGC, // Current Sniffer gain control mode setting + 255, // Current Sniffer gain index. Can be used differently for Manual Gain control/AGC + 255, // Max gain index for the currently loaded Sniffer Gain table + 203 // Min gain index for the currently loaded Sniffer Gain table }; static const mykonosRxProfile_t DEFAULT_ORX_PROFILE = @@ -367,8 +375,8 @@ static const mykonosAuxIo_t DEFAULT_AUX_IO = static const mykonosDigClocks_t DEFAULT_CLOCKS = { - 122880, // CLKPLL and device reference clock frequency in kHz - 9830400, // CLKPLL VCO frequency in kHz + 125000, // CLKPLL and device reference clock frequency in kHz + 10000000, // CLKPLL VCO frequency in kHz VCODIV_2, // CLKPLL VCO divider 4 // CLKPLL high speed clock divider }; diff --git a/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py b/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py new file mode 100644 index 000000000..94d50527d --- /dev/null +++ b/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py @@ -0,0 +1,116 @@ +# +# Copyright 2017 Ettus Research (National Instruments) +# +# 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 <http://www.gnu.org/licenses/>. +# +""" +LMK04828 driver for use with Magnesium +""" + +from ..mpmlog import get_logger +from time import sleep + +class LMK04828Mg(object): + def __init__(self, regs_iface, spi_lock): + self.regs_iface = regs_iface + self.spi_lock = spi_lock + self.log = get_logger("LMK04828") + assert hasattr(self.regs_iface, 'peek8') + assert hasattr(self.regs_iface, 'poke8') + assert hasattr(self.spi_lock, 'lock') + assert hasattr(self.spi_lock, 'unlock') + + def init(self): + # Reset the LMK + self.log.trace("lock?") + self.spi_lock.lock() + self.log.trace("locked") + + addrs = (0x000, 0x000, 0x002, 0x14A) + vals = (0x90, 0x10, 0x00, 0x33) + + for addr, val in zip(addrs, vals): + #self.log.trace("send {0}, {1}".format(hex(addr), hex(val),)) + self.regs_iface.poke8(addr, val) + + # Re-verify chip ID + self.log.trace("check chip id") + if not self.verify_chip_id(): + raise Exception("Unable to locate LMK04828") + + # Write the configuration (10 MHz reference, 125 MHz outputs) + addrs = (0x100, 0x101, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10B, 0x10C, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118, 0x119, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, 0x123, 0x124, 0x125, 0x126, 0x127, 0x128, 0x129, 0x12B, 0x12C, 0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x133, 0x134, 0x135, 0x136, 0x137, 0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141, 0x142, 0x143, 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14B, 0x14C, 0x14D, 0x14E, 0x14F, 0x150, 0x151, 0x152, 0x153, 0x154, 0x155, 0x156, 0x157, 0x158, 0x159, 0x15A, 0x15B, 0x15C, 0x15D, 0x15E, 0x15F, 0x160, 0x161, 0x162, 0x163, 0x164, 0x165, 0x171, 0x172, 0x17C, 0x17D, 0x166, 0x167, 0x168, 0x169, 0x16A, 0x16B, 0x16C, 0x16D, 0x16E, 0x173) + vals = (0x78, 0x55, 0x00, 0x20, 0x00, 0xF2, 0x55, 0x7E, 0x55, 0x00, 0x00, 0x00, 0xF0, 0x55, 0x61, 0x55, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x78, 0x55, 0x00, 0x20, 0x00, 0xF1, 0x00, 0x78, 0x55, 0x00, 0x20, 0x00, 0xF2, 0x55, 0x78, 0x55, 0x00, 0x00, 0x00, 0xF0, 0x50, 0x78, 0x55, 0x00, 0x20, 0x00, 0xF1, 0x05, 0x30, 0x00, 0x01, 0xE0, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x7F, 0x10, 0x1A, 0x01, 0x01, 0x01, 0xF6, 0x00, 0x00, 0x7F, 0x03, 0x02, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x7D, 0xCF, 0x03, 0xE8, 0x00, 0x0B, 0x00, 0x04, 0xA4, 0x00, 0x00, 0x19, 0xAA, 0x02, 0x15, 0x33, 0x00, 0x00, 0x19, 0x51, 0x27, 0x10, 0x00, 0x00, 0x13, 0x00) + + self.log.trace("send init sequence") + for addr, val in zip(addrs, vals): + self.regs_iface.poke8(addr, val) + + self.spi_lock.unlock() + sleep(0.1) + self.spi_lock.lock() + + # Clear Lock Detect Sticky + self.log.trace("clear lock sticky") + addrs = (0x182, 0x182, 0x183, 0x183) + vals = (0x01, 0x00, 0x01, 0x00) + + for addr, val in zip(addrs, vals): + self.regs_iface.poke8(addr, val) + + self.spi_lock.unlock() + sleep(0.1) + self.spi_lock.lock() + + # Check Lock Detects + self.log.trace("check lock status") + pll1_lock_status = self.regs_iface.peek8(0x182) + pll2_lock_status = self.regs_iface.peek8(0x183) + + if not pll1_lock_status == 0x02: + self.log.error("LMK PLL1 did not lock. Status {0}".format(hex(pll1_lock_status))) + + if not pll2_lock_status == 0x02: + self.log.error("LMK PLL2 did not lock. Status {0}".format(hex(pll2_lock_status))) + + # Toggle SYNC polarity to trigger SYNC event + self.regs_iface.poke8(0x143, 0xF1) + self.regs_iface.poke8(0x143, 0xD1) + # Enable SYSREF pulses + self.regs_iface.poke8(0x139, 0x02) + self.regs_iface.poke8(0x144, 0xFF) + self.regs_iface.poke8(0x143, 0x52) + self.spi_lock.unlock() + + self.log.trace("LMK init'd and locked") + + def get_chip_id(self): + """ + Read back the chip ID + """ + # TODO: avoid deadlock by not locking when we already have lock (or use a recursive mutex internally) + #self.spi_lock.lock() + chip_id = self.regs_iface.peek8(0x03) + #self.spi_lock.unlock() + return chip_id + + def verify_chip_id(self): + """ + Returns True if the chip ID matches what we expect, False otherwise. + """ + chip_id = self.get_chip_id() + if chip_id != 6: + self.log.error("wrong chip id {0}".format(chip_id)) + return False + return True diff --git a/mpm/python/usrp_mpm/dboard_manager/magnesium.py b/mpm/python/usrp_mpm/dboard_manager/magnesium.py index fa2dbe9c3..de871abf8 100644 --- a/mpm/python/usrp_mpm/dboard_manager/magnesium.py +++ b/mpm/python/usrp_mpm/dboard_manager/magnesium.py @@ -26,6 +26,25 @@ from .base import DboardManagerBase from .. import nijesdcore from ..uio import UIO from ..mpmlog import get_logger +from .lmk_mg import LMK04828Mg + +def create_spidev_iface(dev_node): + """ + Create a regs iface from a spidev node + """ + SPI_SPEED_HZ = 1000000 + SPI_ADDR_SHIFT = 8 + SPI_DATA_SHIFT = 0 + SPI_READ_FLAG = 1<<23 + SPI_WRIT_FLAG = 0 + return lib.spi.make_spidev_regs_iface( + dev_node, + SPI_SPEED_HZ, + SPI_ADDR_SHIFT, + SPI_DATA_SHIFT, + SPI_READ_FLAG, + SPI_WRIT_FLAG + ) class Magnesium(DboardManagerBase): """ @@ -54,25 +73,16 @@ class Magnesium(DboardManagerBase): """ Execute necessary init dance to bring up dboard """ + self.clock_regs = create_spidev_iface(self._spi_nodes['lmk']) self.log.debug("Loading C++ drivers...") self._device = lib.dboards.magnesium_manager( self._spi_nodes['mykonos'], ) - SPI_SPEED_HZ = 1000000 - SPI_ADDR_SHIFT = 8 - SPI_DATA_SHIFT = 0 - SPI_READ_FLAG = 1<<23 - SPI_WRIT_FLAG = 0 - self.lmk = lib.spi.make_spidev_regs_iface( - dev_node, - SPI_SPEED_HZ, - SPI_ADDR_SHIFT, - SPI_DATA_SHIFT, - SPI_READ_FLAG, - SPI_WRIT_FLAG - ) + self.spi_lock = self._device.get_spi_lock() self.mykonos = self._device.get_radio_ctrl() self.log.debug("Loaded C++ drivers.") + self.lmk = LMK04828Mg(self.clock_regs, self.spi_lock) + self.log.debug("Getting Mg A uio...") self.radio_regs = UIO(label="jesd204b-regs", read_only=False) self.log.info("Radio-register UIO object successfully generated!") @@ -89,9 +99,9 @@ class Magnesium(DboardManagerBase): self.jesdcore.check_core() self.log.trace("Initializing LMK...") self.lmk.init() + self.radio_regs.poke32(0x2078, 0xA000040) + self.log.trace("Verify LMK Chip ID...") self.lmk.verify_chip_id() - self.log.trace("Enabling SYSREF pulses...") - self.lmk.enable_sysref_pulse() self.jesdcore.unreset_mmcm() @@ -105,23 +115,36 @@ class Magnesium(DboardManagerBase): self.jesdcore.send_sysref_pulse() self.mykonos.finish_initialization() - self.log.trace("Stargin Mykonos JESD framing...") + self.log.trace("Starting Mykonos framer...") self.mykonos.start_jesd_rx() + self.jesdcore.send_sysref_pulse() + self.log.trace("Resetting FPGA deframer...") self.jesdcore.init_deframer() + self.log.trace("Resetting FPGA framer...") self.jesdcore.init_framer() + self.log.trace("Starting Mykonos deframer...") self.mykonos.start_jesd_tx() - #TODO add function for Enable FPGA LMFC Generator + self.log.trace("Enable LMFC and send") + self.jesdcore.enable_lmfc() self.jesdcore.send_sysref_pulse() time.sleep(0.2) if not self.jesdcore.get_framer_status(): raise Exception('JESD Core Framer is not synced!') if not self.jesdcore.get_deframer_status(): raise Exception('JESD Core Deframer is not synced!') - #if (!self.mykonos.get_framer_status()) - # raise Exception('Mykonos Framer is not synced!') - #if (!self.mykonos.get_deframer_status()) - # raise Exception('Mykonos Deframer is not synced!') + if (self.mykonos.get_framer_status() & 0xFF != 0x3E): + raise Exception('Mykonos Framer is not synced!') + if (self.mykonos.get_deframer_status() & 0x7F != 0x28): + raise Exception('Mykonos Deframer is not synced!') + self.log.trace("JESD fully synced and ready") + + def dump_jesd_core(self): + for i in range(0x2000, 0x2110, 0x10): + print("0x%04X " % i), + for j in range(0, 0x10, 0x4): + print("%08X" % self.radio_regs.peek32(i + j)), + print("") def read_eeprom_v1(self, data): """ @@ -130,3 +153,4 @@ class Magnesium(DboardManagerBase): # magnesium eeprom contains # nothing return struct.unpack_from("x", data) + diff --git a/mpm/python/usrp_mpm/nijesdcore.py b/mpm/python/usrp_mpm/nijesdcore.py index d4c8d40b9..bb8a3ad43 100644 --- a/mpm/python/usrp_mpm/nijesdcore.py +++ b/mpm/python/usrp_mpm/nijesdcore.py @@ -94,6 +94,12 @@ class NIMgJESDCore(object): self._gt_reset('tx', reset_only=True) self._gt_reset('rx', reset_only=True) self._gt_pll_lock_control() + + def enable_lmfc(self): + """ + Enable LMFC generator in FPGA. This step is woefully incomplete, but this call will work for now. + """ + self.regs.poke32(0x2078, 0) def send_sysref_pulse(self): """ @@ -107,7 +113,7 @@ class NIMgJESDCore(object): " Put MGTs into reset. Optionally unresets and enables them " assert tx_or_rx.lower() in ('rx', 'tx') mgt_reg = {'tx': 0x2020, 'rx': 0x2024}[tx_or_rx] - self.log.trace("Resetting TX MGTs...") + self.log.trace("Resetting %s MGTs..." % tx_or_rx.upper()) self.regs.poke32(mgt_reg, 0x10) if not reset_only: self.regs.poke32(mgt_reg, 0x20) @@ -116,7 +122,7 @@ class NIMgJESDCore(object): rb = self.regs.peek32(mgt_reg) if rb & 0xFFFF0000 == 0x000F0000: return True - time.sleep(0.01) + time.sleep(0.001) raise Exception('Timeout in GT {trx} Reset (Readback: 0x{rb:X})'.format( trx=tx_or_rx.upper(), rb=(rb & 0xFFFF0000), diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py index ea2a145a8..f65d9c780 100644 --- a/mpm/python/usrp_mpm/periph_manager/base.py +++ b/mpm/python/usrp_mpm/periph_manager/base.py @@ -74,7 +74,7 @@ class PeriphManagerBase(object): # eeprom_data = EEPROM().read_eeprom(get_eeprom_path(eeprom_addr)) eeprom_data = None # I know spidev masters on the dboard slots - hw_pid = 3 + hw_pid = 2 if hw_pid in dboard_manager.HW_PIDS: spi_devices = sorted(get_spidev_nodes("e0006000.spi")) self.log.debug("Found spidev nodes: {0}".format(spi_devices)) |