aboutsummaryrefslogtreecommitdiffstats
path: root/mpm
diff options
context:
space:
mode:
authorMark Meserve <mark.meserve@ni.com>2017-05-02 17:09:03 -0500
committerMartin Braun <martin.braun@ettus.com>2017-12-22 15:03:52 -0800
commit24d3011233ba1cd0b8788eccfacd0b67cb776600 (patch)
treecfd2af3212182e76a84b1fcb325b26ebd266bdb6 /mpm
parent8f9f29dabc1a0f9db1101f658d9bcbac526eca39 (diff)
downloaduhd-24d3011233ba1cd0b8788eccfacd0b67cb776600.tar.gz
uhd-24d3011233ba1cd0b8788eccfacd0b67cb776600.tar.bz2
uhd-24d3011233ba1cd0b8788eccfacd0b67cb776600.zip
mg: bring up links
Diffstat (limited to 'mpm')
-rw-r--r--mpm/lib/mykonos/ad937x_device.cpp16
-rw-r--r--mpm/lib/mykonos/adi_ctrl.cpp2
-rw-r--r--mpm/lib/mykonos/config/ad937x_config_t.cpp14
-rw-r--r--mpm/lib/mykonos/config/ad937x_default_config.hpp108
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/lmk_mg.py116
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/magnesium.py66
-rw-r--r--mpm/python/usrp_mpm/nijesdcore.py10
-rw-r--r--mpm/python/usrp_mpm/periph_manager/base.py2
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))