diff options
| author | DJ Epson <daniel.jepson@ni.com> | 2017-09-01 15:20:09 -0700 | 
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:04:01 -0800 | 
| commit | f141f71180e397fa21d23385f154da138bef0a81 (patch) | |
| tree | dd68c27564157cbe8ecaac0056008ec286ddd704 | |
| parent | 04b0f414b9235d36e7572b8c6644630d77de4aab (diff) | |
| download | uhd-f141f71180e397fa21d23385f154da138bef0a81.tar.gz uhd-f141f71180e397fa21d23385f154da138bef0a81.tar.bz2 uhd-f141f71180e397fa21d23385f154da138bef0a81.zip  | |
mpm: Streaming-related improvements to Magnesium controls
| -rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/lmk_mg.py | 212 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/magnesium.py | 177 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/nijesdcore.py | 12 | 
3 files changed, 320 insertions, 81 deletions
diff --git a/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py b/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py index 6c2660521..b295874a1 100644 --- a/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py +++ b/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py @@ -18,7 +18,7 @@  LMK04828 driver for use with Magnesium  """ -from time import sleep +import time  from builtins import zip  from builtins import hex  from ..mpmlog import get_logger @@ -33,66 +33,160 @@ class LMK04828Mg(LMK04828):          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") +        """ +        Basic init. Turns it on. Let's read SPI. +        """ +        self.log.info("Reset LMK & Verify") +        self.pokes8(( +            (0x000, 0x90), # Assert reset +            (0x000, 0x10), # De-assert reset +            (0x002, 0x00), # De-assert power down +            (0x148, 0x33), # Clock Select as SDO +        ))          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 config(self): +        """ +        Write lots of config foo. +        """ +        self.log.trace("LMK Initialization") +        clkin0_r_divider = {10e6: 0x0A, 20e6: 0x14}[10e6] # FIXME: hard coded to use 10 MHz +        self.pokes8(( +            (0x100, 0x78), # CLKout Config +            (0x101, 0x55), # CLKout Config +            (0x102, 0x55), # CLKout Config +            (0x103, 0x00), # CLKout Config +            (0x104, 0x20), # CLKout Config +            (0x105, 0x00), # CLKout Config +            (0x106, 0xF2), # CLKout Config MYK: (0xAB where A = SYSREF, B = CLK) +            (0x107, 0x15), # CLKout Config 0x15 = LVDS, 0x55 = LVPECL +            (0x108, 0x7E), # CLKout Config +            (0x109, 0x55), # CLKout Config +            (0x10A, 0x55), # CLKout Config +            (0x10B, 0x00), # CLKout Config +            (0x10C, 0x00), # CLKout Config +            (0x10D, 0x00), # CLKout Config +            (0x10E, 0xF0), # CLKout Config +            (0x10F, 0x55), # CLKout Config +            (0x110, 0x61), # CLKout Config +            (0x111, 0x55), # CLKout Config +            (0x112, 0x55), # CLKout Config +            (0x113, 0x00), # CLKout Config +            (0x114, 0x00), # CLKout Config +            (0x115, 0x00), # CLKout Config +            (0x116, 0xF9), # CLKout Config +            (0x117, 0x00), # CLKout Config +            (0x118, 0x78), # CLKout Config +            (0x119, 0x55), # CLKout Config +            (0x11A, 0x55), # CLKout Config +            (0x11B, 0x00), # CLKout Config +            (0x11C, 0x20), # CLKout Config +            (0x11D, 0x00), # CLKout Config +            (0x11E, 0xF1), # CLKout Config +            (0x11F, 0x00), # CLKout Config +            (0x120, 0x78), # CLKout Config +            (0x121, 0x55), # CLKout Config +            (0x122, 0x55), # CLKout Config +            (0x123, 0x00), # CLKout Config +            (0x124, 0x20), # CLKout Config +            (0x125, 0x00), # CLKout Config +            (0x126, 0xF2), # CLKout Config FPGA: (0xAB where A = SYSREF, B = CLK) +            (0x127, 0x55), # CLKout Config 0x15 = LVDS, 0x55 = LVPECL +            (0x128, 0x78), # CLKout Config +            (0x129, 0x55), # CLKout Config +            (0x12A, 0x55), # CLKout Config +            (0x12B, 0x00), # CLKout Config +            (0x12C, 0x00), # CLKout Config +            (0x12D, 0x00), # CLKout Config +            (0x12E, 0xF0), # CLKout Config +            (0x12F, 0x50), # CLKout Config +            (0x130, 0x78), # CLKout Config +            (0x131, 0x55), # CLKout Config +            (0x132, 0x55), # CLKout Config +            (0x133, 0x00), # CLKout Config +            (0x134, 0x20), # CLKout Config +            (0x135, 0x00), # CLKout Config +            (0x136, 0xF1), # CLKout Config +            (0x137, 0x05), # CLKout Config +            (0x138, 0x30), # VCO_MUX to VCO 1; OSCout off +            (0x139, 0x00), # SYSREF Source = MUX; SYSREF MUX = Normal SYNC +            (0x13A, 0x01), # SYSREF Divide [12:8] +            (0x13B, 0xE0), # SYSREF Divide [7:0] +            (0x13C, 0x00), # SYSREF DDLY [12:8] +            (0x13D, 0x08), # SYSREF DDLY [7:0] ... 8 is default, <8 is reserved +            (0x13E, 0x00), # SYSREF Pulse Count = 1 pulse/request +            (0x13F, 0x09), # Feedback Mux: Enabled, DCLKout6, drives PLL1N divider +            (0x140, 0x00), # POWERDOWN options +            (0x141, 0x00), # Dynamic digital delay enable +            (0x142, 0x00), # Dynamic digital delay step +            (0x143, 0xD1), # SYNC edge sensitive; SYSREF_CLR; SYNC Enabled; SYNC from pin no pulser +            (0x144, 0x00), # Enable SYNC on all outputs including sysref +            (0x145, 0x7F), # Always program to d127 +            (0x146, 0x10), # CLKin Type & En +            (0x147, 0x1A), # CLKin_SEL = CLKin1 manual; CLKin1 to PLL1 +            # (0x148, 0x01), # CLKin_SEL0 = input with pullup: previously written above! +            (0x149, 0x01), # CLKin_SEL1 = input with pulldown +            (0x14B, 0x01), # Holdover & DAC Manual Mode +            (0x14C, 0xF6), # DAC Manual Mode +            (0x14D, 0x00), # DAC Settings (defaults) +            (0x14E, 0x00), # DAC Settings (defaults) +            (0x14F, 0x7F), # DAC Settings (defaults) +            (0x150, 0x03), # Holdover Settings (defaults) +            (0x151, 0x02), # Holdover Settings (defaults) +            (0x152, 0x00), # Holdover Settings (defaults) +            (0x153, 0x00), # CLKin0_R divider [13:8], default = 0 +            (0x154, clkin0_r_divider), # CLKin0_R divider [7:0], default = d120 +            (0x155, 0x00), # CLKin1_R divider [13:8], default = 0 +            (0x156, clkin0_r_divider), # CLKin1_R divider [7:0], default = d120 +            (0x157, 0x00), # CLKin2_R divider [13:8], default = 0 +            (0x158, 0x01), # CLKin2_R divider [7:0], default = d120 +            (0x159, 0x00), # PLL1 N divider [13:8], default = 0 +            (0x15A, 0x7D), # PLL1 N divider [7:0], default = d120 +            (0x15B, 0xCF), # PLL1 PFD +            (0x15C, 0x27), # PLL1 DLD Count [13:8] +            (0x15D, 0x10), # PLL1 DLD Count [7:0] +            (0x15E, 0x00), # PLL1 R/N delay, defaults = 0 +            (0x15F, 0x0B), # Status LD1 pin = PLL1 LD, push-pull output +            (0x160, 0x00), # PLL2 R divider [11:8]; +            (0x161, 0x04), # PLL2 R divider [7:0] +            (0x162, 0xA4), # PLL2 prescaler; OSCin freq +            (0x163, 0x00), # PLL2 Cal = PLL2 normal val +            (0x164, 0x00), # PLL2 Cal = PLL2 normal val +            (0x165, 0x19), # PLL2 Cal = PLL2 normal val +            (0x171, 0xAA), # Write this val after x165 +            (0x172, 0x02), # Write this val after x165 +            (0x17C, 0x15), # VCo1 Cal; write before x168 +            (0x17D, 0x33), # VCo1 Cal; write before x168 +            (0x166, 0x00), # PLL2 N[17:16] +            (0x167, 0x00), # PLL2 N[15:8] +            (0x168, 0x19), # PLL2 N[7:0] +            (0x169, 0x51), # PLL2 PFD +            (0x16A, 0x27), # PLL2 DLD Count [13:8] = default d32 +            (0x16B, 0x10), # PLL2 DLD Count [7:0] = default d0 +            (0x16C, 0x00), # PLL2 Loop filter r = 200 ohm +            (0x16D, 0x00), # PLL2 loop filter c = 10 pF +            (0x16E, 0x13), # Status LD2 pin = Output push-pull, PLL2 DLD +            (0x173, 0x00), # Do not power down PLL2 or prescaler +        )) +        time.sleep(1.0) # Increased time to wait for DAC and VCXO to settle. +        self.pokes8(( +            (0x182, 0x1), # Clear Lock Detect Sticky +            (0x182, 0x0), # Clear Lock Detect Sticky +            (0x183, 0x1), # Clear Lock Detect Sticky +            (0x183, 0x0), # Clear Lock Detect Sticky +        )) +        time.sleep(0.1) +        if not self.check_plls_locked(): +            raise RuntimeError("At least one LMK PLL did not lock! Check the logs for details.") +        self.log.trace("Setting SYNC and SYSREF config...") +        self.pokes8(( +            (0x143, 0xF1), # toggle SYNC polarity to trigger SYNC event +            (0x143, 0xD1), # toggle SYNC polarity to trigger SYNC event +            (0x139, 0x02), # SYSREF Source = MUX; SYSREF MUX = pulser +            (0x144, 0xFF), # Disable SYNC on all outputs including sysref +            (0x143, 0x52), # Pulser selected; SYNC enabled; 1 shot enabled +        )) +        self.log.info("LMK init'd and locked!") diff --git a/mpm/python/usrp_mpm/dboard_manager/magnesium.py b/mpm/python/usrp_mpm/dboard_manager/magnesium.py index 536503b62..55a53b984 100644 --- a/mpm/python/usrp_mpm/dboard_manager/magnesium.py +++ b/mpm/python/usrp_mpm/dboard_manager/magnesium.py @@ -49,6 +49,26 @@ def create_spidev_iface(dev_node):          SPI_WRIT_FLAG      ) +def create_spidev_iface_cpld(dev_node): +    """ +    Create a regs iface from a spidev node +    """ +    SPI_SPEED_HZ = 1000000 +    SPI_MODE = 0 +    SPI_ADDR_SHIFT = 16 +    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_MODE, +        SPI_ADDR_SHIFT, +        SPI_DATA_SHIFT, +        SPI_READ_FLAG, +        SPI_WRIT_FLAG +    ) +  class Magnesium(DboardManagerBase):      """      Holds all dboard specific information and methods of the magnesium dboard @@ -61,36 +81,92 @@ class Magnesium(DboardManagerBase):      pids = [0x150]      # Maps the chipselects to the corresponding devices: -    spi_chipselect = {"lmk": 0, "mykonos": 1} +    spi_chipselect = {"cpld": 0, "lmk": 1, "mykonos": 2} + +    def _get_mykonos_function(self, name): +        mykfunc = getattr(self.mykonos, name) +        def func(*args): +            return mykfunc(*args) +        func.__doc__ = mykfunc.__doc__ +        return func      def __init__(self, slot_idx, **kwargs):          super(Magnesium, self).__init__(slot_idx, **kwargs)          self.log = get_logger("Magnesium-{}".format(slot_idx))          self.log.trace("Initializing Magnesium daughterboard, slot index {}".format(self.slot_idx)) -    def init(self, args): -        """ -        Execute necessary init dance to bring up dboard -        """ -        self.log.info("init() called with args `{}'".format( -            ",".join(['{}={}'.format(x, args[x]) for x in args]) -        )) -        self.clock_regs = create_spidev_iface(self._spi_nodes['lmk']) +        self.log.debug("Loading C++ drivers for CPLD SPI.") +        self.cpld_regs = create_spidev_iface_cpld(self._spi_nodes['cpld']) +          self.log.debug("Loading C++ drivers...")          self._device = lib.dboards.magnesium_manager(              self._spi_nodes['mykonos'],          )          self.spi_lock = self._device.get_spi_lock() +        self.log.debug("Loading C++ drivers for LMK SPI.") +        self.clock_regs = create_spidev_iface(self._spi_nodes['lmk']) +        self.lmk = LMK04828Mg(self.clock_regs, self.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.radio_regs = UIO(label="dboard-regs-0", read_only=False)          self.log.info("Radio-register UIO object successfully generated!") + +        for mykfuncname in [x for x in dir(self.mykonos) if not x.startswith("_") and callable(getattr(self.mykonos, x))]: +            self.log.trace("adding {}".format(mykfuncname)) +            setattr(self, mykfuncname, self._get_mykonos_function(mykfuncname)) + +    def init(self, args): +        """ +        Execute necessary init dance to bring up dboard +        """ + +        def _init_clock_control(dboard_regs): +            " Create a dboard clock control object and reset it " +            dboard_clk_control = DboardClockControl(dboard_regs, self.log) +            dboard_clk_control.reset_mmcm() +            return dboard_clk_control + + +        self.log.info("init() called with args `{}'".format( +            ",".join(['{}={}'.format(x, args[x]) for x in args]) +        )) + + +        self.dboard_clk_control = _init_clock_control(self.radio_regs) + +        self.lmk.init() +        self.lmk.config() +        self.dboard_clk_control.enable_mmcm() +        self.log.info("Clocking Configured Successfully!") +          self.init_jesd(self.radio_regs) + +        self.mykonos.start_radio() +          return True + + +    def cpld_peek16(self, addr): +        return self.cpld_regs.peek16(addr) + +    def cpld_poke16(self, addr, data): +        return self.cpld_regs.poke16(addr, data) + +    def lmk_peek(self, addr): +        return self.lmk.peek8(addr) + +    def lmk_poke(self, addr, data): +        return self.lmk.poke8(addr, data) + +    def lmk_setup_dbg(self): +        self.lmk.init() +        self.lmk.config() +        return "LMK Init Success" + +      def init_jesd(self, uio):          """          Bring up the JESD link between Mykonos and the N310 @@ -101,16 +177,17 @@ class Magnesium(DboardManagerBase):          self.log.trace("Checking JESD core...")          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.jesdcore.unreset_mmcm() +        self.jesdcore.unreset_qpll()          self.jesdcore.init()          self.log.trace("Resetting Mykonos...") -        self.jesdcore.reset_mykonos() #not sure who owns the reset + +        # YIKES!!! Where does this go?!? CPLD? +        # self.jesdcore.reset_mykonos() #not sure who owns the reset +        self.cpld_poke16(0x13, 0x1) +        self.cpld_poke16(0x13, 0x0) +          self.log.trace("Initializing Mykonos...")          self.mykonos.begin_initialization() @@ -134,12 +211,15 @@ class Magnesium(DboardManagerBase):          time.sleep(0.2)          if not self.jesdcore.get_framer_status():              raise Exception('JESD Core Framer is not synced!') +        if ((self.mykonos.get_deframer_status() & 0x7F) != 0x28): +            raise Exception('Mykonos Deframer is not synced!')          if not self.jesdcore.get_deframer_status():              raise Exception('JESD Core Deframer is not synced!') -        if (self.mykonos.get_framer_status() & 0xFF != 0x3E): +        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!') +        if (self.mykonos.get_multichip_sync_status() & 0xB) != 0xB: +            raise Exception('Mykonos multi chip sync failed!') +          self.log.trace("JESD fully synced and ready")      def dump_jesd_core(self): @@ -149,3 +229,60 @@ class Magnesium(DboardManagerBase):                  print(("%08X" % self.radio_regs.peek32(i + j)), end=' ')              print("") + + +class DboardClockControl(object): +    """ +    Control the FPGA MMCM for Radio Clock control. +    """ +    # Clocking Register address constants +    RADIO_CLK_MMCM      = 0x0020 +    PHASE_SHIFT_CONTROL = 0x0024 +    RADIO_CLK_ENABLES   = 0x0028 +    MGT_REF_CLK_STATUS  = 0x0030 + +    def __init__(self, regs, log): +        self.log = log +        self.regs = regs +        self.poke32 = self.regs.poke32 +        self.peek32 = self.regs.peek32 + +    def enable_outputs(self, enable=True): +        """ +        Enables or disables the MMCM outputs. +        """ +        if enable: +            self.poke32(self.RADIO_CLK_ENABLES, 0x011) +        else: +            self.poke32(self.RADIO_CLK_ENABLES, 0x000) + +    def reset_mmcm(self): +        """ +        Uninitialize and reset the MMCM +        """ +        self.log.trace("Disabling all Radio Clocks, then resetting MMCM...") +        self.enable_outputs(False) +        self.poke32(self.RADIO_CLK_MMCM, 0x1) + +    def enable_mmcm(self): +        """ +        Unreset MMCM and poll lock indicators + +        If MMCM is not locked after unreset, an exception is thrown. +        """ +        self.log.trace("Un-resetting MMCM...") +        self.poke32(self.RADIO_CLK_MMCM, 0x2) +        time.sleep(0.5) # Replace with poll and timeout TODO +        mmcm_locked = bool(self.peek32(self.RADIO_CLK_MMCM) & 0x10) +        if not mmcm_locked: +            self.log.error("MMCM not locked!") +            raise RuntimeError("MMCM not locked!") +        self.log.trace("Enabling output MMCM clocks...") +        self.enable_outputs(True) + +    def check_refclk(self): +        """ +        Not technically a clocking reg, but related. +        """ +        return bool(self.peek32(self.MGT_REF_CLK_STATUS) & 0x1) + diff --git a/mpm/python/usrp_mpm/nijesdcore.py b/mpm/python/usrp_mpm/nijesdcore.py index b3f6af355..cb59f40ed 100644 --- a/mpm/python/usrp_mpm/nijesdcore.py +++ b/mpm/python/usrp_mpm/nijesdcore.py @@ -38,7 +38,7 @@ class NIMgJESDCore(object):          assert hasattr(self.regs, 'peek32')          assert hasattr(self.regs, 'poke32') -    def unreset_mmcm(self): +    def unreset_qpll(self):          # new_val = self.regs.peek32(0x0) & ~0x8          # self.log.trace("Unresetting MMCM, writing value {:X}".format(new_val))          self.regs.poke32(0x0, 0x7) @@ -52,6 +52,7 @@ class NIMgJESDCore(object):              raise Exception('JESD Core signature mismatch! Check that core is mapped correctly')          #if self.regs.peek32(0x2104) != 0xFF          #error here for date revision mismatch +        self.log.trace("JESD Core build code: {0}".format(hex(self.regs.peek32(0x2104))))          return True      def init_deframer(self): @@ -85,6 +86,12 @@ class NIMgJESDCore(object):          " Return True if deframer is in good status "          rb = self.regs.peek32(0x2040)          self.log.trace("Returning deframer status: {0}".format(hex(rb & 0xFFFFFFFF))) +        if rb & 0b100 == 0b0: +            self.log.warning("Deframer warning: Code Group Sync failed to complete!") +        elif rb & 0b1000 == 0b0: +            self.log.warning("Deframer warning: Channel Bonding failed to complete!") +        elif rb & 0x200000 == 0b1: +            self.log.warning("Deframer warning: Misc error!")          return rb & 0xFFFFFFFF == 0xF000001C      def init(self): @@ -96,7 +103,8 @@ class NIMgJESDCore(object):          self._gt_reset('tx', reset_only=True)          self._gt_reset('rx', reset_only=True)          self._gt_pll_lock_control() -         +        self.regs.poke32(0x2078, 0x40) +      def enable_lmfc(self):          """          Enable LMFC generator in FPGA. This step is woefully incomplete, but this call will work for now.  | 
