diff options
author | eb | 2008-10-22 00:56:40 +0000 |
---|---|---|
committer | eb | 2008-10-22 00:56:40 +0000 |
commit | bfe79d23738f24562dc7612049a90e8b20b53f79 (patch) | |
tree | 312e66fc143621f320f6e57592f5194e15e52e1f /usrp2 | |
parent | afc6e2b005581d1061b47c464f47ff2b48c6418b (diff) | |
download | gnuradio-bfe79d23738f24562dc7612049a90e8b20b53f79.tar.gz gnuradio-bfe79d23738f24562dc7612049a90e8b20b53f79.tar.bz2 gnuradio-bfe79d23738f24562dc7612049a90e8b20b53f79.zip |
Added methods to query daughterboard parameters. Merged eb/u2-wip2
-r9804:9814 into trunk; initialized dacmux in firmware.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9816 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'usrp2')
-rw-r--r-- | usrp2/firmware/apps/app_common_v2.c | 37 | ||||
-rw-r--r-- | usrp2/firmware/include/usrp2_eth_packet.h | 34 | ||||
-rw-r--r-- | usrp2/firmware/lib/memory_map.h | 2 | ||||
-rw-r--r-- | usrp2/firmware/lib/u2_init.c | 2 | ||||
-rw-r--r-- | usrp2/host/include/usrp2/usrp2.h | 169 | ||||
-rw-r--r-- | usrp2/host/lib/control.h | 14 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2.cc | 116 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_impl.cc | 194 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_impl.h | 47 |
9 files changed, 565 insertions, 50 deletions
diff --git a/usrp2/firmware/apps/app_common_v2.c b/usrp2/firmware/apps/app_common_v2.c index e267401a9..f132e55fd 100644 --- a/usrp2/firmware/apps/app_common_v2.c +++ b/usrp2/firmware/apps/app_common_v2.c @@ -27,6 +27,7 @@ #include "nonstdio.h" #include "print_rmon_regs.h" #include "db.h" +#include "db_base.h" #include "clocks.h" #include "u2_init.h" #include <string.h> @@ -279,6 +280,38 @@ read_time_cmd(const op_generic_t *p, return r->len; } +static void +fill_db_info(u2_db_info_t *p, const struct db_base *db) +{ + p->dbid = db->dbid; + p->freq_min_hi = u2_fxpt_freq_hi(db->freq_min); + p->freq_min_lo = u2_fxpt_freq_lo(db->freq_min); + p->freq_max_hi = u2_fxpt_freq_hi(db->freq_max); + p->freq_max_lo = u2_fxpt_freq_lo(db->freq_max); + p->gain_min = db->gain_min; + p->gain_max = db->gain_max; + p->gain_step_size = db->gain_step_size; +} + +static size_t +dboard_info_cmd(const op_generic_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_dboard_info_reply_t *r = (op_dboard_info_reply_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) + return 0; // no room + + r->opcode = OP_DBOARD_INFO_REPLY; + r->len = sizeof(*r); + r->rid = p->rid; + r->ok = true; + + fill_db_info(&r->tx_db_info, tx_dboard); + fill_db_info(&r->rx_db_info, rx_dboard); + + return r->len; +} + static size_t generic_reply(const op_generic_t *p, void *reply_payload, size_t reply_payload_space, @@ -374,6 +407,10 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len) subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space); break; + case OP_DBOARD_INFO: + subpktlen = dboard_info_cmd(gp, reply_payload, reply_payload_space); + break; + default: printf("app_common_v2: unhandled opcode = %d\n", gp->opcode); break; diff --git a/usrp2/firmware/include/usrp2_eth_packet.h b/usrp2/firmware/include/usrp2_eth_packet.h index ca13d61ad..ed3ce1fe3 100644 --- a/usrp2/firmware/include/usrp2_eth_packet.h +++ b/usrp2/firmware/include/usrp2_eth_packet.h @@ -181,6 +181,8 @@ typedef struct { #define OP_STOP_RX_REPLY (OP_STOP_RX | OP_REPLY_BIT) #define OP_CONFIG_MIMO 8 #define OP_CONFIG_MIMO_REPLY (OP_CONFIG_MIMO | OP_REPLY_BIT) +#define OP_DBOARD_INFO 9 +#define OP_DBOARD_INFO_REPLY (OP_DBOARD_INFO | OP_REPLY_BIT) //#define OP_WRITE_REG xx // not implemented @@ -199,7 +201,7 @@ typedef struct { * * Used by: * OP_EOP, OP_BURN_MAC_ADDR_REPLY, OP_START_RX_STREAMING_REPLY, - * OP_STOP_RX_REPLY + * OP_STOP_RX_REPLY, OP_DBOARD_INFO */ typedef struct { uint8_t opcode; @@ -348,6 +350,36 @@ typedef struct { } op_config_mimo_t; +/*! + * \brief High-level information about daughterboards + */ +typedef struct { + int32_t dbid; //< d'board ID (-1 none, -2 invalid eeprom) + uint32_t freq_min_hi; //< high 32-bits of 64-bit fxpt_freq (Q44.20) + uint32_t freq_min_lo; //< low 32-bits of 64-bit fxpt_freq (Q44.20) + uint32_t freq_max_hi; //< high 32-bits of 64-bit fxpt_freq (Q44.20) + uint32_t freq_max_lo; //< low 32-bits of 64-bit fxpt_freq (Q44.20) + uint16_t gain_min; //< min gain that can be set. fxpt_db (Q9.7) + uint16_t gain_max; //< max gain that can be set. fxpt_db (Q9.7) + uint16_t gain_step_size; //< fxpt_db (Q9.7) +} u2_db_info_t; + + +/*! + * \brief Reply to d'board info request + */ +typedef struct { + uint8_t opcode; + uint8_t len; + uint8_t rid; + uint8_t ok; // request was successful (bool) + + u2_db_info_t tx_db_info; + u2_db_info_t rx_db_info; +} _AL4 op_dboard_info_reply_t; + + + /* * ================================================================ * union of all of subpacket types diff --git a/usrp2/firmware/lib/memory_map.h b/usrp2/firmware/lib/memory_map.h index 740bf47fa..159b095c1 100644 --- a/usrp2/firmware/lib/memory_map.h +++ b/usrp2/firmware/lib/memory_map.h @@ -412,7 +412,7 @@ typedef struct { * The default value is 0x10 * </pre> */ - volatile uint32_t tx_mux; // FIXME this register is currently unimplemented + volatile uint32_t tx_mux; } dsp_tx_regs_t; diff --git a/usrp2/firmware/lib/u2_init.c b/usrp2/firmware/lib/u2_init.c index 7482040f0..948055694 100644 --- a/usrp2/firmware/lib/u2_init.c +++ b/usrp2/firmware/lib/u2_init.c @@ -87,7 +87,7 @@ u2_init(void) ad9777_write_reg(12, 0); // Initial values for tx and rx mux registers - // dsp_tx_regs->tx_mux = 0x10; + dsp_tx_regs->tx_mux = 0x10; dsp_rx_regs->rx_mux = 0x44444444; // Set up serdes diff --git a/usrp2/host/include/usrp2/usrp2.h b/usrp2/host/include/usrp2/usrp2.h index b76d31c8d..9a1b8b549 100644 --- a/usrp2/host/include/usrp2/usrp2.h +++ b/usrp2/host/include/usrp2/usrp2.h @@ -26,9 +26,15 @@ //#include <iosfwd> #include <usrp2/rx_sample_handler.h> #include <usrp2/tune_result.h> -#include <usrp2/rx_sample_handler.h> +/* + * N.B., The interfaces described here are still in flux. + * + * We will keep all the code in the tree up-to-date with regard to changes + * here, but reserve the right to change this on a whim. + */ + namespace usrp2 { /*! @@ -89,14 +95,6 @@ namespace usrp2 { */ std::string mac_addr(); - /*! - * Burn new mac address into EEPROM on USRP2 - * - * \param new_addr Network mac address, e.g., "01:23:45:67:89:ab" or "89:ab". - * If \p addr is HH:HH, it's treated as if it were 00:50:c2:85:HH:HH - */ - bool burn_mac_addr(const std::string &new_addr); - /* * ---------------------------------------------------------------- * Rx configuration and control @@ -105,14 +103,30 @@ namespace usrp2 { /*! * Set receiver gain + * \param gain in dB (more or less) */ bool set_rx_gain(double gain); + //! return minimum Rx gain + double rx_gain_min(); + + //! return maximum Rx gain + double rx_gain_max(); + + //! return Rx gain db_per_step + double rx_gain_db_per_step(); + /*! * Set receiver center frequency */ bool set_rx_center_freq(double frequency, tune_result *result); + //! return minimum Rx center frequency + double rx_freq_min(); + + //! return maximum Rx center frequency + double rx_freq_max(); + /*! * Set receiver sample rate decimation */ @@ -175,11 +189,26 @@ namespace usrp2 { */ bool set_tx_gain(double gain); + //! return minimum Tx gain + double tx_gain_min(); + + //! return maximum Tx gain + double tx_gain_max(); + + //! return Tx gain db_per_step + double tx_gain_db_per_step(); + /*! * Set transmitter center frequency */ bool set_tx_center_freq(double frequency, tune_result *result); + //! return minimum Tx center frequency + double tx_freq_min(); + + //! return maximum Tx center frequency + double tx_freq_max(); + /*! * Set transmitter sample rate interpolation */ @@ -253,7 +282,11 @@ namespace usrp2 { size_t nitems, const tx_metadata *metadata); - // ---------------------------------------------------------------- + /* + * ---------------------------------------------------------------- + * miscellaneous methods + * ---------------------------------------------------------------- + */ /*! * \brief MIMO configuration @@ -274,6 +307,122 @@ namespace usrp2 { */ bool config_mimo(int flags); + + //! Get frequency of master oscillator in Hz + bool fpga_master_clock_freq(long *freq); + + // Get Sampling rate of A/D converter in Hz + bool adc_rate(long *rate); + + // Get Sampling rate of D/A converter in Hz + bool dac_rate(long *rate); + + /*! + * \brief Get Tx daughterboard ID + * + * \param[out] dbid returns the daughterboard id. + * + * daughterboard id >= 0 if successful, -1 if no daugherboard installed, + * -2 if invalid EEPROM on daughterboard. + */ + bool tx_daughterboard_id(int *dbid); + + /*! + * \brief Get Rx daughterboard ID + * + * \param[out] dbid returns the daughterboard id. + * + * daughterboard id >= 0 if successful, -1 if no daugherboard installed, + * -2 if invalid EEPROM on daughterboard. + */ + bool rx_daughterboard_id(int *dbid); + + /* + * ---------------------------------------------------------------- + * Low level methods + * ---------------------------------------------------------------- + */ + + /*! + * Burn new mac address into EEPROM on USRP2 + * + * \param new_addr Network mac address, e.g., "01:23:45:67:89:ab" or "89:ab". + * If \p addr is HH:HH, it's treated as if it were 00:50:c2:85:HH:HH + */ + bool burn_mac_addr(const std::string &new_addr); + + +#if 0 // not yet implemented + /*! + * \brief Write EEPROM on motherboard or any daughterboard. + * \param i2c_addr I2C bus address of EEPROM + * \param eeprom_offset byte offset in EEPROM to begin writing + * \param buf the data to write + * \returns true iff sucessful + */ + bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string &buf); + + /*! + * \brief Read EEPROM on motherboard or any daughterboard. + * \param i2c_addr I2C bus address of EEPROM + * \param eeprom_offset byte offset in EEPROM to begin reading + * \param len number of bytes to read + * \returns the data read if successful, else a zero length string. + */ + std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); + + /*! + * \brief Write to I2C peripheral + * \param i2c_addr I2C bus address (7-bits) + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of of 64 bytes. + */ + bool write_i2c (int i2c_addr, const std::string &buf); + + /*! + * \brief Read from I2C peripheral + * \param i2c_addr I2C bus address (7-bits) + * \param len number of bytes to read + * \returns the data read if successful, else a zero length string. + * Reads are limited to a maximum of 64 bytes. + */ + std::string read_i2c (int i2c_addr, int len); + + /*! + * \brief Write data to SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripherals to write. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they are + * written to the peripheral immediately prior to writing \p buf. + */ + bool write_spi (int optional_header, int enables, int format, const std::string &buf); + + /* + * \brief Read data from SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripheral to read. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param len number of bytes to read. Must be in [0,64]. + * \returns the data read if sucessful, else a zero length string. + * + * Reads are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they + * are written to the peripheral first. Then \p len bytes are read from + * the peripheral and returned. + */ + std::string read_spi (int optional_header, int enables, int format, int len); +#endif + + class impl; // implementation details private: diff --git a/usrp2/host/lib/control.h b/usrp2/host/lib/control.h index 678f12e4b..fe30b3f74 100644 --- a/usrp2/host/lib/control.h +++ b/usrp2/host/lib/control.h @@ -53,6 +53,13 @@ namespace usrp2 { op_generic_t eop; }; + struct op_config_mimo_cmd + { + u2_eth_packet_t h; + op_config_mimo_t op; + op_generic_t eop; + }; + struct op_burn_mac_addr_cmd { u2_eth_packet_t h; @@ -60,6 +67,13 @@ namespace usrp2 { op_generic_t eop; }; + struct op_dboard_info_cmd { + u2_eth_packet_t h; + op_generic_t op; + op_generic_t eop; + }; + + /*! * Control mechanism to allow API calls to block waiting for reply packets */ diff --git a/usrp2/host/lib/usrp2.cc b/usrp2/host/lib/usrp2.cc index eda73cdc5..114b925ce 100644 --- a/usrp2/host/lib/usrp2.cc +++ b/usrp2/host/lib/usrp2.cc @@ -160,13 +160,6 @@ namespace usrp2 { return d_impl->mac_addr(); } - bool - usrp2::burn_mac_addr(const std::string &new_addr) - { - return d_impl->burn_mac_addr(new_addr); - } - - // Receive bool @@ -175,12 +168,42 @@ namespace usrp2 { return d_impl->set_rx_gain(gain); } + double + usrp2::rx_gain_min() + { + return d_impl->rx_gain_min(); + } + + double + usrp2::rx_gain_max() + { + return d_impl->rx_gain_max(); + } + + double + usrp2::rx_gain_db_per_step() + { + return d_impl->rx_gain_db_per_step(); + } + bool usrp2::set_rx_center_freq(double frequency, tune_result *result) { return d_impl->set_rx_center_freq(frequency, result); } + double + usrp2::rx_freq_min() + { + return d_impl->rx_freq_min(); + } + + double + usrp2::rx_freq_max() + { + return d_impl->rx_freq_max(); + } + bool usrp2::set_rx_decim(int decimation_factor) { @@ -231,12 +254,43 @@ namespace usrp2 { return d_impl->set_tx_gain(gain); } + double + usrp2::tx_gain_min() + { + return d_impl->tx_gain_min(); + } + + double + usrp2::tx_gain_max() + { + return d_impl->tx_gain_max(); + } + + double + usrp2::tx_gain_db_per_step() + { + return d_impl->tx_gain_db_per_step(); + } + bool usrp2::set_tx_center_freq(double frequency, tune_result *result) { return d_impl->set_tx_center_freq(frequency, result); } + double + usrp2::tx_freq_min() + { + return d_impl->tx_freq_min(); + } + + double + usrp2::tx_freq_max() + { + return d_impl->tx_freq_max(); + } + + bool usrp2::set_tx_interp(int interpolation_factor) { @@ -276,6 +330,54 @@ namespace usrp2 { return d_impl->tx_raw(channel, items, nitems, metadata); } + // miscellaneous methods + + bool + usrp2::config_mimo(int flags) + { + return d_impl->config_mimo(flags); + } + + bool + usrp2::fpga_master_clock_freq(long *freq) + { + return d_impl->fpga_master_clock_freq(freq); + } + + bool + usrp2::adc_rate(long *rate) + { + return d_impl->adc_rate(rate); + } + + bool + usrp2::dac_rate(long *rate) + { + return d_impl->dac_rate(rate); + } + + bool + usrp2::tx_daughterboard_id(int *dbid) + { + return d_impl->tx_daughterboard_id(dbid); + } + + bool + usrp2::rx_daughterboard_id(int *dbid) + { + return d_impl->rx_daughterboard_id(dbid); + } + + + // low level methods + + bool + usrp2::burn_mac_addr(const std::string &new_addr) + { + return d_impl->burn_mac_addr(new_addr); + } + + } // namespace usrp2 diff --git a/usrp2/host/lib/usrp2_impl.cc b/usrp2/host/lib/usrp2_impl.cc index 4b64d06c3..5fd671085 100644 --- a/usrp2/host/lib/usrp2_impl.cc +++ b/usrp2/host/lib/usrp2_impl.cc @@ -68,6 +68,9 @@ namespace usrp2 { case OP_CONFIG_TX_REPLY_V2: return "OP_CONFIG_TX_REPLY_V2"; case OP_START_RX_STREAMING: return "OP_START_RX_STREAMING"; case OP_STOP_RX: return "OP_STOP_RX"; + case OP_CONFIG_MIMO: return "OP_CONFIG_MIMO"; + case OP_DBOARD_INFO: return "OP_DBOARD_INFO"; + case OP_DBOARD_INFO_REPLY: return "OP_DBOARD_INFO_REPLY"; #if 0 case OP_WRITE_REG: return "OP_WRITE_REG"; case OP_WRITE_REG_MASKED: return "OP_WRITE_REG_MASKED"; @@ -105,9 +108,13 @@ namespace usrp2 { md->word0 = u2p_word0(fh); md->timestamp = u2p_timestamp(fh); + // FIXME when we've got more info // md->start_of_burst = (md->word0 & XXX) != 0; // md->end_of_burst = (md->word0 & XXX) != 0; // md->rx_overrun = (md->word0 & XXX) != 0; + md->start_of_burst = 0; + md->end_of_burst = 0; + md->rx_overrun = 0; *items = (uint32_t *)(&fh[1]); size_t nbytes = payload_len_in_bytes - sizeof(u2_fixed_hdr_t); @@ -120,7 +127,7 @@ namespace usrp2 { usrp2::impl::impl(const std::string &ifc, props *p) : d_eth_buf(new eth_buffer()), d_pf(0), d_bg_thread(0), d_bg_running(false), - d_rx_decim(0), d_rx_seqno(-1), d_tx_seqno(0), d_next_rid(0), + d_rx_seqno(-1), d_tx_seqno(0), d_next_rid(0), d_num_rx_frames(0), d_num_rx_missing(0), d_num_rx_overruns(0), d_num_rx_bytes(0), d_num_enqueued(0), d_enqueued_mutex(), d_bg_pending_cond(&d_enqueued_mutex), d_channel_rings(NCHANS) @@ -142,6 +149,36 @@ namespace usrp2 { d_bg_thread = new usrp2_thread(this); d_bg_thread->start(); + if (!dboard_info()) // we're hosed + throw std::runtime_error("Unable to retrieve daughterboard info"); + + if (0){ + int dbid; + + tx_daughterboard_id(&dbid); + fprintf(stderr, "Tx dboard 0x%x\n", dbid); + fprintf(stderr, " freq_min = %g\n", tx_freq_min()); + fprintf(stderr, " freq_max = %g\n", tx_freq_max()); + fprintf(stderr, " gain_min = %g\n", tx_gain_min()); + fprintf(stderr, " gain_max = %g\n", tx_gain_max()); + fprintf(stderr, " gain_db_per_step = %g\n", tx_gain_db_per_step()); + + rx_daughterboard_id(&dbid); + fprintf(stderr, "Rx dboard 0x%x\n", dbid); + fprintf(stderr, " freq_min = %g\n", rx_freq_min()); + fprintf(stderr, " freq_max = %g\n", rx_freq_max()); + fprintf(stderr, " gain_min = %g\n", rx_gain_min()); + fprintf(stderr, " gain_max = %g\n", rx_gain_max()); + fprintf(stderr, " gain_db_per_step = %g\n", rx_gain_db_per_step()); + } + + // default gains to mid point + if (!set_tx_gain((tx_gain_min() + tx_gain_max()) / 2)) + std::cerr << "usrp2::ctor set_tx_gain failed\n"; + + if (!set_rx_gain((rx_gain_min() + rx_gain_max()) / 2)) + std::cerr << "usrp2::ctor set_rx_gain failed\n"; + // set workable defaults for scaling if (!set_rx_scale_iq(DEFAULT_RX_SCALE, DEFAULT_RX_SCALE)) std::cerr << "usrp2::ctor set_rx_scale_iq failed\n"; @@ -412,33 +449,6 @@ namespace usrp2 { // ---------------------------------------------------------------- - // misc commands - // ---------------------------------------------------------------- - - bool - usrp2::impl::burn_mac_addr(const std::string &new_addr) - { - op_burn_mac_addr_cmd cmd; - op_generic_t reply; - - memset(&cmd, 0, sizeof(cmd)); - init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); - cmd.op.opcode = OP_BURN_MAC_ADDR; - cmd.op.len = sizeof(cmd.op); - cmd.op.rid = d_next_rid++; - if (!parse_mac_addr(new_addr, &cmd.op.addr)) - return false; - - pending_reply p(cmd.op.rid, &reply, sizeof(reply)); - if (!transmit_cmd(&cmd, sizeof(cmd), &p, 4*DEF_CMD_TIMEOUT)) - return false; - - bool success = (ntohx(reply.ok) == 1); - return success; - } - - - // ---------------------------------------------------------------- // Receive // ---------------------------------------------------------------- @@ -870,5 +880,133 @@ namespace usrp2 { return true; } + // ---------------------------------------------------------------- + // misc commands + // ---------------------------------------------------------------- + + bool + usrp2::impl::config_mimo(int flags) + { + op_config_mimo_cmd cmd; + op_generic_t reply; + + memset(&cmd, 0, sizeof(cmd)); + init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); + cmd.op.opcode = OP_CONFIG_MIMO; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + cmd.eop.opcode = OP_EOP; + cmd.eop.len = sizeof(cmd.eop); + + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); + if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) + return false; + + return ntohx(reply.ok) == 1; + } + + bool + usrp2::impl::fpga_master_clock_freq(long *freq) + { + *freq = 100000000L; // 100 MHz + return true; + } + + bool + usrp2::impl::adc_rate(long *rate) + { + return fpga_master_clock_freq(rate); + } + + bool + usrp2::impl::dac_rate(long *rate) + { + return fpga_master_clock_freq(rate); + } + + bool + usrp2::impl::tx_daughterboard_id(int *dbid) + { + *dbid = d_tx_db_info.dbid; + return true; + } + + bool + usrp2::impl::rx_daughterboard_id(int *dbid) + { + *dbid = d_rx_db_info.dbid; + return true; + } + + + // ---------------------------------------------------------------- + // low-level commands + // ---------------------------------------------------------------- + + bool + usrp2::impl::burn_mac_addr(const std::string &new_addr) + { + op_burn_mac_addr_cmd cmd; + op_generic_t reply; + + memset(&cmd, 0, sizeof(cmd)); + init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); + cmd.op.opcode = OP_BURN_MAC_ADDR; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + if (!parse_mac_addr(new_addr, &cmd.op.addr)) + return false; + + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); + if (!transmit_cmd(&cmd, sizeof(cmd), &p, 4*DEF_CMD_TIMEOUT)) + return false; + + bool success = (ntohx(reply.ok) == 1); + return success; + } + + static void + fill_dboard_info(db_info *dst, const u2_db_info_t *src) + { + dst->dbid = ntohl(src->dbid); + + dst->freq_min = + u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_min_hi), + ntohl(src->freq_min_lo))); + dst->freq_max = + u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_max_hi), + ntohl(src->freq_max_lo))); + + dst->gain_min = u2_fxpt_gain_to_double(ntohs(src->gain_min)); + dst->gain_max = u2_fxpt_gain_to_double(ntohs(src->gain_max)); + dst->gain_step_size = u2_fxpt_gain_to_double(ntohs(src->gain_step_size)); + } + + bool + usrp2::impl::dboard_info() + { + op_dboard_info_cmd cmd; + op_dboard_info_reply_t reply; + + memset(&cmd, 0, sizeof(cmd)); + init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); + cmd.op.opcode = OP_DBOARD_INFO; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + cmd.eop.opcode = OP_EOP; + cmd.eop.len = sizeof(cmd.eop); + + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); + if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) + return false; + + bool success = (ntohx(reply.ok) == 1); + if (success){ + fill_dboard_info(&d_tx_db_info, &reply.tx_db_info); + fill_dboard_info(&d_rx_db_info, &reply.rx_db_info); + } + return success; + } + } // namespace usrp2 diff --git a/usrp2/host/lib/usrp2_impl.h b/usrp2/host/lib/usrp2_impl.h index 0c5849780..a134c9ec1 100644 --- a/usrp2/host/lib/usrp2_impl.h +++ b/usrp2/host/lib/usrp2_impl.h @@ -36,6 +36,19 @@ namespace usrp2 { class pending_reply; class ring; + //! High-level d'board info + struct db_info { + int dbid; + double freq_min; // Hz + double freq_max; // Hz + double gain_min; // dB + double gain_max; // dB + double gain_step_size; // dB + + db_info() : dbid(-1), freq_min(0), freq_max(0), + gain_min(0), gain_max(0), gain_step_size(0) {} + }; + class usrp2::impl : private data_handler { static const size_t NRIDS = 256; @@ -47,7 +60,6 @@ namespace usrp2 { usrp2_thread *d_bg_thread; volatile bool d_bg_running; // TODO: multistate if needed - int d_rx_decim; int d_rx_seqno; int d_tx_seqno; int d_next_rid; @@ -65,6 +77,10 @@ namespace usrp2 { std::vector<ring_sptr> d_channel_rings; // indexed by 5-bit channel number + db_info d_tx_db_info; + db_info d_rx_db_info; + + void inc_enqueued() { omni_mutex_lock l(d_enqueued_mutex); d_num_enqueued++; @@ -87,6 +103,7 @@ namespace usrp2 { virtual data_handler::result operator()(const void *base, size_t len); data_handler::result handle_control_packet(const void *base, size_t len); data_handler::result handle_data_packet(const void *base, size_t len); + bool dboard_info(); public: impl(const std::string &ifc, props *p); @@ -95,10 +112,16 @@ namespace usrp2 { void bg_loop(); std::string mac_addr() const { return d_addr; } // FIXME: convert from u2_mac_addr_t - bool burn_mac_addr(const std::string &new_addr); + + // Rx bool set_rx_gain(double gain); + double rx_gain_min() { return d_rx_db_info.gain_min; } + double rx_gain_max() { return d_rx_db_info.gain_max; } + double rx_gain_db_per_step() { return d_rx_db_info.gain_step_size; } bool set_rx_center_freq(double frequency, tune_result *result); + double rx_freq_min() { return d_rx_db_info.freq_min; } + double rx_freq_max() { return d_rx_db_info.freq_max; } bool set_rx_decim(int decimation_factor); bool set_rx_scale_iq(int scale_i, int scale_q); bool start_rx_streaming(unsigned int channel, unsigned int items_per_frame); @@ -107,8 +130,15 @@ namespace usrp2 { unsigned int rx_overruns() const { return d_num_rx_overruns; } unsigned int rx_missing() const { return d_num_rx_missing; } + // Tx + bool set_tx_gain(double gain); + double tx_gain_min() { return d_tx_db_info.gain_min; } + double tx_gain_max() { return d_tx_db_info.gain_max; } + double tx_gain_db_per_step() { return d_tx_db_info.gain_step_size; } bool set_tx_center_freq(double frequency, tune_result *result); + double tx_freq_min() { return d_tx_db_info.freq_min; } + double tx_freq_max() { return d_tx_db_info.freq_max; } bool set_tx_interp(int interpolation_factor); bool set_tx_scale_iq(int scale_i, int scale_q); @@ -126,6 +156,19 @@ namespace usrp2 { const uint32_t *items, size_t nitems, const tx_metadata *metadata); + + // misc + + bool config_mimo(int flags); + bool fpga_master_clock_freq(long *freq); + bool adc_rate(long *rate); + bool dac_rate(long *rate); + bool tx_daughterboard_id(int *dbid); + bool rx_daughterboard_id(int *dbid); + + // low level + + bool burn_mac_addr(const std::string &new_addr); }; } // namespace usrp2 |