diff options
| -rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_constants.hpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp | 132 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/periph_manager/n310.py | 79 | 
3 files changed, 205 insertions, 8 deletions
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp index 4df645c33..151e68220 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp @@ -12,7 +12,7 @@  #include <cstddef>  static constexpr size_t FPGPIO_MASTER_RADIO = 0; - +static constexpr size_t TOTAL_RADIO_PORTS = 4;  static constexpr double AD9371_RX_MIN_BANDWIDTH = 20.0e6;  // HZ  static constexpr double AD9371_RX_MAX_BANDWIDTH = 100.0e6; // HZ diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp index c781fbfe9..5b0eb60d1 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp @@ -13,7 +13,9 @@  #include <uhd/transport/chdr.hpp>  #include <vector>  #include <string> - +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/case_conv.hpp>  using namespace uhd;  using namespace uhd::rfnoc; @@ -37,6 +39,40 @@ namespace {      };  } +//! Helper function to extract single value of port number. +// +// Each GPIO pins can be controlled by each radio output ports. +// This function convert the format of attribute "Radio_N_M" +// to a single value port number = N*number_of_port_per_radio + M + +uint32_t  extract_port_number(std::string radio_src_string, uhd::property_tree::sptr ptree){ +    std::string s_val = "0"; +    std::vector<std::string> radio_strings; +    boost::algorithm::split( +        radio_strings, +        radio_src_string, +        boost::is_any_of("_/"), +        boost::token_compress_on); +    boost::to_lower(radio_strings[0]); +    if (radio_strings.size()<3) { +        throw uhd::runtime_error(str(boost::format("%s is an invalid GPIO source string.") % radio_src_string)); +    } +    size_t radio_num = std::stoi(radio_strings[1]); +    size_t port_num = std::stoi(radio_strings[2]); +    if (radio_strings[0] != "radio") { +        throw uhd::runtime_error("Front panel GPIO bank can only accept a radio block as its driver."); +    } +    std::string radio_port_out = "Radio_"+  radio_strings[1] + "/ports/out"; +    std::string radio_port_path = radio_port_out + "/"+ radio_strings[2]; +    auto found = ptree->exists(fs_path("xbar")/ radio_port_path); +    if (not found){ +        throw uhd::runtime_error(str(boost::format( +                    "Could not find radio port %s.\n") % radio_port_path)); +    } +    size_t port_size = ptree->list(fs_path("xbar")/ radio_port_out).size(); +    return radio_num*port_size + port_num; +} +  void magnesium_radio_ctrl_impl::_init_defaults()  {      UHD_LOG_TRACE(unique_id(), "Initializing defaults..."); @@ -190,11 +226,9 @@ void magnesium_radio_ctrl_impl::_init_peripherals()              usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL          );      } -    if (get_block_id().get_block_count() == FPGPIO_MASTER_RADIO) { -        UHD_LOG_TRACE(unique_id(), "Initializing front-panel GPIO control...") -        _fp_gpio = usrp::gpio_atr::gpio_atr_3000::make( -                _get_ctrl(0), regs::sr_addr(regs::FP_GPIO), regs::RB_FP_GPIO); -    } +    UHD_LOG_TRACE(unique_id(), "Initializing front-panel GPIO control...") +    _fp_gpio = usrp::gpio_atr::gpio_atr_3000::make( +            _get_ctrl(0), regs::sr_addr(regs::FP_GPIO), regs::RB_FP_GPIO);  }  void magnesium_radio_ctrl_impl::_init_frontend_subtree( @@ -739,8 +773,94 @@ void magnesium_radio_ctrl_impl::_init_prop_tree()              .set_publisher([this](){ return this->get_rate(); })          ;      } + +    // *****FP_GPIO************************ +    for(const auto& attr:  usrp::gpio_atr::gpio_attr_map) { +        if (not _tree->exists(fs_path("gpio") / "FP0" / attr.second)){ +            switch (attr.first){ +                case usrp::gpio_atr::GPIO_SRC: +                    //FIXME:  move this creation of this branch of ptree out side of radio impl; +                    // since there's no data dependency between radio and SRC setting for FP0 +                    _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) +                         .set(std::vector<std::string>( +                            32, +                            usrp::gpio_atr::default_attr_value_map.at(attr.first))) +                         .add_coerced_subscriber([this, attr]( +                            const std::vector<std::string> str_val){ +                            uint32_t radio_src_value = 0; +                            uint32_t master_value = 0; +                            for(size_t i = 0 ; i<str_val.size(); i++){ +                                if(str_val[i] == "PS"){ +                                    master_value += 1<<i;; +                                }else{ +                                    auto port_num = extract_port_number(str_val[i],_tree); +                                    radio_src_value =(1<<(2*i))*port_num + radio_src_value; +                                } +                            } +                            _rpcc->notify_with_token("set_fp_gpio_master", master_value); +                            _rpcc->notify_with_token("set_fp_gpio_radio_src", radio_src_value); +                         }); +                         break; +                case usrp::gpio_atr::GPIO_CTRL: +                case usrp::gpio_atr::GPIO_DDR: +                    _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) +                         .set(std::vector<std::string>( +                            32, +                            usrp::gpio_atr::default_attr_value_map.at(attr.first))) +                         .add_coerced_subscriber([this, attr]( +                             const std::vector<std::string> str_val){ +                            uint32_t val = 0; +                            for(size_t i = 0 ; i < str_val.size() ; i++){ +                                val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; +                            } +                            _fp_gpio->set_gpio_attr(attr.first, val); +                         }); +                    break; +                case usrp::gpio_atr::GPIO_READBACK:{ +                    _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) +                        .set_publisher([this](){ +                            return _fp_gpio->read_gpio(); +                        } +                    ); +                } +                    break; +                default: +                    _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) +                         .set(0) +                         .add_coerced_subscriber([this, attr](const uint32_t val){ +                             _fp_gpio->set_gpio_attr(attr.first, val); +                         }); +            } +        }else{ +            switch (attr.first){ +                case usrp::gpio_atr::GPIO_SRC: +                break; +                case usrp::gpio_atr::GPIO_CTRL: +                case usrp::gpio_atr::GPIO_DDR: +                    _tree->access<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) +                         .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) +                         .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){ +                            uint32_t val = 0; +                            for(size_t i = 0 ; i < str_val.size() ; i++){ +                                val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; +                            } +                            _fp_gpio->set_gpio_attr(attr.first, val); +                         }); +                    break; +                case usrp::gpio_atr::GPIO_READBACK: +                    break; +                default: +                    _tree->access<uint32_t>(fs_path("gpio") / "FP0" / attr.second) +                         .set(0) +                         .add_coerced_subscriber([this, attr](const uint32_t val){ +                             _fp_gpio->set_gpio_attr(attr.first, val); +                         }); +            } +        } +    }  } +  void magnesium_radio_ctrl_impl::_init_mpm_sensors(          const direction_t dir,          const size_t chan_idx diff --git a/mpm/python/usrp_mpm/periph_manager/n310.py b/mpm/python/usrp_mpm/periph_manager/n310.py index e51e4228d..beef6048c 100644 --- a/mpm/python/usrp_mpm/periph_manager/n310.py +++ b/mpm/python/usrp_mpm/periph_manager/n310.py @@ -33,7 +33,7 @@ N3XX_DEFAULT_CLOCK_SOURCE = 'internal'  N3XX_DEFAULT_TIME_SOURCE = 'internal'  N3XX_DEFAULT_ENABLE_GPS = True  N3XX_DEFAULT_ENABLE_FPGPIO = True -N3XX_FPGA_COMPAT = (5, 1) +N3XX_FPGA_COMPAT = (5, 2)  N3XX_MONITOR_THREAD_INTERVAL = 1.0 # seconds  N3XX_SFP_TYPES = {0:"", 1:"1G", 2:"10G", 3:"A"} @@ -185,6 +185,8 @@ class MboardRegsControl(object):      MB_BUS_COUNTER  = 0x0024      MB_SFP0_INFO    = 0x0028      MB_SFP1_INFO    = 0x002C +    MB_GPIO_MASTER  = 0x0030 +    MB_GPIO_RADIO_SRC  = 0x0034      # Bitfield locations for the MB_CLOCK_CTRL register.      MB_CLOCK_CTRL_PPS_SEL_INT_10 = 0 # pps_sel is one-hot encoded! @@ -217,6 +219,46 @@ class MboardRegsControl(object):          major = (compat_number>>16) & 0xff          return (major, minor) +    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 +        """ +        with self.regs.open(): +            return self.poke32(self.MB_GPIO_MASTER, value) + +    def get_fp_gpio_master(self): +        """get "who" is driving front panel gpio +           The return value is a bit mask of 12 pins GPIO. +           0: means the pin is driven by PL +           1: means the pin is driven by PS +        """ +        with self.regs.open(): +            return self.peek32(self.MB_GPIO_MASTER) & 0xfff + +    def set_fp_gpio_radio_src(self, value): +        """set driver for front panel GPIO +        Arguments: +            value {unsigned} -- value is 2-bit bit mask of 12 pins GPIO +           00: means the pin is driven by radio 0 +           01: means the pin is driven by radio 1 +           10: means the pin is driven by radio 2 +           11: means the pin is driven by radio 3 +        """ +        with self.regs.open(): +            return self.poke32(self.MB_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 12 pins GPIO. +           00: means the pin is driven by radio 0 +           01: means the pin is driven by radio 1 +           10: means the pin is driven by radio 2 +           11: means the pin is driven by radio 3 +        """ +        with self.regs.open(): +            return self.peek32(self.MB_GPIO_RADIO_SRC) & 0xffffff +      def get_build_timestamp(self):          """          Returns the build date/time for the FPGA image. @@ -840,6 +882,41 @@ class n310(PeriphManagerBase):          self.mboard_regs_control.set_time_source(              time_source, self.get_ref_clock_freq()) +    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 12 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 12 pins GPIO +           00: means the pin is driven by radio 0 +           01: means the pin is driven by radio 1 +           10: means the pin is driven by radio 2 +           11: means the pin is driven by radio 3 +        """ +        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 12 pins GPIO. +           00: means the pin is driven by radio 0 +           01: means the pin is driven by radio 1 +           10: means the pin is driven by radio 2 +           11: means the pin is driven by radio 3 +        """ +        return self.mboard_regs_control.get_fp_gpio_radio_src()      ###########################################################################      # Hardware periphal controls      ###########################################################################  | 
