summaryrefslogtreecommitdiff
path: root/usrp2
diff options
context:
space:
mode:
authoreb2008-10-22 00:56:40 +0000
committereb2008-10-22 00:56:40 +0000
commitbfe79d23738f24562dc7612049a90e8b20b53f79 (patch)
tree312e66fc143621f320f6e57592f5194e15e52e1f /usrp2
parentafc6e2b005581d1061b47c464f47ff2b48c6418b (diff)
downloadgnuradio-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.c37
-rw-r--r--usrp2/firmware/include/usrp2_eth_packet.h34
-rw-r--r--usrp2/firmware/lib/memory_map.h2
-rw-r--r--usrp2/firmware/lib/u2_init.c2
-rw-r--r--usrp2/host/include/usrp2/usrp2.h169
-rw-r--r--usrp2/host/lib/control.h14
-rw-r--r--usrp2/host/lib/usrp2.cc116
-rw-r--r--usrp2/host/lib/usrp2_impl.cc194
-rw-r--r--usrp2/host/lib/usrp2_impl.h47
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