X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=usrp2%2Fhost%2Flib%2Fusrp2_impl.cc;h=3a0cd918e02327315d0b3754f12512afa018dabe;hb=8056ff424a153dd5bab95bdda1758efe5ed9b246;hp=956f2561eef00562dff22aa74a2e7a92ac79c2bb;hpb=d4bcd458da9a26d8f272447af6e7d35f3c9101d4;p=debian%2Fgnuradio diff --git a/usrp2/host/lib/usrp2_impl.cc b/usrp2/host/lib/usrp2_impl.cc index 956f2561..3a0cd918 100644 --- a/usrp2/host/lib/usrp2_impl.cc +++ b/usrp2/host/lib/usrp2_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2009 Free Software Foundation, Inc. * * 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 @@ -46,7 +46,6 @@ #endif static const int DEFAULT_RX_SCALE = 1024; -static const int DEFAULT_TX_SCALE = 3000; namespace usrp2 { @@ -71,12 +70,16 @@ namespace usrp2 { 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"; - case OP_READ_REG: return "OP_READ_REG"; - case OP_READ_REG_REPLY: return "OP_READ_REG_REPLY"; -#endif + case OP_SYNC_TO_PPS: return "OP_SYNC_TO_PPS"; + case OP_PEEK: return "OP_PEEK"; + case OP_PEEK_REPLY: return "OP_PEEK_REPLY"; + case OP_SET_TX_LO_OFFSET: return "OP_SET_TX_LO_OFFSET"; + case OP_SET_TX_LO_OFFSET_REPLY: return "OP_SET_TX_LO_OFFSET_REPLY"; + case OP_SET_RX_LO_OFFSET: return "OP_SET_RX_LO_OFFSET"; + case OP_SET_RX_LO_OFFSET_REPLY: return "OP_SET_RX_LO_OFFSET_REPLY"; + case OP_SYNC_EVERY_PPS: return "OP_SYNC_EVERY_PPS"; + case OP_SYNC_EVERY_PPS_REPLY: return "OP_SYNC_EVERY_PPS_REPLY"; + default: char buf[64]; snprintf(buf, sizeof(buf), "", opcode); @@ -126,8 +129,8 @@ 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_seqno(-1), d_tx_seqno(0), d_next_rid(0), + : d_eth_buf(new eth_buffer()), d_ifc_name(ifc), d_pf(0), d_bg_thread(0), + d_bg_running(false), 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_tx_interp(0), d_rx_decim(0) @@ -172,6 +175,10 @@ namespace usrp2 { fprintf(stderr, " gain_db_per_step = %g\n", rx_gain_db_per_step()); } + // Ensure any custom values in hardware are cleared + if (!reset_db()) + std::cerr << "usrp2::ctor reset_db failed\n"; + // 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"; @@ -189,9 +196,6 @@ namespace usrp2 { // 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"; - - if (!set_tx_scale_iq(DEFAULT_TX_SCALE, DEFAULT_TX_SCALE)) - std::cerr << "usrp2::ctor set_tx_scale_iq failed\n"; } usrp2::impl::~impl() @@ -477,6 +481,33 @@ namespace usrp2 { return success; } + bool + usrp2::impl::set_rx_lo_offset(double frequency) + { + op_freq_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_SET_RX_LO_OFFSET; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + + u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency); + cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt)); + cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt)); + + 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); + return success; + } + bool usrp2::impl::set_rx_center_freq(double frequency, tune_result *result) { @@ -716,6 +747,33 @@ namespace usrp2 { return success; } + bool + usrp2::impl::set_tx_lo_offset(double frequency) + { + op_freq_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_SET_TX_LO_OFFSET; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + + u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency); + cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt)); + cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt)); + + 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); + return success; + } + bool usrp2::impl::set_tx_center_freq(double frequency, tune_result *result) { @@ -770,11 +828,42 @@ namespace usrp2 { return false; bool success = (ntohx(reply.ok) == 1); - if (success) + if (success) { d_tx_interp = interpolation_factor; + + // Auto-set TX scaling based on interpolation rate + int scale_i, scale_q; + default_tx_scale_iq(d_tx_interp, &scale_i, &scale_q); + return set_tx_scale_iq(scale_i, scale_q); + } + return success; } + void + usrp2::impl::default_tx_scale_iq(int interpolation_factor, int *scale_i, int *scale_q) + { + // Calculate CIC interpolation (i.e., without halfband interpolators) + int i = interpolation_factor; + if (i > 128) + i = i >> 1; + if (i > 128) + i = i >> 1; + + // Calculate dsp_core_tx gain absent scale multipliers + float gain = (1.65*i*i*i)/(4096*pow(2, ceil(log2(i*i*i)))); + + // Calculate closest multiplier constant to reverse gain + int scale = (int)rint(1.0/gain); + // fprintf(stderr, "if=%i i=%i gain=%f scale=%i\n", interpolation_factor, i, gain, scale); + + // Both I and Q are identical in this case + if (scale_i) + *scale_i = scale; + if (scale_q) + *scale_q = scale; + } + bool usrp2::impl::set_tx_scale_iq(int scale_i, int scale_q) { @@ -906,6 +995,7 @@ namespace usrp2 { cmd.op.opcode = OP_CONFIG_MIMO; cmd.op.len = sizeof(cmd.op); cmd.op.rid = d_next_rid++; + cmd.op.flags = flags; cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); @@ -1020,4 +1110,177 @@ namespace usrp2 { } + bool + usrp2::impl::sync_to_pps() + { + op_generic_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_SYNC_TO_PPS; + 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::sync_every_pps(bool enable) + { + op_generic_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_SYNC_EVERY_PPS; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + cmd.op.ok = enable ? 1 : 0; + 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; + } + + std::vector + usrp2::impl::peek32(uint32_t addr, uint32_t words) + { + std::vector result; // zero sized on error return + // fprintf(stderr, "usrp2::peek: addr=%08X words=%u\n", addr, words); + + if (addr % 4 != 0) { + fprintf(stderr, "usrp2::peek: addr (=%08X) must be 32-bit word aligned\n", addr); + return result; + } + + if (words == 0) + return result; + + op_peek_cmd cmd; + op_generic_t *reply; + + int wlen = sizeof(uint32_t); + int rlen = sizeof(op_generic_t); + size_t bytes = words*wlen; + + memset(&cmd, 0, sizeof(cmd)); + init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); + cmd.op.opcode = OP_PEEK; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + cmd.eop.opcode = OP_EOP; + cmd.eop.len = sizeof(cmd.eop); + + cmd.op.addr = htonl(addr); + cmd.op.bytes = htonl(bytes); + + reply = (op_generic_t *)malloc(rlen+bytes); + pending_reply p(cmd.op.rid, reply, rlen+bytes); + if (transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) { + uint32_t nwords = (reply->len-rlen)/sizeof(uint32_t); + uint32_t *data = (uint32_t *)(reply+rlen/wlen); + for (unsigned int i = 0; i < nwords; i++) + result.push_back(ntohl(data[i])); + } + + free(reply); + return result; + } + + bool + usrp2::impl::poke32(uint32_t addr, const std::vector &data) + { + if (addr % 4 != 0) { + fprintf(stderr, "usrp2::poke32: addr (=%08X) must be 32-bit word aligned\n", addr); + return false; + } + + int plen = sizeof(op_poke_cmd); + int wlen = sizeof(uint32_t); + int max_words = (MAX_SUBPKT_LEN-plen)/wlen; + int words = data.size(); + + if (words > max_words) { + fprintf(stderr, "usrp2::poke32: write size (=%u) exceeds maximum of %u words\n", + words, max_words); + return false; + } + + //fprintf(stderr, "usrp2::poke32: addr=%08X words=%u\n", addr, words); + + if (words == 0) + return true; // NOP + + op_poke_cmd *cmd; + op_generic_t *eop; + + // Allocate, clear, and initialize command packet + int bytes = words*wlen; + int l = plen+bytes+sizeof(*eop); // op_poke_cmd+data+eop + cmd = (op_poke_cmd *)malloc(l); + //fprintf(stderr, "cmd=%p l=%i\n", cmd, l); + memset(cmd, 0, l); + init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1); + cmd->op.opcode = OP_POKE; + cmd->op.len = sizeof(cmd->op)+bytes; + cmd->op.rid = d_next_rid++; + cmd->op.addr = htonl(addr); + + // Copy data from vector into packet space + uint32_t *dest = (uint32_t *)((uint8_t *)cmd+plen); + for (int i = 0; i < words; i++) { + //fprintf(stderr, "%03i@%p\n", i, dest); + *dest++ = htonl(data[i]); + } + + // Write end-of-packet subpacket + eop = (op_generic_t *)dest; + eop->opcode = OP_EOP; + eop->len = sizeof(*eop); + //fprintf(stderr, "eop=%p len=%i\n", eop, eop->len); + + // Send command to device and retrieve reply + bool ok = false; + op_generic_t reply; + pending_reply p(cmd->op.rid, &reply, sizeof(reply)); + if (transmit_cmd(cmd, l, &p, DEF_CMD_TIMEOUT)) + ok = (ntohx(reply.ok) == 1); + + free(cmd); + return ok; + } + + bool + usrp2::impl::reset_db() + { + op_generic_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_RESET_DB; + 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); + return success; + } + } // namespace usrp2