diff options
43 files changed, 919 insertions, 978 deletions
| diff --git a/firmware/zpu/apps/txrx_uhd.c b/firmware/zpu/apps/txrx_uhd.c index 4ccb585e2..0c93d2352 100644 --- a/firmware/zpu/apps/txrx_uhd.c +++ b/firmware/zpu/apps/txrx_uhd.c @@ -53,20 +53,34 @@ static void setup_network(void);  // the fast-path setup global variables  // ----------------------------------------------------------------  static eth_mac_addr_t fp_mac_addr_src, fp_mac_addr_dst; -extern struct socket_address fp_socket_src, fp_socket_dst; +struct socket_address fp_socket_src, fp_socket_dst; +extern uint16_t dsp0_dst_port, err0_dst_port, dsp1_dst_port;  static void handle_udp_err0_packet(      struct socket_address src, struct socket_address dst,      unsigned char *payload, int payload_len  ){      sr_udp_sm->err0_port = (((uint32_t)dst.port) << 16) | src.port; +    err0_dst_port = src.port;      printf("Storing for async error path:\n");      printf("  source udp port: %d\n", dst.port);      printf("  destination udp port: %d\n", src.port);      newline();  } -static void handle_udp_data_packet( +static void handle_udp_dsp1_packet( +    struct socket_address src, struct socket_address dst, +    unsigned char *payload, int payload_len +){ +    sr_udp_sm->dsp1_port = (((uint32_t)dst.port) << 16) | src.port; +    dsp1_dst_port = src.port; +    printf("Storing for dsp1 path:\n"); +    printf("  source udp port: %d\n", dst.port); +    printf("  destination udp port: %d\n", src.port); +    newline(); +} + +static void handle_udp_dsp0_packet(      struct socket_address src, struct socket_address dst,      unsigned char *payload, int payload_len  ){ @@ -75,7 +89,8 @@ static void handle_udp_data_packet(      fp_socket_src = dst;      fp_socket_dst = src;      sr_udp_sm->dsp0_port = (((uint32_t)dst.port) << 16) | src.port; -    printf("Storing for fast path:\n"); +    dsp0_dst_port = src.port; +    printf("Storing for dsp0 path:\n");      printf("  source mac addr: ");      print_mac_addr(&fp_mac_addr_src); newline();      printf("  source ip addr: "); @@ -341,13 +356,14 @@ main(void)    //1) register the addresses into the network stack    register_addrs(ethernet_mac_addr(), get_ip_addr()); -  pkt_ctrl_program_inspector(get_ip_addr(), USRP2_UDP_DATA_PORT); +  pkt_ctrl_program_inspector(get_ip_addr(), USRP2_UDP_DSP0_PORT);    //2) register callbacks for udp ports we service    init_udp_listeners();    register_udp_listener(USRP2_UDP_CTRL_PORT, handle_udp_ctrl_packet); -  register_udp_listener(USRP2_UDP_DATA_PORT, handle_udp_data_packet); +  register_udp_listener(USRP2_UDP_DSP0_PORT, handle_udp_dsp0_packet);    register_udp_listener(USRP2_UDP_ERR0_PORT, handle_udp_err0_packet); +  register_udp_listener(USRP2_UDP_DSP1_PORT, handle_udp_dsp1_packet);  #ifdef USRP2P    register_udp_listener(USRP2_UDP_UPDATE_PORT, handle_udp_fw_update_packet);  #endif diff --git a/firmware/zpu/lib/net_common.c b/firmware/zpu/lib/net_common.c index d1b06976d..6a0fd254b 100644 --- a/firmware/zpu/lib/net_common.c +++ b/firmware/zpu/lib/net_common.c @@ -1,6 +1,5 @@ -/* -*- c -*- */  /* - * Copyright 2009,2010 Ettus Research LLC + * Copyright 2009-2011 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 @@ -42,7 +41,7 @@ static const bool debug = false;  static const eth_mac_addr_t BCAST_MAC_ADDR = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};  //used in the top level application... -struct socket_address fp_socket_src, fp_socket_dst; +uint16_t dsp0_dst_port, err0_dst_port, dsp1_dst_port;  // ------------------------------------------------------------------------ @@ -277,15 +276,24 @@ handle_icmp_packet(struct ip_addr src, struct ip_addr dst,        //filter out non udp data response        struct ip_hdr *ip = (struct ip_hdr *)(((uint8_t*)icmp) + sizeof(struct icmp_echo_hdr));        struct udp_hdr *udp = (struct udp_hdr *)(((char *)ip) + IP_HLEN); -      if (IPH_PROTO(ip) != IP_PROTO_UDP || udp->dest != fp_socket_dst.port) return; - -      //end async update packets per second -      sr_tx_ctrl->cyc_per_up = 0; - -      //the end continuous streaming command -      sr_rx_ctrl->cmd = 1 << 31; //no samples now -      sr_rx_ctrl->time_secs = 0; -      sr_rx_ctrl->time_ticks = 0; //latch the command +      if (IPH_PROTO(ip) != IP_PROTO_UDP) break; + +      if (udp->dest == dsp0_dst_port){ +          //the end continuous streaming command +          sr_rx_ctrl0->cmd = 1 << 31; //no samples now +          sr_rx_ctrl0->time_secs = 0; +          sr_rx_ctrl0->time_ticks = 0; //latch the command +      } +      else if (udp->dest == dsp1_dst_port){ +          //the end continuous streaming command +          sr_rx_ctrl1->cmd = 1 << 31; //no samples now +          sr_rx_ctrl1->time_secs = 0; +          sr_rx_ctrl1->time_ticks = 0; //latch the command +      } +      else if (udp->dest == err0_dst_port){ +          //end async update packets per second +          sr_tx_ctrl->cyc_per_up = 0; +      }        //struct udp_hdr *udp = (struct udp_hdr *)((char *)icmp + 28);        //printf("icmp port unr %d\n", udp->dest); diff --git a/firmware/zpu/usrp2/memory_map.h b/firmware/zpu/usrp2/memory_map.h index e728a1ddb..79b11759a 100644 --- a/firmware/zpu/usrp2/memory_map.h +++ b/firmware/zpu/usrp2/memory_map.h @@ -1,4 +1,4 @@ -/* -*- c -*- */ +// Copyright 2010-2011 Ettus Research LLC  /*   * Copyright 2007,2008,2009 Free Software Foundation, Inc.   * @@ -227,8 +227,10 @@ hwconfig_wishbone_divisor(void)  #define SR_UDP_SM 96  #define SR_TX_DSP 208  #define SR_TX_CTRL 224 -#define SR_RX_DSP 160 -#define SR_RX_CTRL 176 +#define SR_RX_DSP0 160 +#define SR_RX_DSP1 240 +#define SR_RX_CTRL0 176 +#define SR_RX_CTRL1 32  #define SR_TIME64 192  #define SR_SIMTIMER 198  #define SR_LAST 255 @@ -350,10 +352,7 @@ typedef struct {  #define sr_udp_sm ((sr_udp_sm_t *) _SR_ADDR(SR_UDP_SM)) -// --- dsp tx regs --- - -#define MIN_CIC_INTERP	1 -#define	MAX_CIC_INTERP  128 +// --- VITA TX CTRL regs ---  typedef struct {    volatile uint32_t     num_chan; @@ -366,52 +365,6 @@ typedef struct {  #define sr_tx_ctrl ((sr_tx_ctrl_t *) _SR_ADDR(SR_TX_CTRL)) -typedef struct { -  volatile int32_t	freq; -  volatile uint32_t	scale_iq;	// {scale_i,scale_q} -  volatile uint32_t     interp_rate; -  volatile uint32_t     _padding0;      // padding for the tx_mux -                                        //   NOT freq, scale, interp -  /*! -   * \brief output mux configuration. -   * -   * <pre> -   *     3                   2                   1                        -   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -   *  +-------------------------------+-------+-------+-------+-------+ -   *  |                                               | DAC1  |  DAC0 | -   *  +-------------------------------+-------+-------+-------+-------+ -   *  -   *  There are N DUCs (1 now) with complex inputs and outputs. -   *  There are two DACs. -   *  -   *  Each 4-bit DACx field specifies the source for the DAC -   *  Each subfield is coded like this:  -   *  -   *     3 2 1 0 -   *    +-------+ -   *    |   N   | -   *    +-------+ -   *  -   *  N specifies which DUC output is connected to this DAC. -   *  -   *   N   which interp output -   *  ---  ------------------- -   *   0   DUC 0 I -   *   1   DUC 0 Q -   *   2   DUC 1 I -   *   3   DUC 1 Q -   *   F   All Zeros -   *    -   * The default value is 0x10 -   * </pre> -   */ -  volatile uint32_t	tx_mux; - -} dsp_tx_regs_t; -   -#define dsp_tx_regs ((dsp_tx_regs_t *) _SR_ADDR(SR_TX_DSP)) -  // --- VITA RX CTRL regs ---  typedef struct {    // The following 3 are logically a single command register. @@ -419,81 +372,10 @@ typedef struct {    volatile uint32_t	cmd;		// {now, chain, num_samples(30)    volatile uint32_t	time_secs;    volatile uint32_t	time_ticks; - -  volatile uint32_t	clear_overrun;	// write anything to clear overrun -  volatile uint32_t	vrt_header;	// word 0 of packet.  FPGA fills in packet counter -  volatile uint32_t	vrt_stream_id;	// word 1 of packet.  -  volatile uint32_t	vrt_trailer; -  volatile uint32_t	nsamples_per_pkt; -  volatile uint32_t     nchannels;      // 1 in basic case, up to 4 for vector sources -  volatile uint32_t     pad[7];         // Make each structure 16 elements long  } sr_rx_ctrl_t; -#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL)) - -// --- dsp rx regs --- -#define	MIN_CIC_DECIM	1 -#define	MAX_CIC_DECIM   128 - -typedef struct { -  volatile int32_t	freq; -  volatile uint32_t	scale_iq;	// {scale_i,scale_q} -  volatile uint32_t     decim_rate; -  volatile uint32_t     dcoffset_i;     // Bit 31 high sets fixed offset mode, using lower 14 bits, -                                        // otherwise it is automatic  -  volatile uint32_t     dcoffset_q;     // Bit 31 high sets fixed offset mode, using lower 14 bits - -  /*! -   * \brief input mux configuration. -   * -   * This determines which ADC (or constant zero) is connected to  -   * each DDC input.  There are N DDCs (1 now).  Each has two inputs. -   * -   * <pre> -   * Mux value: -   * -   *    3                   2                   1                        -   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * |                                                       |Q0 |I0 | -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * -   * Each 2-bit I field is either 00 (A/D A), 01 (A/D B) or 1X (const zero) -   * Each 2-bit Q field is either 00 (A/D A), 01 (A/D B) or 1X (const zero) -   * -   * The default value is 0x4 -   * </pre> -   */ -  volatile uint32_t     rx_mux;        // called adc_mux in dsp_core_rx.v - -  /*! -   * \brief Streaming GPIO configuration -   * -   * This determines whether the LSBs of I and Q samples come from the DSP -   * pipeline or from the io_rx GPIO pins.  To stream GPIO, one must first -   * set the GPIO data direction register to have io_rx[15] and/or io_rx[14] -   * configured as inputs.  The GPIO pins will be sampled at the time the -   * remainder of the DSP sample is strobed into the RX sample FIFO.  There -   * will be a decimation-dependent fixed time offset between the GPIO -   * sample stream and the associated RF samples. -   * -   *    3                   2                   1                        -   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * |                           MBZ                             |Q|I| -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * -   * I         0=LSB comes from DSP pipeline (default) -   *           1=LSB comes from io_rx[15] -   *  -   * Q         0=LSB comes from DSP pipeline (default) -   *           1=LSB comes from io_rx[14] -   */ -  volatile uint32_t gpio_stream_enable; - -} dsp_rx_regs_t; -   -#define dsp_rx_regs ((dsp_rx_regs_t *) _SR_ADDR(SR_RX_DSP)) +#define sr_rx_ctrl0 ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL0)) +#define sr_rx_ctrl1 ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL1))  // ----------------------------------------------------------------  // VITA49 64 bit time (write only) diff --git a/firmware/zpu/usrp2p/memory_map.h b/firmware/zpu/usrp2p/memory_map.h index 36d8ac9f2..2567a4588 100644 --- a/firmware/zpu/usrp2p/memory_map.h +++ b/firmware/zpu/usrp2p/memory_map.h @@ -1,4 +1,4 @@ -/* -*- c -*- */ +// Copyright 2010-2011 Ettus Research LLC  /*   * Copyright 2007,2008,2009 Free Software Foundation, Inc.   * @@ -218,8 +218,10 @@ hwconfig_wishbone_divisor(void)  #define SR_UDP_SM 96  #define SR_TX_DSP 208  #define SR_TX_CTRL 224 -#define SR_RX_DSP 160 -#define SR_RX_CTRL 176 +#define SR_RX_DSP0 160 +#define SR_RX_DSP1 240 +#define SR_RX_CTRL0 176 +#define SR_RX_CTRL1 32  #define SR_TIME64 192  #define SR_SIMTIMER 198  #define SR_LAST 255 @@ -343,10 +345,7 @@ typedef struct {  #define sr_udp_sm ((sr_udp_sm_t *) _SR_ADDR(SR_UDP_SM)) -// --- dsp tx regs --- - -#define MIN_CIC_INTERP	1 -#define	MAX_CIC_INTERP  128 +// --- VITA TX CTRL regs ---  typedef struct {    volatile uint32_t     num_chan; @@ -359,52 +358,6 @@ typedef struct {  #define sr_tx_ctrl ((sr_tx_ctrl_t *) _SR_ADDR(SR_TX_CTRL)) -typedef struct { -  volatile int32_t	freq; -  volatile uint32_t	scale_iq;	// {scale_i,scale_q} -  volatile uint32_t     interp_rate; -  volatile uint32_t     _padding0;      // padding for the tx_mux -                                        //   NOT freq, scale, interp -  /*! -   * \brief output mux configuration. -   * -   * <pre> -   *     3                   2                   1                        -   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -   *  +-------------------------------+-------+-------+-------+-------+ -   *  |                                               | DAC1  |  DAC0 | -   *  +-------------------------------+-------+-------+-------+-------+ -   *  -   *  There are N DUCs (1 now) with complex inputs and outputs. -   *  There are two DACs. -   *  -   *  Each 4-bit DACx field specifies the source for the DAC -   *  Each subfield is coded like this:  -   *  -   *     3 2 1 0 -   *    +-------+ -   *    |   N   | -   *    +-------+ -   *  -   *  N specifies which DUC output is connected to this DAC. -   *  -   *   N   which interp output -   *  ---  ------------------- -   *   0   DUC 0 I -   *   1   DUC 0 Q -   *   2   DUC 1 I -   *   3   DUC 1 Q -   *   F   All Zeros -   *    -   * The default value is 0x10 -   * </pre> -   */ -  volatile uint32_t	tx_mux; - -} dsp_tx_regs_t; -   -#define dsp_tx_regs ((dsp_tx_regs_t *) _SR_ADDR(SR_TX_DSP)) -  // --- VITA RX CTRL regs ---  typedef struct {    // The following 3 are logically a single command register. @@ -412,81 +365,10 @@ typedef struct {    volatile uint32_t	cmd;		// {now, chain, num_samples(30)    volatile uint32_t	time_secs;    volatile uint32_t	time_ticks; - -  volatile uint32_t	clear_overrun;	// write anything to clear overrun -  volatile uint32_t	vrt_header;	// word 0 of packet.  FPGA fills in packet counter -  volatile uint32_t	vrt_stream_id;	// word 1 of packet.  -  volatile uint32_t	vrt_trailer; -  volatile uint32_t	nsamples_per_pkt; -  volatile uint32_t     nchannels;      // 1 in basic case, up to 4 for vector sources -  volatile uint32_t     pad[7];         // Make each structure 16 elements long  } sr_rx_ctrl_t; -#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL)) - -// --- dsp rx regs --- -#define	MIN_CIC_DECIM	1 -#define	MAX_CIC_DECIM   128 - -typedef struct { -  volatile int32_t	freq; -  volatile uint32_t	scale_iq;	// {scale_i,scale_q} -  volatile uint32_t     decim_rate; -  volatile uint32_t     dcoffset_i;     // Bit 31 high sets fixed offset mode, using lower 14 bits, -                                        // otherwise it is automatic  -  volatile uint32_t     dcoffset_q;     // Bit 31 high sets fixed offset mode, using lower 14 bits - -  /*! -   * \brief input mux configuration. -   * -   * This determines which ADC (or constant zero) is connected to  -   * each DDC input.  There are N DDCs (1 now).  Each has two inputs. -   * -   * <pre> -   * Mux value: -   * -   *    3                   2                   1                        -   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * |                                                       |Q0 |I0 | -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * -   * Each 2-bit I field is either 00 (A/D A), 01 (A/D B) or 1X (const zero) -   * Each 2-bit Q field is either 00 (A/D A), 01 (A/D B) or 1X (const zero) -   * -   * The default value is 0x4 -   * </pre> -   */ -  volatile uint32_t     rx_mux;        // called adc_mux in dsp_core_rx.v - -  /*! -   * \brief Streaming GPIO configuration -   * -   * This determines whether the LSBs of I and Q samples come from the DSP -   * pipeline or from the io_rx GPIO pins.  To stream GPIO, one must first -   * set the GPIO data direction register to have io_rx[15] and/or io_rx[14] -   * configured as inputs.  The GPIO pins will be sampled at the time the -   * remainder of the DSP sample is strobed into the RX sample FIFO.  There -   * will be a decimation-dependent fixed time offset between the GPIO -   * sample stream and the associated RF samples. -   * -   *    3                   2                   1                        -   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * |                           MBZ                             |Q|I| -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * -   * I         0=LSB comes from DSP pipeline (default) -   *           1=LSB comes from io_rx[15] -   *  -   * Q         0=LSB comes from DSP pipeline (default) -   *           1=LSB comes from io_rx[14] -   */ -  volatile uint32_t gpio_stream_enable; - -} dsp_rx_regs_t; -   -#define dsp_rx_regs ((dsp_rx_regs_t *) _SR_ADDR(SR_RX_DSP)) +#define sr_rx_ctrl0 ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL0)) +#define sr_rx_ctrl1 ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL1))  // ----------------------------------------------------------------  // VITA49 64 bit time (write only) diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index 296f480b0..e202fcb1c 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -78,7 +78,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl;      boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time -    std::cout << "LO Locked = " << usrp->get_rx_lo_locked() << std::endl;      //setup streaming      uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp index 801d8e361..7ea775764 100644 --- a/host/examples/rx_samples_to_udp.cpp +++ b/host/examples/rx_samples_to_udp.cpp @@ -80,7 +80,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl;      boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time -    std::cout << "LO Locked = " << usrp->get_rx_lo_locked() << std::endl;      //setup streaming      uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp index eb3394230..2c0841146 100644 --- a/host/include/uhd/types/device_addr.hpp +++ b/host/include/uhd/types/device_addr.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -84,9 +84,15 @@ namespace uhd{          }      }; -    //handy typedef for a vector of device addresses +    //! A typedef for a vector of device addresses      typedef std::vector<device_addr_t> device_addrs_t; +    //! Separate an indexed device address into a vector of device addresses +    UHD_API device_addrs_t separate_device_addr(const device_addr_t &dev_addr); + +    //! Combine a vector of device addresses into an indexed device address +    UHD_API device_addr_t combine_device_addrs(const device_addrs_t &dev_addrs); +  } //namespace uhd  #endif /* INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP */ diff --git a/host/include/uhd/types/sensors.hpp b/host/include/uhd/types/sensors.hpp index 6f003bb40..b6215367f 100644 --- a/host/include/uhd/types/sensors.hpp +++ b/host/include/uhd/types/sensors.hpp @@ -37,12 +37,6 @@ namespace uhd{       */      struct UHD_API sensor_value_t{ -        //! typedef for the signed integer type -        typedef signed int_type; - -        //! typedef for the real number type -        typedef double real_type; -          /*!           * Create a sensor value from a boolean.           * \param name the name of the sensor @@ -66,7 +60,7 @@ namespace uhd{           */          sensor_value_t(              const std::string &name, -            int_type value, +            signed value,              const std::string &unit,              const std::string &formatter = "%d"          ); @@ -80,7 +74,7 @@ namespace uhd{           */          sensor_value_t(              const std::string &name, -            real_type value, +            double value,              const std::string &unit,              const std::string &formatter = "%f"          ); @@ -97,6 +91,15 @@ namespace uhd{              const std::string &unit          ); +        //! convert the sensor value to a boolean +        bool to_bool(void) const; + +        //! convert the sensor value to an integer +        signed to_int(void) const; + +        //! convert the sensor value to real number +        double to_real(void) const; +          //! The name of the sensor value          const std::string name; diff --git a/host/include/uhd/usrp/codec_props.hpp b/host/include/uhd/usrp/codec_props.hpp index 5d0a2913c..b0a79e3f6 100644 --- a/host/include/uhd/usrp/codec_props.hpp +++ b/host/include/uhd/usrp/codec_props.hpp @@ -28,12 +28,12 @@ namespace uhd{ namespace usrp{      *   Other properties can be discovered through the others prop.      */      enum codec_prop_t{ -        CODEC_PROP_NAME           = 'n', //ro, std::string -        CODEC_PROP_OTHERS         = 'o', //ro, prop_names_t -        CODEC_PROP_GAIN_I         = 'i', //rw, double -        CODEC_PROP_GAIN_Q         = 'q', //rw, double -        CODEC_PROP_GAIN_RANGE     = 'r', //ro, gain_range_t -        CODEC_PROP_GAIN_NAMES     = 'G'  //ro, prop_names_t +        CODEC_PROP_NAME,            //ro, std::string +        CODEC_PROP_OTHERS,          //ro, prop_names_t +        CODEC_PROP_GAIN_I,          //rw, double +        CODEC_PROP_GAIN_Q ,         //rw, double +        CODEC_PROP_GAIN_RANGE,      //ro, gain_range_t +        CODEC_PROP_GAIN_NAMES       //ro, prop_names_t      }; diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp index aab6c31ce..32ec1c1bf 100644 --- a/host/include/uhd/usrp/dboard_props.hpp +++ b/host/include/uhd/usrp/dboard_props.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -28,13 +28,13 @@ namespace uhd{ namespace usrp{       *    A dboard is considered to be unidirectional (RX or TX).       */      enum dboard_prop_t{ -        DBOARD_PROP_NAME         = 'n', //ro, std::string -        DBOARD_PROP_SUBDEV       = 's', //ro, wax::obj -        DBOARD_PROP_SUBDEV_NAMES = 'S', //ro, prop_names_t -        DBOARD_PROP_DBOARD_ID    = 'i', //rw, dboard_id_t -        DBOARD_PROP_DBOARD_IFACE = 'f', //ro, dboard_iface::sptr -        DBOARD_PROP_CODEC        = 'c', //ro, wax::obj -        DBOARD_PROP_GAIN_GROUP   = 'g'  //ro, gain_group +        DBOARD_PROP_NAME,           //ro, std::string +        DBOARD_PROP_SUBDEV,         //ro, wax::obj +        DBOARD_PROP_SUBDEV_NAMES,   //ro, prop_names_t +        DBOARD_PROP_DBOARD_ID,      //rw, dboard_id_t +        DBOARD_PROP_DBOARD_IFACE,   //ro, dboard_iface::sptr +        DBOARD_PROP_CODEC,          //ro, wax::obj +        DBOARD_PROP_GAIN_GROUP      //ro, gain_group      };   }} //namespace diff --git a/host/include/uhd/usrp/device_props.hpp b/host/include/uhd/usrp/device_props.hpp index 346eec179..3c8f7e225 100644 --- a/host/include/uhd/usrp/device_props.hpp +++ b/host/include/uhd/usrp/device_props.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -29,9 +29,9 @@ namespace uhd{ namespace usrp{       *   will be present in the interface for configuration.       */      enum device_prop_t{ -        DEVICE_PROP_NAME           = 'n', //ro, std::string -        DEVICE_PROP_MBOARD         = 'm', //ro, wax::obj -        DEVICE_PROP_MBOARD_NAMES   = 'M'  //ro, prop_names_t +        DEVICE_PROP_NAME,            //ro, std::string +        DEVICE_PROP_MBOARD,          //ro, wax::obj +        DEVICE_PROP_MBOARD_NAMES,    //ro, prop_names_t      };  }} //namespace diff --git a/host/include/uhd/usrp/dsp_props.hpp b/host/include/uhd/usrp/dsp_props.hpp index 54ea5666b..e68e11deb 100644 --- a/host/include/uhd/usrp/dsp_props.hpp +++ b/host/include/uhd/usrp/dsp_props.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -37,12 +37,12 @@ namespace uhd{ namespace usrp{       *   Set the shift property and read it back to get actual shift.       */      enum dsp_prop_t{ -        DSP_PROP_NAME              = 'n', //ro, std::string -        DSP_PROP_OTHERS            = 'o', //ro, prop_names_t -        DSP_PROP_FREQ_SHIFT        = 'f', //rw, double Hz -        DSP_PROP_FREQ_SHIFT_NAMES  = 'F', //ro, prop_names_t -        DSP_PROP_CODEC_RATE        = 'c', //ro, double Sps -        DSP_PROP_HOST_RATE         = 'h'  //rw, double Sps +        DSP_PROP_NAME,               //ro, std::string +        DSP_PROP_OTHERS,             //ro, prop_names_t +        DSP_PROP_STREAM_CMD,         //wo, stream_cmd_t +        DSP_PROP_FREQ_SHIFT,         //rw, double Hz +        DSP_PROP_CODEC_RATE,         //ro, double Sps +        DSP_PROP_HOST_RATE           //rw, double Sps      };  }} //namespace diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp index d04ad012c..2145ab446 100644 --- a/host/include/uhd/usrp/mboard_props.hpp +++ b/host/include/uhd/usrp/mboard_props.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -29,24 +29,25 @@ namespace uhd{ namespace usrp{       *   and discovered though the others property.       */      enum mboard_prop_t{ -        MBOARD_PROP_NAME            = 'n', //ro, std::string -        MBOARD_PROP_OTHERS          = 'o', //ro, prop_names_t -        MBOARD_PROP_CLOCK_RATE      = 'c', //rw, double -        MBOARD_PROP_RX_DSP          = 'd', //ro, wax::obj -        MBOARD_PROP_RX_DSP_NAMES    = 'D', //ro, prop_names_t -        MBOARD_PROP_TX_DSP          = 'u', //ro, wax::obj -        MBOARD_PROP_TX_DSP_NAMES    = 'U', //ro, prop_names_t -        MBOARD_PROP_RX_DBOARD       = 'e', //ro, wax::obj -        MBOARD_PROP_RX_DBOARD_NAMES = 'E', //ro, prop_names_t -        MBOARD_PROP_TX_DBOARD       = 'v', //ro, wax::obj -        MBOARD_PROP_TX_DBOARD_NAMES = 'V', //ro, prop_names_t -        MBOARD_PROP_RX_SUBDEV_SPEC  = 'r', //rw, subdev_spec_t -        MBOARD_PROP_TX_SUBDEV_SPEC  = 'R', //rw, subdev_spec_t -        MBOARD_PROP_CLOCK_CONFIG    = 'C', //rw, clock_config_t -        MBOARD_PROP_TIME_NOW        = 't', //rw, time_spec_t -        MBOARD_PROP_TIME_PPS        = 'T', //wo, time_spec_t -        MBOARD_PROP_STREAM_CMD      = 's', //wo, stream_cmd_t -        MBOARD_PROP_EEPROM_MAP      = 'M'  //wr, mboard_eeprom_t::sptr +        MBOARD_PROP_NAME,                    //ro, std::string +        MBOARD_PROP_OTHERS,                  //ro, prop_names_t +        MBOARD_PROP_SENSOR,                  //ro, sensor_value_t +        MBOARD_PROP_SENSOR_NAMES,            //ro, prop_names_t +        MBOARD_PROP_CLOCK_RATE,              //rw, double +        MBOARD_PROP_RX_DSP,                  //ro, wax::obj +        MBOARD_PROP_RX_DSP_NAMES,            //ro, prop_names_t +        MBOARD_PROP_TX_DSP,                  //ro, wax::obj +        MBOARD_PROP_TX_DSP_NAMES,            //ro, prop_names_t +        MBOARD_PROP_RX_DBOARD,               //ro, wax::obj +        MBOARD_PROP_RX_DBOARD_NAMES,         //ro, prop_names_t +        MBOARD_PROP_TX_DBOARD,               //ro, wax::obj +        MBOARD_PROP_TX_DBOARD_NAMES,         //ro, prop_names_t +        MBOARD_PROP_RX_SUBDEV_SPEC,          //rw, subdev_spec_t +        MBOARD_PROP_TX_SUBDEV_SPEC,          //rw, subdev_spec_t +        MBOARD_PROP_CLOCK_CONFIG,            //rw, clock_config_t +        MBOARD_PROP_TIME_NOW,                //rw, time_spec_t +        MBOARD_PROP_TIME_PPS,                //wo, time_spec_t +        MBOARD_PROP_EEPROM_MAP               //wr, mboard_eeprom_t::sptr      };  }} //namespace diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 60b757f50..b06975b6c 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -25,6 +25,7 @@  #include <uhd/types/clock_config.hpp>  #include <uhd/types/tune_request.hpp>  #include <uhd/types/tune_result.hpp> +#include <uhd/types/sensors.hpp>  #include <uhd/usrp/subdev_spec.hpp>  #include <uhd/usrp/dboard_iface.hpp>  #include <boost/shared_ptr.hpp> @@ -86,6 +87,9 @@ public:      //! A wildcard motherboard index      static const size_t ALL_MBOARDS = size_t(~0); +    //! A wildcard channel index +    static const size_t ALL_CHANS = size_t(~0); +      //! A wildcard gain element name      static const std::string ALL_GAINS; @@ -214,8 +218,9 @@ public:       * to ensure that the packets can be aligned by their time specs.       *       * \param stream_cmd the stream command to issue +     * \param chan the channel index 0 to N-1       */ -    virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; +    virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan = ALL_CHANS) = 0;      /*!       * Set the clock configuration for the usrp device. @@ -231,6 +236,21 @@ public:       */      virtual size_t get_num_mboards(void) = 0; +    /*! +     * Get a motherboard sensor value. +     * \param name the name of the sensor +     * \param mboard the motherboard index 0 to M-1 +     * \return a sensor value object +     */ +    virtual sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard = 0) = 0; + +    /*! +     * Get a list of possible motherboard sensor names. +     * \param mboard the motherboard index 0 to M-1 +     * \return a vector of sensor names +     */ +    virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0; +      /*******************************************************************       * RX methods       ******************************************************************/ @@ -266,16 +286,18 @@ public:      virtual std::string get_rx_subdev_name(size_t chan = 0) = 0;      /*! -     * Set the RX sample rate across all channels. +     * Set the RX sample rate.       * \param rate the rate in Sps +     * \param chan the channel index 0 to N-1       */ -    virtual void set_rx_rate(double rate) = 0; +    virtual void set_rx_rate(double rate, size_t chan = ALL_CHANS) = 0;      /*! -     * Gets the RX sample rate for all channels. +     * Gets the RX sample rate. +     * \param chan the channel index 0 to N-1       * \return the rate in Sps       */ -    virtual double get_rx_rate(void) = 0; +    virtual double get_rx_rate(size_t chan = 0) = 0;      /*!       * Set the RX center frequency. @@ -377,7 +399,9 @@ public:       * \param chan the channel index 0 to N-1       * \return true for locked       */ -    virtual bool get_rx_lo_locked(size_t chan = 0) = 0; +    UHD_DEPRECATED bool get_rx_lo_locked(size_t chan = 0){ +        return this->get_rx_sensor("lo_locked", chan).to_bool(); +    }      /*!       * Set the RX bandwidth on the subdevice. @@ -399,7 +423,9 @@ public:       * \return the rssi in dB       * \throw exception if RSSI readback not supported       */ -    virtual double read_rssi(size_t chan = 0) = 0; +    UHD_DEPRECATED double read_rssi(size_t chan = 0){ +        return this->get_rx_sensor("rssi", chan).to_real(); +    }      /*!       * Get the dboard interface object for the RX subdevice. @@ -410,6 +436,21 @@ public:       */      virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; +    /*! +     * Get an RX subdevice sensor value. +     * \param name the name of the sensor +     * \param chan the channel index 0 to N-1 +     * \return a sensor value object +     */ +    virtual sensor_value_t get_rx_sensor(const std::string &name, size_t chan = 0) = 0; + +    /*! +     * Get a list of possible RX subdevice sensor names. +     * \param chan the channel index 0 to N-1 +     * \return a vector of sensor names +     */ +    virtual std::vector<std::string> get_rx_sensor_names(size_t chan = 0) = 0; +      /*******************************************************************       * TX methods       ******************************************************************/ @@ -445,16 +486,18 @@ public:      virtual std::string get_tx_subdev_name(size_t chan = 0) = 0;      /*! -     * Set the TX sample rate across all channels. +     * Set the TX sample rate.       * \param rate the rate in Sps +     * \param chan the channel index 0 to N-1       */ -    virtual void set_tx_rate(double rate) = 0; +    virtual void set_tx_rate(double rate, size_t chan = ALL_CHANS) = 0;      /*! -     * Gets the TX sample rate for all channels. +     * Gets the TX sample rate. +     * \param chan the channel index 0 to N-1       * \return the rate in Sps       */ -    virtual double get_tx_rate(void) = 0; +    virtual double get_tx_rate(size_t chan = 0) = 0;      /*!       * Set the TX center frequency. @@ -556,7 +599,9 @@ public:       * \param chan the channel index 0 to N-1       * \return true for locked       */ -    virtual bool get_tx_lo_locked(size_t chan = 0) = 0; +    UHD_DEPRECATED bool get_tx_lo_locked(size_t chan = 0){ +        return this->get_tx_sensor("lo_locked", chan).to_bool(); +    }      /*!       * Set the TX bandwidth on the subdevice. @@ -580,6 +625,21 @@ public:       * \return the dboard interface sptr       */      virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; + +    /*! +     * Get an TX subdevice sensor value. +     * \param name the name of the sensor +     * \param chan the channel index 0 to N-1 +     * \return a sensor value object +     */ +    virtual sensor_value_t get_tx_sensor(const std::string &name, size_t chan = 0) = 0; + +    /*! +     * Get a list of possible TX subdevice sensor names. +     * \param chan the channel index 0 to N-1 +     * \return a vector of sensor names +     */ +    virtual std::vector<std::string> get_tx_sensor_names(size_t chan = 0) = 0;  };  }} diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp index 8d05f4c27..40b339703 100644 --- a/host/include/uhd/usrp/subdev_props.hpp +++ b/host/include/uhd/usrp/subdev_props.hpp @@ -42,21 +42,21 @@ namespace uhd{ namespace usrp{       * Possible device subdev properties       */      enum subdev_prop_t{ -        SUBDEV_PROP_NAME              = 'n', //ro, std::string -        SUBDEV_PROP_OTHERS            = 'o', //ro, prop_names_t -        SUBDEV_PROP_GAIN              = 'g', //rw, double -        SUBDEV_PROP_GAIN_RANGE        = 'r', //ro, gain_range_t -        SUBDEV_PROP_GAIN_NAMES        = 'G', //ro, prop_names_t -        SUBDEV_PROP_FREQ              = 'f', //rw, double -        SUBDEV_PROP_FREQ_RANGE        = 'F', //ro, freq_range_t -        SUBDEV_PROP_ANTENNA           = 'a', //rw, std::string -        SUBDEV_PROP_ANTENNA_NAMES     = 'A', //ro, prop_names_t -        SUBDEV_PROP_LO_LOCKED         = 'L', //ro, bool -        SUBDEV_PROP_CONNECTION        = 'c', //ro, subdev_conn_t -        SUBDEV_PROP_ENABLED           = 'e', //rw, bool -        SUBDEV_PROP_USE_LO_OFFSET     = 'l', //ro, bool -        SUBDEV_PROP_RSSI              = 'R', //ro, double -        SUBDEV_PROP_BANDWIDTH         = 'B'  //rw, double +        SUBDEV_PROP_NAME,               //ro, std::string +        SUBDEV_PROP_OTHERS,             //ro, prop_names_t +        SUBDEV_PROP_SENSOR,             //ro, sensor_value_t +        SUBDEV_PROP_SENSOR_NAMES,       //ro, prop_names_t +        SUBDEV_PROP_GAIN,               //rw, double +        SUBDEV_PROP_GAIN_RANGE,         //ro, gain_range_t +        SUBDEV_PROP_GAIN_NAMES,         //ro, prop_names_t +        SUBDEV_PROP_FREQ,               //rw, double +        SUBDEV_PROP_FREQ_RANGE,         //ro, freq_range_t +        SUBDEV_PROP_ANTENNA,            //rw, std::string +        SUBDEV_PROP_ANTENNA_NAMES,      //ro, prop_names_t +        SUBDEV_PROP_CONNECTION,         //ro, subdev_conn_t +        SUBDEV_PROP_ENABLED,            //rw, bool +        SUBDEV_PROP_USE_LO_OFFSET,      //ro, bool +        SUBDEV_PROP_BANDWIDTH           //rw, double      };  }} //namespace diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp index db12241c1..e97ab0298 100644 --- a/host/include/uhd/usrp/tune_helper.hpp +++ b/host/include/uhd/usrp/tune_helper.hpp @@ -32,24 +32,21 @@ namespace uhd{ namespace usrp{       * The ddc cordic is setup to bring the IF down to baseband.       * \param subdev the dboard subdevice object with properties       * \param ddc the mboard dsp object with properties -     * \param chan the channel of the dsp to tune       * \param tune_request tune request instructions       * \return a tune result struct       */      UHD_API tune_result_t tune_rx_subdev_and_dsp( -        wax::obj subdev, wax::obj ddc, size_t chan, -        const tune_request_t &tune_request +        wax::obj subdev, wax::obj ddc, const tune_request_t &tune_request      );      /*!       * Calculate the overall frequency from the combination of dboard IF and DDC shift.       * \param subdev the dboard subdevice object with properties       * \param ddc the mboard dsp object with properties -     * \param chan the channel of the dsp to tune       * \return the overall tune frequency of the system in Hz       */      UHD_API double derive_freq_from_rx_subdev_and_dsp( -        wax::obj subdev, wax::obj ddc, size_t chan +        wax::obj subdev, wax::obj ddc      );      /*! @@ -59,24 +56,21 @@ namespace uhd{ namespace usrp{       * The duc cordic is setup to bring the baseband up to IF.       * \param subdev the dboard subdevice object with properties       * \param duc the mboard dsp object with properties -     * \param chan the channel of the dsp to tune       * \param tune_request tune request instructions       * \return a tune result struct       */      UHD_API tune_result_t tune_tx_subdev_and_dsp( -        wax::obj subdev, wax::obj duc, size_t chan, -        const tune_request_t &tune_request +        wax::obj subdev, wax::obj duc, const tune_request_t &tune_request      );      /*!       * Calculate the overall frequency from the combination of dboard IF and DUC shift.       * \param subdev the dboard subdevice object with properties       * \param duc the mboard dsp object with properties -     * \param chan the channel of the dsp to tune       * \return the overall tune frequency of the system in Hz       */      UHD_API double derive_freq_from_tx_subdev_and_dsp( -        wax::obj subdev, wax::obj duc, size_t chan +        wax::obj subdev, wax::obj duc      );  }} diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 6f3ac0421..4f8ce7e52 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -300,18 +300,18 @@ template <typename T> UHD_INLINE T get_context_code(      typedef boost::function<bool(managed_send_buffs_t &)> get_send_buffs_t;      typedef boost::function<void(boost::uint32_t *, uhd::transport::vrt::if_packet_info_t &)> vrt_packer_t; +    static const boost::uint64_t zeros = 0; +      struct send_state{          //init the expected seq number          size_t next_packet_seq;          managed_send_buffs_t managed_buffs; -        const boost::uint64_t zeros;          std::vector<const void *> zero_buffs;          std::vector<const void *> io_buffs;          send_state(size_t width = 1):              next_packet_seq(0),              managed_buffs(width), -            zeros(0),              zero_buffs(width, &zeros),              io_buffs(0) //resized later          { diff --git a/host/lib/types/device_addr.cpp b/host/lib/types/device_addr.cpp index 14afaa24b..7f2031272 100644 --- a/host/lib/types/device_addr.cpp +++ b/host/lib/types/device_addr.cpp @@ -16,10 +16,11 @@  //  #include <uhd/types/device_addr.hpp> -#include <boost/algorithm/string.hpp> //for trim +#include <boost/algorithm/string.hpp>  #include <boost/tokenizer.hpp>  #include <boost/foreach.hpp>  #include <boost/format.hpp> +#include <boost/regex.hpp>  #include <stdexcept>  #include <sstream> @@ -71,3 +72,51 @@ std::string device_addr_t::to_string(void) const{      }      return args_str;  } + +#include <uhd/utils/warning.hpp> + +device_addrs_t uhd::separate_device_addr(const device_addr_t &dev_addr){ +    //------------ support old deprecated way and print warning -------- +    if (dev_addr.has_key("addr") and not dev_addr["addr"].empty()){ +        std::vector<std::string> addrs; boost::split(addrs, dev_addr["addr"], boost::is_any_of(" ")); +        if (addrs.size() > 1){ +            device_addr_t fixed_dev_addr = dev_addr; +            fixed_dev_addr.pop("addr"); +            for (size_t i = 0; i < addrs.size(); i++){ +                fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i]; +            } +            uhd::warning::post( +                "addr = <space separated list of ip addresses> is deprecated.\n" +                "To address a multi-device, use multiple <key><index> = <val>.\n" +                "See the USRP-NXXX application notes. Two device example:\n" +                "    addr0 = 192.168.10.2\n" +                "    addr1 = 192.168.10.3\n" +            ); +            return separate_device_addr(fixed_dev_addr); +        } +    } +    //------------------------------------------------------------------ +    device_addrs_t dev_addrs; +    BOOST_FOREACH(const std::string &key, dev_addr.keys()){ +        boost::cmatch matches; +        if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){ +            throw std::runtime_error("unknown key format: " + key); +        } +        std::string key_part(matches[1].first, matches[1].second); +        std::string num_part(matches[2].first, matches[2].second); +        size_t num = (num_part.empty())? 0 : boost::lexical_cast<size_t>(num_part); +        dev_addrs.resize(std::max(num+1, dev_addrs.size())); +        dev_addrs[num][key_part] = dev_addr[key]; +    } +    return dev_addrs; +} + +device_addr_t uhd::combine_device_addrs(const device_addrs_t &dev_addrs){ +    device_addr_t dev_addr; +    for (size_t i = 0; i < dev_addrs.size(); i++){ +        BOOST_FOREACH(const std::string &key, dev_addrs[i].keys()){ +            dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key]; +        } +    } +    return dev_addr; +} diff --git a/host/lib/types/sensors.cpp b/host/lib/types/sensors.cpp index 2bff136a4..5f7115d70 100644 --- a/host/lib/types/sensors.cpp +++ b/host/lib/types/sensors.cpp @@ -17,6 +17,7 @@  #include <uhd/types/sensors.hpp>  #include <uhd/utils/exception.hpp> +#include <boost/lexical_cast.hpp>  #include <boost/format.hpp>  using namespace uhd; @@ -35,7 +36,7 @@ sensor_value_t::sensor_value_t(  sensor_value_t::sensor_value_t(      const std::string &name, -    int_type value, +    signed value,      const std::string &unit,      const std::string &formatter  ): @@ -47,7 +48,7 @@ sensor_value_t::sensor_value_t(  sensor_value_t::sensor_value_t(      const std::string &name, -    real_type value, +    double value,      const std::string &unit,      const std::string &formatter  ): @@ -79,3 +80,15 @@ std::string sensor_value_t::to_pp_string(void) const{      }      UHD_THROW_INVALID_CODE_PATH();  } + +bool sensor_value_t::to_bool(void) const{ +    return value == "true"; +} + +signed sensor_value_t::to_int(void) const{ +    return boost::lexical_cast<signed>(value); +} + +double sensor_value_t::to_real(void) const{ +    return boost::lexical_cast<double>(value); +} diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index b311576d2..b319289db 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -173,10 +173,6 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = true; //there is no LO, so it must be true! -        return; -      case SUBDEV_PROP_BANDWIDTH:          val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq;          return; @@ -284,10 +280,6 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = true; //there is no LO, so it must be true! -        return; -      case SUBDEV_PROP_BANDWIDTH:          val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq;          return; diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 3ea9cea80..98d9479fc 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -25,6 +25,7 @@  #include <uhd/utils/algorithm.hpp>  #include <uhd/utils/warning.hpp>  #include <uhd/types/ranges.hpp> +#include <uhd/types/sensors.hpp>  #include <uhd/types/dict.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dboard_base.hpp> @@ -561,8 +562,13 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = this->get_locked(); +    case SUBDEV_PROP_SENSOR: +        UHD_ASSERT_THROW(key.name == "lo_locked"); +        val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); +        return; + +    case SUBDEV_PROP_SENSOR_NAMES: +        val = prop_names_t(1, "lo_locked");          return;      case SUBDEV_PROP_BANDWIDTH: diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp index defb70ff5..f4b797995 100644 --- a/host/lib/usrp/dboard/db_dbsrx2.cpp +++ b/host/lib/usrp/dboard/db_dbsrx2.cpp @@ -22,6 +22,7 @@  #include <uhd/utils/assert.hpp>  #include <uhd/utils/algorithm.hpp>  #include <uhd/types/ranges.hpp> +#include <uhd/types/sensors.hpp>  #include <uhd/types/dict.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dboard_base.hpp> @@ -400,8 +401,13 @@ void dbsrx2::rx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = this->get_locked(); +    case SUBDEV_PROP_SENSOR: +        UHD_ASSERT_THROW(key.name == "lo_locked"); +        val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); +        return; + +    case SUBDEV_PROP_SENSOR_NAMES: +        val = prop_names_t(1, "lo_locked");          return;      case SUBDEV_PROP_BANDWIDTH: diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 2c672ded8..3e3cf00f2 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -36,6 +36,7 @@  #include <uhd/types/dict.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/types/ranges.hpp> +#include <uhd/types/sensors.hpp>  #include <uhd/utils/assert.hpp>  #include <uhd/utils/static.hpp>  #include <uhd/utils/algorithm.hpp> @@ -449,8 +450,13 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = this->get_locked(dboard_iface::UNIT_RX); +    case SUBDEV_PROP_SENSOR: +        UHD_ASSERT_THROW(key.name == "lo_locked"); +        val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); +        return; + +    case SUBDEV_PROP_SENSOR_NAMES: +        val = prop_names_t(1, "lo_locked");          return;      case SUBDEV_PROP_BANDWIDTH: @@ -546,8 +552,13 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          val = true;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = this->get_locked(dboard_iface::UNIT_TX); +    case SUBDEV_PROP_SENSOR: +        UHD_ASSERT_THROW(key.name == "lo_locked"); +        val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); +        return; + +    case SUBDEV_PROP_SENSOR_NAMES: +        val = prop_names_t(1, "lo_locked");          return;      case SUBDEV_PROP_BANDWIDTH: diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index a9ce38000..578999432 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -32,6 +32,7 @@  #include <uhd/utils/algorithm.hpp>  #include <uhd/utils/warning.hpp>  #include <uhd/types/ranges.hpp> +#include <uhd/types/sensors.hpp>  #include <uhd/types/dict.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dboard_base.hpp> @@ -463,10 +464,6 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = true; -        return; -      case SUBDEV_PROP_BANDWIDTH:          val = 6.0e6;          return; diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index d91d58409..f0a4c000e 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -154,10 +154,6 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = true; //there is no LO, so it must be true! -        return; -      case SUBDEV_PROP_BANDWIDTH:          val = 0.0;          return; @@ -256,10 +252,6 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = true; //there is no LO, so it must be true! -        return; -      case SUBDEV_PROP_BANDWIDTH:          val = 0.0;          return; diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 135997789..0bc2d0ca1 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -68,6 +68,7 @@  #include <uhd/types/dict.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/types/ranges.hpp> +#include <uhd/types/sensors.hpp>  #include <uhd/utils/assert.hpp>  #include <uhd/utils/static.hpp>  #include <uhd/utils/algorithm.hpp> @@ -521,8 +522,13 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = this->get_locked(dboard_iface::UNIT_RX); +    case SUBDEV_PROP_SENSOR: +        UHD_ASSERT_THROW(key.name == "lo_locked"); +        val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); +        return; + +    case SUBDEV_PROP_SENSOR_NAMES: +        val = prop_names_t(1, "lo_locked");          return;      case SUBDEV_PROP_BANDWIDTH: @@ -622,8 +628,13 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = this->get_locked(dboard_iface::UNIT_TX); +    case SUBDEV_PROP_SENSOR: +        UHD_ASSERT_THROW(key.name == "lo_locked"); +        val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); +        return; + +    case SUBDEV_PROP_SENSOR_NAMES: +        val = prop_names_t(1, "lo_locked");          return;      case SUBDEV_PROP_BANDWIDTH: diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 6fb5a26a8..f4f74eb86 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -53,6 +53,7 @@  #include <uhd/utils/algorithm.hpp>  #include <uhd/utils/warning.hpp>  #include <uhd/types/ranges.hpp> +#include <uhd/types/sensors.hpp>  #include <uhd/types/dict.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dboard_base.hpp> @@ -616,12 +617,19 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = this->get_locked(); +    case SUBDEV_PROP_SENSOR: +        if (key.name == "lo_locked") +            val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); +        else if (key.name == "rssi") +            val = sensor_value_t("RSSI", this->get_rssi(), "dB"); +        else +            UHD_THROW_INVALID_CODE_PATH();          return; -    case SUBDEV_PROP_RSSI: -        val = this->get_rssi(); +    case SUBDEV_PROP_SENSOR_NAMES:{ +            prop_names_t names = list_of("lo_locked")("rssi"); +            val = names; +        }          return;      case SUBDEV_PROP_BANDWIDTH: @@ -719,8 +727,13 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){          val = false;          return; -    case SUBDEV_PROP_LO_LOCKED: -        val = this->get_locked(); +    case SUBDEV_PROP_SENSOR: +        UHD_ASSERT_THROW(key.name == "lo_locked"); +        val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); +        return; + +    case SUBDEV_PROP_SENSOR_NAMES: +        val = prop_names_t(1, "lo_locked");          return;      case SUBDEV_PROP_BANDWIDTH: diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 4bdb2bf2e..23049d569 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -85,17 +85,14 @@ public:          //----------- rx side of life ----------------------------------          for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ -            buff += str(boost::format( -                "  RX DSP %d: %s\n" -            ) % m -                % _rx_dsp(m)[DSP_PROP_NAME].as<std::string>() -            );              for (; chan < (m + 1)*get_rx_subdev_spec(m).size(); chan++){                  buff += str(boost::format(                      "  RX Channel: %u\n" +                    "    RX DSP: %s\n"                      "    RX Dboard: %s\n"                      "    RX Subdev: %s\n"                  ) % chan +                    % _rx_dsp(chan)[DSP_PROP_NAME].as<std::string>()                      % _rx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>()                      % _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>()                  ); @@ -104,17 +101,14 @@ public:          //----------- tx side of life ----------------------------------          for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ -            buff += str(boost::format( -                "  TX DSP %d: %s\n" -            ) % m -                % _tx_dsp(m)[DSP_PROP_NAME].as<std::string>() -            );              for (; chan < (m + 1)*get_tx_subdev_spec(m).size(); chan++){                  buff += str(boost::format(                      "  TX Channel: %u\n" +                    "    TX DSP: %s\n"                      "    TX Dboard: %s\n"                      "    TX Subdev: %s\n"                  ) % chan +                    % _tx_dsp(chan)[DSP_PROP_NAME].as<std::string>()                      % _tx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>()                      % _tx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>()                  ); @@ -194,9 +188,13 @@ public:          return true;      } -    void issue_stream_cmd(const stream_cmd_t &stream_cmd){ -        for (size_t m = 0; m < get_num_mboards(); m++){ -            _mboard(m)[MBOARD_PROP_STREAM_CMD] = stream_cmd; +    void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan){ +        if (chan != ALL_CHANS){ +            _rx_dsp(chan)[DSP_PROP_STREAM_CMD] = stream_cmd; +            return; +        } +        for (size_t c = 0; c < get_rx_num_channels(); c++){ +            issue_stream_cmd(stream_cmd, c);          }      } @@ -214,6 +212,14 @@ public:          return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>().size();      } +    sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard){ +        return _mboard(mboard)[named_prop_t(MBOARD_PROP_SENSOR, name)].as<sensor_value_t>(); +    } + +    std::vector<std::string> get_mboard_sensor_names(size_t mboard){ +        return _mboard(mboard)[MBOARD_PROP_SENSOR_NAMES].as<prop_names_t>(); +    } +      /*******************************************************************       * RX methods       ******************************************************************/ @@ -232,36 +238,44 @@ public:      }      size_t get_rx_num_channels(void){ -        return rx_cpm()*get_num_mboards(); //total num channels +        size_t sum = 0; +        for (size_t m = 0; m < get_num_mboards(); m++){ +            sum += get_rx_subdev_spec(m).size(); +        } +        return sum;      }      std::string get_rx_subdev_name(size_t chan){          return _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>();      } -    void set_rx_rate(double rate){ -        for (size_t m = 0; m < get_num_mboards(); m++){ -            _rx_dsp(m)[DSP_PROP_HOST_RATE] = rate; +    void set_rx_rate(double rate, size_t chan){ +        if (chan != ALL_CHANS){ +            _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; +            do_samp_rate_warning_message(rate, get_rx_rate(chan), "RX"); +            return; +        } +        for (size_t c = 0; c < get_rx_num_channels(); c++){ +            set_rx_rate(rate, c);          } -        do_samp_rate_warning_message(rate, get_rx_rate(), "RX");      } -    double get_rx_rate(void){ -        return _rx_dsp(0)[DSP_PROP_HOST_RATE].as<double>(); +    double get_rx_rate(size_t chan){ +        return _rx_dsp(chan)[DSP_PROP_HOST_RATE].as<double>();      }      tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ -        tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), tune_request); +        tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), tune_request);          do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX");          return r;      }      double get_rx_freq(size_t chan){ -        return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm()); +        return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan));      }      freq_range_t get_rx_freq_range(size_t chan){ -        return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan/rx_cpm())); +        return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan));      }      void set_rx_gain(double gain, const std::string &name, size_t chan){ @@ -292,10 +306,6 @@ public:          return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>();      } -    bool get_rx_lo_locked(size_t chan){ -        return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as<bool>(); -    } -      void set_rx_bandwidth(double bandwidth, size_t chan){          _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth;      } @@ -304,14 +314,18 @@ public:          return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as<double>();      } -    double read_rssi(size_t chan){ -        return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as<double>(); -    } -      dboard_iface::sptr get_rx_dboard_iface(size_t chan){          return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as<dboard_iface::sptr>();      } +    sensor_value_t get_rx_sensor(const std::string &name, size_t chan){ +        return _rx_subdev(chan)[named_prop_t(SUBDEV_PROP_SENSOR, name)].as<sensor_value_t>(); +    } + +    std::vector<std::string> get_rx_sensor_names(size_t chan){ +        return _rx_subdev(chan)[SUBDEV_PROP_SENSOR_NAMES].as<prop_names_t>(); +    } +      /*******************************************************************       * TX methods       ******************************************************************/ @@ -334,32 +348,40 @@ public:      }      size_t get_tx_num_channels(void){ -        return tx_cpm()*get_num_mboards(); //total num channels +        size_t sum = 0; +        for (size_t m = 0; m < get_num_mboards(); m++){ +            sum += get_tx_subdev_spec(m).size(); +        } +        return sum;      } -    void set_tx_rate(double rate){ -        for (size_t m = 0; m < get_num_mboards(); m++){ -            _tx_dsp(m)[DSP_PROP_HOST_RATE] = rate; +    void set_tx_rate(double rate, size_t chan){ +        if (chan != ALL_CHANS){ +            _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; +            do_samp_rate_warning_message(rate, get_tx_rate(chan), "TX"); +            return; +        } +        for (size_t c = 0; c < get_tx_num_channels(); c++){ +            set_tx_rate(rate, c);          } -        do_samp_rate_warning_message(rate, get_tx_rate(), "TX");      } -    double get_tx_rate(void){ -        return _tx_dsp(0)[DSP_PROP_HOST_RATE].as<double>(); +    double get_tx_rate(size_t chan){ +        return _tx_dsp(chan)[DSP_PROP_HOST_RATE].as<double>();      }      tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ -        tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), tune_request); +        tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), tune_request);          do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX");          return r;      }      double get_tx_freq(size_t chan){ -        return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm()); +        return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan));      }      freq_range_t get_tx_freq_range(size_t chan){ -        return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan/tx_cpm())); +        return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan));      }      void set_tx_gain(double gain, const std::string &name, size_t chan){ @@ -390,10 +412,6 @@ public:          return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>();      } -    bool get_tx_lo_locked(size_t chan){ -        return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as<bool>(); -    } -      void set_tx_bandwidth(double bandwidth, size_t chan){          _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth;      } @@ -406,61 +424,86 @@ public:          return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as<dboard_iface::sptr>();      } +    sensor_value_t get_tx_sensor(const std::string &name, size_t chan){ +        return _tx_subdev(chan)[named_prop_t(SUBDEV_PROP_SENSOR, name)].as<sensor_value_t>(); +    } + +    std::vector<std::string> get_tx_sensor_names(size_t chan){ +        return _tx_subdev(chan)[SUBDEV_PROP_SENSOR_NAMES].as<prop_names_t>(); +    } +  private:      device::sptr _dev; -    size_t rx_cpm(void){ //channels per mboard -        size_t nchan = get_rx_subdev_spec(0).size(); -        for (size_t m = 1; m < get_num_mboards(); m++){ -            if (nchan != get_rx_subdev_spec(m).size()){ -                throw std::runtime_error("rx subdev spec size inconsistent across all mboards"); -            } +    struct mboard_chan_pair{ +        size_t mboard, chan; +        mboard_chan_pair(void): mboard(0), chan(0){} +    }; + +    mboard_chan_pair rx_chan_to_mcp(size_t chan){ +        mboard_chan_pair mcp; +        mcp.chan = chan; +        for (mcp.mboard = 0; mcp.mboard < get_num_mboards(); mcp.mboard++){ +            size_t sss = get_rx_subdev_spec(mcp.mboard).size(); +            if (mcp.chan < sss) break; +            mcp.chan -= sss;          } -        return nchan; +        return mcp;      } -    size_t tx_cpm(void){ //channels per mboard -        size_t nchan = get_tx_subdev_spec(0).size(); -        for (size_t m = 1; m < get_num_mboards(); m++){ -            if (nchan != get_tx_subdev_spec(m).size()){ -                throw std::runtime_error("tx subdev spec size inconsistent across all mboards"); -            } +    mboard_chan_pair tx_chan_to_mcp(size_t chan){ +        mboard_chan_pair mcp; +        mcp.chan = chan; +        for (mcp.mboard = 0; mcp.mboard < get_num_mboards(); mcp.mboard++){ +            size_t sss = get_tx_subdev_spec(mcp.mboard).size(); +            if (mcp.chan < sss) break; +            mcp.chan -= sss;          } -        return nchan; +        return mcp;      }      wax::obj _mboard(size_t mboard){          std::string mb_name = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>().at(mboard);          return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, mb_name)];      } -    wax::obj _rx_dsp(size_t mboard){ -        return _mboard(mboard)[MBOARD_PROP_RX_DSP]; +    wax::obj _rx_dsp(size_t chan){ +        mboard_chan_pair mcp = rx_chan_to_mcp(chan); +        prop_names_t dsp_names = _mboard(mcp.mboard)[MBOARD_PROP_RX_DSP_NAMES].as<prop_names_t>(); +        return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_RX_DSP, dsp_names.at(mcp.chan))];      } -    wax::obj _tx_dsp(size_t mboard){ -        return _mboard(mboard)[MBOARD_PROP_TX_DSP]; +    wax::obj _tx_dsp(size_t chan){ +        mboard_chan_pair mcp = tx_chan_to_mcp(chan); +        prop_names_t dsp_names = _mboard(mcp.mboard)[MBOARD_PROP_TX_DSP_NAMES].as<prop_names_t>(); +        return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_TX_DSP, dsp_names.at(mcp.chan))];      }      wax::obj _rx_dboard(size_t chan){ -        std::string db_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).db_name; -        return _mboard(chan/rx_cpm())[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; +        mboard_chan_pair mcp = rx_chan_to_mcp(chan); +        std::string db_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).db_name; +        return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)];      }      wax::obj _tx_dboard(size_t chan){ -        std::string db_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).db_name; -        return _mboard(chan/tx_cpm())[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; +        mboard_chan_pair mcp = tx_chan_to_mcp(chan); +        std::string db_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).db_name; +        return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)];      }      wax::obj _rx_subdev(size_t chan){ -        std::string sd_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).sd_name; +        mboard_chan_pair mcp = rx_chan_to_mcp(chan); +        std::string sd_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name;          return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)];      }      wax::obj _tx_subdev(size_t chan){ -        std::string sd_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).sd_name; +        mboard_chan_pair mcp = tx_chan_to_mcp(chan); +        std::string sd_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name;          return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)];      }      gain_group::sptr _rx_gain_group(size_t chan){ -        std::string sd_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).sd_name; +        mboard_chan_pair mcp = rx_chan_to_mcp(chan); +        std::string sd_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name;          return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>();      }      gain_group::sptr _tx_gain_group(size_t chan){ -        std::string sd_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).sd_name; +        mboard_chan_pair mcp = tx_chan_to_mcp(chan); +        std::string sd_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name;          return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>();      }  }; diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index eccee7f4b..ced80c187 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -30,12 +30,11 @@ using namespace uhd::usrp;   **********************************************************************/  static tune_result_t tune_xx_subdev_and_dsp(      dboard_iface::unit_t unit, -    wax::obj subdev, wax::obj dsp, size_t chan, +    wax::obj subdev, wax::obj dsp,      const tune_request_t &tune_request  ){      wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; -    std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan); -    wax::obj dsp_freq_proxy = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)]; +    wax::obj dsp_freq_proxy = dsp[DSP_PROP_FREQ_SHIFT];      //------------------------------------------------------------------      //-- calculate the LO offset, only used with automatic policy @@ -105,13 +104,11 @@ static tune_result_t tune_xx_subdev_and_dsp(  }  static double derive_freq_from_xx_subdev_and_dsp( -    dboard_iface::unit_t unit, -    wax::obj subdev, wax::obj dsp, size_t chan +    dboard_iface::unit_t unit, wax::obj subdev, wax::obj dsp  ){      //extract actual dsp and IF frequencies      double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as<double>(); -    std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan); -    double actual_dsp_freq = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as<double>(); +    double actual_dsp_freq = dsp[DSP_PROP_FREQ_SHIFT].as<double>();      //invert the sign on the dsp freq given the following conditions      if (unit == dboard_iface::UNIT_TX) actual_dsp_freq *= -1.0; @@ -123,30 +120,28 @@ static double derive_freq_from_xx_subdev_and_dsp(   * RX Tune   **********************************************************************/  tune_result_t usrp::tune_rx_subdev_and_dsp( -    wax::obj subdev, wax::obj ddc, size_t chan, -    const tune_request_t &tune_request +    wax::obj subdev, wax::obj ddc, const tune_request_t &tune_request  ){ -    return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan, tune_request); +    return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, tune_request);  }  double usrp::derive_freq_from_rx_subdev_and_dsp( -    wax::obj subdev, wax::obj ddc, size_t chan +    wax::obj subdev, wax::obj ddc  ){ -    return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan); +    return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc);  }  /***********************************************************************   * TX Tune   **********************************************************************/  tune_result_t usrp::tune_tx_subdev_and_dsp( -    wax::obj subdev, wax::obj duc, size_t chan, -    const tune_request_t &tune_request +    wax::obj subdev, wax::obj duc, const tune_request_t &tune_request  ){ -    return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan, tune_request); +    return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, tune_request);  }  double usrp::derive_freq_from_tx_subdev_and_dsp( -    wax::obj subdev, wax::obj duc, size_t chan +    wax::obj subdev, wax::obj duc  ){ -    return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan); +    return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc);  } diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 370f4831f..8152c4e34 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -34,23 +34,25 @@ using namespace uhd::usrp;   **********************************************************************/  void usrp1_impl::rx_dsp_init(void)  { -    _rx_dsp_proxy = wax_obj_proxy::make( -        boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2), -        boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2)); - -    rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16); +    for (size_t i = 0; i < this->get_num_ddcs(); i++){ +        _rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( +            boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2, i), +            boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2, i) +        ); +        rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16, i); +    }  }  /***********************************************************************   * RX DDC Get   **********************************************************************/ -void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){ +void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME: -        val = str(boost::format("usrp1 ddc %uX %s") -            % this->get_num_ddcs() +        val = str(boost::format("usrp1 ddc%d %s") +            % which_dsp              % (this->has_rx_halfband()? "+ hb" : "")          );          return; @@ -60,16 +62,7 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_FREQ_SHIFT: -        val = _rx_dsp_freqs[key.name]; -        return; - -    case DSP_PROP_FREQ_SHIFT_NAMES:{ -            prop_names_t names; -            for(size_t i = 0; i < this->get_num_ddcs(); i++){ -                names.push_back(boost::lexical_cast<std::string>(i)); -            } -            val = names; -        } +        val = _rx_dsp_freqs[which_dsp];          return;      case DSP_PROP_CODEC_RATE: @@ -88,7 +81,7 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){  /***********************************************************************   * RX DDC Set   **********************************************************************/ -void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){ +void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()) { @@ -97,16 +90,17 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){              boost::uint32_t reg_word = dsp_type1::calc_cordic_word_and_update(                  new_freq, _clock_ctrl->get_master_clock_freq()); -            static const uhd::dict<std::string, boost::uint32_t> -            freq_name_to_reg_val = boost::assign::map_list_of -                ("0", FR_RX_FREQ_0) ("1", FR_RX_FREQ_1) -                ("2", FR_RX_FREQ_2) ("3", FR_RX_FREQ_3) -            ; -            _iface->poke32(freq_name_to_reg_val[key.name], ~reg_word + 1); -            _rx_dsp_freqs[key.name] = new_freq; +            static const boost::uint32_t dsp_index_to_reg_val[4] = { +                FR_RX_FREQ_0, FR_RX_FREQ_1, FR_RX_FREQ_2, FR_RX_FREQ_3 +            }; +            _iface->poke32(dsp_index_to_reg_val[which_dsp], ~reg_word + 1); +            _rx_dsp_freqs[which_dsp] = new_freq;              return;          } -    case DSP_PROP_HOST_RATE: { + +    case DSP_PROP_HOST_RATE: +        if (which_dsp != 0) return; //only for dsp[0] as this is vectorized +        {              size_t rate = size_t(_clock_ctrl->get_master_clock_freq() / val.as<double>());              if ((rate & 0x01) || (rate < 4) || (rate > 256)) { @@ -123,6 +117,11 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){          }          return; +    case DSP_PROP_STREAM_CMD: +        if (which_dsp != 0) return; //only for dsp[0] as this is vectorized +        _soft_time_ctrl->issue_stream_cmd(val.as<stream_cmd_t>()); +        return; +      default: UHD_THROW_PROP_SET_ERROR();      } @@ -133,24 +132,25 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){   **********************************************************************/  void usrp1_impl::tx_dsp_init(void)  { -    _tx_dsp_proxy = wax_obj_proxy::make( -                          boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2), -                          boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2)); - -    //initial config and update -    tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() * 2 / 16); +    for (size_t i = 0; i < this->get_num_ducs(); i++){ +        _tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( +            boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2, i), +            boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2, i) +        ); +        tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16, i); +    }  }  /***********************************************************************   * TX DUC Get   **********************************************************************/ -void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){ +void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()) {      case DSP_PROP_NAME: -        val = str(boost::format("usrp1 duc %uX %s") -            % this->get_num_ducs() +        val = str(boost::format("usrp1 duc%d %s") +            % which_dsp              % (this->has_tx_halfband()? "+ hb" : "")          );          return; @@ -160,16 +160,7 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_FREQ_SHIFT: -        val = _tx_dsp_freqs[key.name]; -        return; - -    case DSP_PROP_FREQ_SHIFT_NAMES:{ -            prop_names_t names; -            for(size_t i = 0; i < this->get_num_ducs(); i++){ -                names.push_back(boost::lexical_cast<std::string>(i)); -            } -            val = names; -        } +        val = _tx_dsp_freqs[which_dsp];          return;      case DSP_PROP_CODEC_RATE: @@ -188,7 +179,7 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){  /***********************************************************************   * TX DUC Set   **********************************************************************/ -void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){ +void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()) { @@ -197,15 +188,17 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){              double new_freq = val.as<double>();              //map the freq shift key to a subdev spec to a particular codec chip -            std::string db_name = _tx_subdev_spec.at(boost::lexical_cast<size_t>(key.name)).db_name; +            std::string db_name = _tx_subdev_spec.at(which_dsp).db_name;              if (db_name == "A") _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq);              if (db_name == "B") _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq); -            _tx_dsp_freqs[key.name] = new_freq; +            _tx_dsp_freqs[which_dsp] = new_freq;              return;          } -    case DSP_PROP_HOST_RATE: { +    case DSP_PROP_HOST_RATE: +        if (which_dsp != 0) return; //only for dsp[0] as this is vectorized +        {              size_t rate = size_t(_clock_ctrl->get_master_clock_freq() * 2 / val.as<double>());              if ((rate & 0x01) || (rate < 8) || (rate > 512)) { diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 6d5bf466d..26d3e41d4 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -280,21 +280,19 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val)          return;      case MBOARD_PROP_RX_DSP: -        UHD_ASSERT_THROW(key.name == ""); -        val = _rx_dsp_proxy->get_link(); +        val = _rx_dsp_proxies.get(key.name)->get_link();          return;      case MBOARD_PROP_RX_DSP_NAMES: -        val = prop_names_t(1, ""); +        val = _rx_dsp_proxies.keys();          return;      case MBOARD_PROP_TX_DSP: -        UHD_ASSERT_THROW(key.name == ""); -        val = _tx_dsp_proxy->get_link(); +        val = _tx_dsp_proxies.get(key.name)->get_link();          return;      case MBOARD_PROP_TX_DSP_NAMES: -        val = prop_names_t(1, ""); +        val = _tx_dsp_proxies.keys();          return;      case MBOARD_PROP_CLOCK_CONFIG: @@ -342,10 +340,6 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)      //handle the get request conditioned on the key      switch(key.as<mboard_prop_t>()){ -    case MBOARD_PROP_STREAM_CMD: -        _soft_time_ctrl->issue_stream_cmd(val.as<stream_cmd_t>()); -        return; -      case MBOARD_PROP_RX_SUBDEV_SPEC:          _rx_subdev_spec = val.as<subdev_spec_t>();          if (_rx_subdev_spec.size() > this->get_num_ddcs()){ diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 1d9f6709f..9755c466d 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -182,19 +182,19 @@ private:      //rx dsp functions and settings      void rx_dsp_init(void); -    void rx_dsp_get(const wax::obj &, wax::obj &); -    void rx_dsp_set(const wax::obj &, const wax::obj &); -    uhd::dict<std::string, double> _rx_dsp_freqs; +    void rx_dsp_get(const wax::obj &, wax::obj &, size_t); +    void rx_dsp_set(const wax::obj &, const wax::obj &, size_t); +    uhd::dict<size_t, double> _rx_dsp_freqs;      size_t _rx_dsp_decim; -    wax_obj_proxy::sptr _rx_dsp_proxy; +    uhd::dict<std::string, wax_obj_proxy::sptr> _rx_dsp_proxies;      //tx dsp functions and settings      void tx_dsp_init(void); -    void tx_dsp_get(const wax::obj &, wax::obj &); -    void tx_dsp_set(const wax::obj &, const wax::obj &); -    uhd::dict<std::string, double> _tx_dsp_freqs; +    void tx_dsp_get(const wax::obj &, wax::obj &, size_t); +    void tx_dsp_set(const wax::obj &, const wax::obj &, size_t); +    uhd::dict<size_t, double> _tx_dsp_freqs;      size_t _tx_dsp_interp; -    wax_obj_proxy::sptr _tx_dsp_proxy; +    uhd::dict<std::string, wax_obj_proxy::sptr> _tx_dsp_proxies;      //transports      uhd::transport::usb_zero_copy::sptr _data_transport; diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 8340f7cdd..cdd559e94 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -28,12 +28,79 @@  using namespace uhd;  using namespace uhd::usrp; -static const size_t default_decim = 16; -static const size_t default_interp = 16; -  /*********************************************************************** - * DDC Helper Methods + * DSP impl and methods   **********************************************************************/ +struct usrp2_mboard_impl::dsp_impl{ +    uhd::dict<size_t, size_t> ddc_decim; +    uhd::dict<size_t, double> ddc_freq; +    uhd::dict<size_t, size_t> duc_interp; +    uhd::dict<size_t, double> duc_freq; +    std::vector<size_t> decim_and_interp_rates; +    uhd::dict<size_t, bool> continuous_streaming; +}; + +void usrp2_mboard_impl::dsp_init(void){ +    //create new dsp impl +    _dsp_impl = UHD_PIMPL_MAKE(dsp_impl, ()); + +    //load the allowed decim/interp rates +    //range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) +    for (size_t i = 4; i <= 128; i+=1){ +        _dsp_impl->decim_and_interp_rates.push_back(i); +    } +    for (size_t i = 130; i <= 256; i+=2){ +        _dsp_impl->decim_and_interp_rates.push_back(i); +    } +    for (size_t i = 260; i <= 512; i+=4){ +        _dsp_impl->decim_and_interp_rates.push_back(i); +    } + +    //bind and initialize the rx dsps +    for (size_t i = 0; i < NUM_RX_DSPS; i++){ +        _rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( +            boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2, i), +            boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2, i) +        ); + +        //initial config and update +        ddc_set(DSP_PROP_FREQ_SHIFT, double(0), i); +        ddc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/16), i); + +        //setup the rx control registers +        _iface->poke32(_iface->regs.rx_ctrl[i].clear_overrun, 1); //reset +        _iface->poke32(_iface->regs.rx_ctrl[i].nsamps_per_pkt, _device.get_max_recv_samps_per_packet()); +        _iface->poke32(_iface->regs.rx_ctrl[i].nchannels, 1); +        _iface->poke32(_iface->regs.rx_ctrl[i].vrt_header, 0 +            | (0x1 << 28) //if data with stream id +            | (0x1 << 26) //has trailer +            | (0x3 << 22) //integer time other +            | (0x1 << 20) //fractional time sample count +        ); +        _iface->poke32(_iface->regs.rx_ctrl[i].vrt_stream_id, usrp2_impl::RECV_SID); +        _iface->poke32(_iface->regs.rx_ctrl[i].vrt_trailer, 0); +        _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq())); +    } + +    //bind and initialize the tx dsps +    for (size_t i = 0; i < NUM_TX_DSPS; i++){ +        _tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( +            boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2, i), +            boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2, i) +        ); + +        //initial config and update +        duc_set(DSP_PROP_FREQ_SHIFT, double(0), i); +        duc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/16), i); + +        //init the tx control registers +        _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset +        _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0);    //1 channel +        _iface->poke32(_iface->regs.tx_ctrl_report_sid, usrp2_impl::ASYNC_SID); +        _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); +    } +} +  template <typename rate_type>  static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_type> &rates){      unsigned closest_match = rates.front(); @@ -44,27 +111,28 @@ static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_typ      return closest_match;  } -void usrp2_mboard_impl::init_ddc_config(void){ -    //create the ddc in the rx dsp dict -    _rx_dsp_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2), -        boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2) -    ); +void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd, size_t which_dsp){ +    _dsp_impl->continuous_streaming[which_dsp] = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS; +    _iface->poke32(_iface->regs.rx_ctrl[which_dsp].stream_cmd, dsp_type1::calc_stream_cmd_word(stream_cmd)); +    _iface->poke32(_iface->regs.rx_ctrl[which_dsp].time_secs,  boost::uint32_t(stream_cmd.time_spec.get_full_secs())); +    _iface->poke32(_iface->regs.rx_ctrl[which_dsp].time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); +} -    //initial config and update -    ddc_set(DSP_PROP_FREQ_SHIFT, double(0)); -    ddc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/default_decim)); +void usrp2_mboard_impl::handle_overflow(size_t which_dsp){ +    if (_dsp_impl->continuous_streaming[which_dsp]){ //re-issue the stream command if already continuous +        this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS, which_dsp); +    }  }  /***********************************************************************   * DDC Properties   **********************************************************************/ -void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME: -        val = _iface->get_cname() + " ddc0"; +        val = str(boost::format("%s ddc%d") % _iface->get_cname() % which_dsp);          return;      case DSP_PROP_OTHERS: @@ -72,11 +140,7 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_FREQ_SHIFT: -        val = _ddc_freq; -        return; - -    case DSP_PROP_FREQ_SHIFT_NAMES: -        val = prop_names_t(1, ""); +        val = _dsp_impl->ddc_freq[which_dsp];          return;      case DSP_PROP_CODEC_RATE: @@ -84,37 +148,41 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_HOST_RATE: -        val = get_master_clock_freq()/_ddc_decim; +        val = get_master_clock_freq()/_dsp_impl->ddc_decim[which_dsp];          return;      default: UHD_THROW_PROP_GET_ERROR();      }  } -void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){ +void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){ +    case DSP_PROP_STREAM_CMD: +        issue_ddc_stream_cmd(val.as<stream_cmd_t>(), which_dsp); +        return; +      case DSP_PROP_FREQ_SHIFT:{              double new_freq = val.as<double>(); -            _iface->poke32(_iface->regs.dsp_rx_freq, +            _iface->poke32(_iface->regs.dsp_rx[which_dsp].freq,                  dsp_type1::calc_cordic_word_and_update(new_freq, get_master_clock_freq())              ); -            _ddc_freq = new_freq; //shadow +            _dsp_impl->ddc_freq[which_dsp] = new_freq; //shadow          }          return;      case DSP_PROP_HOST_RATE:{              double extact_rate = get_master_clock_freq()/val.as<double>(); -            _ddc_decim = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates); +            _dsp_impl->ddc_decim[which_dsp] = pick_closest_rate(extact_rate, _dsp_impl->decim_and_interp_rates);              //set the decimation -            _iface->poke32(_iface->regs.dsp_rx_decim_rate, dsp_type1::calc_cic_filter_word(_ddc_decim)); +            _iface->poke32(_iface->regs.dsp_rx[which_dsp].decim_rate, dsp_type1::calc_cic_filter_word(_dsp_impl->ddc_decim[which_dsp]));              //set the scaling              static const boost::int16_t default_rx_scale_iq = 1024; -            _iface->poke32(_iface->regs.dsp_rx_scale_iq, +            _iface->poke32(_iface->regs.dsp_rx[which_dsp].scale_iq,                  dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq)              );          } @@ -125,29 +193,14 @@ void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){  }  /*********************************************************************** - * DUC Helper Methods - **********************************************************************/ -void usrp2_mboard_impl::init_duc_config(void){ -    //create the duc in the tx dsp dict -    _tx_dsp_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2), -        boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2) -    ); - -    //initial config and update -    duc_set(DSP_PROP_FREQ_SHIFT, double(0)); -    duc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/default_interp)); -} - -/***********************************************************************   * DUC Properties   **********************************************************************/ -void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME: -        val = _iface->get_cname() + " duc0"; +        val = str(boost::format("%s duc%d") % _iface->get_cname() % which_dsp);          return;      case DSP_PROP_OTHERS: @@ -155,11 +208,7 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_FREQ_SHIFT: -        val = _duc_freq; -        return; - -    case DSP_PROP_FREQ_SHIFT_NAMES: -        val = prop_names_t(1, ""); +        val = _dsp_impl->duc_freq[which_dsp];          return;      case DSP_PROP_CODEC_RATE: @@ -167,14 +216,14 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_HOST_RATE: -        val = get_master_clock_freq()/_duc_interp; +        val = get_master_clock_freq()/_dsp_impl->duc_interp[which_dsp];          return;      default: UHD_THROW_PROP_GET_ERROR();      }  } -void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){ +void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){ @@ -196,19 +245,19 @@ void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){              _iface->poke32(_iface->regs.dsp_tx_freq,                  dsp_type1::calc_cordic_word_and_update(new_freq, codec_rate)              ); -            _duc_freq = new_freq + dac_shift; //shadow +            _dsp_impl->duc_freq[which_dsp] = new_freq + dac_shift; //shadow          }          return;      case DSP_PROP_HOST_RATE:{              double extact_rate = get_master_clock_freq()/val.as<double>(); -            _duc_interp = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates); +            _dsp_impl->duc_interp[which_dsp] = pick_closest_rate(extact_rate, _dsp_impl->decim_and_interp_rates);              //set the interpolation -            _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_duc_interp)); +            _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_dsp_impl->duc_interp[which_dsp]));              //set the scaling -            _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_duc_interp)); +            _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_dsp_impl->duc_interp[which_dsp]));          }          return; diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index a22f805e1..6eb047454 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -30,8 +30,8 @@ extern "C" {  #endif  //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 4 -#define USRP2_FW_COMPAT_NUM 8 +#define USRP2_FPGA_COMPAT_NUM 5 +#define USRP2_FW_COMPAT_NUM 9  //used to differentiate control packets over data port  #define USRP2_INVALID_VRT_HEADER 0 @@ -40,8 +40,9 @@ extern "C" {  // Dynamic and/or private ports: 49152-65535  #define USRP2_UDP_CTRL_PORT 49152  //#define USRP2_UDP_UPDATE_PORT 49154 -#define USRP2_UDP_DATA_PORT 49156 +#define USRP2_UDP_DSP0_PORT 49156  #define USRP2_UDP_ERR0_PORT 49157 +#define USRP2_UDP_DSP1_PORT 49158  ////////////////////////////////////////////////////////////////////////  // I2C addresses diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index b20b6652e..e59ee2d24 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -18,6 +18,7 @@  #include "../../transport/vrt_packet_handler.hpp"  #include "usrp2_impl.hpp"  #include "usrp2_regs.hpp" +#include <uhd/usrp/mboard_props.hpp>  #include <uhd/utils/byteswap.hpp>  #include <uhd/utils/thread_priority.hpp>  #include <uhd/transport/bounded_buffer.hpp> @@ -119,27 +120,27 @@ private:   **********************************************************************/  struct usrp2_impl::io_impl{ -    io_impl(size_t send_frame_size, const std::vector<zero_copy_if::sptr> &xports): -        xports(xports), +    io_impl(std::vector<zero_copy_if::sptr> &dsp_xports): +        dsp_xports(dsp_xports), //the assumption is that all data transports should be identical          get_recv_buffs_fcn(boost::bind(&usrp2_impl::io_impl::get_recv_buffs, this, _1)),          get_send_buffs_fcn(boost::bind(&usrp2_impl::io_impl::get_send_buffs, this, _1)), -        packet_handler_recv_state(xports.size()), -        packet_handler_send_state(xports.size()),          async_msg_fifo(100/*messages deep*/)      { -        for (size_t i = 0; i < xports.size(); i++){ -            fc_mons.push_back(flow_control_monitor::sptr( -                new flow_control_monitor(usrp2_impl::sram_bytes/send_frame_size) -            )); -            //init empty packet infos -            vrt::if_packet_info_t packet_info; -            packet_info.packet_count = 0xf; -            packet_info.has_tsi = true; -            packet_info.tsi = 0; -            packet_info.has_tsf = true; -            packet_info.tsf = 0; -            prev_infos.push_back(packet_info); +        size_t num_monitors = dsp_xports.size()/usrp2_mboard_impl::MAX_NUM_DSPS*usrp2_mboard_impl::NUM_TX_DSPS; +        for (size_t i = 0; i < num_monitors; i++){ +            fc_mons.push_back(flow_control_monitor::sptr(new flow_control_monitor( +                usrp2_impl::sram_bytes/dsp_xports.front()->get_send_frame_size() +            )));;          } + +        //init empty packet infos +        vrt::if_packet_info_t packet_info = vrt::if_packet_info_t(); +        packet_info.packet_count = 0xf; +        packet_info.has_tsi = true; +        packet_info.tsi = 0; +        packet_info.has_tsf = true; +        packet_info.tsf = 0; +        prev_infos.resize(dsp_xports.size(), packet_info);      }      ~io_impl(void){ @@ -149,15 +150,15 @@ struct usrp2_impl::io_impl{      }      bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &buffs){ -        UHD_ASSERT_THROW(xports.size() == buffs.size()); +        UHD_ASSERT_THROW(send_map.size() == buffs.size());          //calculate the flow control word          const boost::uint32_t fc_word32 = packet_handler_send_state.next_packet_seq;          //grab a managed buffer for each index          for (size_t i = 0; i < buffs.size(); i++){ -            if (not fc_mons[i]->check_fc_condition(fc_word32, send_timeout)) return false; -            buffs[i] = xports[i]->get_send_buff(send_timeout); +            if (not fc_mons[send_map[i]]->check_fc_condition(fc_word32, send_timeout)) return false; +            buffs[i] = dsp_xports[send_map[i]]->get_send_buff(send_timeout);              if (not buffs[i].get()) return false;              buffs[i]->cast<boost::uint32_t *>()[0] = uhd::htonx(fc_word32);          } @@ -166,7 +167,10 @@ struct usrp2_impl::io_impl{      bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs); -    const std::vector<zero_copy_if::sptr> &xports; +    std::vector<zero_copy_if::sptr> &dsp_xports; + +    //mappings from channel index to dsp xport +    std::vector<size_t> send_map, recv_map;      //timeouts set on calls to recv/send (passed into get buffs methods)      double recv_timeout, send_timeout; @@ -186,7 +190,7 @@ struct usrp2_impl::io_impl{      vrt_packet_handler::send_state packet_handler_send_state;      //methods and variables for the pirate crew -    void recv_pirate_loop(zero_copy_if::sptr, usrp2_mboard_impl::sptr, size_t); +    void recv_pirate_loop(usrp2_mboard_impl::sptr, zero_copy_if::sptr, size_t);      boost::thread_group recv_pirate_crew;      bool recv_pirate_crew_raiding;      bounded_buffer<async_metadata_t> async_msg_fifo; @@ -200,9 +204,7 @@ struct usrp2_impl::io_impl{   * - put async message packets into queue   **********************************************************************/  void usrp2_impl::io_impl::recv_pirate_loop( -    zero_copy_if::sptr zc_if_err0, -    usrp2_mboard_impl::sptr mboard, -    size_t index +    usrp2_mboard_impl::sptr mboard, zero_copy_if::sptr err_xport, size_t index  ){      set_thread_priority_safe();      recv_pirate_crew_raiding = true; @@ -210,7 +212,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(      spawn_mutex.unlock();      while(recv_pirate_crew_raiding){ -        managed_recv_buffer::sptr buff = zc_if_err0->get_recv_buff(); +        managed_recv_buffer::sptr buff = err_xport->get_recv_buff();          if (not buff.get()) continue; //ignore timeout/error buffers          try{ @@ -258,27 +260,52 @@ void usrp2_impl::io_impl::recv_pirate_loop(   **********************************************************************/  void usrp2_impl::io_init(void){ -    //the assumption is that all data transports should be identical -    const size_t send_frame_size = _data_transports.front()->get_send_frame_size(); -      //create new io impl -    _io_impl = UHD_PIMPL_MAKE(io_impl, (send_frame_size, _data_transports)); +    _io_impl = UHD_PIMPL_MAKE(io_impl, (dsp_xports));      //create a new pirate thread for each zc if (yarr!!) -    for (size_t i = 0; i < _data_transports.size(); i++){ +    for (size_t i = 0; i < _mboards.size(); i++){          //lock the unlocked mutex (non-blocking)          _io_impl->spawn_mutex.lock();          //spawn a new pirate to plunder the recv booty          _io_impl->recv_pirate_crew.create_thread(boost::bind(              &usrp2_impl::io_impl::recv_pirate_loop, -            _io_impl.get(), _err0_transports.at(i), -            _mboards.at(i), i +            _io_impl.get(), _mboards.at(i), err_xports.at(i), i          ));          //block here until the spawned thread unlocks          _io_impl->spawn_mutex.lock();          //exit loop iteration in an unlocked condition          _io_impl->spawn_mutex.unlock();      } + +    //update mapping here since it didnt b4 when io init not called first +    update_xport_channel_mapping(); +} + +void usrp2_impl::update_xport_channel_mapping(void){ +    if (_io_impl.get() == NULL) return; //not inited yet + +    _io_impl->recv_map.clear(); +    _io_impl->send_map.clear(); + +    for (size_t i = 0; i < _mboards.size(); i++){ + +        subdev_spec_t rx_subdev_spec = _mboards[i]->get_link()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>(); +        for (size_t j = 0; j < rx_subdev_spec.size(); j++){ +            _io_impl->recv_map.push_back(i*usrp2_mboard_impl::MAX_NUM_DSPS+j); +            //std::cout << "recv_map.back() " << _io_impl->recv_map.back() << std::endl; +        } + +        subdev_spec_t tx_subdev_spec = _mboards[i]->get_link()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>(); +        for (size_t j = 0; j < tx_subdev_spec.size(); j++){ +            _io_impl->send_map.push_back(i*usrp2_mboard_impl::MAX_NUM_DSPS+j); +            //std::cout << "send_map.back() " << _io_impl->send_map.back() << std::endl; +        } + +    } + +    _io_impl->packet_handler_recv_state = vrt_packet_handler::recv_state(_io_impl->recv_map.size()); +    _io_impl->packet_handler_send_state = vrt_packet_handler::send_state(_io_impl->send_map.size());  }  /*********************************************************************** @@ -300,7 +327,7 @@ size_t usrp2_impl::get_max_send_samps_per_packet(void) const{          + vrt_send_header_offset_words32*sizeof(boost::uint32_t)          - sizeof(vrt::if_packet_info_t().cid) //no class id ever used      ; -    const size_t bpp = _data_transports.front()->get_send_frame_size() - hdr_size; +    const size_t bpp = dsp_xports.front()->get_send_frame_size() - hdr_size;      return bpp/_tx_otw_type.get_sample_size();  } @@ -383,14 +410,15 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs(      vrt_packet_handler::managed_recv_buffs_t &buffs  ){      if (buffs.size() == 1){ -        buffs[0] = xports[0]->get_recv_buff(recv_timeout); +        buffs[0] = dsp_xports[recv_map[0]]->get_recv_buff(recv_timeout);          if (buffs[0].get() == NULL) return false;          bool clear, msg; time_spec_t time; //unused variables          //call extract_packet_info to handle printing the overflows -        extract_packet_info(buffs[0], this->prev_infos[0], time, clear, msg); +        extract_packet_info(buffs[0], this->prev_infos[recv_map[0]], time, clear, msg);          return true;      }      //-------------------- begin alignment logic ---------------------// +    UHD_ASSERT_THROW(recv_map.size() == buffs.size());      boost::system_time exit_time = boost::get_system_time() + to_time_dur(recv_timeout);      managed_recv_buffer::sptr buff_tmp;      alignment_indexes indexes_to_do; @@ -404,9 +432,9 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs(      //do an initial pop to load an initial sequence id      size_t index = indexes_to_do.front(); -    buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); +    buff_tmp = dsp_xports[recv_map[index]]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time()));      if (buff_tmp.get() == NULL) return false; -    extract_packet_info(buff_tmp, this->prev_infos[index], expected_time, clear, msg); +    extract_packet_info(buff_tmp, this->prev_infos[recv_map[index]], expected_time, clear, msg);      if (clear) goto got_clear;      buffs[index] = buff_tmp;      if (msg) return handle_msg_packet(buffs, index); @@ -417,10 +445,10 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs(          //pop an element off for this index          index = indexes_to_do.front(); -        buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); +        buff_tmp = dsp_xports[recv_map[index]]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time()));          if (buff_tmp.get() == NULL) return false;          time_spec_t this_time; -        extract_packet_info(buff_tmp, this->prev_infos[index], this_time, clear, msg); +        extract_packet_info(buff_tmp, this->prev_infos[recv_map[index]], this_time, clear, msg);          if (clear) goto got_clear;          buffs[index] = buff_tmp;          if (msg) return handle_msg_packet(buffs, index); @@ -458,13 +486,14 @@ size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{          + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer          - sizeof(vrt::if_packet_info_t().cid) //no class id ever used      ; -    const size_t bpp = _data_transports.front()->get_recv_frame_size() - hdr_size; +    const size_t bpp = dsp_xports.front()->get_recv_frame_size() - hdr_size;      return bpp/_rx_otw_type.get_sample_size();  } -static void handle_overflow(std::vector<usrp2_mboard_impl::sptr> &mboards, size_t chan){ +void usrp2_impl::handle_overflow(size_t chan){      std::cerr << "O" << std::flush; -    mboards.at(chan/mboards.size())->handle_overflow(); +    div_t indexes = div(chan, usrp2_mboard_impl::NUM_RX_DSPS); +    _mboards.at(indexes.quot)->handle_overflow(indexes.rem);  }  size_t usrp2_impl::recv( @@ -481,6 +510,6 @@ size_t usrp2_impl::recv(          _mboards.front()->get_master_clock_freq(), //master clock tick rate          uhd::transport::vrt::if_hdr_unpack_be,          _io_impl->get_recv_buffs_fcn, -        boost::bind(&handle_overflow, boost::ref(_mboards), _1) +        boost::bind(&usrp2_impl::handle_overflow, this, _1)      );  } diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 397fae636..b8849f65b 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -21,8 +21,8 @@  #include <uhd/usrp/misc_utils.hpp>  #include <uhd/usrp/dsp_utils.hpp>  #include <uhd/usrp/mboard_props.hpp> -#include <uhd/utils/assert.hpp>  #include <uhd/utils/byteswap.hpp> +#include <uhd/utils/assert.hpp>  #include <uhd/utils/algorithm.hpp>  #include <boost/bind.hpp>  #include <iostream> @@ -33,35 +33,66 @@ static const size_t mimo_clock_sync_delay_cycles = 137;  using namespace uhd;  using namespace uhd::usrp; +using namespace uhd::transport;  /*********************************************************************** - * Structors + * Helpers   **********************************************************************/ -usrp2_mboard_impl::usrp2_mboard_impl( -    size_t index, -    transport::udp_simple::sptr ctrl_transport, -    transport::zero_copy_if::sptr data_transport, -    transport::zero_copy_if::sptr err0_transport, -    const device_addr_t &device_args, -    size_t recv_samps_per_packet -): -    _index(index), -    _iface(usrp2_iface::make(ctrl_transport)) -{ +static void init_xport(zero_copy_if::sptr xport){      //Send a small data packet so the usrp2 knows the udp source port.      //This setup must happen before further initialization occurs      //or the async update packets will cause ICMP destination unreachable. -    transport::managed_send_buffer::sptr send_buff;      static const boost::uint32_t data[2] = {          uhd::htonx(boost::uint32_t(0 /* don't care seq num */)),          uhd::htonx(boost::uint32_t(USRP2_INVALID_VRT_HEADER))      }; -    send_buff = data_transport->get_send_buff(); -    std::memcpy(send_buff->cast<void*>(), &data, sizeof(data)); -    send_buff->commit(sizeof(data)); -    send_buff = err0_transport->get_send_buff(); + +    transport::managed_send_buffer::sptr send_buff = xport->get_send_buff();      std::memcpy(send_buff->cast<void*>(), &data, sizeof(data));      send_buff->commit(sizeof(data)); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp2_mboard_impl::usrp2_mboard_impl( +    const device_addr_t &device_addr, +    size_t index, usrp2_impl &device +): +    _index(index), _device(device), +    _iface(usrp2_iface::make(udp_simple::make_connected( +        device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT) +    ))) +{ + +    //setup the dsp transport hints (default to a large recv buff) +    device_addr_t dsp_xport_hints = device_addr; +    if (not dsp_xport_hints.has_key("recv_buff_size")){ +        //only enable on platforms that are happy with the large buffer resize +        #if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) +            //set to half-a-second of buffering at max rate +            dsp_xport_hints["recv_buff_size"] = "50e6"; +        #endif /*defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)*/ +    } + +    //construct transports for dsp and async errors +    std::cout << "Making transport for DSP0..." << std::endl; +    device.dsp_xports.push_back(udp_zero_copy::make( +        device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_DSP0_PORT), dsp_xport_hints +    )); +    init_xport(device.dsp_xports.back()); + +    std::cout << "Making transport for DSP1..." << std::endl; +    device.dsp_xports.push_back(udp_zero_copy::make( +        device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_DSP1_PORT), dsp_xport_hints +    )); +    init_xport(device.dsp_xports.back()); + +    std::cout << "Making transport for ERR0..." << std::endl; +    device.err_xports.push_back(udp_zero_copy::make( +        device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_ERR0_PORT), device_addr_t() +    )); +    init_xport(device.err_xports.back());      //contruct the interfaces to mboard perifs      _clock_ctrl = usrp2_clock_ctrl::make(_iface); @@ -72,66 +103,30 @@ usrp2_mboard_impl::usrp2_mboard_impl(      //if(_gps_ctrl->gps_detected()) std::cout << "GPS time: " << _gps_ctrl->get_time() << std::endl; -    //TODO move to dsp impl... -    //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(); -    for (size_t i = 4; i <= 128; i+=1){ -        _allowed_decim_and_interp_rates.push_back(i); -    } -    for (size_t i = 130; i <= 256; i+=2){ -        _allowed_decim_and_interp_rates.push_back(i); -    } -    for (size_t i = 260; i <= 512; i+=4){ -        _allowed_decim_and_interp_rates.push_back(i); -    } - -    //setup the vrt rx registers -    _iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //reset -    _iface->poke32(_iface->regs.rx_ctrl_nsamps_per_pkt, recv_samps_per_packet); -    _iface->poke32(_iface->regs.rx_ctrl_nchannels, 1); -    _iface->poke32(_iface->regs.rx_ctrl_vrt_header, 0 -        | (0x1 << 28) //if data with stream id -        | (0x1 << 26) //has trailer -        | (0x3 << 22) //integer time other -        | (0x1 << 20) //fractional time sample count -    ); -    _iface->poke32(_iface->regs.rx_ctrl_vrt_stream_id, usrp2_impl::RECV_SID); -    _iface->poke32(_iface->regs.rx_ctrl_vrt_trailer, 0); -    _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq())); - -    //init the tx control registers -    _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset -    _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0);    //1 channel -    _iface->poke32(_iface->regs.tx_ctrl_report_sid, usrp2_impl::ASYNC_SID); -    _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); +    //init the dsp stuff (before setting update packets) +    dsp_init();      //setting the cycles per update (disabled by default) -    const double ups_per_sec = device_args.cast<double>("ups_per_sec", 0.0); +    const double ups_per_sec = device_addr.cast<double>("ups_per_sec", 0.0);      if (ups_per_sec > 0.0){          const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec);          _iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up);      }      //setting the packets per update (enabled by default) -    const double ups_per_fifo = device_args.cast<double>("ups_per_fifo", 8.0); +    size_t send_frame_size = device.dsp_xports[0]->get_send_frame_size(); +    const double ups_per_fifo = device_addr.cast<double>("ups_per_fifo", 8.0);      if (ups_per_fifo > 0.0){ -        const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size()); +        const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/send_frame_size);          _iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up);      } -    //init the ddc -    init_ddc_config(); - -    //init the duc -    init_duc_config(); -      //initialize the clock configuration -    if (device_args.has_key("mimo_mode")){ -        if (device_args["mimo_mode"] == "master"){ +    if (device_addr.has_key("mimo_mode")){ +        if (device_addr["mimo_mode"] == "master"){              _mimo_clocking_mode_is_master = true;          } -        else if (device_args["mimo_mode"] == "slave"){ +        else if (device_addr["mimo_mode"] == "slave"){              _mimo_clocking_mode_is_master = false;          }          else throw std::runtime_error( @@ -158,13 +153,18 @@ usrp2_mboard_impl::usrp2_mboard_impl(      (*this)[MBOARD_PROP_RX_SUBDEV_SPEC] = subdev_spec_t();      (*this)[MBOARD_PROP_TX_SUBDEV_SPEC] = subdev_spec_t(); +    //------------------------------------------------------------------      //This is a hack/fix for the lingering packet problem.      stream_cmd_t stream_cmd(stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); -    stream_cmd.num_samps = 1; -    this->issue_ddc_stream_cmd(stream_cmd); -    data_transport->get_recv_buff().get(); //recv with timeout for lingering -    data_transport->get_recv_buff().get(); //recv with timeout for expected -    _iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //resets sequence +    for (size_t i = 0; i < NUM_RX_DSPS; i++){ +        size_t index = device.dsp_xports.size() - NUM_RX_DSPS + i; +        stream_cmd.num_samps = 1; +        this->issue_ddc_stream_cmd(stream_cmd, i); +        device.dsp_xports.at(index)->get_recv_buff(0.01).get(); //recv with timeout for lingering +        device.dsp_xports.at(index)->get_recv_buff(0.01).get(); //recv with timeout for expected +        _iface->poke32(_iface->regs.rx_ctrl[i].clear_overrun, 1); //resets sequence +    } +    //------------------------------------------------------------------  }  usrp2_mboard_impl::~usrp2_mboard_impl(void){ @@ -265,19 +265,6 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){      _iface->poke32(_iface->regs.time64_secs, boost::uint32_t(time_spec.get_full_secs()));  } -void usrp2_mboard_impl::handle_overflow(void){ -    if (_continuous_streaming){ //re-issue the stream command if already continuous -        this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); -    } -} - -void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ -    _continuous_streaming = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS; -    _iface->poke32(_iface->regs.rx_ctrl_stream_cmd, dsp_type1::calc_stream_cmd_word(stream_cmd)); -    _iface->poke32(_iface->regs.rx_ctrl_time_secs,  boost::uint32_t(stream_cmd.time_spec.get_full_secs())); -    _iface->poke32(_iface->regs.rx_ctrl_time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); -} -  /***********************************************************************   * MBoard Get Properties   **********************************************************************/ @@ -314,21 +301,19 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){          return;      case MBOARD_PROP_RX_DSP: -        UHD_ASSERT_THROW(key.name == ""); -        val = _rx_dsp_proxy->get_link(); +        val = _rx_dsp_proxies[key.name]->get_link();          return;      case MBOARD_PROP_RX_DSP_NAMES: -        val = prop_names_t(1, ""); +        val = _rx_dsp_proxies.keys();          return;      case MBOARD_PROP_TX_DSP: -        UHD_ASSERT_THROW(key.name == ""); -        val = _tx_dsp_proxy->get_link(); +        val = _tx_dsp_proxies[key.name]->get_link();          return;      case MBOARD_PROP_TX_DSP_NAMES: -        val = prop_names_t(1, ""); +        val = _tx_dsp_proxies.keys();          return;      case MBOARD_PROP_CLOCK_CONFIG: @@ -391,30 +376,32 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){          set_time_spec(val.as<time_spec_t>(), false);          return; -    case MBOARD_PROP_STREAM_CMD: -        issue_ddc_stream_cmd(val.as<stream_cmd_t>()); -        return; -      case MBOARD_PROP_RX_SUBDEV_SPEC:          _rx_subdev_spec = val.as<subdev_spec_t>();          verify_rx_subdev_spec(_rx_subdev_spec, this->get_link());          //sanity check -        UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); +        UHD_ASSERT_THROW(_rx_subdev_spec.size() <= NUM_RX_DSPS);          //set the mux -        _iface->poke32(_iface->regs.dsp_rx_mux, dsp_type1::calc_rx_mux_word( -            _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() -        )); +        for (size_t i = 0; i < _rx_subdev_spec.size(); i++){ +            if (_rx_subdev_spec.size() >= 1) _iface->poke32(_iface->regs.dsp_rx[i].mux, dsp_type1::calc_rx_mux_word( +                _dboard_manager->get_rx_subdev(_rx_subdev_spec[i].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() +            )); +        } +        _device.update_xport_channel_mapping();          return;      case MBOARD_PROP_TX_SUBDEV_SPEC:          _tx_subdev_spec = val.as<subdev_spec_t>();          verify_tx_subdev_spec(_tx_subdev_spec, this->get_link());          //sanity check -        UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); +        UHD_ASSERT_THROW(_tx_subdev_spec.size() <= NUM_TX_DSPS);          //set the mux -        _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word( -            _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() -        )); +        for (size_t i = 0; i < _rx_subdev_spec.size(); i++){ +            _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word( +                _dboard_manager->get_tx_subdev(_tx_subdev_spec[i].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() +            )); +        } +        _device.update_xport_channel_mapping();          return;      case MBOARD_PROP_EEPROM_MAP: diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 9ce0f7359..6230ec41c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -22,14 +22,13 @@  #include <uhd/utils/assert.hpp>  #include <uhd/utils/static.hpp>  #include <uhd/utils/warning.hpp> -#include <boost/algorithm/string.hpp> //for split +#include <uhd/utils/byteswap.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/format.hpp>  #include <boost/foreach.hpp>  #include <boost/lexical_cast.hpp> -#include <boost/regex.hpp>  #include <boost/bind.hpp> -#include <boost/asio.hpp> //htonl and ntohl +#include <boost/asio/ip/address_v4.hpp>  #include <iostream>  #include <vector> @@ -39,66 +38,11 @@ using namespace uhd::transport;  namespace asio = boost::asio;  /*********************************************************************** - * Helper Functions - **********************************************************************/ -template <class T> std::string num2str(T num){ -    return boost::lexical_cast<std::string>(num); -} - -//! separate indexed device addresses into a vector of device addresses -device_addrs_t sep_indexed_dev_addrs(const device_addr_t &dev_addr){ -    //------------ support old deprecated way and print warning -------- -    if (dev_addr.has_key("addr") and not dev_addr["addr"].empty()){ -        std::vector<std::string> addrs; boost::split(addrs, dev_addr["addr"], boost::is_any_of(" ")); -        if (addrs.size() > 1){ -            device_addr_t fixed_dev_addr = dev_addr; -            fixed_dev_addr.pop("addr"); -            for (size_t i = 0; i < addrs.size(); i++){ -                fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i]; -            } -            uhd::warning::post( -                "addr = <space separated list of ip addresses> is deprecated.\n" -                "To address a multi-device, use multiple <key><index> = <val>.\n" -                "See the USRP-NXXX application notes. Two device example:\n" -                "    addr0 = 192.168.10.2\n" -                "    addr1 = 192.168.10.3\n" -            ); -            return sep_indexed_dev_addrs(fixed_dev_addr); -        } -    } -    //------------------------------------------------------------------ -    device_addrs_t dev_addrs; -    BOOST_FOREACH(const std::string &key, dev_addr.keys()){ -        boost::cmatch matches; -        if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){ -            throw std::runtime_error("unknown key format: " + key); -        } -        std::string key_part(matches[1].first, matches[1].second); -        std::string num_part(matches[2].first, matches[2].second); -        size_t num = (num_part.empty())? 0 : boost::lexical_cast<size_t>(num_part); -        dev_addrs.resize(std::max(num+1, dev_addrs.size())); -        dev_addrs[num][key_part] = dev_addr[key]; -    } -    return dev_addrs; -} - -//! combine a vector in device addresses into an indexed device address -device_addr_t combine_dev_addr_vector(const device_addrs_t &dev_addrs){ -    device_addr_t dev_addr; -    for (size_t i = 0; i < dev_addrs.size(); i++){ -        BOOST_FOREACH(const std::string &key, dev_addrs[i].keys()){ -            dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key]; -        } -    } -    return dev_addr; -} - -/***********************************************************************   * Discovery over the udp transport   **********************************************************************/  static device_addrs_t usrp2_find(const device_addr_t &hint_){      //handle the multi-device discovery -    device_addrs_t hints = sep_indexed_dev_addrs(hint_); +    device_addrs_t hints = separate_device_addr(hint_);      if (hints.size() > 1){          device_addrs_t found_devices;          BOOST_FOREACH(const device_addr_t &hint_i, hints){ @@ -108,7 +52,7 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){              ) % hint_i.to_string()));              found_devices.push_back(found_devices_i[0]);          } -        return device_addrs_t(1, combine_dev_addr_vector(found_devices)); +        return device_addrs_t(1, combine_device_addrs(found_devices));      }      //initialize the hint for a single device case @@ -147,8 +91,8 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){      //send a hello control packet      usrp2_ctrl_data_t ctrl_data_out; -    ctrl_data_out.proto_ver = htonl(USRP2_FW_COMPAT_NUM); -    ctrl_data_out.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO); +    ctrl_data_out.proto_ver = uhd::htonx<boost::uint32_t>(USRP2_FW_COMPAT_NUM); +    ctrl_data_out.id = uhd::htonx<boost::uint32_t>(USRP2_CTRL_ID_WAZZUP_BRO);      udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out)));      //loop and recieve until the timeout @@ -157,9 +101,9 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){      while(true){          size_t len = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem));          //std::cout << len << "\n"; -        if (len > offsetof(usrp2_ctrl_data_t, data) and ntohl(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE){ +        if (len > offsetof(usrp2_ctrl_data_t, data) and uhd::ntohx(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE){              //make a boost asio ipv4 with the raw addr in host byte order -            boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.ip_addr)); +            boost::asio::ip::address_v4 ip_addr(uhd::ntohx(ctrl_data_in->data.ip_addr));              device_addr_t new_addr;              new_addr["type"] = "usrp2";              new_addr["addr"] = ip_addr.to_string(); @@ -167,9 +111,9 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){              //This operation can throw due to compatibility mismatch.              //In this case, the discovered device will be ignored.              try{ -                mboard_eeprom_t mb_eeprom = usrp2_iface::make( -                    udp_simple::make_connected(new_addr["addr"], num2str(USRP2_UDP_CTRL_PORT)) -                )->mb_eeprom; +                mboard_eeprom_t mb_eeprom = usrp2_iface::make(udp_simple::make_connected( +                    new_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT) +                ))->mb_eeprom;                  new_addr["name"] = mb_eeprom["name"];                  new_addr["serial"] = mb_eeprom["serial"];                  if ( @@ -198,39 +142,7 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){   * Make   **********************************************************************/  static device::sptr usrp2_make(const device_addr_t &device_addr){ - -    //setup the dsp transport hints (default to a large recv buff) -    device_addr_t dsp_xport_hints = device_addr; -    if (not dsp_xport_hints.has_key("recv_buff_size")){ -        //only enable on platforms that are happy with the large buffer resize -        #if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) -            //set to half-a-second of buffering at max rate -            dsp_xport_hints["recv_buff_size"] = "50e6"; -        #endif /*defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)*/ -    } - -    //create a ctrl and data transport for each address -    std::vector<udp_simple::sptr> ctrl_transports; -    std::vector<zero_copy_if::sptr> data_transports; -    std::vector<zero_copy_if::sptr> err0_transports; -    const device_addrs_t device_addrs = sep_indexed_dev_addrs(device_addr); - -    BOOST_FOREACH(const device_addr_t &dev_addr_i, device_addrs){ -        ctrl_transports.push_back(udp_simple::make_connected( -            dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT) -        )); -        data_transports.push_back(udp_zero_copy::make( -            dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), dsp_xport_hints -        )); -        err0_transports.push_back(udp_zero_copy::make( -            dev_addr_i["addr"], num2str(USRP2_UDP_ERR0_PORT), device_addr_t() -        )); -    } - -    //create the usrp2 implementation guts -    return device::sptr(new usrp2_impl( -        ctrl_transports, data_transports, err0_transports, device_addrs -    )); +    return device::sptr(new usrp2_impl(device_addr));  }  UHD_STATIC_BLOCK(register_usrp2_device){ @@ -240,15 +152,9 @@ UHD_STATIC_BLOCK(register_usrp2_device){  /***********************************************************************   * Structors   **********************************************************************/ -usrp2_impl::usrp2_impl( -    std::vector<udp_simple::sptr> ctrl_transports, -    std::vector<zero_copy_if::sptr> data_transports, -    std::vector<zero_copy_if::sptr> err0_transports, -    const device_addrs_t &device_args -): -    _data_transports(data_transports), -    _err0_transports(err0_transports) -{ +usrp2_impl::usrp2_impl(const device_addr_t &device_addr){ +    device_addrs_t device_args = separate_device_addr(device_addr); +      //setup rx otw type      _rx_otw_type.width = 16;      _rx_otw_type.shift = 0; @@ -263,13 +169,16 @@ usrp2_impl::usrp2_impl(      //create a new mboard handler for each control transport      for(size_t i = 0; i < device_args.size(); i++){ -        _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( -            i, ctrl_transports[i], data_transports[i], -            err0_transports[i], device_args[i], -            this->get_max_recv_samps_per_packet() -        ))); +        device_addr_t dev_addr_i = device_args[i]; +        BOOST_FOREACH(const std::string &key, device_addr.keys()){ +            if (dev_addr_i.has_key(key)) continue; +            dev_addr_i[key] = device_addr[key]; +        } +        _mboards.push_back(usrp2_mboard_impl::sptr( +            new usrp2_mboard_impl(dev_addr_i, i, *this) +        ));          //use an empty name when there is only one mboard -        std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : ""; +        std::string name = (device_args.size() > 1)? boost::lexical_cast<std::string>(i) : "";          _mboard_dict[name] = _mboards.back();      } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 337f842d6..0676cecf2 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -71,6 +71,8 @@ private:      void set(const wax::obj &key, const wax::obj &val){return _set(key, val);}  }; +class usrp2_impl; +  /*!   * USRP2 mboard implementation guts:   * The implementation details are encapsulated here. @@ -80,14 +82,14 @@ class usrp2_mboard_impl : public wax::obj{  public:      typedef boost::shared_ptr<usrp2_mboard_impl> sptr; +    static const size_t NUM_RX_DSPS = 2; +    static const size_t NUM_TX_DSPS = 1; +    static const size_t MAX_NUM_DSPS = 2; +      //structors      usrp2_mboard_impl( -        size_t index, -        uhd::transport::udp_simple::sptr, -        uhd::transport::zero_copy_if::sptr, -        uhd::transport::zero_copy_if::sptr, -        const uhd::device_addr_t &device_args, -        size_t recv_samps_per_packet +        const uhd::device_addr_t &device_addr, +        size_t index, usrp2_impl &device      );      ~usrp2_mboard_impl(void); @@ -95,11 +97,11 @@ public:          return _clock_ctrl->get_master_clock_rate();      } -    void handle_overflow(void); +    void handle_overflow(size_t);  private:      size_t _index; -    bool _continuous_streaming; +    usrp2_impl &_device;      bool _mimo_clocking_mode_is_master;      //interfaces @@ -147,27 +149,20 @@ private:      wax_obj_proxy::sptr _tx_dboard_proxy;      uhd::usrp::dboard_eeprom_t _tx_db_eeprom; -    //methods and shadows for the ddc dsp -    std::vector<size_t> _allowed_decim_and_interp_rates; -    size_t _ddc_decim; -    double _ddc_freq; -    void init_ddc_config(void); -    void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd); - -    //methods and shadows for the duc dsp -    size_t _duc_interp; -    double _duc_freq; -    void init_duc_config(void); +    //methods and shadows for the dsps +    UHD_PIMPL_DECL(dsp_impl) _dsp_impl; +    void dsp_init(void); +    void issue_ddc_stream_cmd(const uhd::stream_cmd_t &, size_t);      //properties interface for ddc -    void ddc_get(const wax::obj &, wax::obj &); -    void ddc_set(const wax::obj &, const wax::obj &); -    wax_obj_proxy::sptr _rx_dsp_proxy; +    void ddc_get(const wax::obj &, wax::obj &, size_t); +    void ddc_set(const wax::obj &, const wax::obj &, size_t); +    uhd::dict<std::string, wax_obj_proxy::sptr> _rx_dsp_proxies;      //properties interface for duc -    void duc_get(const wax::obj &, wax::obj &); -    void duc_set(const wax::obj &, const wax::obj &); -    wax_obj_proxy::sptr _tx_dsp_proxy; +    void duc_get(const wax::obj &, wax::obj &, size_t); +    void duc_set(const wax::obj &, const wax::obj &, size_t); +    uhd::dict<std::string, wax_obj_proxy::sptr> _tx_dsp_proxies;  }; @@ -182,19 +177,7 @@ public:      static const boost::uint32_t RECV_SID = 1;      static const boost::uint32_t ASYNC_SID = 2; -    /*! -     * Create a new usrp2 impl base. -     * \param ctrl_transports the udp transports for control -     * \param data_transports the udp transports for data -     * \param err0_transports the udp transports for error -     * \param device_args optional misc device parameters -     */ -    usrp2_impl( -        std::vector<uhd::transport::udp_simple::sptr> ctrl_transports, -        std::vector<uhd::transport::zero_copy_if::sptr> data_transports, -        std::vector<uhd::transport::zero_copy_if::sptr> err0_transports, -        const uhd::device_addrs_t &device_args -    ); +    usrp2_impl(const uhd::device_addr_t &);      ~usrp2_impl(void); @@ -213,6 +196,14 @@ public:      size_t get_max_recv_samps_per_packet(void) const;      bool recv_async_msg(uhd::async_metadata_t &, double); +    void update_xport_channel_mapping(void); + +    //public frame sizes, set by mboard, used by io impl +    size_t recv_frame_size, send_frame_size; + +    std::vector<uhd::transport::zero_copy_if::sptr> dsp_xports; +    std::vector<uhd::transport::zero_copy_if::sptr> err_xports; +  private:      //device properties interface      void get(const wax::obj &, wax::obj &); @@ -223,11 +214,10 @@ private:      uhd::dict<std::string, usrp2_mboard_impl::sptr> _mboard_dict;      //io impl methods and members -    std::vector<uhd::transport::zero_copy_if::sptr> _data_transports; -    std::vector<uhd::transport::zero_copy_if::sptr> _err0_transports;      uhd::otw_type_t _rx_otw_type, _tx_otw_type;      UHD_PIMPL_DECL(io_impl) _io_impl;      void io_init(void); +    void handle_overflow(size_t);  };  #endif /* INCLUDED_USRP2_IMPL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp index 84907c32e..66c3ac137 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.cpp +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -38,8 +38,10 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) {    x.sr_udp_sm = 96;    x.sr_tx_dsp = 208;    x.sr_tx_ctrl = 224; -  x.sr_rx_dsp = 160; -  x.sr_rx_ctrl = 176; +  x.sr_rx_dsp0 = 160; +  x.sr_rx_ctrl0 = 176; +  x.sr_rx_dsp1 = 240; +  x.sr_rx_ctrl1 = 32;    x.sr_time64 = 192;    x.sr_simtimer = 198;    x.sr_last = 255; @@ -68,12 +70,18 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) {    x.dsp_tx_scale_iq = sr_addr(misc_output_base, x.sr_tx_dsp + 1);    x.dsp_tx_interp_rate = sr_addr(misc_output_base, x.sr_tx_dsp + 2);    x.dsp_tx_mux = sr_addr(misc_output_base, x.sr_tx_dsp + 4); -  x.dsp_rx_freq = sr_addr(misc_output_base, x.sr_rx_dsp + 0); -  x.dsp_rx_scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp + 1); -  x.dsp_rx_decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp + 2); -  x.dsp_rx_dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp + 3); -  x.dsp_rx_dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp + 4); -  x.dsp_rx_mux = sr_addr(misc_output_base, x.sr_rx_dsp + 5); +  x.dsp_rx[0].freq = sr_addr(misc_output_base, x.sr_rx_dsp0 + 0); +  x.dsp_rx[0].scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp0 + 1); +  x.dsp_rx[0].decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp0 + 2); +  x.dsp_rx[0].dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp0 + 3); +  x.dsp_rx[0].dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp0 + 4); +  x.dsp_rx[0].mux = sr_addr(misc_output_base, x.sr_rx_dsp0 + 5); +  x.dsp_rx[1].freq = sr_addr(misc_output_base, x.sr_rx_dsp1 + 0); +  x.dsp_rx[1].scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp1 + 1); +  x.dsp_rx[1].decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp1 + 2); +  x.dsp_rx[1].dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp1 + 3); +  x.dsp_rx[1].dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp1 + 4); +  x.dsp_rx[1].mux = sr_addr(misc_output_base, x.sr_rx_dsp1 + 5);    x.gpio_io = gpio_base + 0;    x.gpio_ddr = gpio_base + 4;    x.gpio_tx_sel = gpio_base + 8; @@ -86,15 +94,24 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) {    x.atr_inrx_rxside = atr_base + 10;    x.atr_full_txside = atr_base + 12;    x.atr_full_rxside = atr_base + 14; -  x.rx_ctrl_stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl + 0); -  x.rx_ctrl_time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl + 1); -  x.rx_ctrl_time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl + 2); -  x.rx_ctrl_clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl + 3); -  x.rx_ctrl_vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl + 4); -  x.rx_ctrl_vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl + 5); -  x.rx_ctrl_vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl + 6); -  x.rx_ctrl_nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl + 7); -  x.rx_ctrl_nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl + 8); +  x.rx_ctrl[0].stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 0); +  x.rx_ctrl[0].time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 1); +  x.rx_ctrl[0].time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 2); +  x.rx_ctrl[0].clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 3); +  x.rx_ctrl[0].vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 4); +  x.rx_ctrl[0].vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 5); +  x.rx_ctrl[0].vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 6); +  x.rx_ctrl[0].nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 7); +  x.rx_ctrl[0].nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 8); +  x.rx_ctrl[1].stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 0); +  x.rx_ctrl[1].time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 1); +  x.rx_ctrl[1].time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 2); +  x.rx_ctrl[1].clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 3); +  x.rx_ctrl[1].vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 4); +  x.rx_ctrl[1].vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 5); +  x.rx_ctrl[1].vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 6); +  x.rx_ctrl[1].nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 7); +  x.rx_ctrl[1].nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 8);    x.tx_ctrl_num_chan = sr_addr(misc_output_base, x.sr_tx_ctrl + 0);    x.tx_ctrl_clear_state = sr_addr(misc_output_base, x.sr_tx_ctrl + 1);    x.tx_ctrl_report_sid = sr_addr(misc_output_base, x.sr_tx_ctrl + 2); diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 977b342cb..01f5ee65a 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -38,8 +38,10 @@ typedef struct {      int sr_udp_sm;      int sr_tx_dsp;      int sr_tx_ctrl; -    int sr_rx_dsp; -    int sr_rx_ctrl; +    int sr_rx_dsp0; +    int sr_rx_ctrl0; +    int sr_rx_dsp1; +    int sr_rx_ctrl1;      int sr_time64;      int sr_simtimer;      int sr_last; @@ -68,12 +70,14 @@ typedef struct {      int dsp_tx_scale_iq;      int dsp_tx_interp_rate;      int dsp_tx_mux; -    int dsp_rx_freq; -    int dsp_rx_scale_iq; -    int dsp_rx_decim_rate; -    int dsp_rx_dcoffset_i; -    int dsp_rx_dcoffset_q; -    int dsp_rx_mux; +    struct{ +        int freq; +        int scale_iq; +        int decim_rate; +        int dcoffset_i; +        int dcoffset_q; +        int mux; +    } dsp_rx[2];      int gpio_base;      int gpio_io;      int gpio_ddr; @@ -88,15 +92,17 @@ typedef struct {      int atr_inrx_rxside;      int atr_full_txside;      int atr_full_rxside; -    int rx_ctrl_stream_cmd; -    int rx_ctrl_time_secs; -    int rx_ctrl_time_ticks; -    int rx_ctrl_clear_overrun; -    int rx_ctrl_vrt_header; -    int rx_ctrl_vrt_stream_id; -    int rx_ctrl_vrt_trailer; -    int rx_ctrl_nsamps_per_pkt; -    int rx_ctrl_nchannels; +    struct{ +        int stream_cmd; +        int time_secs; +        int time_ticks; +        int clear_overrun; +        int vrt_header; +        int vrt_stream_id; +        int vrt_trailer; +        int nsamps_per_pkt; +        int nchannels; +    } rx_ctrl[2];      int tx_ctrl_num_chan;      int tx_ctrl_clear_state;      int tx_ctrl_report_sid; diff --git a/host/lib/usrp/usrp_e100/dsp_impl.cpp b/host/lib/usrp/usrp_e100/dsp_impl.cpp index 7d358a607..8d084f066 100644 --- a/host/lib/usrp/usrp_e100/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e100/dsp_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -60,10 +60,6 @@ void usrp_e100_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){          val = _ddc_freq;          return; -    case DSP_PROP_FREQ_SHIFT_NAMES: -        val = prop_names_t(1, ""); -        return; -      case DSP_PROP_CODEC_RATE:          val = _clock_ctrl->get_fpga_clock_rate();          return; @@ -84,6 +80,10 @@ void usrp_e100_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){      switch(key.as<dsp_prop_t>()){ +    case DSP_PROP_STREAM_CMD: +        issue_stream_cmd(val.as<stream_cmd_t>()); +        return; +      case DSP_PROP_FREQ_SHIFT:{              double new_freq = val.as<double>();              _iface->poke32(UE_REG_DSP_RX_FREQ, @@ -143,10 +143,6 @@ void usrp_e100_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){          val = _duc_freq;          return; -    case DSP_PROP_FREQ_SHIFT_NAMES: -        val = prop_names_t(1, ""); -        return; -      case DSP_PROP_CODEC_RATE:          val = _clock_ctrl->get_fpga_clock_rate();          return; diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp index 0e08cd435..a4db53715 100644 --- a/host/lib/usrp/usrp_e100/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -167,10 +167,6 @@ void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){      //handle the get request conditioned on the key      switch(key.as<mboard_prop_t>()){ -    case MBOARD_PROP_STREAM_CMD: -        issue_stream_cmd(val.as<stream_cmd_t>()); -        return; -      case MBOARD_PROP_TIME_NOW:      case MBOARD_PROP_TIME_PPS:{              time_spec_t time_spec = val.as<time_spec_t>(); diff --git a/host/tests/tune_helper_test.cpp b/host/tests/tune_helper_test.cpp index 735e7e948..aabaaaf6e 100644 --- a/host/tests/tune_helper_test.cpp +++ b/host/tests/tune_helper_test.cpp @@ -153,10 +153,6 @@ private:              val = _freq_shift;              return; -        case DSP_PROP_FREQ_SHIFT_NAMES: -            val = prop_names_t(1, ""); -            return; -          default: UHD_THROW_PROP_GET_ERROR();          }      } @@ -190,12 +186,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){      dummy_dsp dsp(100e6);      std::cout << "Testing tune helper RX automatic IF offset" << std::endl; -    tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); +    tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9);      std::cout << tr.to_pp_string() << std::endl;      BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);      BOOST_CHECK_CLOSE(tr.actual_dsp_freq, -100e3, tolerance); -    double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); +    double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link());      BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance);  } @@ -204,12 +200,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){      dummy_dsp dsp(100e6);      std::cout << "Testing tune helper TX automatic IF offset" << std::endl; -    tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); +    tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9);      std::cout << tr.to_pp_string() << std::endl;      BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);      BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 100e3, tolerance); -    double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); +    double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link());      BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance);  } @@ -218,12 +214,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){      dummy_dsp dsp(100e6);      std::cout << "Testing tune helper RX dummy basic board" << std::endl; -    tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 55e6); +    tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 55e6);      std::cout << tr.to_pp_string() << std::endl;      BOOST_CHECK_CLOSE(tr.actual_inter_freq, 0.0, tolerance);      BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 45e6, tolerance); -    double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); +    double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link());      BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance);  } @@ -235,21 +231,21 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){      std::cout << "Testing tune helper RX automatic LO offset B >> fs" << std::endl;      subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);      dsp[DSP_PROP_HOST_RATE] = double(4e6); -    tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); +    tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);      std::cout << tr.to_pp_string() << std::endl;      BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+4e6/2, tolerance);      std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl;      subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);      dsp[DSP_PROP_HOST_RATE] = double(25e6); -    tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); +    tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);      std::cout << tr.to_pp_string() << std::endl;      BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+(40e6-25e6)/2, tolerance);      std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl;      subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6);      dsp[DSP_PROP_HOST_RATE] = double(25e6); -    tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); +    tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);      std::cout << tr.to_pp_string() << std::endl;      BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9, tolerance);  } | 
