From 275b29e07f97cdf638ecb22c602d26b7d340547a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 2 Apr 2010 17:54:06 -0700 Subject: some work on rfx board code --- host/lib/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'host/lib/CMakeLists.txt') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a5345cae4..a4bf46f1a 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -28,6 +28,7 @@ SET(libuhd_sources transport/udp_simple.cpp transport/vrt.cpp usrp/dboard/db_basic_and_lf.cpp + usrp/dboard/db_rfx.cpp usrp/dboard_base.cpp usrp/dboard_interface.cpp usrp/simple_usrp.cpp -- cgit v1.2.3 From b66a74ff1f629af714e26040b410d472c08be522 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Apr 2010 00:46:42 -0700 Subject: Reworked the spi part of the dboard interface. It turns out to be more complicated. The integer type is better for holding the bits. The edges can be different, so the spi config hold 2 edge setting for mosi and miso. --- firmware/microblaze/apps/txrx.c | 25 ++------ host/include/uhd/usrp/dboard_interface.hpp | 100 ++++++++++++++++------------- host/lib/CMakeLists.txt | 1 - host/lib/usrp/dboard/db_rfx.cpp | 16 ++--- host/lib/usrp/dboard_interface.cpp | 53 --------------- host/lib/usrp/usrp2/dboard_interface.cpp | 95 ++++++++++++++++----------- host/lib/usrp/usrp2/fw_common.h | 7 +- 7 files changed, 128 insertions(+), 169 deletions(-) delete mode 100644 host/lib/usrp/dboard_interface.cpp (limited to 'host/lib/CMakeLists.txt') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 69a04d771..561f3148f 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -253,29 +253,18 @@ void handle_udp_ctrl_packet( * SPI ******************************************************************/ case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:{ - uint8_t num_bytes = ctrl_data_in->data.spi_args.bytes; - - //load the data from the array of bytes - uint32_t data = 0x0; - for (size_t i = 0; i < num_bytes; i++){ - data = (data << 8) | ctrl_data_in->data.spi_args.data[i]; - } - //transact uint32_t result = spi_transact( (ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX, - ctrl_data_in->data.spi_args.dev, - data, num_bytes*8, //length in bits - (ctrl_data_in->data.spi_args.edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_RISE : SPIF_PUSH_FALL | - (ctrl_data_in->data.spi_args.edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL + ctrl_data_in->data.spi_args.dev, //which device + ctrl_data_in->data.spi_args.data, //32 bit data + ctrl_data_in->data.spi_args.num_bits, //length in bits + (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | + (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL ); - //load the result into the array of bytes - for (size_t i = 0; i < num_bytes; i++){ - uint8_t byte_shift = num_bytes - i - 1; - ctrl_data_out.data.spi_args.data[i] = (result >> (byte_shift*8)) & 0xff; - } - ctrl_data_out.data.spi_args.bytes = num_bytes; + //load output + ctrl_data_out.data.spi_args.data = result; ctrl_data_out.id = USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE; } break; diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index b3bab131d..dab5a2281 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -42,16 +42,31 @@ public: UNIT_TYPE_TX = 't' }; - //tells the host which device to use - enum spi_dev_t{ - SPI_DEV_RX = 'r', - SPI_DEV_TX = 't' - }; - - //args for spi format - enum spi_edge_t{ - SPI_EDGE_RISE = 'r', - SPI_EDGE_FALL = 'f' + //spi configuration struct + struct UHD_API spi_config_t{ + /*! + * The edge type specifies when data is valid + * relative to the edge of the serial clock. + */ + enum edge_t{ + EDGE_RISE = 'r', + EDGE_FALL = 'f' + }; + + //! on what edge is the mosi data valid? + edge_t mosi_edge; + + //! on what edge is the miso data valid? + edge_t miso_edge; + + /*! + * Create a new spi config. + * \param edge the default edge for mosi and miso + */ + spi_config_t(edge_t edge = EDGE_RISE){ + mosi_edge = edge; + miso_edge = edge; + } }; //tell the host which gpio bank @@ -68,10 +83,6 @@ public: ATR_REG_FULL_DUPLEX = 'f' }; - //structors - dboard_interface(void); - virtual ~dboard_interface(void); - /*! * Write to an aux dac. * \param unit which unit rx or tx @@ -131,61 +142,60 @@ public: /*! * \brief Write data to SPI bus peripheral. * - * \param dev which spi device - * \param edge args for format - * \param buf the data to write + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write LSB first + * \param num_bits the number of bits in data */ - void write_spi(spi_dev_t dev, spi_edge_t edge, const byte_vector_t &buf); + virtual void write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ) = 0; /*! * \brief Read data to SPI bus peripheral. * - * \param dev which spi device - * \param edge args for format - * \param num_bytes number of bytes to read + * \param unit which unit, rx or tx + * \param config configuration settings + * \param num_bits the number of bits * \return the data that was read */ - byte_vector_t read_spi(spi_dev_t dev, spi_edge_t edge, size_t num_bytes); + virtual boost::uint32_t read_spi( + unit_type_t unit, + const spi_config_t &config, + size_t num_bits + ) = 0; /*! * \brief Read and write data to SPI bus peripheral. * The data read back will be the same length as the input buffer. * - * \param dev which spi device - * \param edge args for format - * \param buf the data to write + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write LSB first + * \param num_bits the number of bits in data * \return the data that was read */ - byte_vector_t read_write_spi(spi_dev_t dev, spi_edge_t edge, const byte_vector_t &buf); + virtual boost::uint32_t read_write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ) = 0; /*! * \brief Get the rate of the rx dboard clock. - * \return the clock rate + * \return the clock rate in Hz */ virtual double get_rx_clock_rate(void) = 0; /*! * \brief Get the rate of the tx dboard clock. - * \return the clock rate + * \return the clock rate in Hz */ virtual double get_tx_clock_rate(void) = 0; - -private: - /*! - * \brief Read and write data to SPI bus peripheral. - * - * \param dev which spi device - * \param edge args for format - * \param buf the data to write - * \param readback false for write only - * \return the data that was read - */ - virtual byte_vector_t transact_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf, - bool readback - ) = 0; }; }} //namespace diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a4bf46f1a..f21a4a491 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -30,7 +30,6 @@ SET(libuhd_sources usrp/dboard/db_basic_and_lf.cpp usrp/dboard/db_rfx.cpp usrp/dboard_base.cpp - usrp/dboard_interface.cpp usrp/simple_usrp.cpp usrp/dboard_manager.cpp usrp/tune_helper.cpp diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 57ea03da5..68fa51144 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -136,17 +136,11 @@ void rfx_xcvr::reload_adf4360_regs(void){ (adf4360_regs_t::ADDR_RCOUNTER) ; BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ - boost::uint32_t reg = _adf4360_regs.get_reg(addr); - dboard_interface::byte_vector_t spi_bytes = list_of - ((reg >> 16) & 0xff) - ((reg >> 8) & 0xff) - ((reg >> 0) & 0xff) - ; - //this->get_interface.write_spi( - // dboard_interface::SPI_DEV_TX, - // dboard_interface::SPI_EDGE_FALL, - // spi_bytes - //); + this->get_interface()->write_spi( + dboard_interface::UNIT_TYPE_TX, + dboard_interface::spi_config_t::EDGE_RISE, + _adf4360_regs.get_reg(addr), 24 + ); } } diff --git a/host/lib/usrp/dboard_interface.cpp b/host/lib/usrp/dboard_interface.cpp deleted file mode 100644 index c40c9b398..000000000 --- a/host/lib/usrp/dboard_interface.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include - -using namespace uhd::usrp; - -dboard_interface::dboard_interface(void){ - /* NOP */ -} - -dboard_interface::~dboard_interface(void){ - /* NOP */ -} - -void dboard_interface::write_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf -){ - transact_spi(dev, edge, buf, false); //dont readback -} - -dboard_interface::byte_vector_t dboard_interface::read_spi( - spi_dev_t dev, - spi_edge_t edge, - size_t num_bytes -){ - byte_vector_t buf(num_bytes, 0x00); //dummy data - return transact_spi(dev, edge, buf, true); //readback -} - -dboard_interface::byte_vector_t dboard_interface::read_write_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf -){ - return transact_spi(dev, edge, buf, true); //readback -} diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index 6dd756420..eee7c087a 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -42,9 +42,35 @@ public: double get_rx_clock_rate(void); double get_tx_clock_rate(void); + void write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ){ + transact_spi(unit, config, data, num_bits, false /*no rb*/); + } + + boost::uint32_t read_spi( + unit_type_t unit, + const spi_config_t &config, + size_t num_bits + ){ + return transact_spi(unit, config, 0, num_bits, true /*rb*/); + } + + boost::uint32_t read_write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ){ + return transact_spi(unit, config, data, num_bits, true /*rb*/); + } + private: - byte_vector_t transact_spi( - spi_dev_t, spi_edge_t, const byte_vector_t &, bool + boost::uint32_t transact_spi( + unit_type_t, const spi_config_t &, boost::uint32_t, size_t, bool ); usrp2_impl *_impl; @@ -136,17 +162,17 @@ void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost: * SPI **********************************************************************/ /*! - * Static function to convert a spi dev enum - * to an over-the-wire value for the usrp2 control. - * \param dev the dboard interface spi dev enum + * Static function to convert a unit type enum + * to an over-the-wire value for the spi device. + * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ - switch(dev){ - case uhd::usrp::dboard_interface::SPI_DEV_TX: return SPI_SS_TX_DB; - case uhd::usrp::dboard_interface::SPI_DEV_RX: return SPI_SS_RX_DB; +static boost::uint8_t unit_to_otw_dev(dboard_interface::unit_type_t unit){ + switch(unit){ + case dboard_interface::UNIT_TYPE_TX: return SPI_SS_TX_DB; + case dboard_interface::UNIT_TYPE_RX: return SPI_SS_RX_DB; } - throw std::invalid_argument("unknown spi device type"); + throw std::invalid_argument("unknown unit type type"); } /*! @@ -155,43 +181,36 @@ static boost::uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ * \param edge the dboard interface spi edge enum * \return an over the wire representation */ -static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_edge_t edge){ +static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_config_t::edge_t edge){ switch(edge){ - case uhd::usrp::dboard_interface::SPI_EDGE_RISE: return USRP2_CLK_EDGE_RISE; - case uhd::usrp::dboard_interface::SPI_EDGE_FALL: return USRP2_CLK_EDGE_FALL; + case dboard_interface::spi_config_t::EDGE_RISE: return USRP2_CLK_EDGE_RISE; + case dboard_interface::spi_config_t::EDGE_FALL: return USRP2_CLK_EDGE_FALL; } throw std::invalid_argument("unknown spi edge type"); } -dboard_interface::byte_vector_t usrp2_dboard_interface::transact_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf, +boost::uint32_t usrp2_dboard_interface::transact_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits, bool readback ){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); - out_data.data.spi_args.dev = spi_dev_to_otw(dev); - out_data.data.spi_args.edge = spi_edge_to_otw(edge); + out_data.data.spi_args.dev = unit_to_otw_dev(unit); + out_data.data.spi_args.miso_edge = spi_edge_to_otw(config.miso_edge); + out_data.data.spi_args.mosi_edge = spi_edge_to_otw(config.mosi_edge); out_data.data.spi_args.readback = (readback)? 1 : 0; - out_data.data.spi_args.bytes = buf.size(); - - //limitation of spi transaction size - ASSERT_THROW(buf.size() <= sizeof(out_data.data.spi_args.data)); - - //copy in the data - std::copy(buf.begin(), buf.end(), out_data.data.spi_args.data); + out_data.data.spi_args.num_bits = num_bits; + out_data.data.spi_args.data = htonl(data); //send and recv usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); - ASSERT_THROW(in_data.data.spi_args.bytes == buf.size()); - //copy out the data - byte_vector_t result(buf.size()); - std::copy(in_data.data.spi_args.data, in_data.data.spi_args.data + buf.size(), result.begin()); - return result; + return ntohl(out_data.data.spi_args.data); } /*********************************************************************** @@ -245,19 +264,19 @@ dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, s * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t spi_dev_to_otw(dboard_interface::unit_type_t unit){ +static boost::uint8_t unit_to_otw(dboard_interface::unit_type_t unit){ switch(unit){ - case uhd::usrp::dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; - case uhd::usrp::dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; + case dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; + case dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; } throw std::invalid_argument("unknown unit type type"); } -void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, int which, int value){ +void usrp2_dboard_interface::write_aux_dac(unit_type_t unit, int which, int value){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO); - out_data.data.aux_args.dir = spi_dev_to_otw(unit); + out_data.data.aux_args.dir = unit_to_otw(unit); out_data.data.aux_args.which = which; out_data.data.aux_args.value = htonl(value); @@ -266,11 +285,11 @@ void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, i ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); } -int usrp2_dboard_interface::read_aux_adc(dboard_interface::unit_type_t unit, int which){ +int usrp2_dboard_interface::read_aux_adc(unit_type_t unit, int which){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO); - out_data.data.aux_args.dir = spi_dev_to_otw(unit); + out_data.data.aux_args.dir = unit_to_otw(unit); out_data.data.aux_args.which = which; //send and recv diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 019f3b931..b600a2a70 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -110,10 +110,11 @@ typedef struct{ } dboard_ids; struct { _SINS_ uint8_t dev; - _SINS_ uint8_t edge; + _SINS_ uint8_t miso_edge; + _SINS_ uint8_t mosi_edge; _SINS_ uint8_t readback; - _SINS_ uint8_t bytes; - _SINS_ uint8_t data[sizeof(_SINS_ uint32_t)]; + _SINS_ uint32_t data; + _SINS_ uint8_t num_bits; } spi_args; struct { _SINS_ uint8_t addr; -- cgit v1.2.3 From fdd80e548dcda3e4ee0c022d7d04b5ba581c5ad9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 9 Apr 2010 08:13:19 -0700 Subject: added python+cheetah build requirement, generating vrt.cpp --- host/CMakeLists.txt | 20 +- host/lib/CMakeLists.txt | 46 +++- host/lib/transport/gen_vrt.py | 3 +- host/lib/transport/vrt.cpp | 549 ------------------------------------------ 4 files changed, 57 insertions(+), 561 deletions(-) delete mode 100644 host/lib/transport/vrt.cpp (limited to 'host/lib/CMakeLists.txt') diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index baae90861..6334b44ff 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -25,8 +25,8 @@ ENABLE_TESTING() SET(CPACK_PACKAGE_VERSION_MAJOR 0) SET(CPACK_PACKAGE_VERSION_MINOR 0) SET(CPACK_PACKAGE_VERSION_PATCH 0) -SET(CPACK_RESOURCE_FILE_README ${CMAKE_SOURCE_DIR}/README) -SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE) +SET(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README) +SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) INCLUDE(CPack) #include after setting vars ######################################################################## @@ -42,18 +42,18 @@ MESSAGE(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") ######################################################################## # Local Include Dir ######################################################################## -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) ######################################################################## # Optional Compiler Flags ######################################################################## INCLUDE(CheckCXXCompilerFlag) -FUNCTION(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG flag have) +MACRO(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG flag have) CHECK_CXX_COMPILER_FLAG(${flag} ${have}) IF(${have}) ADD_DEFINITIONS(${flag}) ENDIF(${have}) -ENDFUNCTION(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG) +ENDMACRO(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG) IF(UNIX) UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-Wall HAVE_WALL) @@ -114,7 +114,7 @@ ADD_CUSTOM_TARGET(uninstall # Create Pkg Config File ######################################################################## CONFIGURE_FILE( - ${CMAKE_SOURCE_DIR}/uhd.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/uhd.pc.in ${CMAKE_CURRENT_BINARY_DIR}/uhd.pc @ONLY) @@ -131,7 +131,7 @@ INCLUDE(FindDoxygen) IF(DOXYGEN_FOUND) SET(CMAKE_CURRENT_BINARY_DIR_DOXYGEN ${CMAKE_CURRENT_BINARY_DIR}/doxygen) CONFIGURE_FILE( - ${CMAKE_SOURCE_DIR}/Doxyfile.in + ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR_DOXYGEN} @@ -143,9 +143,9 @@ IF(DOXYGEN_FOUND) ENDIF(DOXYGEN_FOUND) INSTALL(FILES - ${CMAKE_SOURCE_DIR}/README - ${CMAKE_SOURCE_DIR}/LICENSE - ${CMAKE_SOURCE_DIR}/AUTHORS + ${CMAKE_CURRENT_SOURCE_DIR}/README + ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE + ${CMAKE_CURRENT_SOURCE_DIR}/AUTHORS DESTINATION ${PKG_DOC_DIR} ) diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index f21a4a491..87e35f412 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -15,6 +15,33 @@ # along with this program. If not, see . # + +######################################################################## +# Setup Python +######################################################################## +INCLUDE(FindPythonInterp) + +MACRO(PYTHON_CHECK_MODULE module have) + MESSAGE(STATUS "Checking for python module ${module}") + EXECUTE_PROCESS( + COMMAND ${PYTHON_EXECUTABLE} -c "import ${module}" + RESULT_VARIABLE ${have} + ) + IF(${have} EQUAL 0) + MESSAGE(STATUS "Checking for python module ${module} - found") + SET(${have} TRUE) + ELSE(${have} EQUAL 0) + MESSAGE(STATUS "Checking for python module ${module} - not found") + SET(${have} FALSE) + ENDIF(${have} EQUAL 0) +ENDMACRO(PYTHON_CHECK_MODULE) + +PYTHON_CHECK_MODULE("Cheetah" HAVE_PYTHON_MODULE_CHEETAH) + +IF(NOT HAVE_PYTHON_MODULE_CHEETAH) + MESSAGE(FATAL_ERROR "Error: Cheetah Templates needed for pre-build generation.") +ENDIF(NOT HAVE_PYTHON_MODULE_CHEETAH) + ######################################################################## # Create a list of libuhd sources ######################################################################## @@ -26,7 +53,6 @@ SET(libuhd_sources wax.cpp transport/if_addrs.cpp transport/udp_simple.cpp - transport/vrt.cpp usrp/dboard/db_basic_and_lf.cpp usrp/dboard/db_rfx.cpp usrp/dboard_base.cpp @@ -41,6 +67,24 @@ SET(libuhd_sources usrp/usrp2/usrp2_impl.cpp ) +######################################################################## +# Generate Files +######################################################################## +MACRO(UHD_PYTHON_GEN_FILE pyfile outfile) + ADD_CUSTOM_COMMAND( + OUTPUT ${outfile} DEPENDS ${pyfile} + COMMAND ${PYTHON_EXECUTABLE} ${pyfile} ${outfile} + COMMENT "Calling ${pyfile} to generate ${outfile}" + ) +ENDMACRO(UHD_PYTHON_GEN_FILE) +UHD_PYTHON_GEN_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/transport/gen_vrt.py + ${CMAKE_CURRENT_BINARY_DIR}/transport/vrt.cpp +) +LIST(APPEND libuhd_sources + ${CMAKE_CURRENT_BINARY_DIR}/transport/vrt.cpp +) + ######################################################################## # Conditionally add the udp sources ######################################################################## diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py index bc6635d78..0f961efc2 100755 --- a/host/lib/transport/gen_vrt.py +++ b/host/lib/transport/gen_vrt.py @@ -200,9 +200,10 @@ void vrt::unpack( } """ +import sys from Cheetah import Template def parse_str(_tmpl_text, **kwargs): return str(Template.Template(_tmpl_text, kwargs)) if __name__ == '__main__': from Cheetah import Template - print parse_str(TMPL_TEXT, file=__file__) + open(sys.argv[1], 'w').write(parse_str(TMPL_TEXT, file=__file__)) diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp deleted file mode 100644 index 78c3cf2cb..000000000 --- a/host/lib/transport/vrt.cpp +++ /dev/null @@ -1,549 +0,0 @@ - - - -/*********************************************************************** - * This file was generated by gen_vrt.py on 04/08/10 10:55:26 - **********************************************************************/ - -#include -#include //endianness conversion -#include - -using namespace uhd; -using namespace uhd::transport; - -void vrt::pack( - const tx_metadata_t &metadata, //input - boost::uint32_t *header_buff, //output - size_t &num_header_words32, //output - size_t num_payload_words32, //input - size_t &num_packet_words32, //output - size_t packet_count, //input - double tick_rate //input -){ - boost::uint32_t vrt_hdr_flags; - - boost::uint8_t pred = 0; - if (metadata.has_stream_id) pred |= 0x1; - if (metadata.has_time_spec) pred |= 0xc; - - switch(pred){ - case 0: - num_header_words32 = 1; - num_packet_words32 = 1 + num_payload_words32; - vrt_hdr_flags = 0x0; - break; - case 1: - header_buff[1] = htonl(metadata.stream_id); - num_header_words32 = 2; - num_packet_words32 = 2 + num_payload_words32; - vrt_hdr_flags = 0x10000000; - break; - case 2: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - num_header_words32 = 3; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x8000000; - break; - case 3: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - num_header_words32 = 4; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x18000000; - break; - case 4: - header_buff[1] = htonl(metadata.time_spec.secs); - num_header_words32 = 2; - num_packet_words32 = 2 + num_payload_words32; - vrt_hdr_flags = 0xc00000; - break; - case 5: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(metadata.time_spec.secs); - num_header_words32 = 3; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x10c00000; - break; - case 6: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.secs); - num_header_words32 = 4; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x8c00000; - break; - case 7: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.secs); - num_header_words32 = 5; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x18c00000; - break; - case 8: - header_buff[1] = htonl(0); - header_buff[2] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 3; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x100000; - break; - case 9: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 4; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x10100000; - break; - case 10: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 5; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x8100000; - break; - case 11: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 6; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0x18100000; - break; - case 12: - header_buff[1] = htonl(metadata.time_spec.secs); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 4; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0xd00000; - break; - case 13: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(metadata.time_spec.secs); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 5; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x10d00000; - break; - case 14: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.secs); - header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 6; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0x8d00000; - break; - case 15: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.secs); - header_buff[5] = htonl(0); - header_buff[6] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 7; - num_packet_words32 = 7 + num_payload_words32; - vrt_hdr_flags = 0x18d00000; - break; - case 16: - num_header_words32 = 1; - num_packet_words32 = 2 + num_payload_words32; - vrt_hdr_flags = 0x4000000; - break; - case 17: - header_buff[1] = htonl(metadata.stream_id); - num_header_words32 = 2; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x14000000; - break; - case 18: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - num_header_words32 = 3; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0xc000000; - break; - case 19: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - num_header_words32 = 4; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x1c000000; - break; - case 20: - header_buff[1] = htonl(metadata.time_spec.secs); - num_header_words32 = 2; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x4c00000; - break; - case 21: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(metadata.time_spec.secs); - num_header_words32 = 3; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x14c00000; - break; - case 22: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.secs); - num_header_words32 = 4; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0xcc00000; - break; - case 23: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.secs); - num_header_words32 = 5; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0x1cc00000; - break; - case 24: - header_buff[1] = htonl(0); - header_buff[2] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 3; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x4100000; - break; - case 25: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 4; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x14100000; - break; - case 26: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 5; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0xc100000; - break; - case 27: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 6; - num_packet_words32 = 7 + num_payload_words32; - vrt_hdr_flags = 0x1c100000; - break; - case 28: - header_buff[1] = htonl(metadata.time_spec.secs); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 4; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x4d00000; - break; - case 29: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(metadata.time_spec.secs); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 5; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0x14d00000; - break; - case 30: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.secs); - header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 6; - num_packet_words32 = 7 + num_payload_words32; - vrt_hdr_flags = 0xcd00000; - break; - case 31: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.secs); - header_buff[5] = htonl(0); - header_buff[6] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 7; - num_packet_words32 = 8 + num_payload_words32; - vrt_hdr_flags = 0x1cd00000; - break; - } - - //set the burst flags - if (metadata.start_of_burst) vrt_hdr_flags |= 0x2000000; - if (metadata.end_of_burst) vrt_hdr_flags |= 0x1000000; - - //fill in complete header word - header_buff[0] = htonl(vrt_hdr_flags | - ((packet_count & 0xf) << 16) | - (num_packet_words32 & 0xffff) - ); -} - -void vrt::unpack( - rx_metadata_t &metadata, //output - const boost::uint32_t *header_buff, //input - size_t &num_header_words32, //output - size_t &num_payload_words32, //output - size_t num_packet_words32, //input - size_t &packet_count, //output - double tick_rate //input -){ - //clear the metadata - metadata = rx_metadata_t(); - - //extract vrt header - boost::uint32_t vrt_hdr_word = ntohl(header_buff[0]); - size_t packet_words32 = vrt_hdr_word & 0xffff; - packet_count = (vrt_hdr_word >> 16) & 0xf; - - //failure cases - if (packet_words32 == 0 or num_packet_words32 < packet_words32) - throw std::runtime_error("bad vrt header or packet fragment"); - if (vrt_hdr_word & (0x7 << 29)) - throw std::runtime_error("unsupported vrt packet type"); - - boost::uint8_t pred = 0; - if(vrt_hdr_word & 0x10000000) pred |= 0x1; - if(vrt_hdr_word & 0x8000000) pred |= 0x2; - if(vrt_hdr_word & 0xc00000) pred |= 0x4; - if(vrt_hdr_word & 0x300000) pred |= 0x8; - if(vrt_hdr_word & 0x4000000) pred |= 0x10; - - switch(pred){ - case 0: - num_header_words32 = 1; - num_payload_words32 = packet_words32 - 1; - break; - case 1: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - num_header_words32 = 2; - num_payload_words32 = packet_words32 - 2; - break; - case 2: - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 3; - break; - case 3: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 4; - break; - case 4: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[1]); - num_header_words32 = 2; - num_payload_words32 = packet_words32 - 2; - break; - case 5: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[2]); - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 3; - break; - case 6: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[3]); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 4; - break; - case 7: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[4]); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 5; - break; - case 8: - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[2]), tick_rate); - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 3; - break; - case 9: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 4; - break; - case 10: - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 5; - break; - case 11: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); - num_header_words32 = 6; - num_payload_words32 = packet_words32 - 6; - break; - case 12: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[1]); - metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 4; - break; - case 13: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[2]); - metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 5; - break; - case 14: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[3]); - metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); - num_header_words32 = 6; - num_payload_words32 = packet_words32 - 6; - break; - case 15: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[4]); - metadata.time_spec.set_ticks(ntohl(header_buff[6]), tick_rate); - num_header_words32 = 7; - num_payload_words32 = packet_words32 - 7; - break; - case 16: - num_header_words32 = 1; - num_payload_words32 = packet_words32 - 2; - break; - case 17: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - num_header_words32 = 2; - num_payload_words32 = packet_words32 - 3; - break; - case 18: - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 4; - break; - case 19: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 5; - break; - case 20: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[1]); - num_header_words32 = 2; - num_payload_words32 = packet_words32 - 3; - break; - case 21: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[2]); - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 4; - break; - case 22: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[3]); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 5; - break; - case 23: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[4]); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 6; - break; - case 24: - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[2]), tick_rate); - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 4; - break; - case 25: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 5; - break; - case 26: - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 6; - break; - case 27: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); - num_header_words32 = 6; - num_payload_words32 = packet_words32 - 7; - break; - case 28: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[1]); - metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 5; - break; - case 29: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[2]); - metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 6; - break; - case 30: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[3]); - metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); - num_header_words32 = 6; - num_payload_words32 = packet_words32 - 7; - break; - case 31: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[4]); - metadata.time_spec.set_ticks(ntohl(header_buff[6]), tick_rate); - num_header_words32 = 7; - num_payload_words32 = packet_words32 - 8; - break; - } -} - -- cgit v1.2.3 From 01cb9070c7b136d44d3de36d102d302d2f2de55f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 9 Apr 2010 14:01:10 -0700 Subject: generate the register file, added lib include dir --- host/lib/CMakeLists.txt | 22 +++- host/lib/include/gen_adf4360_regs.py | 169 ++++++++++++++++++++++++++++ host/lib/usrp/dboard/adf4360_regs.hpp | 185 ------------------------------- host/lib/usrp/dboard/gen_adf4360_regs.py | 168 ---------------------------- 4 files changed, 186 insertions(+), 358 deletions(-) create mode 100755 host/lib/include/gen_adf4360_regs.py delete mode 100644 host/lib/usrp/dboard/adf4360_regs.hpp delete mode 100755 host/lib/usrp/dboard/gen_adf4360_regs.py (limited to 'host/lib/CMakeLists.txt') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 87e35f412..dc4986f8c 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -16,6 +16,14 @@ # +######################################################################## +# Library Includes (not part of API) +######################################################################## +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include #generated includes +) + ######################################################################## # Setup Python ######################################################################## @@ -70,19 +78,23 @@ SET(libuhd_sources ######################################################################## # Generate Files ######################################################################## -MACRO(UHD_PYTHON_GEN_FILE pyfile outfile) +MACRO(UHD_PYTHON_GEN_SOURCE_FILE pyfile outfile) ADD_CUSTOM_COMMAND( OUTPUT ${outfile} DEPENDS ${pyfile} COMMAND ${PYTHON_EXECUTABLE} ${pyfile} ${outfile} COMMENT "Calling ${pyfile} to generate ${outfile}" ) -ENDMACRO(UHD_PYTHON_GEN_FILE) -UHD_PYTHON_GEN_FILE( + LIST(APPEND libuhd_sources ${outfile}) +ENDMACRO(UHD_PYTHON_GEN_SOURCE_FILE) + +UHD_PYTHON_GEN_SOURCE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/transport/gen_vrt.py ${CMAKE_CURRENT_BINARY_DIR}/transport/vrt.cpp ) -LIST(APPEND libuhd_sources - ${CMAKE_CURRENT_BINARY_DIR}/transport/vrt.cpp + +UHD_PYTHON_GEN_SOURCE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/include/gen_adf4360_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/include/adf4360_regs.hpp ) ######################################################################## diff --git a/host/lib/include/gen_adf4360_regs.py b/host/lib/include/gen_adf4360_regs.py new file mode 100755 index 000000000..702c3060f --- /dev/null +++ b/host/lib/include/gen_adf4360_regs.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright 2008,2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either asversion 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +import re +import sys +from Cheetah.Template import Template +def parse_tmpl(_tmpl_text, **kwargs): + return str(Template(_tmpl_text, kwargs)) + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_DATA_TMPL="""\ +######################################################################## +## address 0 +######################################################################## +core_power_level 0[2:3] 0 5ma, 10ma, 15ma, 20ma +counter_reset 0[4] 0 normal, reset +muxout_control 0[5:7] 0 3state, dld, ndiv, dvdd, rdiv, nchan_od_ld, sdo, dgnd +phase_detector_polarity 0[8] 0 neg, pos +cp_three_state 0[9] 0 normal, 3state +cp_gain_0 0[10] 0 set1, set2 +mute_till_ld 0[11] 0 dis, enb +output_power_level 0[12:13] 0 3_5ma, 5_0ma, 7_5ma, 11_0ma +#set $current_setting_enums = "0_31, 0_62, 0_93, 1_25, 1_56, 1_87, 2_18, 2_50" +current_setting1 0[14:16] 0 $current_setting_enums +current_setting2 0[17:19] 0 $current_setting_enums +power_down 0[20:21] 0 normal_op=0, async_pd=1, sync_pd=3 +prescaler_value 0[22:23] 0 8_9, 16_17, 32_33 +######################################################################## +## address 2 +######################################################################## +a_counter 2[2:6] 0 +b_counter 2[8:20] 0 +cp_gain_1 2[21] 0 set1, set2 +divide_by_2_output 2[22] 0 fund, div2 +divide_by_2_prescaler 2[23] 0 fund, div2 +######################################################################## +## address 1 +######################################################################## +r_counter 1[2:15] 0 +ablpw 1[16:17] 0 3_0ns, 1_3ns, 6_0ns +lock_detect_precision 1[18] 0 3cycles, 5cycles +test_mode_bit 1[19] 0 +band_select_clock_div 1[20:21] 0 1, 2, 4, 8 +""" + +######################################################################## +# Header and Source templates below +######################################################################## +HEADER_TEXT=""" +#import time + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#ifndef INCLUDED_ADF4360_REGS_HPP +\#define INCLUDED_ADF4360_REGS_HPP + +\#include + +struct adf4360_regs_t{ +#for $reg in $regs + #if $reg.get_enums() + enum $(reg.get_name())_t{ + #for $i, $enum in enumerate($reg.get_enums()) + #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' + $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma + #end for + } $reg.get_name(); + #else + boost::$reg.get_stdint_type() $reg.get_name(); + #end if +#end for + + adf4360_regs_t(void){ +#for $reg in $regs + $reg.get_name() = $reg.get_default(); +#end for + } + + enum addr_t{ + ADDR_CONTROL = 0, + ADDR_NCOUNTER = 2, + ADDR_RCOUNTER = 1 + }; + + boost::uint32_t get_reg(addr_t addr){ + boost::uint32_t reg = addr & 0x3; + switch(addr){ + #for $addr in (0, 1, 2) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return reg; + } +}; + +\#endif /* INCLUDED_ADF4360_REGS_HPP */ +""" + +class reg: + def __init__(self, reg_des): + x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des) + name, addr, bit_range, default, enums = x.groups() + + #store variables + self._name = name + self._addr = int(addr) + if ':' in bit_range: self._addr_spec = map(int, bit_range.split(':')) + else: self._addr_spec = int(bit_range), int(bit_range) + self._default = int(default) + + #extract enum + self._enums = list() + if enums: + enum_val = 0 + for enum_str in map(str.strip, enums.split(',')): + if '=' in enum_str: + enum_name, enum_val = enum_str.split('=') + enum_val = int(enum_val) + else: enum_name = enum_str + self._enums.append((enum_name, enum_val)) + enum_val += 1 + + def get_addr(self): return self._addr + def get_enums(self): return self._enums + def get_name(self): return self._name + def get_default(self): + for key, val in self.get_enums(): + if val == self._default: return str.upper('%s_%s'%(self.get_name(), key)) + return self._default + def get_stdint_type(self): + if self.get_bit_width() <= 8: return 'uint8_t' + if self.get_bit_width() <= 16: return 'uint16_t' + if self.get_bit_width() <= 32: return 'uint32_t' + if self.get_bit_width() <= 64: return 'uint64_t' + raise Exception, 'too damn big' + def get_shift(self): return self._addr_spec[0] + def get_mask(self): return hex(int('1'*self.get_bit_width(), 2)) + def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1 + +if __name__ == '__main__': + regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) + open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__)) diff --git a/host/lib/usrp/dboard/adf4360_regs.hpp b/host/lib/usrp/dboard/adf4360_regs.hpp deleted file mode 100644 index 309ff50e9..000000000 --- a/host/lib/usrp/dboard/adf4360_regs.hpp +++ /dev/null @@ -1,185 +0,0 @@ - - -/*********************************************************************** - * This file was generated by gen_adf4360_regs.py on Tue Apr 6 18:40:51 2010 - **********************************************************************/ - -#ifndef INCLUDED_ADF4360_REGS_HPP -#define INCLUDED_ADF4360_REGS_HPP - -#include - -struct adf4360_regs_t{ - enum core_power_level_t{ - CORE_POWER_LEVEL_5MA = 0, - CORE_POWER_LEVEL_10MA = 1, - CORE_POWER_LEVEL_15MA = 2, - CORE_POWER_LEVEL_20MA = 3 - } core_power_level; - enum counter_reset_t{ - COUNTER_RESET_NORMAL = 0, - COUNTER_RESET_RESET = 1 - } counter_reset; - enum muxout_control_t{ - MUXOUT_CONTROL_3STATE = 0, - MUXOUT_CONTROL_DLD = 1, - MUXOUT_CONTROL_NDIV = 2, - MUXOUT_CONTROL_DVDD = 3, - MUXOUT_CONTROL_RDIV = 4, - MUXOUT_CONTROL_NCHAN_OD_LD = 5, - MUXOUT_CONTROL_SDO = 6, - MUXOUT_CONTROL_DGND = 7 - } muxout_control; - enum phase_detector_polarity_t{ - PHASE_DETECTOR_POLARITY_NEG = 0, - PHASE_DETECTOR_POLARITY_POS = 1 - } phase_detector_polarity; - enum cp_three_state_t{ - CP_THREE_STATE_NORMAL = 0, - CP_THREE_STATE_3STATE = 1 - } cp_three_state; - enum cp_gain_0_t{ - CP_GAIN_0_SET1 = 0, - CP_GAIN_0_SET2 = 1 - } cp_gain_0; - enum mute_till_ld_t{ - MUTE_TILL_LD_DIS = 0, - MUTE_TILL_LD_ENB = 1 - } mute_till_ld; - enum output_power_level_t{ - OUTPUT_POWER_LEVEL_3_5MA = 0, - OUTPUT_POWER_LEVEL_5_0MA = 1, - OUTPUT_POWER_LEVEL_7_5MA = 2, - OUTPUT_POWER_LEVEL_11_0MA = 3 - } output_power_level; - enum current_setting1_t{ - CURRENT_SETTING1_0_31 = 0, - CURRENT_SETTING1_0_62 = 1, - CURRENT_SETTING1_0_93 = 2, - CURRENT_SETTING1_1_25 = 3, - CURRENT_SETTING1_1_56 = 4, - CURRENT_SETTING1_1_87 = 5, - CURRENT_SETTING1_2_18 = 6, - CURRENT_SETTING1_2_50 = 7 - } current_setting1; - enum current_setting2_t{ - CURRENT_SETTING2_0_31 = 0, - CURRENT_SETTING2_0_62 = 1, - CURRENT_SETTING2_0_93 = 2, - CURRENT_SETTING2_1_25 = 3, - CURRENT_SETTING2_1_56 = 4, - CURRENT_SETTING2_1_87 = 5, - CURRENT_SETTING2_2_18 = 6, - CURRENT_SETTING2_2_50 = 7 - } current_setting2; - enum power_down_t{ - POWER_DOWN_NORMAL_OP = 0, - POWER_DOWN_ASYNC_PD = 1, - POWER_DOWN_SYNC_PD = 3 - } power_down; - enum prescaler_value_t{ - PRESCALER_VALUE_8_9 = 0, - PRESCALER_VALUE_16_17 = 1, - PRESCALER_VALUE_32_33 = 2 - } prescaler_value; - boost::uint8_t a_counter; - boost::uint16_t b_counter; - enum cp_gain_1_t{ - CP_GAIN_1_SET1 = 0, - CP_GAIN_1_SET2 = 1 - } cp_gain_1; - enum divide_by_2_output_t{ - DIVIDE_BY_2_OUTPUT_FUND = 0, - DIVIDE_BY_2_OUTPUT_DIV2 = 1 - } divide_by_2_output; - enum divide_by_2_prescaler_t{ - DIVIDE_BY_2_PRESCALER_FUND = 0, - DIVIDE_BY_2_PRESCALER_DIV2 = 1 - } divide_by_2_prescaler; - boost::uint16_t r_counter; - enum ablpw_t{ - ABLPW_3_0NS = 0, - ABLPW_1_3NS = 1, - ABLPW_6_0NS = 2 - } ablpw; - enum lock_detect_precision_t{ - LOCK_DETECT_PRECISION_3CYCLES = 0, - LOCK_DETECT_PRECISION_5CYCLES = 1 - } lock_detect_precision; - boost::uint8_t test_mode_bit; - enum band_select_clock_div_t{ - BAND_SELECT_CLOCK_DIV_1 = 0, - BAND_SELECT_CLOCK_DIV_2 = 1, - BAND_SELECT_CLOCK_DIV_4 = 2, - BAND_SELECT_CLOCK_DIV_8 = 3 - } band_select_clock_div; - - adf4360_regs_t(void){ - core_power_level = CORE_POWER_LEVEL_5MA; - counter_reset = COUNTER_RESET_NORMAL; - muxout_control = MUXOUT_CONTROL_3STATE; - phase_detector_polarity = PHASE_DETECTOR_POLARITY_NEG; - cp_three_state = CP_THREE_STATE_NORMAL; - cp_gain_0 = CP_GAIN_0_SET1; - mute_till_ld = MUTE_TILL_LD_DIS; - output_power_level = OUTPUT_POWER_LEVEL_3_5MA; - current_setting1 = CURRENT_SETTING1_0_31; - current_setting2 = CURRENT_SETTING2_0_31; - power_down = POWER_DOWN_NORMAL_OP; - prescaler_value = PRESCALER_VALUE_8_9; - a_counter = 0; - b_counter = 0; - cp_gain_1 = CP_GAIN_1_SET1; - divide_by_2_output = DIVIDE_BY_2_OUTPUT_FUND; - divide_by_2_prescaler = DIVIDE_BY_2_PRESCALER_FUND; - r_counter = 0; - ablpw = ABLPW_3_0NS; - lock_detect_precision = LOCK_DETECT_PRECISION_3CYCLES; - test_mode_bit = 0; - band_select_clock_div = BAND_SELECT_CLOCK_DIV_1; - } - - enum addr_t{ - ADDR_CONTROL = 0, - ADDR_NCOUNTER = 2, - ADDR_RCOUNTER = 1 - }; - - boost::uint32_t get_reg(addr_t addr){ - boost::uint32_t reg = addr & 0x3; - switch(addr){ - case 0: - reg |= (boost::uint32_t(core_power_level) & 0x3) << 2; - reg |= (boost::uint32_t(counter_reset) & 0x1) << 4; - reg |= (boost::uint32_t(muxout_control) & 0x7) << 5; - reg |= (boost::uint32_t(phase_detector_polarity) & 0x1) << 8; - reg |= (boost::uint32_t(cp_three_state) & 0x1) << 9; - reg |= (boost::uint32_t(cp_gain_0) & 0x1) << 10; - reg |= (boost::uint32_t(mute_till_ld) & 0x1) << 11; - reg |= (boost::uint32_t(output_power_level) & 0x3) << 12; - reg |= (boost::uint32_t(current_setting1) & 0x7) << 14; - reg |= (boost::uint32_t(current_setting2) & 0x7) << 17; - reg |= (boost::uint32_t(power_down) & 0x3) << 20; - reg |= (boost::uint32_t(prescaler_value) & 0x3) << 22; - break; - case 1: - reg |= (boost::uint32_t(r_counter) & 0x3fff) << 2; - reg |= (boost::uint32_t(ablpw) & 0x3) << 16; - reg |= (boost::uint32_t(lock_detect_precision) & 0x1) << 18; - reg |= (boost::uint32_t(test_mode_bit) & 0x1) << 19; - reg |= (boost::uint32_t(band_select_clock_div) & 0x3) << 20; - break; - case 2: - reg |= (boost::uint32_t(a_counter) & 0x1f) << 2; - reg |= (boost::uint32_t(b_counter) & 0x1fff) << 8; - reg |= (boost::uint32_t(cp_gain_1) & 0x1) << 21; - reg |= (boost::uint32_t(divide_by_2_output) & 0x1) << 22; - reg |= (boost::uint32_t(divide_by_2_prescaler) & 0x1) << 23; - break; - } - return reg; - } -}; - -#endif /* INCLUDED_ADF4360_REGS_HPP */ - diff --git a/host/lib/usrp/dboard/gen_adf4360_regs.py b/host/lib/usrp/dboard/gen_adf4360_regs.py deleted file mode 100755 index f16e59e2a..000000000 --- a/host/lib/usrp/dboard/gen_adf4360_regs.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008,2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either asversion 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -import re -from Cheetah.Template import Template -def parse_tmpl(_tmpl_text, **kwargs): - return str(Template(_tmpl_text, kwargs)) - -######################################################################## -# Template for raw text data describing registers -# name addr[bit range inclusive] default optional enums -######################################################################## -REGS_DATA_TMPL="""\ -######################################################################## -## address 0 -######################################################################## -core_power_level 0[2:3] 0 5ma, 10ma, 15ma, 20ma -counter_reset 0[4] 0 normal, reset -muxout_control 0[5:7] 0 3state, dld, ndiv, dvdd, rdiv, nchan_od_ld, sdo, dgnd -phase_detector_polarity 0[8] 0 neg, pos -cp_three_state 0[9] 0 normal, 3state -cp_gain_0 0[10] 0 set1, set2 -mute_till_ld 0[11] 0 dis, enb -output_power_level 0[12:13] 0 3_5ma, 5_0ma, 7_5ma, 11_0ma -#set $current_setting_enums = "0_31, 0_62, 0_93, 1_25, 1_56, 1_87, 2_18, 2_50" -current_setting1 0[14:16] 0 $current_setting_enums -current_setting2 0[17:19] 0 $current_setting_enums -power_down 0[20:21] 0 normal_op=0, async_pd=1, sync_pd=3 -prescaler_value 0[22:23] 0 8_9, 16_17, 32_33 -######################################################################## -## address 2 -######################################################################## -a_counter 2[2:6] 0 -b_counter 2[8:20] 0 -cp_gain_1 2[21] 0 set1, set2 -divide_by_2_output 2[22] 0 fund, div2 -divide_by_2_prescaler 2[23] 0 fund, div2 -######################################################################## -## address 1 -######################################################################## -r_counter 1[2:15] 0 -ablpw 1[16:17] 0 3_0ns, 1_3ns, 6_0ns -lock_detect_precision 1[18] 0 3cycles, 5cycles -test_mode_bit 1[19] 0 -band_select_clock_div 1[20:21] 0 1, 2, 4, 8 -""" - -######################################################################## -# Header and Source templates below -######################################################################## -HEADER_TEXT=""" -#import time - -/*********************************************************************** - * This file was generated by $file on $time.strftime("%c") - **********************************************************************/ - -\#ifndef INCLUDED_ADF4360_REGS_HPP -\#define INCLUDED_ADF4360_REGS_HPP - -\#include - -struct adf4360_regs_t{ -#for $reg in $regs - #if $reg.get_enums() - enum $(reg.get_name())_t{ - #for $i, $enum in enumerate($reg.get_enums()) - #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' - $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma - #end for - } $reg.get_name(); - #else - boost::$reg.get_stdint_type() $reg.get_name(); - #end if -#end for - - adf4360_regs_t(void){ -#for $reg in $regs - $reg.get_name() = $reg.get_default(); -#end for - } - - enum addr_t{ - ADDR_CONTROL = 0, - ADDR_NCOUNTER = 2, - ADDR_RCOUNTER = 1 - }; - - boost::uint32_t get_reg(addr_t addr){ - boost::uint32_t reg = addr & 0x3; - switch(addr){ - #for $addr in (0, 1, 2) - case $addr: - #for $reg in filter(lambda r: r.get_addr() == addr, $regs) - reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); - #end for - break; - #end for - } - return reg; - } -}; - -\#endif /* INCLUDED_ADF4360_REGS_HPP */ -""" - -class reg: - def __init__(self, reg_des): - x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des) - name, addr, bit_range, default, enums = x.groups() - - #store variables - self._name = name - self._addr = int(addr) - if ':' in bit_range: self._addr_spec = map(int, bit_range.split(':')) - else: self._addr_spec = int(bit_range), int(bit_range) - self._default = int(default) - - #extract enum - self._enums = list() - if enums: - enum_val = 0 - for enum_str in map(str.strip, enums.split(',')): - if '=' in enum_str: - enum_name, enum_val = enum_str.split('=') - enum_val = int(enum_val) - else: enum_name = enum_str - self._enums.append((enum_name, enum_val)) - enum_val += 1 - - def get_addr(self): return self._addr - def get_enums(self): return self._enums - def get_name(self): return self._name - def get_default(self): - for key, val in self.get_enums(): - if val == self._default: return str.upper('%s_%s'%(self.get_name(), key)) - return self._default - def get_stdint_type(self): - if self.get_bit_width() <= 8: return 'uint8_t' - if self.get_bit_width() <= 16: return 'uint16_t' - if self.get_bit_width() <= 32: return 'uint32_t' - if self.get_bit_width() <= 64: return 'uint64_t' - raise Exception, 'too damn big' - def get_shift(self): return self._addr_spec[0] - def get_mask(self): return hex(int('1'*self.get_bit_width(), 2)) - def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1 - -if __name__ == '__main__': - regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) - print parse_tmpl(HEADER_TEXT, regs=regs, file=__file__) -- cgit v1.2.3 From fa96b25b99dbd19ac0689cab9bcab84063287ad3 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 10 Apr 2010 07:20:16 -0700 Subject: moved regs generator to ic reg maps folder, others will go there as well --- host/lib/CMakeLists.txt | 14 +-- host/lib/ic_reg_maps/gen_adf4360_regs.py | 169 +++++++++++++++++++++++++++++++ host/lib/include/gen_adf4360_regs.py | 169 ------------------------------- 3 files changed, 173 insertions(+), 179 deletions(-) create mode 100755 host/lib/ic_reg_maps/gen_adf4360_regs.py delete mode 100755 host/lib/include/gen_adf4360_regs.py (limited to 'host/lib/CMakeLists.txt') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index dc4986f8c..58afe099d 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -16,14 +16,6 @@ # -######################################################################## -# Library Includes (not part of API) -######################################################################## -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_BINARY_DIR}/include #generated includes -) - ######################################################################## # Setup Python ######################################################################## @@ -92,9 +84,11 @@ UHD_PYTHON_GEN_SOURCE_FILE( ${CMAKE_CURRENT_BINARY_DIR}/transport/vrt.cpp ) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps) + UHD_PYTHON_GEN_SOURCE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/include/gen_adf4360_regs.py - ${CMAKE_CURRENT_BINARY_DIR}/include/adf4360_regs.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_adf4360_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/adf4360_regs.hpp ) ######################################################################## diff --git a/host/lib/ic_reg_maps/gen_adf4360_regs.py b/host/lib/ic_reg_maps/gen_adf4360_regs.py new file mode 100755 index 000000000..702c3060f --- /dev/null +++ b/host/lib/ic_reg_maps/gen_adf4360_regs.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright 2008,2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either asversion 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +import re +import sys +from Cheetah.Template import Template +def parse_tmpl(_tmpl_text, **kwargs): + return str(Template(_tmpl_text, kwargs)) + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_DATA_TMPL="""\ +######################################################################## +## address 0 +######################################################################## +core_power_level 0[2:3] 0 5ma, 10ma, 15ma, 20ma +counter_reset 0[4] 0 normal, reset +muxout_control 0[5:7] 0 3state, dld, ndiv, dvdd, rdiv, nchan_od_ld, sdo, dgnd +phase_detector_polarity 0[8] 0 neg, pos +cp_three_state 0[9] 0 normal, 3state +cp_gain_0 0[10] 0 set1, set2 +mute_till_ld 0[11] 0 dis, enb +output_power_level 0[12:13] 0 3_5ma, 5_0ma, 7_5ma, 11_0ma +#set $current_setting_enums = "0_31, 0_62, 0_93, 1_25, 1_56, 1_87, 2_18, 2_50" +current_setting1 0[14:16] 0 $current_setting_enums +current_setting2 0[17:19] 0 $current_setting_enums +power_down 0[20:21] 0 normal_op=0, async_pd=1, sync_pd=3 +prescaler_value 0[22:23] 0 8_9, 16_17, 32_33 +######################################################################## +## address 2 +######################################################################## +a_counter 2[2:6] 0 +b_counter 2[8:20] 0 +cp_gain_1 2[21] 0 set1, set2 +divide_by_2_output 2[22] 0 fund, div2 +divide_by_2_prescaler 2[23] 0 fund, div2 +######################################################################## +## address 1 +######################################################################## +r_counter 1[2:15] 0 +ablpw 1[16:17] 0 3_0ns, 1_3ns, 6_0ns +lock_detect_precision 1[18] 0 3cycles, 5cycles +test_mode_bit 1[19] 0 +band_select_clock_div 1[20:21] 0 1, 2, 4, 8 +""" + +######################################################################## +# Header and Source templates below +######################################################################## +HEADER_TEXT=""" +#import time + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#ifndef INCLUDED_ADF4360_REGS_HPP +\#define INCLUDED_ADF4360_REGS_HPP + +\#include + +struct adf4360_regs_t{ +#for $reg in $regs + #if $reg.get_enums() + enum $(reg.get_name())_t{ + #for $i, $enum in enumerate($reg.get_enums()) + #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' + $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma + #end for + } $reg.get_name(); + #else + boost::$reg.get_stdint_type() $reg.get_name(); + #end if +#end for + + adf4360_regs_t(void){ +#for $reg in $regs + $reg.get_name() = $reg.get_default(); +#end for + } + + enum addr_t{ + ADDR_CONTROL = 0, + ADDR_NCOUNTER = 2, + ADDR_RCOUNTER = 1 + }; + + boost::uint32_t get_reg(addr_t addr){ + boost::uint32_t reg = addr & 0x3; + switch(addr){ + #for $addr in (0, 1, 2) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return reg; + } +}; + +\#endif /* INCLUDED_ADF4360_REGS_HPP */ +""" + +class reg: + def __init__(self, reg_des): + x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des) + name, addr, bit_range, default, enums = x.groups() + + #store variables + self._name = name + self._addr = int(addr) + if ':' in bit_range: self._addr_spec = map(int, bit_range.split(':')) + else: self._addr_spec = int(bit_range), int(bit_range) + self._default = int(default) + + #extract enum + self._enums = list() + if enums: + enum_val = 0 + for enum_str in map(str.strip, enums.split(',')): + if '=' in enum_str: + enum_name, enum_val = enum_str.split('=') + enum_val = int(enum_val) + else: enum_name = enum_str + self._enums.append((enum_name, enum_val)) + enum_val += 1 + + def get_addr(self): return self._addr + def get_enums(self): return self._enums + def get_name(self): return self._name + def get_default(self): + for key, val in self.get_enums(): + if val == self._default: return str.upper('%s_%s'%(self.get_name(), key)) + return self._default + def get_stdint_type(self): + if self.get_bit_width() <= 8: return 'uint8_t' + if self.get_bit_width() <= 16: return 'uint16_t' + if self.get_bit_width() <= 32: return 'uint32_t' + if self.get_bit_width() <= 64: return 'uint64_t' + raise Exception, 'too damn big' + def get_shift(self): return self._addr_spec[0] + def get_mask(self): return hex(int('1'*self.get_bit_width(), 2)) + def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1 + +if __name__ == '__main__': + regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) + open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__)) diff --git a/host/lib/include/gen_adf4360_regs.py b/host/lib/include/gen_adf4360_regs.py deleted file mode 100755 index 702c3060f..000000000 --- a/host/lib/include/gen_adf4360_regs.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008,2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either asversion 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -import re -import sys -from Cheetah.Template import Template -def parse_tmpl(_tmpl_text, **kwargs): - return str(Template(_tmpl_text, kwargs)) - -######################################################################## -# Template for raw text data describing registers -# name addr[bit range inclusive] default optional enums -######################################################################## -REGS_DATA_TMPL="""\ -######################################################################## -## address 0 -######################################################################## -core_power_level 0[2:3] 0 5ma, 10ma, 15ma, 20ma -counter_reset 0[4] 0 normal, reset -muxout_control 0[5:7] 0 3state, dld, ndiv, dvdd, rdiv, nchan_od_ld, sdo, dgnd -phase_detector_polarity 0[8] 0 neg, pos -cp_three_state 0[9] 0 normal, 3state -cp_gain_0 0[10] 0 set1, set2 -mute_till_ld 0[11] 0 dis, enb -output_power_level 0[12:13] 0 3_5ma, 5_0ma, 7_5ma, 11_0ma -#set $current_setting_enums = "0_31, 0_62, 0_93, 1_25, 1_56, 1_87, 2_18, 2_50" -current_setting1 0[14:16] 0 $current_setting_enums -current_setting2 0[17:19] 0 $current_setting_enums -power_down 0[20:21] 0 normal_op=0, async_pd=1, sync_pd=3 -prescaler_value 0[22:23] 0 8_9, 16_17, 32_33 -######################################################################## -## address 2 -######################################################################## -a_counter 2[2:6] 0 -b_counter 2[8:20] 0 -cp_gain_1 2[21] 0 set1, set2 -divide_by_2_output 2[22] 0 fund, div2 -divide_by_2_prescaler 2[23] 0 fund, div2 -######################################################################## -## address 1 -######################################################################## -r_counter 1[2:15] 0 -ablpw 1[16:17] 0 3_0ns, 1_3ns, 6_0ns -lock_detect_precision 1[18] 0 3cycles, 5cycles -test_mode_bit 1[19] 0 -band_select_clock_div 1[20:21] 0 1, 2, 4, 8 -""" - -######################################################################## -# Header and Source templates below -######################################################################## -HEADER_TEXT=""" -#import time - -/*********************************************************************** - * This file was generated by $file on $time.strftime("%c") - **********************************************************************/ - -\#ifndef INCLUDED_ADF4360_REGS_HPP -\#define INCLUDED_ADF4360_REGS_HPP - -\#include - -struct adf4360_regs_t{ -#for $reg in $regs - #if $reg.get_enums() - enum $(reg.get_name())_t{ - #for $i, $enum in enumerate($reg.get_enums()) - #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' - $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma - #end for - } $reg.get_name(); - #else - boost::$reg.get_stdint_type() $reg.get_name(); - #end if -#end for - - adf4360_regs_t(void){ -#for $reg in $regs - $reg.get_name() = $reg.get_default(); -#end for - } - - enum addr_t{ - ADDR_CONTROL = 0, - ADDR_NCOUNTER = 2, - ADDR_RCOUNTER = 1 - }; - - boost::uint32_t get_reg(addr_t addr){ - boost::uint32_t reg = addr & 0x3; - switch(addr){ - #for $addr in (0, 1, 2) - case $addr: - #for $reg in filter(lambda r: r.get_addr() == addr, $regs) - reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); - #end for - break; - #end for - } - return reg; - } -}; - -\#endif /* INCLUDED_ADF4360_REGS_HPP */ -""" - -class reg: - def __init__(self, reg_des): - x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des) - name, addr, bit_range, default, enums = x.groups() - - #store variables - self._name = name - self._addr = int(addr) - if ':' in bit_range: self._addr_spec = map(int, bit_range.split(':')) - else: self._addr_spec = int(bit_range), int(bit_range) - self._default = int(default) - - #extract enum - self._enums = list() - if enums: - enum_val = 0 - for enum_str in map(str.strip, enums.split(',')): - if '=' in enum_str: - enum_name, enum_val = enum_str.split('=') - enum_val = int(enum_val) - else: enum_name = enum_str - self._enums.append((enum_name, enum_val)) - enum_val += 1 - - def get_addr(self): return self._addr - def get_enums(self): return self._enums - def get_name(self): return self._name - def get_default(self): - for key, val in self.get_enums(): - if val == self._default: return str.upper('%s_%s'%(self.get_name(), key)) - return self._default - def get_stdint_type(self): - if self.get_bit_width() <= 8: return 'uint8_t' - if self.get_bit_width() <= 16: return 'uint16_t' - if self.get_bit_width() <= 32: return 'uint32_t' - if self.get_bit_width() <= 64: return 'uint64_t' - raise Exception, 'too damn big' - def get_shift(self): return self._addr_spec[0] - def get_mask(self): return hex(int('1'*self.get_bit_width(), 2)) - def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1 - -if __name__ == '__main__': - regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) - open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__)) -- cgit v1.2.3 From e611e610f64b473cdd9d0aa5e40690d7550c3cc0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 13:39:09 -0700 Subject: Added data type conversion routines to transport api. --- host/include/uhd/transport/CMakeLists.txt | 1 + host/include/uhd/transport/convert_types.hpp | 59 +++++++++++ host/include/uhd/transport/vrt.hpp | 2 +- host/lib/CMakeLists.txt | 1 + host/lib/transport/convert_types.cpp | 144 +++++++++++++++++++++++++++ host/lib/transport/udp_zero_copy_asio.cpp | 11 +- host/lib/usrp/usrp2/io_impl.cpp | 128 ++++-------------------- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 + 8 files changed, 236 insertions(+), 112 deletions(-) create mode 100644 host/include/uhd/transport/convert_types.hpp create mode 100644 host/lib/transport/convert_types.cpp (limited to 'host/lib/CMakeLists.txt') diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 9a94ead1b..4cefffa24 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -17,6 +17,7 @@ INSTALL(FILES + convert_types.hpp if_addrs.hpp udp_simple.hpp udp_zero_copy.hpp diff --git a/host/include/uhd/transport/convert_types.hpp b/host/include/uhd/transport/convert_types.hpp new file mode 100644 index 000000000..a4d999240 --- /dev/null +++ b/host/include/uhd/transport/convert_types.hpp @@ -0,0 +1,59 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP +#define INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP + +#include +#include +#include + +namespace uhd{ namespace transport{ + +/*! + * Convert IO samples to OWT samples. + * + * \param io_buff memory containing samples + * \param io_type the type of these samples + * \param otw_buff memory to write converted samples + * \param otw_type the type of these samples + * \param num_samps the number of samples in io_buff + */ +UHD_API void convert_io_type_to_otw_type( + const void *io_buff, const io_type_t &io_type, + void *otw_buff, const otw_type_t &otw_type, + size_t num_samps +); + +/*! + * Convert OTW samples to IO samples. + * + * \param otw_buff memory containing samples + * \param otw_type the type of these samples + * \param io_buff memory to write converted samples + * \param io_type the type of these samples + * \param num_samps the number of samples in io_buff + */ +UHD_API void convert_otw_type_to_io_type( + const void *otw_buff, const otw_type_t &otw_type, + void *io_buff, const io_type_t &io_type, + size_t num_samps +); + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP */ diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp index 04945b347..c30a73489 100644 --- a/host/include/uhd/transport/vrt.hpp +++ b/host/include/uhd/transport/vrt.hpp @@ -26,7 +26,7 @@ namespace uhd{ namespace transport{ namespace vrt{ - static const size_t max_header_words32 = 7; + static const size_t max_header_words32 = 5; //hdr+sid+tsi+tsf (no class id supported) /*! * Pack a vrt header from metadata. diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a5345cae4..fac1bd19f 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -24,6 +24,7 @@ SET(libuhd_sources load_modules.cpp types.cpp wax.cpp + transport/convert_types.cpp transport/if_addrs.cpp transport/udp_simple.cpp transport/vrt.cpp diff --git a/host/lib/transport/convert_types.cpp b/host/lib/transport/convert_types.cpp new file mode 100644 index 000000000..2a6854f50 --- /dev/null +++ b/host/lib/transport/convert_types.cpp @@ -0,0 +1,144 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include //endianness conversion +#include + +using namespace uhd; + +/*********************************************************************** + * Constants + **********************************************************************/ +typedef std::complex fc32_t; + +static const float shorts_per_float = float(1 << 15); +static const float floats_per_short = float(1.0/shorts_per_float); + +#define unrolled_loop(__inst, __len){ \ + size_t __i = 0; \ + for(; __i < (__len & ~0x3); __i+= 4){ \ + __inst(__i+0); __inst(__i+1); \ + __inst(__i+2); __inst(__i+3); \ + } \ + for(; __i < __len; __i++){ \ + __inst(__i); \ + } \ +} + +// set a boolean flag that indicates the endianess +#ifdef HAVE_BIG_ENDIAN +static const bool is_big_endian = true; +#else +static const bool is_big_endian = false; +#endif + +static inline void host_floats_to_usrp2_items( + boost::uint32_t *usrp2_items, + const fc32_t *host_floats, + size_t num_samps +){ + #define host_floats_to_usrp2_items_i(i){ \ + boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); \ + boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); \ + usrp2_items[i] = htonl((real << 16) | (imag << 0)); \ + } + unrolled_loop(host_floats_to_usrp2_items_i, num_samps); +} + +static inline void usrp2_items_to_host_floats( + fc32_t *host_floats, + const boost::uint32_t *usrp2_items, + size_t num_samps +){ + #define usrp2_items_to_host_floats_i(i){ \ + boost::uint32_t item = ntohl(usrp2_items[i]); \ + boost::int16_t real = boost::uint16_t(item >> 16); \ + boost::int16_t imag = boost::uint16_t(item >> 0); \ + host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); \ + } + unrolled_loop(usrp2_items_to_host_floats_i, num_samps); +} + +static inline void host_items_to_usrp2_items( + boost::uint32_t *usrp2_items, + const boost::uint32_t *host_items, + size_t num_samps +){ + #define host_items_to_usrp2_items_i(i) usrp2_items[i] = htonl(host_items[i]) + if (is_big_endian){ + std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t)); + } + else{ + unrolled_loop(host_items_to_usrp2_items_i, num_samps); + } +} + +static inline void usrp2_items_to_host_items( + boost::uint32_t *host_items, + const boost::uint32_t *usrp2_items, + size_t num_samps +){ + #define usrp2_items_to_host_items_i(i) host_items[i] = ntohl(usrp2_items[i]) + if (is_big_endian){ + std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t)); + } + else{ + unrolled_loop(usrp2_items_to_host_items_i, num_samps); + } +} + +void transport::convert_io_type_to_otw_type( + const void *io_buff, const io_type_t &io_type, + void *otw_buff, const otw_type_t &otw_type, + size_t num_samps +){ + //all we handle for now: + ASSERT_THROW(otw_type.width == 16 and otw_type.byteorder == otw_type_t::BO_BIG_ENDIAN); + + switch(io_type.tid){ + case io_type_t::COMPLEX_FLOAT32: + host_floats_to_usrp2_items((boost::uint32_t *)otw_buff, (const fc32_t*)io_buff, num_samps); + break; + case io_type_t::COMPLEX_INT16: + host_items_to_usrp2_items((boost::uint32_t *)otw_buff, (const boost::uint32_t*)io_buff, num_samps); + break; + default: + throw std::runtime_error(str(boost::format("convert_types: cannot handle type \"%c\"") % io_type.tid)); + } +} + +void transport::convert_otw_type_to_io_type( + const void *otw_buff, const otw_type_t &otw_type, + void *io_buff, const io_type_t &io_type, + size_t num_samps +){ + //all we handle for now: + ASSERT_THROW(otw_type.width == 16 and otw_type.byteorder == otw_type_t::BO_BIG_ENDIAN); + + switch(io_type.tid){ + case io_type_t::COMPLEX_FLOAT32: + usrp2_items_to_host_floats((fc32_t*)io_buff, (const boost::uint32_t *)otw_buff, num_samps); + break; + case io_type_t::COMPLEX_INT16: + usrp2_items_to_host_items((boost::uint32_t*)io_buff, (const boost::uint32_t *)otw_buff, num_samps); + break; + default: + throw std::runtime_error(str(boost::format("convert_types: cannot handle type \"%c\"") % io_type.tid)); + } +} diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 13fd50f65..3e0e80bd8 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -110,6 +110,9 @@ private: size_t get_recv_buff_size(void); void set_recv_buff_size(size_t); + + static const size_t _mtu = 1500; //FIXME we have no idea + static const size_t _hdrs = (2 + 14 + 20 + 8); //size of headers (pad, eth, ip, udp) }; udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ @@ -143,7 +146,7 @@ udp_zero_copy_impl::~udp_zero_copy_impl(void){ } managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ - boost::uint32_t *buff_mem = new boost::uint32_t[1500/sizeof(boost::uint32_t)]; + boost::uint32_t *buff_mem = new boost::uint32_t[_mtu/sizeof(boost::uint32_t)]; //implement timeout through polling and sleeping size_t available = 0; @@ -155,7 +158,7 @@ managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ //receive only if data is available if (available){ - available = _socket->receive(boost::asio::buffer(buff_mem, available)); + available = _socket->receive(boost::asio::buffer(buff_mem, _mtu)); } //create a new managed buffer to house the data @@ -165,9 +168,9 @@ managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ } managed_send_buffer::sptr udp_zero_copy_impl::get_send_buff(void){ - boost::uint32_t *buff_mem = new boost::uint32_t[1500/sizeof(boost::uint32_t)]; + boost::uint32_t *buff_mem = new boost::uint32_t[_mtu/sizeof(boost::uint32_t)]; return managed_send_buffer::sptr( - new managed_send_buffer_impl(boost::asio::buffer(buff_mem, 1500), _socket) + new managed_send_buffer_impl(boost::asio::buffer(buff_mem, _mtu-_hdrs), _socket) ); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index a54c0a409..19a1ecf0f 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -15,28 +15,25 @@ // along with this program. If not, see . // -#include -#include #include "usrp2_impl.hpp" +#include +#include +#include using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -/*********************************************************************** - * Constants - **********************************************************************/ -typedef std::complex fc32_t; -typedef std::complex sc16_t; - -static const float shorts_per_float = float(1 << 15); -static const float floats_per_short = float(1.0/shorts_per_float); - /*********************************************************************** * Helper Functions **********************************************************************/ void usrp2_impl::io_init(void){ + //setup otw type + _otw_type.width = 16; + _otw_type.shift = 0; + _otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; + //initially empty copy buffer _rx_copy_buff = asio::buffer("", 0); @@ -51,79 +48,6 @@ void usrp2_impl::io_init(void){ send_buff->done(sizeof(data)); } -#define unrolled_loop(__inst, __len){ \ - size_t __i = 0; \ - for(; __i < (__len & ~0x3); __i+= 4){ \ - __inst(__i+0); __inst(__i+1); \ - __inst(__i+2); __inst(__i+3); \ - } \ - for(; __i < __len; __i++){ \ - __inst(__i); \ - } \ -} - -// set a boolean flag that indicates the endianess -#ifdef HAVE_BIG_ENDIAN -static const bool is_big_endian = true; -#else -static const bool is_big_endian = false; -#endif - -static inline void host_floats_to_usrp2_items( - boost::uint32_t *usrp2_items, - const fc32_t *host_floats, - size_t num_samps -){ - #define host_floats_to_usrp2_items_i(i){ \ - boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); \ - boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); \ - usrp2_items[i] = htonl((real << 16) | (imag << 0)); \ - } - unrolled_loop(host_floats_to_usrp2_items_i, num_samps); -} - -static inline void usrp2_items_to_host_floats( - fc32_t *host_floats, - const boost::uint32_t *usrp2_items, - size_t num_samps -){ - #define usrp2_items_to_host_floats_i(i){ \ - boost::uint32_t item = ntohl(usrp2_items[i]); \ - boost::int16_t real = boost::uint16_t(item >> 16); \ - boost::int16_t imag = boost::uint16_t(item >> 0); \ - host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); \ - } - unrolled_loop(usrp2_items_to_host_floats_i, num_samps); -} - -static inline void host_items_to_usrp2_items( - boost::uint32_t *usrp2_items, - const boost::uint32_t *host_items, - size_t num_samps -){ - #define host_items_to_usrp2_items_i(i) usrp2_items[i] = htonl(host_items[i]) - if (is_big_endian){ - std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t)); - } - else{ - unrolled_loop(host_items_to_usrp2_items_i, num_samps); - } -} - -static inline void usrp2_items_to_host_items( - boost::uint32_t *host_items, - const boost::uint32_t *usrp2_items, - size_t num_samps -){ - #define usrp2_items_to_host_items_i(i) host_items[i] = ntohl(usrp2_items[i]) - if (is_big_endian){ - std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t)); - } - else{ - unrolled_loop(usrp2_items_to_host_items_i, num_samps); - } -} - /*********************************************************************** * Receive Raw Data **********************************************************************/ @@ -182,7 +106,7 @@ size_t usrp2_impl::send( boost::uint32_t *tx_mem = send_buff->cast(); size_t num_samps = std::min( asio::buffer_size(buff), - send_buff->size() + send_buff->size()-vrt::max_header_words32*sizeof(boost::uint32_t) )/io_type.size; //kill the end of burst flag if this is a fragment @@ -204,17 +128,12 @@ size_t usrp2_impl::send( boost::uint32_t *items = tx_mem + num_header_words32; //offset for data - //copy the samples into the send buffer - switch(io_type.tid){ - case io_type_t::COMPLEX_FLOAT32: - host_floats_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); - break; - case io_type_t::COMPLEX_INT16: - host_items_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); - break; - default: - throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%c\"") % io_type.tid)); - } + //copy-convert the samples into the send buffer + convert_io_type_to_otw_type( + asio::buffer_cast(buff), io_type, + (void*)items, _otw_type, + num_samps + ); //send and return number of samples send_buff->done(num_packet_words32*sizeof(boost::uint32_t)); @@ -254,17 +173,12 @@ size_t usrp2_impl::recv( metadata.fragment_offset = _fragment_offset_in_samps; _fragment_offset_in_samps += num_samps; //set for next time - //copy the samples from the recv buffer - switch(io_type.tid){ - case io_type_t::COMPLEX_FLOAT32: - usrp2_items_to_host_floats(asio::buffer_cast(buff), items, num_samps); - break; - case io_type_t::COMPLEX_INT16: - usrp2_items_to_host_items(asio::buffer_cast(buff), items, num_samps); - break; - default: - throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%c\"") % io_type.tid)); - } + //copy-convert the samples from the recv buffer + convert_otw_type_to_io_type( + (const void*)items, _otw_type, + asio::buffer_cast(buff), io_type, + num_samps + ); //update the rx copy buffer to reflect the bytes copied _rx_copy_buff = asio::buffer( diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index be09c4ee1..4e7154afa 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -139,6 +140,7 @@ private: uhd::transport::managed_recv_buffer::sptr _rx_smart_buff; boost::asio::const_buffer _rx_copy_buff; size_t _fragment_offset_in_samps; + uhd::otw_type_t _otw_type; void io_init(void); //udp transports for control and data -- cgit v1.2.3 From 7da6f4e3e3f41d12f68bd618390b9eae12e902e9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 18:45:24 -0700 Subject: reg map for ad9510 --- host/lib/CMakeLists.txt | 5 + host/lib/ic_reg_maps/gen_ad9510_regs.py | 215 ++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100755 host/lib/ic_reg_maps/gen_ad9510_regs.py (limited to 'host/lib/CMakeLists.txt') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 7369e7600..0483cd11c 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -92,6 +92,11 @@ UHD_PYTHON_GEN_SOURCE_FILE( ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/adf4360_regs.hpp ) +UHD_PYTHON_GEN_SOURCE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_ad9510_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad9510_regs.hpp +) + ######################################################################## # Conditionally add the udp sources ######################################################################## diff --git a/host/lib/ic_reg_maps/gen_ad9510_regs.py b/host/lib/ic_reg_maps/gen_ad9510_regs.py new file mode 100755 index 000000000..624249563 --- /dev/null +++ b/host/lib/ic_reg_maps/gen_ad9510_regs.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python +# +# Copyright 2008,2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either asversion 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +import re +import os +import sys +from Cheetah.Template import Template +def parse_tmpl(_tmpl_text, **kwargs): + return str(Template(_tmpl_text, kwargs)) +def safe_makedirs(path): + not os.path.isdir(path) and os.makedirs(path) + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_DATA_TMPL="""\ +######################################################################## +## serial control port config +######################################################################## +long_instruction 0[4] 1 8bits, 16bits +soft_reset 0[5] 0 +lsb_first 0[6] 0 msb, lsb +sdo_inactive 0[7] 0 active, inactive +######################################################################## +## pll settings +######################################################################## +acounter 4[0:5] 0 +bcounter_msb 5[0:4] 0 +bcounter_lsb 6[0:7] 0 +lor_enable 7[2] 0 enb, dis +lor_ildd 7[5:6] 0 3cyc, 6cyc, 12cyc, 24cyc +charge_pump_mode 8[0:1] 0 3state, pump_up, pump_down, normal +pll_mux_control 8[2:5] 0 off, dld_high, ndiv, dld_low, rdiv, ald_nchan, acounter, prescaler, pfd_up, pfd_down, lor_high, 3state, ald_pchan, lor_lol_high, lor_lol_low, lor_low +pfd_polarity 8[6] 0 neg, pos +reset_all_counters 9[0] 0 +ncounter_reset 9[1] 0 +rcounter_reset 9[2] 0 +cp_current_setting 9[4:6] 0 0_60ma, 1_2ma, 1_8ma, 2_4ma, 3_0ma, 3_6ma, 4_2ma, 4_8ma +pll_power_down A[0:1] 0 normal=0, async_pd=1, sync_pd=3 +prescaler_value A[2:4] 0 div1, div2, 2_3, 4_5, 8_9, 16_17, 32_33, div3 +b_counter_bypass A[6] 0 +ref_counter_msb B[0:5] 0 +ref_counter_lsb C[0:7] 0 +antibacklash_pw D[0:1] 0 1_3ns, 2_9ns, 6_0ns, 1_3ns +dld_window D[5] 0 9_5ns, 3_5ns +lock_detect_disable D[6] 0 enb, dis +######################################################################## +## fine delay adjust +######################################################################## +#for $i, $o in ((5, 0), (6, 4)) +delay_control_out$i $hex(0x34+$o)[0] 0 +ramp_current_out$i $hex(0x35+$o)[0:2] 0 200ua, 400ua, 600ua, 800ua, 1000ua, 1200ua, 1400ua, 1600ua +ramp_capacitor_out$i $hex(0x35+$o)[3:5] 0 4caps=0, 3caps=1, 2caps=3, 3caps=4, 1cap=7 +delay_fine_adjust_out$i $hex(0x36+$o)[1:5] 0 +#end for +######################################################################## +## outputs +######################################################################## +#for $i, $o in ((0, 0), (1, 1), (2, 2), (3, 3)) +power_down_lvpecl_out$i $hex(0x3C+$o)[0:1] 0 normal, test, safe_pd, total_pd +output_level_lvpecl_out$i $hex(0x3C+$o)[2:3] 2 500mv, 340mv, 810mv, 660mv +#end for +#for $i, $o in ((4, 0), (5, 1), (6, 2), (7, 3)) +power_down_lvds_cmos_out$i $hex(0x40+$o)[0] 0 +output_level_lvds_out$i $hex(0x40+$o)[1:2] 1 1_75ma, 3_5ma, 5_25ma, 7ma +lvds_cmos_select_out$i $hex(0x40+$o)[3] 1 lvds, cmos +inverted_cmos_driver_out$i $hex(0x40+$o)[4] 0 dis, enb +#end for +clock_select 45[0] 1 clk2_drives, clk1_drives +clk1_power_down 45[1] 0 +clk2_power_down 45[2] 0 +prescaler_clock_pd 45[3] 0 +refin_power_down 45[4] 0 +all_clock_inputs_pd 45[5] 0 +######################################################################## +## dividers +######################################################################## +#for $i, $o in ((0, 0), (1, 2), (2, 4), (3, 6), (4, 8), (5, 10), (6, 12), (7, 14)) +divider_high_cycles_out$i $hex(0x48+$o)[0:3] 0 +divider_low_cycles_out$i $hex(0x48+$o)[4:7] 0 +phase_offset_out$i $hex(0x49+$o)[0:3] 0 +start_out$i $hex(0x49+$o)[4] 0 +force_out$i $hex(0x49+$o)[5] 0 +nosync_out$i $hex(0x49+$o)[6] 0 +bypass_divider_out$i $hex(0x49+$o)[7] 0 +#end for +######################################################################## +## function +######################################################################## +sync_detect_enable 58[0] 0 dis, enb +sync_select 58[1] 0 1_to_0_5, 0_5_to_1 +soft_sync 58[2] 0 +dist_power_down 58[3] 0 +sync_power_down 58[4] 0 +function_pin_select 58[5:6] 0 resetb, syncb, test, pdb +update_registers 5A[0] 0 +""" + +######################################################################## +# Header and Source templates below +######################################################################## +HEADER_TEXT=""" +#import time + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#ifndef INCLUDED_AD9510_REGS_HPP +\#define INCLUDED_AD9510_REGS_HPP + +\#include + +struct adf4360_regs_t{ +#for $reg in $regs + #if $reg.get_enums() + enum $(reg.get_name())_t{ + #for $i, $enum in enumerate($reg.get_enums()) + #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' + $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma + #end for + } $reg.get_name(); + #else + boost::$reg.get_stdint_type() $reg.get_name(); + #end if +#end for + + adf4360_regs_t(void){ +#for $reg in $regs + $reg.get_name() = $reg.get_default(); +#end for + } + + boost::uint8_t get_reg(boost::uint8_t addr){ + boost::uint8_t reg = 0; + switch(addr){ + #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return reg; + } +}; + +\#endif /* INCLUDED_AD9510_REGS_HPP */ +""" + +class reg: + def __init__(self, reg_des): + x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des) + name, addr, bit_range, default, enums = x.groups() + + #store variables + self._name = name + self._addr = int(addr, 16) + if ':' in bit_range: self._addr_spec = map(int, bit_range.split(':')) + else: self._addr_spec = int(bit_range), int(bit_range) + self._default = int(default, 16) + + #extract enum + self._enums = list() + if enums: + enum_val = 0 + for enum_str in map(str.strip, enums.split(',')): + if '=' in enum_str: + enum_name, enum_val = enum_str.split('=') + enum_val = int(enum_val) + else: enum_name = enum_str + self._enums.append((enum_name, enum_val)) + enum_val += 1 + + def get_addr(self): return self._addr + def get_enums(self): return self._enums + def get_name(self): return self._name + def get_default(self): + for key, val in self.get_enums(): + if val == self._default: return str.upper('%s_%s'%(self.get_name(), key)) + return self._default + def get_stdint_type(self): + if self.get_bit_width() <= 8: return 'uint8_t' + if self.get_bit_width() <= 16: return 'uint16_t' + if self.get_bit_width() <= 32: return 'uint32_t' + if self.get_bit_width() <= 64: return 'uint64_t' + raise Exception, 'too damn big' + def get_shift(self): return self._addr_spec[0] + def get_mask(self): return hex(int('1'*self.get_bit_width(), 2)) + def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1 + +if __name__ == '__main__': + regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) + safe_makedirs(os.path.dirname(sys.argv[1])) + open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__)) -- cgit v1.2.3 From ad0d641b38dd79cc29b4ca7a3a02c02e35eb8f71 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 13 Apr 2010 12:42:23 -0700 Subject: Moved clock control into abstraction clock control class. --- host/include/uhd/usrp/dboard_interface.hpp | 8 --- host/lib/CMakeLists.txt | 19 ++++--- host/lib/usrp/usrp2/clock_control.cpp | 84 ++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/clock_control.hpp | 55 +++++++++++++++++++ host/lib/usrp/usrp2/dboard_interface.cpp | 27 ++-------- host/lib/usrp/usrp2/mboard_impl.cpp | 6 +++ host/lib/usrp/usrp2/usrp2_impl.hpp | 5 ++ 7 files changed, 167 insertions(+), 37 deletions(-) create mode 100644 host/lib/usrp/usrp2/clock_control.cpp create mode 100644 host/lib/usrp/usrp2/clock_control.hpp (limited to 'host/lib/CMakeLists.txt') diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index 2fa05c09d..c4e822751 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -183,14 +183,6 @@ public: * \param enb true for enabled */ virtual void set_clock_enabled(unit_t unit, bool enb) = 0; - - /*! - * Get the enabled status of a dboard block. - * - * \param unit which unit rx or tx - * \return true for enabled - */ - virtual bool get_clock_enabled(unit_t unit) = 0; }; }} //namespace diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 0483cd11c..b25ba38e2 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -60,12 +60,6 @@ SET(libuhd_sources usrp/simple_usrp.cpp usrp/dboard_manager.cpp usrp/tune_helper.cpp - usrp/usrp2/dboard_impl.cpp - usrp/usrp2/dboard_interface.cpp - usrp/usrp2/dsp_impl.cpp - usrp/usrp2/io_impl.cpp - usrp/usrp2/mboard_impl.cpp - usrp/usrp2/usrp2_impl.cpp ) ######################################################################## @@ -97,6 +91,19 @@ UHD_PYTHON_GEN_SOURCE_FILE( ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad9510_regs.hpp ) +######################################################################## +# Add usrp2 sources +######################################################################## +LIST(APPEND libuhd_sources + usrp/usrp2/clock_control.cpp + usrp/usrp2/dboard_impl.cpp + usrp/usrp2/dboard_interface.cpp + usrp/usrp2/dsp_impl.cpp + usrp/usrp2/io_impl.cpp + usrp/usrp2/mboard_impl.cpp + usrp/usrp2/usrp2_impl.cpp +) + ######################################################################## # Conditionally add the udp sources ######################################################################## diff --git a/host/lib/usrp/usrp2/clock_control.cpp b/host/lib/usrp/usrp2/clock_control.cpp new file mode 100644 index 000000000..74db5958a --- /dev/null +++ b/host/lib/usrp/usrp2/clock_control.cpp @@ -0,0 +1,84 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "usrp2_impl.hpp" +#include "clock_control.hpp" +#include "ad9510_regs.hpp" +#include "usrp2_regs.hpp" //spi slave constants +#include + +using namespace uhd::usrp; + +/*! + * A usrp2 clock control specific to the ad9510 ic. + */ +class clock_control_ad9510 : public clock_control{ +public: + clock_control_ad9510(usrp2_impl *impl){ + _impl = impl; + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + } + + ~clock_control_ad9510(void){ + /* NOP */ + } + + void enable_rx_dboard_clock(bool enb){ + _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; + _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; + this->write_reg(0x43); + this->update_regs(); + } + + void enable_tx_dboard_clock(bool enb){ + _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS; + _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; + this->write_reg(0x42); + this->update_regs(); + } + +private: + /*! + * Write a single register to the spi regs. + * \param addr the address to write + */ + void write_reg(boost::uint8_t addr){ + boost::uint32_t data = _ad9510_regs.get_write_reg(addr); + _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); + } + + /*! + * Tells the ad9510 to latch the settings into the operational registers. + */ + void update_regs(void){ + _ad9510_regs.update_registers = 1; + this->write_reg(0x5a); + } + + usrp2_impl *_impl; + ad9510_regs_t _ad9510_regs; +}; + +/*********************************************************************** + * Public make function for the ad9510 clock control + **********************************************************************/ +clock_control::sptr clock_control::make_ad9510(usrp2_impl *impl){ + return clock_control::sptr(new clock_control_ad9510(impl)); +} diff --git a/host/lib/usrp/usrp2/clock_control.hpp b/host/lib/usrp/usrp2/clock_control.hpp new file mode 100644 index 000000000..366e09c28 --- /dev/null +++ b/host/lib/usrp/usrp2/clock_control.hpp @@ -0,0 +1,55 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INCLUDED_CLOCK_CONTROL_HPP +#define INCLUDED_CLOCK_CONTROL_HPP + +class usrp2_impl; //dummy class + +#include +#include + +class clock_control : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a clock config for the ad9510 ic. + * \param impl a pointer to the usrp2 implementation object + * \return a new clock control object + */ + static sptr make_ad9510(usrp2_impl *impl); + + /*! + * Enable/disable the rx dboard clock. + * \param enb true to enable + */ + virtual void enable_rx_dboard_clock(bool enb) = 0; + + /*! + * Enable/disable the tx dboard clock. + * \param enb true to enable + */ + virtual void enable_tx_dboard_clock(bool enb) = 0; + + /*! + * TODO other clock control api here.... + */ + +}; + +#endif /* INCLUDED_CLOCK_CONTROL_HPP */ diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index 8a3df08cb..c74bdaf44 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -17,7 +17,6 @@ #include "usrp2_impl.hpp" #include "usrp2_regs.hpp" -#include "ad9510_regs.hpp" #include #include #include @@ -61,8 +60,6 @@ public: private: usrp2_impl *_impl; boost::uint32_t _ddr_shadow; - ad9510_regs_t _ad9510_regs; - uhd::dict _clock_enb_shadow; }; /*********************************************************************** @@ -100,30 +97,14 @@ double usrp2_dboard_interface::get_clock_rate(unit_t){ } void usrp2_dboard_interface::set_clock_enabled(unit_t unit, bool enb){ - uint16_t data = 0; switch(unit){ case UNIT_RX: - _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; - _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; - data = _ad9510_regs.get_write_reg(0x43); - break; + _impl->get_clock_control()->enable_rx_dboard_clock(enb); + return; case UNIT_TX: - _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS; - _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; - data = _ad9510_regs.get_write_reg(0x42); - break; + _impl->get_clock_control()->enable_tx_dboard_clock(enb); + return; } - _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); - - _ad9510_regs.update_registers = 1; - _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, _ad9510_regs.get_write_reg(0x5a), 24, false /*no rb*/); - _clock_enb_shadow[unit] = unit; -} - -bool usrp2_dboard_interface::get_clock_enabled(unit_t unit){ - return _clock_enb_shadow[unit]; } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 2fa2e5211..faa34d0b3 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -33,6 +33,12 @@ void usrp2_impl::mboard_init(void){ boost::bind(&usrp2_impl::mboard_get, this, _1, _2), boost::bind(&usrp2_impl::mboard_set, this, _1, _2) ); + + _clock_control = clock_control::make_ad9510(this); +} + +clock_control::sptr usrp2_impl::get_clock_control(void){ + return _clock_control; } void usrp2_impl::init_clock_config(void){ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 5a02b33dc..f2e823391 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -18,6 +18,7 @@ #ifndef INCLUDED_USRP2_IMPL_HPP #define INCLUDED_USRP2_IMPL_HPP +#include "clock_control.hpp" #include #include #include @@ -110,6 +111,9 @@ public: void poke16(boost::uint32_t addr, boost::uint16_t data); boost::uint16_t peek16(boost::uint32_t addr); + //clock control + clock_control::sptr get_clock_control(void); + //spi read and write boost::uint32_t transact_spi( int which_slave, @@ -130,6 +134,7 @@ private: //device properties interface void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); + clock_control::sptr _clock_control; //the raw io interface (samples are in the usrp2 native format) void recv_raw(uhd::rx_metadata_t &); -- cgit v1.2.3 From 75dd8f674004d015425f194f8f4714b08f9ec018 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 13 Apr 2010 15:45:55 -0700 Subject: added ad9777 register map --- host/lib/CMakeLists.txt | 6 + host/lib/ic_reg_maps/gen_ad9777_regs.py | 202 ++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 host/lib/ic_reg_maps/gen_ad9777_regs.py (limited to 'host/lib/CMakeLists.txt') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index b25ba38e2..4f38c94c5 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -91,6 +91,12 @@ UHD_PYTHON_GEN_SOURCE_FILE( ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad9510_regs.hpp ) +UHD_PYTHON_GEN_SOURCE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_ad9777_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad9777_regs.hpp +) + + ######################################################################## # Add usrp2 sources ######################################################################## diff --git a/host/lib/ic_reg_maps/gen_ad9777_regs.py b/host/lib/ic_reg_maps/gen_ad9777_regs.py new file mode 100644 index 000000000..5bfd404c2 --- /dev/null +++ b/host/lib/ic_reg_maps/gen_ad9777_regs.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python +# +# Copyright 2008,2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either asversion 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +import re +import os +import sys +from Cheetah.Template import Template +def parse_tmpl(_tmpl_text, **kwargs): + return str(Template(_tmpl_text, kwargs)) +def safe_makedirs(path): + not os.path.isdir(path) and os.makedirs(path) + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_DATA_TMPL="""\ +######################################################################## +## address 0 +######################################################################## +sdio_bidirectional 0[7] 0 input, io +lsb_msb_first 0[6] 0 msb, lsb +soft_reset 0[5] 0 +sleep_mode 0[4] 0 +power_down_mode 0[3] 0 +x_1r_2r_mode 0[2] 0 2r, 1r +pll_lock_indicator 0[1] 0 +######################################################################## +## address 1 +######################################################################## +filter_interp_rate 1[6:7] 0 1x, 2x, 4x, 8x +modulation_mode 1[4:5] 0 none, fs_2, fs_4, fs_8 +zero_stuff_mode 1[3] 0 +real_mix_mode 1[2] 0 +modulation_form 1[1] 0 e_minus_jwt, e_plus_jwt +data_clk_pll_lock_sel 1[0] 0 pll_lock, data_clk +######################################################################## +## address 2 +######################################################################## +signed_input_data 2[7] 0 signed, unsigned +two_port_mode 2[6] 0 two_port, one_port +dataclk_driver_strength 2[5] 0 weak, strong +dataclk_invert 2[4] 0 +oneportclk_invert 2[2] 0 +iqsel_invert 2[1] 0 +iq_first 2[0] 0 i_first, q_first +######################################################################## +## address 3 +######################################################################## +data_rate_clock_output 3[7] 0 pll_lock, spi_sdo +pll_divide_ratio 3[0:1] 0 div1, div2, div4, div8 +######################################################################## +## address 4 +######################################################################## +pll_off 4[7] 0 off, on +auto_cp_control 4[6] 0 dis, enb +pll_cp_control 4[0:2] 0 50ua=0, 100ua=1, 200ua=2, 400ua=3, 800ua=7 +######################################################################## +## address 5 and 9 +######################################################################## +idac_fine_gain_adjust 5[0:7] 0 +qdac_fine_gain_adjust 9[0:7] 0 +######################################################################## +## address 6 and A +######################################################################## +idac_fine_coarse_adjust 6[0:3] 0 +qdac_fine_coarse_adjust A[0:3] 0 +######################################################################## +## address 7, 8 and B, C +######################################################################## +idac_offset_adjust_msb 7[0:7] 0 +idac_offset_adjust_lsb 8[0:1] 0 +idac_ioffset_direction 8[7] 0 out_a, out_b +qdac_offset_adjust_msb B[0:7] 0 +qdac_offset_adjust_lsb C[0:1] 0 +qdac_ioffset_direction C[7] 0 out_a, out_b +""" + +######################################################################## +# Header and Source templates below +######################################################################## +HEADER_TEXT=""" +#import time + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#ifndef INCLUDED_AD9777_REGS_HPP +\#define INCLUDED_AD9777_REGS_HPP + +\#include + +struct ad9777_regs_t{ +#for $reg in $regs + #if $reg.get_enums() + enum $(reg.get_name())_t{ + #for $i, $enum in enumerate($reg.get_enums()) + #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' + $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma + #end for + } $reg.get_name(); + #else + boost::$reg.get_stdint_type() $reg.get_name(); + #end if +#end for + + ad9777_regs_t(void){ +#for $reg in $regs + $reg.get_name() = $reg.get_default(); +#end for + } + + boost::uint32_t get_reg(boost::uint8_t addr){ + boost::uint32_t reg = 0; + switch(addr){ + #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return reg; + } + + boost::uint16_t get_write_reg(boost::uint8_t addr){ + return (boost::uint16_t(addr) << 8) | get_reg(addr); + } + + boost::uint16_t get_read_reg(boost::uint8_t addr){ + return (boost::uint16_t(addr) << 8) | (1 << 7); + } +}; + +\#endif /* INCLUDED_AD9777_REGS_HPP */ +""" + +class reg: + def __init__(self, reg_des): + x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des) + name, addr, bit_range, default, enums = x.groups() + + #store variables + self._name = name + self._addr = int(addr, 16) + if ':' in bit_range: self._addr_spec = sorted(map(int, bit_range.split(':'))) + else: self._addr_spec = int(bit_range), int(bit_range) + self._default = int(default, 16) + + #extract enum + self._enums = list() + if enums: + enum_val = 0 + for enum_str in map(str.strip, enums.split(',')): + if '=' in enum_str: + enum_name, enum_val = enum_str.split('=') + enum_val = int(enum_val) + else: enum_name = enum_str + self._enums.append((enum_name, enum_val)) + enum_val += 1 + + def get_addr(self): return self._addr + def get_enums(self): return self._enums + def get_name(self): return self._name + def get_default(self): + for key, val in self.get_enums(): + if val == self._default: return str.upper('%s_%s'%(self.get_name(), key)) + return self._default + def get_stdint_type(self): + if self.get_bit_width() <= 8: return 'uint8_t' + if self.get_bit_width() <= 16: return 'uint16_t' + if self.get_bit_width() <= 32: return 'uint32_t' + if self.get_bit_width() <= 64: return 'uint64_t' + raise Exception, 'too damn big' + def get_shift(self): return self._addr_spec[0] + def get_mask(self): return hex(int('1'*self.get_bit_width(), 2)) + def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1 + +if __name__ == '__main__': + regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) + safe_makedirs(os.path.dirname(sys.argv[1])) + open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__)) -- cgit v1.2.3 From 51a9c2d42d12caa607ae33feb12a6f16ab8a3fe5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 13 Apr 2010 17:48:48 -0700 Subject: Created a usrp2 interface class with the control, spi, peek/poke functionality. Its used in all the implementation level code --- host/lib/CMakeLists.txt | 3 +- host/lib/usrp/usrp2/clock_control.cpp | 16 +- host/lib/usrp/usrp2/clock_control.hpp | 7 +- host/lib/usrp/usrp2/dboard_iface.cpp | 278 +++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/dboard_impl.cpp | 10 +- host/lib/usrp/usrp2/dboard_interface.cpp | 271 ------------------------------ host/lib/usrp/usrp2/dsp_impl.cpp | 13 +- host/lib/usrp/usrp2/io_impl.cpp | 1 + host/lib/usrp/usrp2/mboard_impl.cpp | 37 ++-- host/lib/usrp/usrp2/usrp2_iface.cpp | 168 +++++++++++++++++++ host/lib/usrp/usrp2/usrp2_iface.hpp | 103 ++++++++++++ host/lib/usrp/usrp2/usrp2_impl.cpp | 110 +----------- host/lib/usrp/usrp2/usrp2_impl.hpp | 55 ++---- 13 files changed, 614 insertions(+), 458 deletions(-) create mode 100644 host/lib/usrp/usrp2/dboard_iface.cpp delete mode 100644 host/lib/usrp/usrp2/dboard_interface.cpp create mode 100644 host/lib/usrp/usrp2/usrp2_iface.cpp create mode 100644 host/lib/usrp/usrp2/usrp2_iface.hpp (limited to 'host/lib/CMakeLists.txt') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 4f38c94c5..b9e525bad 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -103,10 +103,11 @@ UHD_PYTHON_GEN_SOURCE_FILE( LIST(APPEND libuhd_sources usrp/usrp2/clock_control.cpp usrp/usrp2/dboard_impl.cpp - usrp/usrp2/dboard_interface.cpp + usrp/usrp2/dboard_iface.cpp usrp/usrp2/dsp_impl.cpp usrp/usrp2/io_impl.cpp usrp/usrp2/mboard_impl.cpp + usrp/usrp2/usrp2_iface.cpp usrp/usrp2/usrp2_impl.cpp ) diff --git a/host/lib/usrp/usrp2/clock_control.cpp b/host/lib/usrp/usrp2/clock_control.cpp index 2d27361a8..dcd7ce9da 100644 --- a/host/lib/usrp/usrp2/clock_control.cpp +++ b/host/lib/usrp/usrp2/clock_control.cpp @@ -28,8 +28,8 @@ using namespace uhd::usrp; */ class clock_control_ad9510 : public clock_control{ public: - clock_control_ad9510(usrp2_impl *impl){ - _impl = impl; + clock_control_ad9510(usrp2_iface::sptr iface){ + _iface = iface; _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; this->write_reg(0x09); @@ -71,8 +71,8 @@ public: ~clock_control_ad9510(void){ /* private clock enables, must be set here */ - //this->enable_dac_clock(false); - //this->enable_adc_clock(false); //FIXME cant do yet + this->enable_dac_clock(false); + this->enable_adc_clock(false); } //uses output clock 7 (cmos) @@ -114,7 +114,7 @@ private: */ void write_reg(boost::uint8_t addr){ boost::uint32_t data = _ad9510_regs.get_write_reg(addr); - _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); + _iface->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); } /*! @@ -144,13 +144,13 @@ private: this->update_regs(); } - usrp2_impl *_impl; + usrp2_iface::sptr _iface; ad9510_regs_t _ad9510_regs; }; /*********************************************************************** * Public make function for the ad9510 clock control **********************************************************************/ -clock_control::sptr clock_control::make_ad9510(usrp2_impl *impl){ - return clock_control::sptr(new clock_control_ad9510(impl)); +clock_control::sptr clock_control::make_ad9510(usrp2_iface::sptr iface){ + return clock_control::sptr(new clock_control_ad9510(iface)); } diff --git a/host/lib/usrp/usrp2/clock_control.hpp b/host/lib/usrp/usrp2/clock_control.hpp index 4302941f0..b64a53196 100644 --- a/host/lib/usrp/usrp2/clock_control.hpp +++ b/host/lib/usrp/usrp2/clock_control.hpp @@ -18,8 +18,7 @@ #ifndef INCLUDED_CLOCK_CONTROL_HPP #define INCLUDED_CLOCK_CONTROL_HPP -class usrp2_impl; //dummy class - +#include "usrp2_iface.hpp" #include #include @@ -29,10 +28,10 @@ public: /*! * Make a clock config for the ad9510 ic. - * \param impl a pointer to the usrp2 implementation object + * \param _iface a pointer to the usrp2 interface object * \return a new clock control object */ - static sptr make_ad9510(usrp2_impl *impl); + static sptr make_ad9510(usrp2_iface::sptr iface); /*! * Enable/disable the rx dboard clock. diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp new file mode 100644 index 000000000..d0c4bf6c1 --- /dev/null +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -0,0 +1,278 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "usrp2_iface.hpp" +#include "clock_control.hpp" +#include "usrp2_regs.hpp" +#include +#include +#include +#include //htonl and ntohl +#include + +using namespace uhd::usrp; + +class usrp2_dboard_iface : public dboard_interface{ +public: + usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl); + ~usrp2_dboard_iface(void); + + void write_aux_dac(unit_t, int, int); + int read_aux_adc(unit_t, int); + + void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); + void set_gpio_ddr(unit_t, boost::uint16_t); + boost::uint16_t read_gpio(unit_t); + + void write_i2c(int, const byte_vector_t &); + byte_vector_t read_i2c(int, size_t); + + double get_clock_rate(unit_t); + void set_clock_enabled(unit_t, bool); + bool get_clock_enabled(unit_t); + + void write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ); + + boost::uint32_t read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ); + +private: + usrp2_iface::sptr _iface; + clock_control::sptr _clk_ctrl; + boost::uint32_t _ddr_shadow; +}; + +/*********************************************************************** + * Make Function + **********************************************************************/ +dboard_interface::sptr make_usrp2_dboard_iface( + usrp2_iface::sptr iface, + clock_control::sptr clk_ctrl +){ + return dboard_interface::sptr(new usrp2_dboard_iface(iface, clk_ctrl)); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl){ + _iface = iface; + _clk_ctrl = clk_ctrl; + _ddr_shadow = 0; + + //set the selection mux to use atr + boost::uint32_t new_sels = 0x0; + for(size_t i = 0; i < 16; i++){ + new_sels |= FRF_GPIO_SEL_ATR << (i*2); + } + _iface->poke32(FR_GPIO_TX_SEL, new_sels); + _iface->poke32(FR_GPIO_RX_SEL, new_sels); +} + +usrp2_dboard_iface::~usrp2_dboard_iface(void){ + /* NOP */ +} + +/*********************************************************************** + * Clocks + **********************************************************************/ +double usrp2_dboard_iface::get_clock_rate(unit_t){ + return _iface->get_master_clock_freq(); +} + +void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ + switch(unit){ + case UNIT_RX: + _clk_ctrl->enable_rx_dboard_clock(enb); + return; + case UNIT_TX: + _clk_ctrl->enable_tx_dboard_clock(enb); + return; + } +} + +/*********************************************************************** + * GPIO + **********************************************************************/ +static int unit_to_shift(dboard_interface::unit_t unit){ + switch(unit){ + case dboard_interface::UNIT_RX: return 0; + case dboard_interface::UNIT_TX: return 16; + } + throw std::runtime_error("unknown unit type"); +} + +void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ + _ddr_shadow = \ + (_ddr_shadow & ~(0xffff << unit_to_shift(unit))) | + (boost::uint32_t(value) << unit_to_shift(unit)); + _iface->poke32(FR_GPIO_DDR, _ddr_shadow); +} + +boost::uint16_t usrp2_dboard_iface::read_gpio(unit_t unit){ + return boost::uint16_t(_iface->peek32(FR_GPIO_IO) >> unit_to_shift(unit)); +} + +void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ + //define mapping of unit to atr regs to register address + static const uhd::dict< + unit_t, uhd::dict + > unit_to_atr_to_addr = boost::assign::map_list_of + (UNIT_RX, boost::assign::map_list_of + (ATR_REG_IDLE, FR_ATR_IDLE_RXSIDE) + (ATR_REG_TX_ONLY, FR_ATR_INTX_RXSIDE) + (ATR_REG_RX_ONLY, FR_ATR_INRX_RXSIDE) + (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE) + ) + (UNIT_TX, boost::assign::map_list_of + (ATR_REG_IDLE, FR_ATR_IDLE_TXSIDE) + (ATR_REG_TX_ONLY, FR_ATR_INTX_TXSIDE) + (ATR_REG_RX_ONLY, FR_ATR_INRX_TXSIDE) + (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE) + ) + ; + _iface->poke16(unit_to_atr_to_addr[unit][atr], value); +} + +/*********************************************************************** + * SPI + **********************************************************************/ +/*! + * Static function to convert a unit type enum + * to an over-the-wire value for the spi device. + * \param unit the dboard interface unit type enum + * \return an over the wire representation + */ +static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){ + switch(unit){ + case dboard_interface::UNIT_TX: return SPI_SS_TX_DB; + case dboard_interface::UNIT_RX: return SPI_SS_RX_DB; + } + throw std::invalid_argument("unknown unit type"); +} + +void usrp2_dboard_iface::write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); +} + +boost::uint32_t usrp2_dboard_iface::read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + return _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); +} + +/*********************************************************************** + * I2C + **********************************************************************/ +void usrp2_dboard_iface::write_i2c(int i2c_addr, const byte_vector_t &buf){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO); + out_data.data.i2c_args.addr = i2c_addr; + out_data.data.i2c_args.bytes = buf.size(); + + //limitation of i2c transaction size + ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data)); + + //copy in the data + std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data); + + //send and recv + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE); +} + +dboard_interface::byte_vector_t usrp2_dboard_iface::read_i2c(int i2c_addr, size_t num_bytes){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); + out_data.data.i2c_args.addr = i2c_addr; + out_data.data.i2c_args.bytes = num_bytes; + + //limitation of i2c transaction size + ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data)); + + //send and recv + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE); + ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes); + + //copy out the data + byte_vector_t result(num_bytes); + std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin()); + return result; +} + +/*********************************************************************** + * Aux DAX/ADC + **********************************************************************/ +/*! + * Static function to convert a unit type enum + * to an over-the-wire value for the usrp2 control. + * \param unit the dboard interface unit type enum + * \return an over the wire representation + */ +static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){ + switch(unit){ + case dboard_interface::UNIT_TX: return USRP2_DIR_TX; + case dboard_interface::UNIT_RX: return USRP2_DIR_RX; + } + throw std::invalid_argument("unknown unit type"); +} + +void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, int value){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO); + out_data.data.aux_args.dir = unit_to_otw(unit); + out_data.data.aux_args.which = which; + out_data.data.aux_args.value = htonl(value); + + //send and recv + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); +} + +int usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO); + out_data.data.aux_args.dir = unit_to_otw(unit); + out_data.data.aux_args.which = which; + + //send and recv + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE); + return ntohl(in_data.data.aux_args.value); +} diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 3ac805421..4b300de68 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include //htonl and ntohl #include using namespace uhd; @@ -34,7 +36,7 @@ void usrp2_impl::dboard_init(void){ //grab the dboard ids over the control line usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO); - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE); //extract the dboard ids an convert them @@ -43,7 +45,7 @@ void usrp2_impl::dboard_init(void){ //create a new dboard interface and manager dboard_interface::sptr _dboard_interface( - make_usrp2_dboard_interface(this) + make_usrp2_dboard_iface(_iface, _clk_ctrl) ); _dboard_manager = dboard_manager::make( rx_dboard_id, tx_dboard_id, _dboard_interface @@ -82,7 +84,7 @@ void usrp2_impl::update_rx_mux_config(void){ rx_mux = (((rx_mux >> 0) & 0x3) << 2) | (((rx_mux >> 2) & 0x3) << 0); } - this->poke32(FR_DSP_RX_MUX, rx_mux); + _iface->poke32(FR_DSP_RX_MUX, rx_mux); } void usrp2_impl::update_tx_mux_config(void){ @@ -95,7 +97,7 @@ void usrp2_impl::update_tx_mux_config(void){ tx_mux = (((tx_mux >> 0) & 0x1) << 1) | (((tx_mux >> 1) & 0x1) << 0); } - this->poke32(FR_DSP_TX_MUX, tx_mux); + _iface->poke32(FR_DSP_TX_MUX, tx_mux); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp deleted file mode 100644 index c74bdaf44..000000000 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp2_impl.hpp" -#include "usrp2_regs.hpp" -#include -#include -#include -#include - -using namespace uhd::usrp; - -class usrp2_dboard_interface : public dboard_interface{ -public: - usrp2_dboard_interface(usrp2_impl *impl); - ~usrp2_dboard_interface(void); - - void write_aux_dac(unit_t, int, int); - int read_aux_adc(unit_t, int); - - void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); - void set_gpio_ddr(unit_t, boost::uint16_t); - boost::uint16_t read_gpio(unit_t); - - void write_i2c(int, const byte_vector_t &); - byte_vector_t read_i2c(int, size_t); - - double get_clock_rate(unit_t); - void set_clock_enabled(unit_t, bool); - bool get_clock_enabled(unit_t); - - void write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits - ); - - boost::uint32_t read_write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits - ); - -private: - usrp2_impl *_impl; - boost::uint32_t _ddr_shadow; -}; - -/*********************************************************************** - * Make Function - **********************************************************************/ -dboard_interface::sptr make_usrp2_dboard_interface(usrp2_impl *impl){ - return dboard_interface::sptr(new usrp2_dboard_interface(impl)); -} - -/*********************************************************************** - * Structors - **********************************************************************/ -usrp2_dboard_interface::usrp2_dboard_interface(usrp2_impl *impl){ - _impl = impl; - _ddr_shadow = 0; - - //set the selection mux to use atr - boost::uint32_t new_sels = 0x0; - for(size_t i = 0; i < 16; i++){ - new_sels |= FRF_GPIO_SEL_ATR << (i*2); - } - _impl->poke32(FR_GPIO_TX_SEL, new_sels); - _impl->poke32(FR_GPIO_RX_SEL, new_sels); -} - -usrp2_dboard_interface::~usrp2_dboard_interface(void){ - /* NOP */ -} - -/*********************************************************************** - * Clocks - **********************************************************************/ -double usrp2_dboard_interface::get_clock_rate(unit_t){ - return _impl->get_master_clock_freq(); -} - -void usrp2_dboard_interface::set_clock_enabled(unit_t unit, bool enb){ - switch(unit){ - case UNIT_RX: - _impl->get_clock_control()->enable_rx_dboard_clock(enb); - return; - case UNIT_TX: - _impl->get_clock_control()->enable_tx_dboard_clock(enb); - return; - } -} - -/*********************************************************************** - * GPIO - **********************************************************************/ -static int unit_to_shift(dboard_interface::unit_t unit){ - switch(unit){ - case dboard_interface::UNIT_RX: return 0; - case dboard_interface::UNIT_TX: return 16; - } - throw std::runtime_error("unknown unit type"); -} - -void usrp2_dboard_interface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ - _ddr_shadow = \ - (_ddr_shadow & ~(0xffff << unit_to_shift(unit))) | - (boost::uint32_t(value) << unit_to_shift(unit)); - _impl->poke32(FR_GPIO_DDR, _ddr_shadow); -} - -boost::uint16_t usrp2_dboard_interface::read_gpio(unit_t unit){ - return boost::uint16_t(_impl->peek32(FR_GPIO_IO) >> unit_to_shift(unit)); -} - -void usrp2_dboard_interface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ - //define mapping of unit to atr regs to register address - static const uhd::dict< - unit_t, uhd::dict - > unit_to_atr_to_addr = boost::assign::map_list_of - (UNIT_RX, boost::assign::map_list_of - (ATR_REG_IDLE, FR_ATR_IDLE_RXSIDE) - (ATR_REG_TX_ONLY, FR_ATR_INTX_RXSIDE) - (ATR_REG_RX_ONLY, FR_ATR_INRX_RXSIDE) - (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE) - ) - (UNIT_TX, boost::assign::map_list_of - (ATR_REG_IDLE, FR_ATR_IDLE_TXSIDE) - (ATR_REG_TX_ONLY, FR_ATR_INTX_TXSIDE) - (ATR_REG_RX_ONLY, FR_ATR_INRX_TXSIDE) - (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE) - ) - ; - _impl->poke16(unit_to_atr_to_addr[unit][atr], value); -} - -/*********************************************************************** - * SPI - **********************************************************************/ -/*! - * Static function to convert a unit type enum - * to an over-the-wire value for the spi device. - * \param unit the dboard interface unit type enum - * \return an over the wire representation - */ -static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){ - switch(unit){ - case dboard_interface::UNIT_TX: return SPI_SS_TX_DB; - case dboard_interface::UNIT_RX: return SPI_SS_RX_DB; - } - throw std::invalid_argument("unknown unit type"); -} - -void usrp2_dboard_interface::write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits -){ - _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); -} - -boost::uint32_t usrp2_dboard_interface::read_write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits -){ - return _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); -} - -/*********************************************************************** - * I2C - **********************************************************************/ -void usrp2_dboard_interface::write_i2c(int i2c_addr, const byte_vector_t &buf){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO); - out_data.data.i2c_args.addr = i2c_addr; - out_data.data.i2c_args.bytes = buf.size(); - - //limitation of i2c transaction size - ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data)); - - //copy in the data - std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data); - - //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE); -} - -dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, size_t num_bytes){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); - out_data.data.i2c_args.addr = i2c_addr; - out_data.data.i2c_args.bytes = num_bytes; - - //limitation of i2c transaction size - ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data)); - - //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE); - ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes); - - //copy out the data - byte_vector_t result(num_bytes); - std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin()); - return result; -} - -/*********************************************************************** - * Aux DAX/ADC - **********************************************************************/ -/*! - * Static function to convert a unit type enum - * to an over-the-wire value for the usrp2 control. - * \param unit the dboard interface unit type enum - * \return an over the wire representation - */ -static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){ - switch(unit){ - case dboard_interface::UNIT_TX: return USRP2_DIR_TX; - case dboard_interface::UNIT_RX: return USRP2_DIR_RX; - } - throw std::invalid_argument("unknown unit type"); -} - -void usrp2_dboard_interface::write_aux_dac(unit_t unit, int which, int value){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO); - out_data.data.aux_args.dir = unit_to_otw(unit); - out_data.data.aux_args.which = which; - out_data.data.aux_args.value = htonl(value); - - //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); -} - -int usrp2_dboard_interface::read_aux_adc(unit_t unit, int which){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO); - out_data.data.aux_args.dir = unit_to_otw(unit); - out_data.data.aux_args.which = which; - - //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE); - return ntohl(in_data.data.aux_args.value); -} diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 92b55d029..664d69948 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -82,11 +83,11 @@ void usrp2_impl::init_ddc_config(void){ void usrp2_impl::update_ddc_config(void){ //set the decimation - this->poke32(FR_DSP_RX_DECIM_RATE, _ddc_decim); + _iface->poke32(FR_DSP_RX_DECIM_RATE, _ddc_decim); //set the scaling static const boost::int16_t default_rx_scale_iq = 1024; - this->poke32(FR_DSP_RX_SCALE_IQ, + _iface->poke32(FR_DSP_RX_SCALE_IQ, calculate_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) ); } @@ -126,7 +127,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); _ddc_freq = new_freq; //shadow - this->poke32(FR_DSP_RX_FREQ, + _iface->poke32(FR_DSP_RX_FREQ, calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq()) ); } @@ -170,10 +171,10 @@ void usrp2_impl::update_duc_config(void){ boost::int16_t scale = rint((4096*std::pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed)); //set the interpolation - this->poke32(FR_DSP_TX_INTERP_RATE, _ddc_decim); + _iface->poke32(FR_DSP_TX_INTERP_RATE, _ddc_decim); //set the scaling - this->poke32(FR_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale)); + _iface->poke32(FR_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale)); } /*********************************************************************** @@ -211,7 +212,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); _duc_freq = new_freq; //shadow - this->poke32(FR_DSP_TX_FREQ, + _iface->poke32(FR_DSP_TX_FREQ, calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq()) ); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 87fc88ceb..367a1d9fb 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -18,6 +18,7 @@ #include "usrp2_impl.hpp" #include #include +#include //htonl and ntohl #include using namespace uhd; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index ea268651a..1521de1fe 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -22,6 +22,9 @@ #include #include #include +#include +#include //htonl and ntohl +#include using namespace uhd; using namespace uhd::usrp; @@ -35,7 +38,7 @@ void usrp2_impl::mboard_init(void){ boost::bind(&usrp2_impl::mboard_set, this, _1, _2) ); - _clock_control = clock_control::make_ad9510(this); + _clk_ctrl = clock_control::make_ad9510(_iface); //setup the ad9777 dac ad9777_regs_t ad9777_regs; @@ -58,14 +61,10 @@ void usrp2_impl::mboard_init(void){ //write all regs for(boost::uint8_t addr = 0; addr <= 0xC; addr++){ boost::uint16_t data = ad9777_regs.get_write_reg(addr); - this->transact_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, data, 16, false /*no rb*/); + _iface->transact_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, data, 16, false /*no rb*/); } } -clock_control::sptr usrp2_impl::get_clock_control(void){ - return _clock_control; -} - void usrp2_impl::init_clock_config(void){ //setup the clock configuration settings _clock_config.ref_source = clock_config_t::REF_INT; @@ -94,28 +93,28 @@ void usrp2_impl::update_clock_config(void){ } //set the pps flags - this->poke32(FR_TIME64_FLAGS, pps_flags); + _iface->poke32(FR_TIME64_FLAGS, pps_flags); //clock source ref 10mhz switch(_clock_config.ref_source){ - case clock_config_t::REF_INT : this->poke32(FR_CLOCK_CONTROL, 0x10); break; - case clock_config_t::REF_SMA : this->poke32(FR_CLOCK_CONTROL, 0x1C); break; - case clock_config_t::REF_MIMO: this->poke32(FR_CLOCK_CONTROL, 0x15); break; + case clock_config_t::REF_INT : _iface->poke32(FR_CLOCK_CONTROL, 0x10); break; + case clock_config_t::REF_SMA : _iface->poke32(FR_CLOCK_CONTROL, 0x1C); break; + case clock_config_t::REF_MIMO: _iface->poke32(FR_CLOCK_CONTROL, 0x15); break; } //clock source ref 10mhz bool use_external = _clock_config.ref_source != clock_config_t::REF_INT; - this->get_clock_control()->enable_external_ref(use_external); + _clk_ctrl->enable_external_ref(use_external); } void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){ //set ticks and seconds - this->poke32(FR_TIME64_SECS, time_spec.secs); - this->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq())); + _iface->poke32(FR_TIME64_SECS, time_spec.secs); + _iface->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq())); //set the register to latch it all in boost::uint32_t imm_flags = (now)? FRF_TIME64_LATCH_NOW : FRF_TIME64_LATCH_NEXT_PPS; - this->poke32(FR_TIME64_IMM, imm_flags); + _iface->poke32(FR_TIME64_IMM, imm_flags); } void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ @@ -151,7 +150,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ } //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE); } @@ -170,7 +169,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO); //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); //extract the address @@ -184,7 +183,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); //extract the address @@ -272,7 +271,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr); //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); return; } @@ -284,7 +283,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(val.as()).to_ulong()); //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); return; } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp new file mode 100644 index 000000000..5c84fd8d3 --- /dev/null +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -0,0 +1,168 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "usrp2_iface.hpp" +#include +#include +#include +#include //used for htonl and ntohl +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +class usrp2_iface_impl : public usrp2_iface{ +public: +/*********************************************************************** + * Structors + **********************************************************************/ + usrp2_iface_impl(transport::udp_simple::sptr ctrl_transport){ + _ctrl_transport = ctrl_transport; + } + + ~usrp2_iface_impl(void){ + /* NOP */ + } + +/*********************************************************************** + * Peek and Poke + **********************************************************************/ + void poke32(boost::uint32_t addr, boost::uint32_t data){ + return this->poke(addr, data); + } + + boost::uint32_t peek32(boost::uint32_t addr){ + return this->peek(addr); + } + + void poke16(boost::uint32_t addr, boost::uint16_t data){ + return this->poke(addr, data); + } + + boost::uint16_t peek16(boost::uint32_t addr){ + return this->peek(addr); + } + +/*********************************************************************** + * SPI + **********************************************************************/ + boost::uint32_t transact_spi( + int which_slave, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ){ + static const uhd::dict spi_edge_to_otw = boost::assign::map_list_of + (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE) + (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL) + ; + + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); + out_data.data.spi_args.dev = which_slave; + out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge]; + out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge]; + out_data.data.spi_args.readback = (readback)? 1 : 0; + out_data.data.spi_args.num_bits = num_bits; + out_data.data.spi_args.data = htonl(data); + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); + + return ntohl(out_data.data.spi_args.data); + } + +/*********************************************************************** + * Send/Recv over control + **********************************************************************/ + usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){ + boost::mutex::scoped_lock lock(_ctrl_mutex); + + //fill in the seq number and send + usrp2_ctrl_data_t out_copy = out_data; + out_copy.seq = htonl(++_ctrl_seq_num); + _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t))); + + //loop until we get the packet or timeout + while(true){ + usrp2_ctrl_data_t in_data; + size_t len = _ctrl_transport->recv(boost::asio::buffer(&in_data, sizeof(in_data))); + if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(in_data.seq) == _ctrl_seq_num){ + return in_data; + } + if (len == 0) break; //timeout + //didnt get seq or bad packet, continue looking... + } + throw std::runtime_error("usrp2 no control response"); + } + +/*********************************************************************** + * Master Clock! Ahhhhh + **********************************************************************/ + double get_master_clock_freq(void){ + return 100e6; + } + +private: + //this lovely lady makes it all possible + transport::udp_simple::sptr _ctrl_transport; + + //used in send/recv + boost::mutex _ctrl_mutex; + boost::uint32_t _ctrl_seq_num; + +/*********************************************************************** + * Private Templated Peek and Poke + **********************************************************************/ + template void poke(boost::uint32_t addr, T data){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO); + out_data.data.poke_args.addr = htonl(addr); + out_data.data.poke_args.data = htonl(boost::uint32_t(data)); + out_data.data.poke_args.num_bytes = sizeof(T); + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE); + } + + template T peek(boost::uint32_t addr){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO); + out_data.data.poke_args.addr = htonl(addr); + out_data.data.poke_args.num_bytes = sizeof(T); + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE); + return T(ntohl(out_data.data.poke_args.data)); + } + +}; + +/*********************************************************************** + * Public make function for usrp2 interface + **********************************************************************/ +usrp2_iface::sptr usrp2_iface::make(transport::udp_simple::sptr ctrl_transport){ + return usrp2_iface::sptr(new usrp2_iface_impl(ctrl_transport)); +} diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp new file mode 100644 index 000000000..7b4321c0b --- /dev/null +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -0,0 +1,103 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INCLUDED_USRP2_IFACE_HPP +#define INCLUDED_USRP2_IFACE_HPP + +#include +#include //spi config +#include +#include +#include +#include "fw_common.h" + +/*! + * The usrp2 interface class: + * Provides a set of functions to implementation layer. + * Including spi, peek, poke, control... + */ +class usrp2_iface : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new usrp2 interface with the control transport. + * \param ctrl_transport the udp transport object + * \return a new usrp2 interface object + */ + static sptr make(uhd::transport::udp_simple::sptr ctrl_transport); + + /*! + * Perform a control transaction. + * \param data a control data struct + * \return the result control data + */ + virtual usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &data) = 0; + + /*! + * Write a register (32 bits) + * \param addr the address + * \param data the 32bit data + */ + virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; + + /*! + * Read a register (32 bits) + * \param addr the address + * \return the 32bit data + */ + virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; + + /*! + * Write a register (16 bits) + * \param addr the address + * \param data the 16bit data + */ + virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; + + /*! + * Read a register (16 bits) + * \param addr the address + * \return the 16bit data + */ + virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; + + /*! + * Perform an spi transaction. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write + * \param num_bits how many bits in data + * \param readback true to readback a value + * \return spi data if readback set + */ + virtual boost::uint32_t transact_spi( + int which_slave, + const uhd::usrp::spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ) = 0; + + /*! + * Get the master clock frequency. + * \return the frequency in Hz + */ + virtual double get_master_clock_freq(void) = 0; +}; + +#endif /* INCLUDED_USRP2_IFACE_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 6d8c1a86c..3bdc5bd02 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -17,6 +17,7 @@ #include "usrp2_impl.hpp" #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include //htonl and ntohl #include using namespace uhd; @@ -61,7 +63,6 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){ } //create a udp transport to communicate - //TODO if an addr is not provided, search all interfaces? std::string ctrl_port = boost::lexical_cast(USRP2_UDP_CTRL_PORT); udp_simple::sptr udp_transport = udp_simple::make_broadcast( hint["addr"], ctrl_port @@ -128,9 +129,11 @@ usrp2_impl::usrp2_impl( udp_simple::sptr ctrl_transport, udp_zero_copy::sptr data_transport ){ - _ctrl_transport = ctrl_transport; _data_transport = data_transport; + //make a new interface for usrp2 stuff + _iface = usrp2_iface::make(ctrl_transport); + //load the allowed decim/interp rates //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) _allowed_decim_and_interp_rates.clear(); @@ -168,109 +171,6 @@ usrp2_impl::~usrp2_impl(void){ /* NOP */ } -/*********************************************************************** - * Misc Access Methods - **********************************************************************/ -double usrp2_impl::get_master_clock_freq(void){ - return 100e6; -} - -template void impl_poke(usrp2_impl *impl, boost::uint32_t addr, T data){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO); - out_data.data.poke_args.addr = htonl(addr); - out_data.data.poke_args.data = htonl(boost::uint32_t(data)); - out_data.data.poke_args.num_bytes = sizeof(T); - - //send and recv - usrp2_ctrl_data_t in_data = impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE); -} - -template T impl_peek(usrp2_impl *impl, boost::uint32_t addr){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO); - out_data.data.poke_args.addr = htonl(addr); - out_data.data.poke_args.num_bytes = sizeof(T); - - //send and recv - usrp2_ctrl_data_t in_data = impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE); - return T(ntohl(out_data.data.poke_args.data)); -} - - -void usrp2_impl::poke32(boost::uint32_t addr, boost::uint32_t data){ - return impl_poke(this, addr, data); -} - -boost::uint32_t usrp2_impl::peek32(boost::uint32_t addr){ - return impl_peek(this, addr); -} - -void usrp2_impl::poke16(boost::uint32_t addr, boost::uint16_t data){ - return impl_poke(this, addr, data); -} - -boost::uint16_t usrp2_impl::peek16(boost::uint32_t addr){ - return impl_peek(this, addr); -} - -boost::uint32_t usrp2_impl::transact_spi( - int which_slave, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits, - bool readback -){ - static const uhd::dict spi_edge_to_otw = boost::assign::map_list_of - (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE) - (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL) - ; - - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); - out_data.data.spi_args.dev = which_slave; - out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge]; - out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge]; - out_data.data.spi_args.readback = (readback)? 1 : 0; - out_data.data.spi_args.num_bits = num_bits; - out_data.data.spi_args.data = htonl(data); - - //send and recv - usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); - - return ntohl(out_data.data.spi_args.data); -} - -/*********************************************************************** - * Control Send/Recv - **********************************************************************/ -usrp2_ctrl_data_t usrp2_impl::ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){ - boost::mutex::scoped_lock lock(_ctrl_mutex); - - //fill in the seq number and send - usrp2_ctrl_data_t out_copy = out_data; - out_copy.seq = htonl(++_ctrl_seq_num); - _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t))); - - //loop until we get the packet or timeout - while(true){ - usrp2_ctrl_data_t in_data; - size_t len = _ctrl_transport->recv(asio::buffer(&in_data, sizeof(in_data))); - if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(in_data.seq) == _ctrl_seq_num){ - return in_data; - } - if (len == 0) break; //timeout - //didnt get seq or bad packet, continue looking... - } - throw std::runtime_error("usrp2 no control response"); -} - /*********************************************************************** * Device Properties **********************************************************************/ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index f2e823391..7eea1e250 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -18,31 +18,29 @@ #ifndef INCLUDED_USRP2_IMPL_HPP #define INCLUDED_USRP2_IMPL_HPP +#include "usrp2_iface.hpp" #include "clock_control.hpp" #include #include #include #include #include -#include -#include #include #include -#include #include -#include #include #include -#include "fw_common.h" - -class usrp2_impl; //dummy class declaration /*! * Make a usrp2 dboard interface. - * \param impl a pointer to the usrp2 impl object + * \param iface the usrp2 interface object + * \param clk_ctrl the clock control object * \return a sptr to a new dboard interface */ -uhd::usrp::dboard_interface::sptr make_usrp2_dboard_interface(usrp2_impl *impl); +uhd::usrp::dboard_interface::sptr make_usrp2_dboard_iface( + usrp2_iface::sptr iface, + clock_control::sptr clk_ctrl +); /*! * Simple wax obj proxy class: @@ -101,40 +99,22 @@ public: ~usrp2_impl(void); - //performs a control transaction - usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &); - - //peek and poke registers - void poke32(boost::uint32_t addr, boost::uint32_t data); - boost::uint32_t peek32(boost::uint32_t addr); - - void poke16(boost::uint32_t addr, boost::uint16_t data); - boost::uint16_t peek16(boost::uint32_t addr); - - //clock control - clock_control::sptr get_clock_control(void); - - //spi read and write - boost::uint32_t transact_spi( - int which_slave, - const uhd::usrp::spi_config_t &config, - boost::uint32_t data, - size_t num_bits, - bool readback - ); - - //misc access methods - double get_master_clock_freq(void); - //the io interface size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &); size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &); private: + double get_master_clock_freq(void){ + return _iface->get_master_clock_freq(); + } + //device properties interface void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); - clock_control::sptr _clock_control; + + //interfaces + clock_control::sptr _clk_ctrl; + usrp2_iface::sptr _iface; //the raw io interface (samples are in the usrp2 native format) void recv_raw(uhd::rx_metadata_t &); @@ -158,13 +138,8 @@ private: void io_init(void); //udp transports for control and data - uhd::transport::udp_simple::sptr _ctrl_transport; uhd::transport::udp_zero_copy::sptr _data_transport; - //private vars for dealing with send/recv control - boost::uint32_t _ctrl_seq_num; - boost::mutex _ctrl_mutex; - //methods and shadows for clock configuration uhd::clock_config_t _clock_config; void init_clock_config(void); -- cgit v1.2.3