aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py
diff options
context:
space:
mode:
Diffstat (limited to 'mpm/python/usrp_mpm/periph_manager/e31x_periphs.py')
-rw-r--r--mpm/python/usrp_mpm/periph_manager/e31x_periphs.py166
1 files changed, 141 insertions, 25 deletions
diff --git a/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py b/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py
index 0b166e5bc..330cd830e 100644
--- a/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py
+++ b/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py
@@ -33,23 +33,40 @@ class MboardRegsControl(object):
Control the FPGA Motherboard registers
"""
# Motherboard registers
- MB_COMPAT_NUM = 0x0000
- MB_DATESTAMP = 0x0004
- MB_GIT_HASH = 0x0008
- MB_SCRATCH = 0x000C
- MB_NUM_CE = 0x0010
- MB_NUM_IO_CE = 0x0014
- MB_CLOCK_CTRL = 0x0018
- MB_XADC_RB = 0x001C
- MB_BUS_CLK_RATE = 0x0020
- MB_BUS_COUNTER = 0x0024
- MB_GPIO_MASTER = 0x0030
- MB_GPIO_RADIO_SRC = 0x0034
- MB_GPS_CTRL = 0x0038
- MB_GPS_STATUS = 0x003C
- MB_DBOARD_CTRL = 0x0040
- MB_DBOARD_STATUS = 0x0044
- MB_XBAR_BASEPORT = 0x0048
+ MB_COMPAT_NUM = 0x0000
+ MB_DATESTAMP = 0x0004
+ MB_GIT_HASH = 0x0008
+ MB_SCRATCH = 0x000C
+ MB_DEVICE_ID = 0x0010
+ MB_RFNOC_INFO = 0x0014
+ MB_CLOCK_CTRL = 0x0018
+ MB_XADC_RB = 0x001C
+ MB_BUS_CLK_RATE = 0x0020
+ MB_BUS_COUNTER = 0x0024
+ MB_SFP_PORT_INFO = 0x0028
+ MB_GPIO_CTRL = 0x002C
+ MB_GPIO_MASTER = 0x0030
+ MB_GPIO_RADIO_SRC = 0x0034
+ MB_GPS_CTRL = 0x0038
+ MB_GPS_STATUS = 0x003C
+ MB_DBOARD_CTRL = 0x0040
+ MB_DBOARD_STATUS = 0x0044
+ MB_NUM_TIMEKEEPERS = 0x0048
+ # Timekeeper registers
+ MB_TIME_NOW_LO = 0x1000
+ MB_TIME_NOW_HI = 0x1004
+ MB_TIME_EVENT_LO = 0x1008
+ MB_TIME_EVENT_HI = 0x100C
+ MB_TIME_CTRL = 0x1010
+ MB_TIME_LAST_PPS_LO = 0x1014
+ MB_TIME_LAST_PPS_HI = 0x1018
+ MB_TIME_BASE_PERIOD_LO = 0x101C
+ MB_TIME_BASE_PERIOD_HI = 0x1020
+ MB_TIMEKEEPER_OFFSET = 12
+
+ # Bitfield locations for the MB_RFNOC_INFO register.
+ MB_RFNOC_INFO_PROTO_VER = 0
+ MB_RFNOC_INFO_CHDR_WIDTH = 16
# Bitfield locations for the MB_CLOCK_CTRL register.
MB_CLOCK_CTRL_PPS_SEL_INT = 0
@@ -100,6 +117,26 @@ class MboardRegsControl(object):
major = (compat_number>>16) & 0xff
return (major, minor)
+ def get_proto_ver(self):
+ """
+ Return RFNoC protocol version
+ """
+ with self.regs:
+ reg_val = self.peek32(self.MB_RFNOC_INFO)
+ proto_ver = (reg_val & 0x0000ffff) >> self.MB_RFNOC_INFO_PROTO_VER
+ self.log.trace("Read RFNOC_PROTO_VER 0x{:08X}".format(proto_ver))
+ return proto_ver
+
+ def get_chdr_width(self):
+ """
+ Return RFNoC CHDR width
+ """
+ with self.regs:
+ reg_val = self.peek32(self.MB_RFNOC_INFO)
+ chdr_width = (reg_val & 0xffff0000) >> self.MB_RFNOC_INFO_CHDR_WIDTH
+ self.log.trace("Read RFNOC_CHDR_WIDTH 0x{:08X}".format(chdr_width))
+ return chdr_width
+
def set_fp_gpio_master(self, value):
"""set driver for front panel GPIO
Arguments:
@@ -136,6 +173,24 @@ class MboardRegsControl(object):
with self.regs:
return self.peek32(self.MB_GPIO_RADIO_SRC) & 0xffffff
+ def set_device_id(self, device_id):
+ """
+ Set device ID
+ """
+ with self.regs:
+ self.log.trace("Writing MB_DEVICE_ID with 0x{:08X}".format(device_id))
+ return self.poke32(self.MB_DEVICE_ID, device_id)
+
+ def get_device_id(self):
+ """
+ Get device ID
+ """
+ with self.regs:
+ regs_val = self.peek32(self.MB_DEVICE_ID)
+ device_id = regs_val & 0x0000ffff
+ self.log.trace("Read MB_DEVICE_ID 0x{:08X}".format(device_id))
+ return device_id
+
def get_build_timestamp(self):
"""
Returns the build date/time for the FPGA image.
@@ -206,6 +261,71 @@ class MboardRegsControl(object):
else:
assert False, "Cannot set to invalid clock source: {}".format(clock_source)
+ def get_num_timekeepers(self):
+ """
+ Return the number of timekeepers
+ """
+ with self.regs:
+ return self.peek32(self.MB_NUM_TIMEKEEPERS)
+
+ def get_timekeeper_time(self, tk_idx, last_pps):
+ """
+ Get the time in ticks
+
+ Arguments:
+ tk_idx: Index of timekeeper
+ next_pps: If True, get time at last PPS. Otherwise, get time now.
+ """
+ addr_lo = \
+ (self.MB_TIME_LAST_PPS_LO if last_pps else self.MB_TIME_NOW_LO) + \
+ tk_idx * self.MB_TIMEKEEPER_OFFSET
+ addr_hi = addr_lo + 4
+ with self.regs:
+ time_lo = self.peek32(addr_lo)
+ time_hi = self.peek32(addr_hi)
+ return time_hi << 32 | time_lo
+
+
+ def set_timekeeper_time(self, tk_idx, ticks, next_pps):
+ """
+ Set the time in ticks
+
+ Arguments:
+ tk_idx: Index of timekeeper
+ ticks: Time in ticks
+ next_pps: If True, set time at next PPS. Otherwise, set time now.
+ """
+ addr_lo = \
+ self.MB_TIME_EVENT_LO + tk_idx * self.MB_TIMEKEEPER_OFFSET
+ addr_hi = addr_lo + 4
+ addr_ctrl = \
+ self.MB_TIME_CTRL + tk_idx * self.MB_TIMEKEEPER_OFFSET
+ time_lo = ticks & 0xFFFFFFFF
+ time_hi = (ticks > 32) & 0xFFFFFFFF
+ time_ctrl = 0x2 if next_pps else 0x1
+ self.log.trace("Setting time on timekeeper %d to %d %s", tk_idx, ticks,
+ ("on next pps" if next_pps else "now"))
+ with self.regs:
+ self.poke32(addr_lo, time_lo)
+ self.poke32(addr_hi, time_hi)
+ self.poke32(addr_ctrl, time_ctrl)
+
+ def set_tick_period(self, tk_idx, period_ns):
+ """
+ Set the time per tick in nanoseconds (tick period)
+
+ Arguments:
+ tk_idx: Index of timekeeper
+ period_ns: Period in nanoseconds
+ """
+ addr_lo = self.MB_TIME_BASE_PERIOD_LO + tk_idx * self.MB_TIMEKEEPER_OFFSET
+ addr_hi = addr_lo + 4
+ period_lo = period_ns & 0xFFFFFFFF
+ period_hi = (period_ns > 32) & 0xFFFFFFFF
+ with self.regs:
+ self.poke32(addr_lo, period_lo)
+ self.poke32(addr_hi, period_hi)
+
def get_fpga_type(self):
"""
Reads the type of the FPGA image currently loaded
@@ -248,7 +368,8 @@ class MboardRegsControl(object):
reg_val = self.peek32(self.MB_DBOARD_CTRL)
if channel_mode == "MIMO":
reg_val = (0b1 << self.MB_DBOARD_CTRL_MIMO)
- self.log.trace("Setting channel mode in AD9361 interface: {}".format("2R2T" if channel_mode == 2 else "1R1T"))
+ self.log.trace("Setting channel mode in AD9361 interface: %s",
+ "2R2T" if channel_mode == 2 else "1R1T")
else:
# Warn if user tries to set either tx0/tx1 in mimo mode
# as both will be set automatically
@@ -269,7 +390,7 @@ class MboardRegsControl(object):
"""
mask = 0b1 << self.MB_DBOARD_STATUS_TX_LOCK
with self.regs:
- reg_val = self.peek32(self.MB_DBOARD_STATUS)
+ reg_val = self.peek32(self.MB_DBOARD_STATUS)
locked = (reg_val & mask) > 0
if not locked:
self.log.warning("TX RF PLL reporting unlocked. ")
@@ -283,15 +404,10 @@ class MboardRegsControl(object):
"""
mask = 0b1 << self.MB_DBOARD_STATUS_RX_LOCK
with self.regs:
- reg_val = self.peek32(self.MB_DBOARD_STATUS)
+ reg_val = self.peek32(self.MB_DBOARD_STATUS)
locked = (reg_val & mask) > 0
if not locked:
self.log.warning("RX RF PLL reporting unlocked. ")
else:
self.log.trace("RX RF PLL locked")
return locked
-
- def get_xbar_baseport(self):
- "Get the RFNoC crossbar base port"
- with self.regs:
- return self.peek32(self.MB_XBAR_BASEPORT)