diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-11-14 13:35:20 -0800 |
---|---|---|
committer | Brent Stapleton <brent.stapleton@ettus.com> | 2020-01-23 11:37:51 -0800 |
commit | 354886ed4cee82317f6ad45bc57a14af67cce85f (patch) | |
tree | 0bb7b1d99055676c28fd20f04f90dfbcd424ffae /mpm/python/usrp_mpm/periph_manager/e31x.py | |
parent | 90a72e8cd4cd1d4971c0e09d9813c9fc43371062 (diff) | |
download | uhd-354886ed4cee82317f6ad45bc57a14af67cce85f.tar.gz uhd-354886ed4cee82317f6ad45bc57a14af67cce85f.tar.bz2 uhd-354886ed4cee82317f6ad45bc57a14af67cce85f.zip |
mpm: e320/e310: Expose APIs to drive GPIO source via UHD
This enables the *gpio_src* APIs for the E320 and the E31x.
Diffstat (limited to 'mpm/python/usrp_mpm/periph_manager/e31x.py')
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/e31x.py | 98 |
1 files changed, 66 insertions, 32 deletions
diff --git a/mpm/python/usrp_mpm/periph_manager/e31x.py b/mpm/python/usrp_mpm/periph_manager/e31x.py index 355945de4..d2e22b498 100644 --- a/mpm/python/usrp_mpm/periph_manager/e31x.py +++ b/mpm/python/usrp_mpm/periph_manager/e31x.py @@ -33,6 +33,10 @@ E310_DEFAULT_ENABLE_FPGPIO = True E310_DEFAULT_DONT_RELOAD_FPGA = False # False means idle image gets reloaded E310_FPGA_COMPAT = (5, 0) E310_DBOARD_SLOT_IDX = 0 +E310_GPIO_SRC_PS = "PS" +# We use the index positions of RFA and RFB to map between name and radio index +E310_GPIO_SRCS = ("RFA", "RFB", E310_GPIO_SRC_PS) +E310_FPGPIO_WIDTH = 6 ############################################################################### # Transport managers @@ -565,40 +569,70 @@ class e31x(ZynqComponents, PeriphManagerBase): self.mboard_regs_control.set_time_source(time_source) ########################################################################### - # Hardware peripheral controls + # GPIO API ########################################################################### - def set_fp_gpio_master(self, value): - """set driver for front panel GPIO - Arguments: - value {unsigned} -- value is a single bit bit mask of 12 pins GPIO - """ - self.mboard_regs_control.set_fp_gpio_master(value) - - def get_fp_gpio_master(self): - """get "who" is driving front panel gpio - The return value is a bit mask of 8 pins GPIO. - 0: means the pin is driven by PL - 1: means the pin is driven by PS - """ - return self.mboard_regs_control.get_fp_gpio_master() - - def set_fp_gpio_radio_src(self, value): - """set driver for front panel GPIO - Arguments: - value {unsigned} -- value is 2-bit bit mask of 8 pins GPIO - 00: means the pin is driven by radio 0 - 01: means the pin is driven by radio 1 - """ - self.mboard_regs_control.set_fp_gpio_radio_src(value) - - def get_fp_gpio_radio_src(self): - """get which radio is driving front panel gpio - The return value is 2-bit bit mask of 8 pins GPIO. - 00: means the pin is driven by radio 0 - 01: means the pin is driven by radio 1 - """ - return self.mboard_regs_control.get_fp_gpio_radio_src() + def get_gpio_banks(self): + """ + Returns a list of GPIO banks over which MPM has any control + """ + return E310_GPIO_BANKS + + def get_gpio_srcs(self, bank): + """ + Return a list of valid GPIO sources for a given bank + """ + assert bank in self.get_gpio_banks(), "Invalid GPIO bank: {}".format(bank) + return self._fp_gpio_srcs + + def get_gpio_src(self, bank): + """ + Return the currently selected GPIO source for a given bank. The return + value is a list of strings. The length of the vector is identical to + the number of controllable GPIO pins on this bank. + """ + assert bank in self.get_gpio_banks(), "Invalid GPIO bank: {}".format(bank) + gpio_master_reg = self.mboard_regs_control.get_fp_gpio_master() + gpio_radio_src_reg = self.mboard_regs_control.get_fp_gpio_radio_src() + def get_gpio_src_i(gpio_pin_index): + """ + Return the current radio source given a pin index. + """ + if gpio_master_reg & (1 << gpio_pin_index): + return E310_GPIO_SRC_PS + radio_src = (gpio_radio_src_reg >> (2 * gpio_pin_index)) & 0b11 + assert radio_src in (0, 1) + return E310_GPIO_SRCS[radio_src] + return [get_gpio_src_i(i) for i in range(E310_FPGPIO_WIDTH)] + + def set_gpio_src(self, bank, src): + """ + Set the GPIO source for a given bank. + """ + assert bank in self.get_gpio_banks(), "Invalid GPIO bank: {}".format(bank) + assert len(src) == E310_FPGPIO_WIDTH, \ + "Invalid number of GPIO sources!" + gpio_master_reg = 0x00 + gpio_radio_src_reg = self.mboard_regs_control.get_fp_gpio_radio_src() + for src_index, src_name in enumerate(src): + if src_name not in self.get_gpio_srcs(bank): + raise RuntimeError( + "Invalid GPIO source name `{}' at bit position {}!" + .format(src_name, src_index)) + gpio_master_flag = (src_name == E310_GPIO_SRC_PS) + gpio_master_reg = gpio_master_reg | (gpio_master_flag << src_index) + if gpio_master_flag: + continue + # If PS is not the master, we also need to update the radio source: + radio_index = E310_GPIO_SRCS.index(src_name) + gpio_radio_src_reg = gpio_radio_src_reg | (radio_index << (2*src_index)) + self.log.trace("Updating GPIO source: master==0x{:02X} radio_src={:03X}" + .format(gpio_master_reg, gpio_radio_src_reg)) + self.mboard_regs_control.set_fp_gpio_master(gpio_master_reg) + self.mboard_regs_control.set_fp_gpio_radio_src(gpio_radio_src_reg) + ########################################################################### + # Hardware peripheral controls + ########################################################################### def set_channel_mode(self, channel_mode): "Set channel mode in FPGA and select which tx channel to use" self.mboard_regs_control.set_channel_mode(channel_mode) |