diff options
Diffstat (limited to 'mpm/python/usrp_mpm/periph_manager/e31x_periphs.py')
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/e31x_periphs.py | 166 |
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) |