diff options
Diffstat (limited to 'host/lib/usrp/x400/x400_gpio_control.cpp')
-rw-r--r-- | host/lib/usrp/x400/x400_gpio_control.cpp | 80 |
1 files changed, 69 insertions, 11 deletions
diff --git a/host/lib/usrp/x400/x400_gpio_control.cpp b/host/lib/usrp/x400/x400_gpio_control.cpp index b0eb4f27e..94b61f8c1 100644 --- a/host/lib/usrp/x400/x400_gpio_control.cpp +++ b/host/lib/usrp/x400/x400_gpio_control.cpp @@ -32,7 +32,7 @@ constexpr uint32_t DIO_DIRECTION_REG = 0x4; } // namespace gpio_regmap // There are two ports, each with 12 pins -constexpr size_t NUM_PORTS = 2; +constexpr size_t NUM_PORTS = 2; constexpr size_t NUM_PINS_PER_PORT = 12; // Start of Port B pin numbers relative to Port A: @@ -45,22 +45,24 @@ constexpr uint32_t PORTB_MAPPING[12] = {10, 11, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0}; const char* uhd::rfnoc::x400::GPIO_BANK_NAME = "GPIO"; -gpio_control::gpio_control( - uhd::usrp::x400_rpc_iface::sptr rpcc, uhd::wb_iface::sptr iface) - : _rpcc(rpcc), _regs(iface) +gpio_control::gpio_control(uhd::usrp::x400_rpc_iface::sptr rpcc, + uhd::rfnoc::mpmd_mb_controller::sptr mb_control, + uhd::wb_iface::sptr iface) + : _rpcc(rpcc), _mb_control(mb_control), _regs(iface) { _rpcc->dio_set_port_mapping("DIO"); _rpcc->dio_set_voltage_level("PORTA", "3V3"); _rpcc->dio_set_voltage_level("PORTB", "3V3"); - // Hardcode classic ATR (channels operate independently) - _regs->poke32(gpio_regmap::CLASSIC_MODE_OFFSET, 0x1); + // Hardcode new ATR (channel ATRs are combined into 4-bit index) + // Note that we emulate classic ATR + _regs->poke32(gpio_regmap::CLASSIC_MODE_OFFSET, 0x0); // Initialize everything as inputs _rpcc->dio_set_pin_directions("PORTA", 0x0); _rpcc->dio_set_pin_directions("PORTB", 0x0); - for (size_t bank = 0; bank < 2; bank++) { + for (size_t bank = 0; bank < 4; bank++) { const wb_iface::wb_addr_type atr_base = bank * gpio_regmap::ATR_STRIDE; usrp::gpio_atr::gpio_atr_offsets regmap{ atr_base + gpio_regmap::ATR_IDLE_OFFSET, @@ -85,13 +87,58 @@ void gpio_control::set_gpio_attr( _rpcc->dio_set_pin_directions("PORTB", value >> 12); } - const uint32_t internal_value = map_dio(value); - _gpios[0]->set_gpio_attr(attr, internal_value); if (is_atr_attr(attr)) { - _gpios[1]->set_gpio_attr(attr, internal_value); + const uint32_t rf1_mask = build_rf1_mask(); + + for (size_t i = 0; i < 4; i++) { + const uint32_t previous_value = unmap_dio(_gpios[i]->get_attr_reg(attr)); + const uint32_t new_value = (previous_value & rf1_mask) | (value & ~rf1_mask); + _gpios[i]->set_gpio_attr(attr, map_dio(new_value)); + } + + // Set the RF1 settings + for (const auto subattr : {uhd::usrp::gpio_atr::GPIO_ATR_0X, + uhd::usrp::gpio_atr::GPIO_ATR_RX, + uhd::usrp::gpio_atr::GPIO_ATR_TX, + uhd::usrp::gpio_atr::GPIO_ATR_XX}) { + const uint32_t previous_value = + unmap_dio(_gpios[atr_attr_index(attr)]->get_attr_reg(subattr)); + const uint32_t new_value = (previous_value & ~rf1_mask) | (value & rf1_mask); + _gpios[atr_attr_index(attr)]->set_gpio_attr(subattr, map_dio(new_value)); + } + } else { + const uint32_t internal_value = map_dio(value); + _gpios[0]->set_gpio_attr(attr, internal_value); } } +uint32_t gpio_control::build_rf1_mask() +{ + auto porta_sources = _mb_control->get_gpio_src("GPIO0"); + auto portb_sources = _mb_control->get_gpio_src("GPIO1"); + + uint32_t rf1_mask = 0; + for (size_t i = 0; i < 12; i++) { + if (porta_sources[i].find("RF1") != std::string::npos) { + rf1_mask |= 1 << i; + } + if (portb_sources[i].find("RF1") != std::string::npos) { + rf1_mask |= 1 << (i + 12); + } + } + + return rf1_mask; +} + +size_t gpio_control::atr_attr_index(const uhd::usrp::gpio_atr::gpio_attr_t attr) +{ + return attr == uhd::usrp::gpio_atr::GPIO_ATR_0X ? 0 + : attr == uhd::usrp::gpio_atr::GPIO_ATR_RX ? 1 + : attr == uhd::usrp::gpio_atr::GPIO_ATR_TX ? 2 + : attr == uhd::usrp::gpio_atr::GPIO_ATR_XX ? 3 + : 0; +} + bool gpio_control::is_atr_attr(const uhd::usrp::gpio_atr::gpio_attr_t attr) { return attr == uhd::usrp::gpio_atr::GPIO_ATR_0X @@ -136,6 +183,16 @@ uint32_t gpio_control::get_gpio_attr(const uhd::usrp::gpio_atr::gpio_attr_t attr return unmap_dio(raw_value); } + if (is_atr_attr(attr)) { + const uint32_t rf1_mask = build_rf1_mask(); + + // Grab the values for each channel + const uint32_t rf0_atr = unmap_dio(_gpios[0]->get_attr_reg(attr)); + const uint32_t rf1_atr = unmap_dio( + _gpios[atr_attr_index(attr)]->get_attr_reg(uhd::usrp::gpio_atr::GPIO_ATR_0X)); + return (rf0_atr & ~rf1_mask) | (rf1_atr & rf1_mask); + } + const uint32_t raw_value = _gpios[0]->get_attr_reg(attr); return unmap_dio(raw_value); } @@ -151,7 +208,8 @@ uint32_t uhd::rfnoc::x400::x400_gpio_port_mapping::map_value(const uint32_t& val } } throw uhd::lookup_error( - std::string("Could not find corresponding GPIO pin number for given SPI pin ") + std::to_string(value)); + std::string("Could not find corresponding GPIO pin number for given SPI pin ") + + std::to_string(value)); } uint32_t uhd::rfnoc::x400::x400_gpio_port_mapping::unmap_value(const uint32_t& value) |