📄 usrp_basic.cc
字号:
/* -*- c++ -*- *//* * Copyright 2003,2004 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "usrp_basic.h"#include "usrp_prims.h"#include "usrp_interfaces.h"#include "fpga_regs_common.h"#include "fusb.h"#include <usb.h>#include <stdexcept>#include <assert.h>#include <math.h>#include <ad9862.h>#include <string.h>using namespace ad9862;#define NELEM(x) (sizeof (x) / sizeof (x[0]))// These set the buffer size used for each end point using the fast// usb interface. The kernel ends up locking down this much memory.static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size();static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size();static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE;static const double POLLING_INTERVAL = 0.1; // seconds////////////////////////////////////////////////////////////////static struct usb_dev_handle *open_rx_interface (struct usb_device *dev){ struct usb_dev_handle *udh = usrp_open_rx_interface (dev); if (udh == 0){ fprintf (stderr, "usrp_basic_rx: can't open rx interface\n"); usb_strerror (); } return udh;}static struct usb_dev_handle *open_tx_interface (struct usb_device *dev){ struct usb_dev_handle *udh = usrp_open_tx_interface (dev); if (udh == 0){ fprintf (stderr, "usrp_basic_tx: can't open tx interface\n"); usb_strerror (); } return udh;}////////////////////////////////////////////////////////////////////// usrp_basic//////////////////////////////////////////////////////////////////// Given:// CLKIN = 64 MHz// CLKSEL pin = high //// These settings give us:// CLKOUT1 = CLKIN = 64 MHz// CLKOUT2 = CLKIN = 64 MHz// ADC is clocked at 64 MHz// DAC is clocked at 128 MHzstatic unsigned char common_regs[] = { REG_GENERAL, 0, REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC | DLL_MULT_2X | DLL_FAST), REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4};usrp_basic::usrp_basic (int which_board, struct usb_dev_handle * open_interface (struct usb_device *dev), const std::string fpga_filename, const std::string firmware_filename) : d_udh (0), d_usb_data_rate (16000000), // SWAG, see below d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)), d_verbose (false){ /* * SWAG: Scientific Wild Ass Guess. * * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the * actual rate. This doesn't change our throughput, that's determined by the signal * processing code in the FPGA (which we know nothing about), and the system limits * determined by libusb, fusb_*, and the underlying drivers. */ memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); usrp_one_time_init (); if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename)) throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); struct usb_device *dev = usrp_find_device (which_board); if (dev == 0){ fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); throw std::runtime_error ("usrp_basic/usrp_find_device"); } if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); throw std::runtime_error ("usrp_basic/bad_rev"); } if ((d_udh = open_interface (dev)) == 0) throw std::runtime_error ("usrp_basic/open_interface"); // initialize registers that are common to rx and tx if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); throw std::runtime_error ("usrp_basic/init_9862"); } _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs}usrp_basic::~usrp_basic (){ if (d_udh) usb_close (d_udh);}boolusrp_basic::start (){ return true; // nop}boolusrp_basic::stop (){ return true; // nop}voidusrp_basic::set_usb_data_rate (int usb_data_rate){ d_usb_data_rate = usb_data_rate; d_bytes_per_poll = (int) (usb_data_rate * POLLING_INTERVAL);}boolusrp_basic::write_aux_dac (int slot, int which_dac, int value){ return usrp_write_aux_dac (d_udh, slot, which_dac, value);}boolusrp_basic::read_aux_adc (int slot, int which_adc, int *value){ return usrp_read_aux_adc (d_udh, slot, which_adc, value);}intusrp_basic::read_aux_adc (int slot, int which_adc){ int value; if (!read_aux_adc (slot, which_adc, &value)) return READ_FAILED; return value;}boolusrp_basic::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf){ return usrp_eeprom_write (d_udh, i2c_addr, eeprom_offset, buf.data (), buf.size ());}std::stringusrp_basic::read_eeprom (int i2c_addr, int eeprom_offset, int len){ if (len <= 0) return ""; char buf[len]; if (!usrp_eeprom_read (d_udh, i2c_addr, eeprom_offset, buf, len)) return ""; return std::string (buf, len);}boolusrp_basic::write_i2c (int i2c_addr, const std::string buf){ return usrp_i2c_write (d_udh, i2c_addr, buf.data (), buf.size ());}std::stringusrp_basic::read_i2c (int i2c_addr, int len){ if (len <= 0) return ""; char buf[len]; if (!usrp_i2c_read (d_udh, i2c_addr, buf, len)) return ""; return std::string (buf, len);}std::stringusrp_basic::serial_number(){ return usrp_serial_number(d_udh);}// ----------------------------------------------------------------boolusrp_basic::set_adc_offset (int which, int offset){ if (which < 0 || which > 3) return false; return _write_fpga_reg (FR_ADC_OFFSET_0 + which, offset);}boolusrp_basic::set_dac_offset (int which, int offset, int offset_pin){ if (which < 0 || which > 3) return false; int which_codec = which >> 1; int tx_a = (which & 0x1) == 0; int lo = ((offset & 0x3) << 6) | (offset_pin & 0x1); int hi = (offset >> 2); bool ok; if (tx_a){ ok = _write_9862 (which_codec, REG_TX_A_OFFSET_LO, lo); ok &= _write_9862 (which_codec, REG_TX_A_OFFSET_HI, hi); } else { ok = _write_9862 (which_codec, REG_TX_B_OFFSET_LO, lo); ok &= _write_9862 (which_codec, REG_TX_B_OFFSET_HI, hi); } return ok;}boolusrp_basic::set_adc_buffer_bypass (int which, bool bypass){ if (which < 0 || which > 3) return false; int codec = which >> 1; int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B; unsigned char cur_rx; unsigned char cur_pwr_dn; // If the input buffer is bypassed, we need to power it down too. bool ok = _read_9862 (codec, reg, &cur_rx); ok &= _read_9862 (codec, REG_RX_PWR_DN, &cur_pwr_dn); if (!ok) return false; if (bypass){ cur_rx |= RX_X_BYPASS_INPUT_BUFFER; cur_pwr_dn |= ((which & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B; } else { cur_rx &= ~RX_X_BYPASS_INPUT_BUFFER; cur_pwr_dn &= ~(((which & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B); } ok &= _write_9862 (codec, reg, cur_rx); ok &= _write_9862 (codec, REG_RX_PWR_DN, cur_pwr_dn); return ok;}// ----------------------------------------------------------------boolusrp_basic::_write_fpga_reg (int regno, int value){ if (d_verbose){ fprintf (stdout, "_write_fpga_reg(%3d, 0x%08x)\n", regno, value); fflush (stdout); } if (regno >= 0 && regno < MAX_REGS) d_fpga_shadows[regno] = value; return usrp_write_fpga_reg (d_udh, regno, value);}boolusrp_basic::_write_fpga_reg_masked (int regno, int value, int mask){ //Only use this for registers who actually use a mask in the verilog firmware, like FR_RX_MASTER_SLAVE //value is a 16 bits value and mask is a 16 bits mask if (d_verbose){ fprintf (stdout, "_write_fpga_reg_masked(%3d, 0x%04x,0x%04x)\n", regno, value, mask); fflush (stdout); } if (regno >= 0 && regno < MAX_REGS) d_fpga_shadows[regno] = value; return usrp_write_fpga_reg (d_udh, regno, (value & 0xffff) | ((mask & 0xffff)<<16));}boolusrp_basic::_read_fpga_reg (int regno, int *value){ return usrp_read_fpga_reg (d_udh, regno, value);}intusrp_basic::_read_fpga_reg (int regno){ int value; if (!_read_fpga_reg (regno, &value)) return READ_FAILED; return value;}boolusrp_basic::_write_9862 (int which_codec, int regno, unsigned char value){ if (0 && d_verbose){ // FIXME really want to enable logging in usrp_prims:usrp_9862_write fprintf(stdout, "_write_9862(codec = %d, regno = %2d, val = 0x%02x)\n", which_codec, regno, value); fflush(stdout); } return usrp_9862_write (d_udh, which_codec, regno, value);}boolusrp_basic::_read_9862 (int which_codec, int regno, unsigned char *value) const{ return usrp_9862_read (d_udh, which_codec, regno, value);}intusrp_basic::_read_9862 (int which_codec, int regno) const{ unsigned char value; if (!_read_9862 (which_codec, regno, &value)) return READ_FAILED; return value;}boolusrp_basic::_write_spi (int optional_header, int enables, int format, std::string buf){ return usrp_spi_write (d_udh, optional_header, enables, format, buf.data(), buf.size());}std::stringusrp_basic::_read_spi (int optional_header, int enables, int format, int len){ if (len <= 0) return ""; char buf[len]; if (!usrp_spi_read (d_udh, optional_header, enables, format, buf, len)) return ""; return std::string (buf, len);}bool
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -