From ee8e4f2c9b1bae8085dff6199c2bade0914748f7 Mon Sep 17 00:00:00 2001 From: Martin Anderseck Date: Wed, 15 Dec 2021 16:27:23 +0100 Subject: SPI: Implement SPI engine for x410 Add SPI Core host implementation for x410 and a discoverable feature to make it accessible. --- host/docs/x400_gpio_api.dox | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'host/docs/x400_gpio_api.dox') diff --git a/host/docs/x400_gpio_api.dox b/host/docs/x400_gpio_api.dox index 80c59cae7..592bff4ba 100644 --- a/host/docs/x400_gpio_api.dox +++ b/host/docs/x400_gpio_api.dox @@ -130,5 +130,68 @@ Valid values can be enumerated with the uhd::features::gpio_power_iface::supported_voltages() call, and are "1V8", "2V5", and "3V3". +\section x4x0_spi_iface The x4x0 SPI Mode + +The GPIO ports of the x4x0 can be used with the Serial Peripheral Interface (SPI) to control +external components. To use SPI mode, set the pins you need on the desired GPIO port to be +controlled by the SPI engine and configure the data direction. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} +auto usrp = uhd::usrp::multi_usrp::make(args); +auto& spi_getter_iface = + usrp->get_radio_control().get_feature(); +usrp->set_gpio_src("GPIO0", + {"DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI", + "DB0_SPI"}); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The example shows the usage of GPIO port 0 (GPIO0) for SPI and needs to be run for +GPIO1 again to use that port with SPI, too. + +\subsection x4x0_spi_cfg Configuration of SPI lines + +The x4x0 SPI mode supports up to 4 slaves. All of these slaves may have a different SPI pin +configuration. The pins available for the usage with SPI are listed in \ref x4x0gpio_fpanel_pins. +For GPIO0 the available pins are enumerated from 0 through 11, for GPIO1 the available pins are +from 12 through 23. +The vector of slave configurations is passed to the spi_iface_getter to get the reference: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + uhd::features::spi_slave_config_t slave_cfg; + slave_cfg.slave_clk = 0; + slave_cfg.slave_miso = 1; + slave_cfg.slave_mosi = 2; + slave_cfg.slave_ss = 3; + std::vector slave_cfgs; + slave_cfgs.push_back(slave_cfg); + auto spi_ref = spi_getter_iface.get_spi_ref(slave_cfgs); + + // Set data direction register (set all to outgoing except for MISO) + usrp->set_gpio_attr("GPIOA", "DDR", 0xD, 0xF); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +\subsection x4x0_spi_r_w Write and read on SPI + +With the SPI reference read and write operations can be performed. For doing this, +some characteristics of the SPI need to be configured: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + uhd::spi_config_t config; + config.divider = 4; + config.miso_edge = config.EDGE_RISE; + ... + spi_ref->write_spi(0, config, 0xFEFE, 32); + uint32_t read_data = spi_ref->read_spi(0, config, 0xFEFE, 32); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The SPI clock \f$SCLK\f$ is derived from the Radio clock and the SPI clock divider as follows: + +\f[SCLK = \frac{Radio\_Clk}{SPI\_CLK\_DIV + 1}\f] + */ // vim:ft=doxygen: -- cgit v1.2.3