metadata.send_now = 1;
metadata.start_of_burst = 1;
- bool ok = d_u2->tx_16sc(0, // FIXME: use channel number instead of 0
+ bool ok = d_u2->tx_16sc(0, // FIXME: someday, streams will have channel numbers
in, noutput_items, &metadata);
if (!ok){
std::cerr << "usrp2_sink_16sc: tx_16sc failed" << std::endl;
metadata.send_now = 1;
metadata.start_of_burst = 1;
- bool ok = d_u2->tx_32fc(0, // FIXME: use channel number instead of 0
+ bool ok = d_u2->tx_32fc(0, // FIXME: someday, streams will have channel numbers
in, noutput_items, &metadata);
if (!ok){
std::cerr << "usrp2_sink_32fc: tx_32fc failed" << std::endl;
#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>
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,
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;
#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
*
* 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;
} 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
* 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;
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
//#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 {
/*!
*/
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
/*!
* 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
*/
*/
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
*/
size_t nitems,
const tx_metadata *metadata);
- // ----------------------------------------------------------------
+ /*
+ * ----------------------------------------------------------------
+ * miscellaneous methods
+ * ----------------------------------------------------------------
+ */
/*!
* \brief MIMO configuration
*/
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:
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;
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
*/
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
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)
{
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)
{
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
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";
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);
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)
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";
}
- // ----------------------------------------------------------------
- // 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
// ----------------------------------------------------------------
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
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;
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;
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++;
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);
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);
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);
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