📄 usrp_basic.cc
字号:
usrp_basic_rx::set_dc_offset_cl_enable(int bits, int mask){ return _write_fpga_reg(FR_DC_OFFSET_CL_EN, (d_fpga_shadows[FR_DC_OFFSET_CL_EN] & ~mask) | (bits & mask));}//////////////////////////////////////////////////////////////////// usrp_basic_tx////////////////////////////////////////////////////////////////////// DAC input rate 64 MHz interleaved for a total input rate of 128 MHz// DAC input is latched on rising edge of CLKOUT2// NCO is disabled// interpolate 2x// coarse modulator disabled//static unsigned char tx_init_regs[] = { REG_TX_PWR_DN, 0, REG_TX_A_OFFSET_LO, 0, REG_TX_A_OFFSET_HI, 0, REG_TX_B_OFFSET_LO, 0, REG_TX_B_OFFSET_HI, 0, REG_TX_A_GAIN, (TX_X_GAIN_COARSE_FULL | 0), REG_TX_B_GAIN, (TX_X_GAIN_COARSE_FULL | 0), REG_TX_PGA, 0xff, // maximum gain (0 dB) REG_TX_MISC, 0, REG_TX_IF, (TX_IF_USE_CLKOUT1 | TX_IF_I_FIRST | TX_IF_INV_TX_SYNC | TX_IF_2S_COMP | TX_IF_INTERLEAVED), REG_TX_DIGITAL, (TX_DIGITAL_2_DATA_PATHS | TX_DIGITAL_INTERPOLATE_4X), REG_TX_MODULATOR, (TX_MODULATOR_DISABLE_NCO | TX_MODULATOR_COARSE_MODULATION_NONE), REG_TX_NCO_FTW_7_0, 0, REG_TX_NCO_FTW_15_8, 0, REG_TX_NCO_FTW_23_16, 0};usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nblocks, const std::string fpga_filename, const std::string firmware_filename) : usrp_basic (which_board, open_tx_interface, fpga_filename, firmware_filename), d_devhandle (0), d_ephandle (0), d_bytes_seen (0), d_first_write (true), d_tx_enable (false){ if (!usrp_9862_write_many_all (d_udh, tx_init_regs, sizeof (tx_init_regs))){ fprintf (stderr, "usrp_basic_tx: failed to init AD9862 TX regs\n"); throw std::runtime_error ("usrp_basic_tx/init_9862"); } if (0){ // FIXME power down 2nd codec tx path usrp_9862_write (d_udh, 1, REG_TX_PWR_DN, (TX_PWR_DN_TX_DIGITAL | TX_PWR_DN_TX_ANALOG_BOTH)); } // Reset the tx path and leave it disabled. set_tx_enable (false); usrp_set_fpga_tx_reset (d_udh, true); usrp_set_fpga_tx_reset (d_udh, false); set_fpga_tx_sample_rate_divisor (4); // we're using interp x4 probe_tx_slots (false); // check fusb buffering parameters if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE) throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size"); if (fusb_nblocks < 0) throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); if (fusb_block_size == 0) fusb_block_size = FUSB_BLOCK_SIZE; if (fusb_nblocks == 0) fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); d_devhandle = fusb_sysconfig::make_devhandle (d_udh); d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false, fusb_block_size, fusb_nblocks); _write_fpga_reg(FR_ATR_MASK_0, 0); // zero Tx side Auto Transmit/Receive regs _write_fpga_reg(FR_ATR_TXVAL_0, 0); _write_fpga_reg(FR_ATR_RXVAL_0, 0); _write_fpga_reg(FR_ATR_MASK_2, 0); _write_fpga_reg(FR_ATR_TXVAL_2, 0); _write_fpga_reg(FR_ATR_RXVAL_2, 0);}static unsigned char tx_fini_regs[] = { REG_TX_PWR_DN, (TX_PWR_DN_TX_DIGITAL | TX_PWR_DN_TX_ANALOG_BOTH), REG_TX_MODULATOR, (TX_MODULATOR_DISABLE_NCO | TX_MODULATOR_COARSE_MODULATION_NONE)};usrp_basic_tx::~usrp_basic_tx (){ d_ephandle->stop (); delete d_ephandle; delete d_devhandle; if (!usrp_9862_write_many_all (d_udh, tx_fini_regs, sizeof (tx_fini_regs))){ fprintf (stderr, "usrp_basic_tx: failed to fini AD9862 TX regs\n"); }}boolusrp_basic_tx::start (){ if (!usrp_basic::start ()) return false; if (!set_tx_enable (true)){ fprintf (stderr, "usrp_basic_tx: set_tx_enable failed\n"); usb_strerror (); return false; } if (!d_ephandle->start ()){ fprintf (stderr, "usrp_basic_tx: failed to start end point streaming"); usb_strerror (); return false; } return true;}boolusrp_basic_tx::stop (){ bool ok = usrp_basic::stop (); if (!d_ephandle->stop ()){ fprintf (stderr, "usrp_basic_tx: failed to stop end point streaming"); usb_strerror (); ok = false; } if (!set_tx_enable (false)){ fprintf (stderr, "usrp_basic_tx: set_tx_enable(false) failed\n"); usb_strerror (); ok = false; } return ok;}usrp_basic_tx *usrp_basic_tx::make (int which_board, int fusb_block_size, int fusb_nblocks, const std::string fpga_filename, const std::string firmware_filename){ usrp_basic_tx *u = 0; try { u = new usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, fpga_filename, firmware_filename); return u; } catch (...){ delete u; return 0; } return u;}boolusrp_basic_tx::set_fpga_tx_sample_rate_divisor (unsigned int div){ return _write_fpga_reg (FR_TX_SAMPLE_RATE_DIV, div - 1);}/*! * \brief Write data to the A/D's via the FPGA. * * \p len must be a multiple of 512 bytes. * \returns number of bytes written or -1 on error. * * if \p underrun is non-NULL, it will be set to true iff * a transmit underrun condition is detected. */intusrp_basic_tx::write (const void *buf, int len, bool *underrun){ int r; if (underrun) *underrun = false; if (len < 0 || (len % 512) != 0){ fprintf (stderr, "usrp_basic_tx::write: invalid length = %d\n", len); return -1; } r = d_ephandle->write (buf, len); if (r > 0) d_bytes_seen += r; /* * In many cases, the FPGA reports an tx underrun right after we * enable the Tx path. If this is our first write, check for the * underrun to clear the condition, then ignore the result. */ if (d_first_write && d_bytes_seen >= 4 * FUSB_BLOCK_SIZE){ d_first_write = false; bool bogus_underrun; usrp_check_tx_underrun (d_udh, &bogus_underrun); } if (underrun != 0 && d_bytes_seen >= d_bytes_per_poll){ d_bytes_seen = 0; if (!usrp_check_tx_underrun (d_udh, underrun)){ fprintf (stderr, "usrp_basic_tx: usrp_check_tx_underrun failed\n"); usb_strerror (); } } return r;}voidusrp_basic_tx::wait_for_completion (){ d_ephandle->wait_for_completion ();}boolusrp_basic_tx::set_tx_enable (bool on){ d_tx_enable = on; // fprintf (stderr, "set_tx_enable %d\n", on); return usrp_set_fpga_tx_enable (d_udh, on);}// conditional disable, return prev stateboolusrp_basic_tx::disable_tx (){ bool enabled = tx_enable (); if (enabled) set_tx_enable (false); return enabled;}// conditional setvoidusrp_basic_tx::restore_tx (bool on){ if (on != tx_enable ()) set_tx_enable (on);}boolusrp_basic_tx::set_pga (int which, double gain){ if (which < 0 || which > 3) return false; gain = std::max (pga_min (), gain); gain = std::min (pga_max (), gain); int codec = which >> 1; // 0 and 1 are same, as are 2 and 3 int int_gain = (int) rint ((gain - pga_min ()) / pga_db_per_step()); return _write_9862 (codec, REG_TX_PGA, int_gain);}doubleusrp_basic_tx::pga (int which) const{ if (which < 0 || which > 3) return READ_FAILED; int codec = which >> 1; unsigned char v; bool ok = _read_9862 (codec, REG_TX_PGA, &v); if (!ok) return READ_FAILED; return (pga_db_per_step() * v) + pga_min();}voidusrp_basic_tx::probe_tx_slots (bool verbose){ struct usrp_dboard_eeprom eeprom; static int slot_id_map[2] = { SLOT_TX_A, SLOT_TX_B }; static const char *slot_name[2] = { "TX d'board A", "TX d'board B" }; for (int i = 0; i < 2; i++){ int slot_id = slot_id_map [i]; const char *msg = 0; usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom); switch (s){ case UDBE_OK: d_dbid[i] = eeprom.id; msg = usrp_dbid_to_string (eeprom.id).c_str (); // FIXME, figure out interpretation of dc offset for TX d'boards // offset = (eeprom.offset[1] << 16) | (eeprom.offset[0] & 0xffff); _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; case UDBE_NO_EEPROM: d_dbid[i] = -1; msg = "<none>"; _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; case UDBE_INVALID_EEPROM: d_dbid[i] = -2; msg = "Invalid EEPROM contents"; _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; case UDBE_BAD_SLOT: default: assert (0); } if (verbose){ fflush (stdout); fprintf (stderr, "%s: %s\n", slot_name[i], msg); } }}boolusrp_basic_tx::_write_oe (int which_dboard, int value, int mask){ if (! (0 <= which_dboard && which_dboard <= 1)) return false; return _write_fpga_reg (slot_id_to_oe_reg (dboard_to_slot (which_dboard)), (mask << 16) | (value & 0xffff));}boolusrp_basic_tx::write_io (int which_dboard, int value, int mask){ if (! (0 <= which_dboard && which_dboard <= 1)) return false; return _write_fpga_reg (slot_id_to_io_reg (dboard_to_slot (which_dboard)), (mask << 16) | (value & 0xffff));}boolusrp_basic_tx::read_io (int which_dboard, int *value){ if (! (0 <= which_dboard && which_dboard <= 1)) return false; int t; int reg = which_dboard + 1; // FIXME, *very* magic number (fix in serial_io.v) bool ok = _read_fpga_reg (reg, &t); if (!ok) return false; *value = t & 0xffff; // FIXME, more magic return true;}intusrp_basic_tx::read_io (int which_dboard){ int value; if (!read_io (which_dboard, &value)) return READ_FAILED; return value;}boolusrp_basic_tx::write_aux_dac (int which_dboard, int which_dac, int value){ return usrp_basic::write_aux_dac (dboard_to_slot (which_dboard), which_dac, value);}boolusrp_basic_tx::read_aux_adc (int which_dboard, int which_adc, int *value){ return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), which_adc, value);}intusrp_basic_tx::read_aux_adc (int which_dboard, int which_adc){ return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), which_adc);}intusrp_basic_tx::block_size () const { return d_ephandle->block_size(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -