diff options
-rw-r--r-- | Transceiver52M/DriveLoop.cpp | 4 | ||||
-rw-r--r-- | Transceiver52M/DriveLoop.h | 7 | ||||
-rw-r--r-- | Transceiver52M/Makefile.am | 14 | ||||
-rw-r--r-- | Transceiver52M/Transceiver.cpp | 27 | ||||
-rw-r--r-- | Transceiver52M/Transceiver.h | 12 | ||||
-rw-r--r-- | Transceiver52M/UHDDevice.cpp | 207 | ||||
-rw-r--r-- | Transceiver52M/multiTRX.cpp | 125 | ||||
-rw-r--r-- | Transceiver52M/radioDevice.h | 16 | ||||
-rw-r--r-- | Transceiver52M/radioInterface.cpp | 96 | ||||
-rw-r--r-- | Transceiver52M/radioInterface.h | 54 | ||||
-rw-r--r-- | Transceiver52M/radioInterfaceResamp.cpp | 332 | ||||
-rw-r--r-- | Transceiver52M/runTransceiver.cpp | 2 |
12 files changed, 227 insertions, 669 deletions
diff --git a/Transceiver52M/DriveLoop.cpp b/Transceiver52M/DriveLoop.cpp index 1f1ea7c..cd84d03 100644 --- a/Transceiver52M/DriveLoop.cpp +++ b/Transceiver52M/DriveLoop.cpp @@ -26,9 +26,9 @@ #include <Logger.h> DriveLoop::DriveLoop(int wBasePort, const char *TRXAddress, + RadioInterface *wRadioInterface, int wChanM, int wC0, int wSamplesPerSymbol, - GSM::Time wTransmitLatency, - RadioInterface *wRadioInterface) + GSM::Time wTransmitLatency) :mClockSocket(wBasePort, TRXAddress, wBasePort + 100), mC0(wC0) { mChanM = wChanM; diff --git a/Transceiver52M/DriveLoop.h b/Transceiver52M/DriveLoop.h index f97bb1d..7a2dfc3 100644 --- a/Transceiver52M/DriveLoop.h +++ b/Transceiver52M/DriveLoop.h @@ -104,9 +104,10 @@ public: @param radioInterface associated radioInterface object */ DriveLoop(int wBasePort, const char *TRXAddress, - int wChanM, int wC0, int wSamplesPerSymbol, - GSM::Time wTransmitLatency, - RadioInterface *wRadioInterface); + RadioInterface *wRadioInterface, + int wChanM = 1, int wC0 = 0, + int wSamplesPerSymbol = SAMPSPERSYM, + GSM::Time wTransmitLatency = GSM::Time(3, 0)); /** Destructor */ ~DriveLoop(); diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am index 6fcef7c..1103e6e 100644 --- a/Transceiver52M/Makefile.am +++ b/Transceiver52M/Makefile.am @@ -52,15 +52,14 @@ COMMON_SOURCES = \ radioVector.cpp \ radioClock.cpp \ sigProcLib.cpp \ + DriveLoop.cpp \ Transceiver.cpp \ DummyLoad.cpp libtransceiver_la_SOURCES = \ - $(COMMON_SOURCES) \ - radioInterfaceResamp.cpp + $(COMMON_SOURCES) noinst_PROGRAMS = \ - USRPping \ transceiver \ sigProcLibTest @@ -77,12 +76,7 @@ noinst_HEADERS = \ rcvLPF_651.h \ sendLPF_961.h -USRPping_SOURCES = USRPping.cpp -USRPping_LDADD = \ - libtransceiver.la \ - $(COMMON_LA) $(SQLITE_LA) - -transceiver_SOURCES = runTransceiver.cpp +transceiver_SOURCES = multiTRX.cpp transceiver_LDADD = \ libtransceiver.la \ $(GSM_LA) \ @@ -98,13 +92,11 @@ sigProcLibTest_LDADD = \ if UHD libtransceiver_la_SOURCES += UHDDevice.cpp transceiver_LDADD += $(UHD_LIBS) -USRPping_LDADD += $(UHD_LIBS) sigProcLibTest_LDADD += $(UHD_LIBS) else if USRP1 libtransceiver_la_SOURCES += USRPDevice.cpp transceiver_LDADD += $(USRP_LIBS) -USRPping_LDADD += $(USRP_LIBS) sigProcLibTest_LDADD += $(USRP_LIBS) else #we should never be here, as one of the above mustbe defined for us to build diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp index b8d9d9d..3895ae5 100644 --- a/Transceiver52M/Transceiver.cpp +++ b/Transceiver52M/Transceiver.cpp @@ -48,23 +48,18 @@ using namespace GSM; #define INIT_ENERGY_THRSHD 5.0f -Transceiver::Transceiver(int wBasePort, - const char *TRXAddress, - int wSamplesPerSymbol, - RadioInterface *wRadioInterface, - DriveLoop *wDriveLoop, - int wChannel, bool wPrimary) +Transceiver::Transceiver(int wBasePort, const char *TRXAddress, + DriveLoop *wDriveLoop, RadioInterface *wRadioInterface, + int wSamplesPerSymbol, int wChannel, bool wPrimary) :mDataSocket(wBasePort+2,TRXAddress,wBasePort+102), mControlSocket(wBasePort+1,TRXAddress,wBasePort+101), - mDriveLoop(wDriveLoop), mTransmitPriorityQueue(NULL), - mChannel(wChannel), mPrimary(wPrimary), mTSC(-1) + mDriveLoop(wDriveLoop), mRadioInterface(wRadioInterface), + mSamplesPerSymbol(wSamplesPerSymbol), mTransmitPriorityQueue(NULL), + mChannel(wChannel), mPrimary(wPrimary) { mFIFOServiceLoopThread = NULL; mControlServiceLoopThread = NULL; mTransmitPriorityQueueServiceLoopThread = NULL; - - mSamplesPerSymbol = wSamplesPerSymbol; - mRadioInterface = wRadioInterface; mMaxExpectedDelay = 0; // generate pulse and setup up signal processing library @@ -89,11 +84,7 @@ Transceiver::Transceiver(int wBasePort, mRunning = false; mTxFreq = 0.0; mRxFreq = 0.0; - - if (mPrimary) - mFreqOffset = mChannel * CHAN_RATE; - else - mFreqOffset = 0.0; + mFreqOffset = 0.0; mPower = -10; mEnergyThreshold = INIT_ENERGY_THRSHD; @@ -461,7 +452,7 @@ void Transceiver::driveControl() int freqKhz; sscanf(buffer,"%3s %s %d",cmdcheck,command,&freqKhz); mRxFreq = freqKhz * 1.0e3 + mFreqOffset; - if (mPrimary && (!mRadioInterface->tuneRx(mRxFreq))) { + if (!mRadioInterface->tuneRx(mRxFreq, mChannel)) { LOG(ALERT) << "RX failed to tune"; sprintf(response,"RSP RXTUNE 1 %d",freqKhz); } else { @@ -474,7 +465,7 @@ void Transceiver::driveControl() sscanf(buffer,"%3s %s %d",cmdcheck,command,&freqKhz); //freqKhz = 890e3; mTxFreq = freqKhz * 1.0e3 + mFreqOffset; - if (mPrimary && (!mRadioInterface->tuneTx(mTxFreq))) { + if (!mRadioInterface->tuneTx(mTxFreq, mChannel)) { LOG(ALERT) << "TX failed to tune"; sprintf(response,"RSP TXTUNE 1 %d",freqKhz); } else { diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h index 56acd9c..c58ca8c 100644 --- a/Transceiver52M/Transceiver.h +++ b/Transceiver52M/Transceiver.h @@ -97,7 +97,6 @@ private: double mRxFreq; ///< the receive frequency double mFreqOffset; ///< RF frequency offset int mPower; ///< the transmit power in dB - int mTSC; ///< the midamble sequence code double mEnergyThreshold; ///< threshold to determine if received data is potentially a GSM burst GSM::Time prevFalseDetectionTime; ///< last timestamp of a false energy detection unsigned mMaxExpectedDelay; ///< maximum expected time-of-arrival offset in GSM symbols @@ -121,12 +120,11 @@ public: @param wTransmitLatency initial setting of transmit latency @param radioInterface associated radioInterface object */ - Transceiver(int wBasePort, - const char *TRXAddress, - int wSamplesPerSymbol, - RadioInterface *wRadioInterface, - DriveLoop *wDriveLoop, - int wChannel, bool wPrimary); + Transceiver(int wBasePort, const char *TRXAddress, + DriveLoop *wDriveLoop, RadioInterface *wRadioInterface, + int wSamplesPerSymbol = SAMPSPERSYM, + int wChannel = 0, bool wPrimary = true); + /** Destructor */ ~Transceiver(); diff --git a/Transceiver52M/UHDDevice.cpp b/Transceiver52M/UHDDevice.cpp index 61cc76e..fc31231 100644 --- a/Transceiver52M/UHDDevice.cpp +++ b/Transceiver52M/UHDDevice.cpp @@ -33,6 +33,7 @@ #endif #define NUM_TX_CHANS 2 +#define NUM_RX_CHANS NUM_TX_CHANS #define TX_CHAN_OFFSET 2e6 #define B100_CLK_RT 52e6 #define USRP2_BASE_RT 400e3 @@ -75,7 +76,7 @@ static struct uhd_dev_offset uhd_offsets[NUM_USRP_TYPES * 3] = { { B100, 1, 9.4778e-5 }, { B100, 2, 5.1100e-5 }, { B100, 4, 2.9418e-5 }, - { UMTRX, 1, 0.0 }, + { UMTRX, 1, 9.1738e-5 }, { UMTRX, 2, 0.0 }, { UMTRX, 4, 0.0 }, }; @@ -115,7 +116,7 @@ static double select_rate(uhd_dev_type type, int sps) return USRP2_BASE_RT * sps; break; case B100: - case UmTRX: + case UMTRX: return GSMRATE * sps; break; } @@ -224,16 +225,16 @@ public: void setPriority(); enum TxWindowType getWindowType() { return tx_window; } - int readSamples(short *buf, int len, bool *overrun, - TIMESTAMP timestamp, bool *underrun, unsigned *RSSI); + int readSamples(short **buf, int chans, int len, TIMESTAMP timestamp, + bool *overrun, bool *underrun, unsigned *RSSI); - int writeSamples(short *buf, int len, bool *underrun, - TIMESTAMP timestamp, bool isControl); + int writeSamples(short **buf, int chans, int len, TIMESTAMP timestamp, + bool *underrun, bool isControl); bool updateAlignment(TIMESTAMP timestamp); - bool setTxFreq(double wFreq); - bool setRxFreq(double wFreq); + bool setTxFreq(double wFreq, int chan); + bool setRxFreq(double wFreq, int chan); inline TIMESTAMP initialWriteTimestamp() { return init_rd_ts; } inline TIMESTAMP initialReadTimestamp() { return init_rd_ts; } @@ -298,7 +299,7 @@ private: uhd::time_spec_t prev_ts; TIMESTAMP ts_offset; - smpl_buf *rx_smpl_buf; + smpl_buf *rx_smpl_buf[NUM_RX_CHANS]; void init_gains(); void set_ref_clk(bool ext_clk); @@ -349,19 +350,23 @@ uhd_device::uhd_device(int sps, bool skip_rx) rx_gain(0.0), rx_gain_min(0.0), rx_gain_max(0.0), tx_freq(0.0), rx_freq(0.0), tx_spp(0), rx_spp(0), started(false), aligned(false), rx_pkt_cnt(0), drop_cnt(0), - prev_ts(0,0), ts_offset(0), rx_smpl_buf(NULL) - async_event_thrd(NULL) + prev_ts(0,0), ts_offset(0), async_event_thrd(NULL) { this->sps = sps; this->skip_rx = skip_rx; + + for (int i = 0; i < NUM_RX_CHANS; i++) + rx_smpl_buf[i] = NULL; } uhd_device::~uhd_device() { stop(); - if (rx_smpl_buf) - delete rx_smpl_buf; + for (int i = 0; i < NUM_RX_CHANS; i++) { + if (rx_smpl_buf) + delete rx_smpl_buf; + } } void uhd_device::init_gains() @@ -463,10 +468,11 @@ double uhd_device::setTxGain(double db) double uhd_device::setRxGain(double db) { - usrp_dev->set_rx_gain(db); - rx_gain = usrp_dev->get_rx_gain(); - - LOG(INFO) << "Set RX gain to " << rx_gain << "dB"; + for (int i = 0; i < NUM_RX_CHANS; i++) { + usrp_dev->set_rx_gain(db); + rx_gain = usrp_dev->get_rx_gain(); + LOG(INFO) << "Set RX gain to " << rx_gain << "dB"; + } return rx_gain; } @@ -509,8 +515,8 @@ bool uhd_device::parse_dev_type() usrp1_str = dev_str.find("USRP1"); usrp2_str = dev_str.find("USRP2"); + umtrx_str = dev_str.find("UmTRX"); b100_str = mboard_str.find("B100"); - umtrx_str = mboard_str.find("UmTRX"); if (usrp1_str != std::string::npos) { LOG(ALERT) << "USRP1 is not supported using the UHD driver"; @@ -572,28 +578,29 @@ int uhd_device::open(const std::string &args) if (NUM_TX_CHANS == 2) { uhd::usrp::subdev_spec_t subdev_spec("A:0 B:0"); usrp_dev->set_tx_subdev_spec(subdev_spec); + usrp_dev->set_rx_subdev_spec(subdev_spec); } + // Set rates + desired_smpl_rt = select_rate(dev_type, sps); + if (set_rates(desired_smpl_rt) < 0) + return -1; + // Create TX and RX streamers uhd::stream_args_t stream_args("sc16"); - rx_stream = usrp_dev->get_rx_stream(stream_args); - for (int i = 0; i < NUM_TX_CHANS; i++) stream_args.channels.push_back(i); tx_stream = usrp_dev->get_tx_stream(stream_args); + rx_stream = usrp_dev->get_rx_stream(stream_args); // Number of samples per over-the-wire packet tx_spp = tx_stream->get_max_num_samps(); rx_spp = rx_stream->get_max_num_samps(); - // Set rates - desired_smpl_rt = select_rate(dev_type, sps); - if (set_rates(desired_smpl_rt) < 0) - return -1; - // Create receive buffer size_t buf_len = SAMPLE_BUF_SZ / sizeof(uint32_t); - rx_smpl_buf = new smpl_buf(buf_len, actual_smpl_rt); + for (int i = 0; i < NUM_RX_CHANS; i++) + rx_smpl_buf[i] = new smpl_buf(buf_len, actual_smpl_rt); // Set receive chain sample offset double offset = get_dev_offset(dev_type, sps); @@ -620,14 +627,19 @@ bool uhd_device::flush_recv(size_t num_pkts) { uhd::rx_metadata_t md; size_t num_smpls; - uint32_t buff[rx_spp]; float timeout; // Use .01 sec instead of the default .1 sec timeout = .01; + std::vector<std::vector<std::complex<short> > > bufs( + NUM_RX_CHANS, std::vector<std::complex<short> >(rx_spp)); + std::vector<std::complex<short> *> buf_ptrs; + for (int i = 0; i < bufs.size(); i++) + buf_ptrs.push_back(&bufs[i].front()); + for (size_t i = 0; i < num_pkts; i++) { - num_smpls = rx_stream->recv(buff, rx_spp, md, + num_smpls = rx_stream->recv(buf_ptrs, rx_spp, md, timeout, true); if (!num_smpls) { switch (md.error_code) { @@ -644,30 +656,15 @@ bool uhd_device::flush_recv(size_t num_pkts) void uhd_device::restart(uhd::time_spec_t ts) { - uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; - usrp_dev->issue_stream_cmd(cmd); - - flush_recv(50); - usrp_dev->set_time_now(ts); aligned = false; - cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS; - cmd.stream_now = true; + uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS; + cmd.time_spec = uhd::time_spec_t(0.1); + cmd.stream_now = false; usrp_dev->issue_stream_cmd(cmd); uhd::rx_metadata_t md; - uint32_t buff[rx_spp]; - - for (int i = 0; i < 50; i++) { - usrp_dev->get_device()->recv(buff, - rx_spp, - md, - uhd::io_type_t::COMPLEX_INT16, - uhd::device::RECV_MODE_ONE_PACKET); - } - - init_rd_ts = convert_time(md.time_spec, actual_smpl_rt); } bool uhd_device::start() @@ -760,39 +757,48 @@ int uhd_device::check_rx_md_err(uhd::rx_metadata_t &md, ssize_t num_smpls) return 0; } -int uhd_device::readSamples(short *buf, int len, bool *overrun, - TIMESTAMP timestamp, bool *underrun, unsigned *RSSI) +int uhd_device::readSamples(short **buf, int chans, int len, + TIMESTAMP timestamp, bool *overrun, + bool *underrun, unsigned *RSSI) { ssize_t rc; uhd::time_spec_t ts; uhd::rx_metadata_t metadata; - uint32_t pkt_buf[rx_spp]; - if (skip_rx) + if (skip_rx) { + LOG(INFO) << "Skipping Rx"; return 0; + } + + if (chans != NUM_RX_CHANS) { + LOG(ERR) << "Number of requested channels does not match build"; + return -1; + } // Shift read time with respect to transmit clock timestamp += ts_offset; ts = convert_time(timestamp, actual_smpl_rt); - LOG(DEBUG) << "Requested timestamp = " << ts.get_real_secs(); + LOG(DEBUG) << "Requested UHD timestamp = " << ts.get_real_secs(); // Check that timestamp is valid - rc = rx_smpl_buf->avail_smpls(timestamp); + rc = rx_smpl_buf[0]->avail_smpls(timestamp); if (rc < 0) { - LOG(ERR) << rx_smpl_buf->str_code(rc); - LOG(ERR) << rx_smpl_buf->str_status(); + LOG(ERR) << rx_smpl_buf[0]->str_code(rc); + LOG(ERR) << rx_smpl_buf[0]->str_status(); return 0; } + std::vector<std::vector<std::complex<short> > > bufs( + NUM_RX_CHANS, std::vector<std::complex<short> >(rx_spp)); + std::vector<std::complex<short> *> buf_ptrs; + for (int i = 0; i < bufs.size(); i++) + buf_ptrs.push_back(&bufs[i].front()); + // Receive samples from the usrp until we have enough - while (rx_smpl_buf->avail_smpls(timestamp) < len) { - size_t num_smpls = rx_stream->recv( - (void*)pkt_buf, - rx_spp, - metadata, - 0.1, - true); + while (rx_smpl_buf[0]->avail_smpls(timestamp) < len) { + size_t num_smpls = rx_stream->recv(buf_ptrs, rx_spp, + metadata, 0.1, true); rx_pkt_cnt++; // Check for errors @@ -805,39 +811,45 @@ int uhd_device::readSamples(short *buf, int len, bool *overrun, case ERROR_TIMING: restart(prev_ts); case ERROR_UNHANDLED: + LOG(ALERT) << "UHD: Unhandled error"; continue; } - ts = metadata.time_spec; - LOG(DEBUG) << "Received timestamp = " << ts.get_real_secs(); - - rc = rx_smpl_buf->write(pkt_buf, - num_smpls, - metadata.time_spec); - - // Continue on local overrun, exit on other errors - if ((rc < 0)) { - LOG(ERR) << rx_smpl_buf->str_code(rc); - LOG(ERR) << rx_smpl_buf->str_status(); - if (rc != smpl_buf::ERROR_OVERFLOW) - return 0; + LOG(DEBUG) << "Received " << num_smpls << " samples " + << "with timestamp = " << ts.get_real_secs(); + + for (int i = 0; i < NUM_RX_CHANS; i++) { + rc = rx_smpl_buf[i]->write((short *) &bufs[i].front(), + num_smpls, + metadata.time_spec); + + // Continue on local overrun, exit on other errors + if ((rc < 0)) { + LOG(ERR) << rx_smpl_buf[i]->str_code(rc); + LOG(ERR) << rx_smpl_buf[i]->str_status(); + if (rc != smpl_buf::ERROR_OVERFLOW) + return 0; + } } } // We have enough samples - rc = rx_smpl_buf->read(buf, len, timestamp); - if ((rc < 0) || (rc != len)) { - LOG(ERR) << rx_smpl_buf->str_code(rc); - LOG(ERR) << rx_smpl_buf->str_status(); - return 0; + for (int i = 0; i < NUM_RX_CHANS; i++) { + rc = rx_smpl_buf[i]->read(buf[i], len, timestamp); + if ((rc < 0) || (rc != len)) { + LOG(ERR) << rx_smpl_buf[i]->str_code(rc); + LOG(ERR) << rx_smpl_buf[i]->str_status(); + return 0; + } } return len; } -int uhd_device::writeSamples(short *buf, int len, bool *underrun, - unsigned long long timestamp,bool isControl) +int uhd_device::writeSamples(short **buf, int chans, int len, + TIMESTAMP timestamp, bool *underrun, + bool isControl) { uhd::tx_metadata_t metadata; metadata.has_time_spec = true; @@ -870,9 +882,11 @@ int uhd_device::writeSamples(short *buf, int len, bool *underrun, } } - std::vector<short *> bufs(NUM_TX_CHANS, buf); - size_t num_smpls = tx_stream->send(bufs, len, metadata); + std::vector<short *> bufs(NUM_TX_CHANS); + for (int i = 0; i < NUM_TX_CHANS; i++) + bufs[i] = buf[i]; + size_t num_smpls = tx_stream->send(bufs, len, metadata); if (num_smpls != (unsigned) len) { LOG(ALERT) << "UHD: Device send timed out"; LOG(ALERT) << "UHD: Version " << uhd::get_version_string(); @@ -888,25 +902,30 @@ bool uhd_device::updateAlignment(TIMESTAMP timestamp) return true; } -bool uhd_device::setTxFreq(double wFreq) +bool uhd_device::setTxFreq(double wFreq, int chan) { - for (int i = 0; i < NUM_TX_CHANS; i++) { - if (i) - wFreq += TX_CHAN_OFFSET; - - uhd::tune_result_t tr = usrp_dev->set_tx_freq(wFreq, i); - LOG(INFO) << "\n" << tr.to_pp_string(); - tx_freq = usrp_dev->get_tx_freq(i); + if (chan >= NUM_TX_CHANS) { + LOG(ALERT) << "Attempting to tune non-existent channel"; + return false; } + uhd::tune_result_t tr = usrp_dev->set_tx_freq(wFreq, chan); + LOG(INFO) << "\n" << tr.to_pp_string(); + tx_freq = usrp_dev->get_tx_freq(chan); + return true; } -bool uhd_device::setRxFreq(double wFreq) +bool uhd_device::setRxFreq(double wFreq, int chan) { - uhd::tune_result_t tr = usrp_dev->set_rx_freq(wFreq); + if (chan >= NUM_RX_CHANS) { + LOG(ALERT) << "Attempting to tune non-existent channel"; + return false; + } + + uhd::tune_result_t tr = usrp_dev->set_rx_freq(wFreq, chan); LOG(INFO) << "\n" << tr.to_pp_string(); - rx_freq = usrp_dev->get_rx_freq(); + rx_freq = usrp_dev->get_rx_freq(chan); return true; } diff --git a/Transceiver52M/multiTRX.cpp b/Transceiver52M/multiTRX.cpp index 04e2c95..e988eec 100644 --- a/Transceiver52M/multiTRX.cpp +++ b/Transceiver52M/multiTRX.cpp @@ -26,13 +26,11 @@ #include "Transceiver.h" #include "radioDevice.h" -#define DEVICERATE (400e3 * CHAN_M) - ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db"); volatile bool gbShutdown = false; -int Transceiver::mTSC = 0; +int Transceiver::mTSC = -1; static void sigHandler(int signum) { @@ -50,72 +48,26 @@ static int setupSignals() if (sigaction(SIGINT, &action, NULL) < 0) return -1; - if (sigaction(SIGTERM, &action, NULL) < 0) return -1; return 0; } -/* - * Generate the channel-transceiver ordering. Attempt to match the RAD1 - * ordering where the active channels are centered in the overall device - * bandwidth. C0 is always has the lowest ARFCN with increasing subsequent - * channels. When an even number of channels is selected, the carriers will - * be offset from the RF center by -200 kHz, or half ARFCN spacing. - */ -static void genChanMap(int numARFCN, int chanM, int *chans) -{ - int i, n; - - chans[0] = numARFCN / 2; - - for (i = 1, n = 1; i < numARFCN; i++) { - if (!chans[i - 1]) - chans[i] = chanM - 1; - else - chans[i] = chans[i - 1] - 1; - } -} - -static void createTrx(Transceiver **trx, int *map, int num, - RadioInterface *radio, DriveLoop *drive) -{ - int i; - bool primary = true; - - for (i = 0; i < num; i++) { - LOG(NOTICE) << "Creating TRX" << i - << " attached on channel " << map[i]; - - radio->activateChan(map[i]); - trx[i] = new Transceiver(5700 + 2 * i, "127.0.0.1", - SAMPSPERSYM, radio, drive, - map[i], primary); - trx[i]->start(); - primary = false; - } -} - int main(int argc, char *argv[]) { - int i, chanM, numARFCN = 1; - int chanMap[CHAN_MAX]; - RadioDevice *usrp; - RadioInterface* radio; - DriveLoop *drive; - Transceiver *trx[CHAN_MAX]; - - gLogInit("transceiver", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7); + int numARFCN = 1; if (argc > 1) { numARFCN = atoi(argv[1]); - if (numARFCN > (CHAN_MAX - 1)) { - LOG(ALERT) << numARFCN << " channels not supported with current build"; + if (numARFCN > CHAN_MAX) { + LOG(ALERT) << numARFCN << " channels not supported " + << " with with current build"; exit(-1); } } + gLogInit("transceiver", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7); srandom(time(NULL)); if (setupSignals() < 0) { @@ -123,58 +75,49 @@ int main(int argc, char *argv[]) exit(-1); } - /* - * Select the number of channels according to the number of ARFCNs's - * and generate ARFCN-to-channelizer path mappings. The channelizer - * aliases and extracts 'M' equally spaced channels to baseband. The - * number of ARFCN's must be less than the number of channels in the - * channelizer. - */ - switch (numARFCN) { - case 1: - chanM = 1; - break; - case 2: - case 3: - chanM = 5; - break; - default: - chanM = 10; + RadioDevice *device = RadioDevice::make(SAMPSPERSYM); + int radioType = device->open(""); + if (radioType < 0) { + LOG(ALERT) << "Failed to open device, exiting..."; + return EXIT_FAILURE; } - genChanMap(numARFCN, chanM, chanMap); - usrp = RadioDevice::make(DEVICERATE); - if (!usrp->open()) { - LOG(ALERT) << "Failed to open device, exiting..."; + RadioInterface *radio; + switch (radioType) { + case RadioDevice::NORMAL: + radio = new RadioInterface(device, numARFCN); + break; + case RadioDevice::RESAMP: + default: + LOG(ALERT) << "Unsupported configuration"; return EXIT_FAILURE; } - radio = new RadioInterface(usrp, chanM, 3, SAMPSPERSYM, 0, false); - drive = new DriveLoop(5700, "127.0.0.1", chanM, chanMap[0], - SAMPSPERSYM, GSM::Time(3,0), radio); + DriveLoop *drive = new DriveLoop(5700, "127.0.0.1", radio, numARFCN, 0); - /* Create, attach, and activate all transceivers */ - createTrx(trx, chanMap, numARFCN, radio, drive); + Transceiver *trx[CHAN_MAX]; + bool primary = true; + for (int i = 0; i < numARFCN; i++) { + trx[i] = new Transceiver(5700 + 2 * i, "127.0.0.1", + drive, radio, SAMPSPERSYM, + i, primary); + trx[i]->start(); + primary = false; + } - while (!gbShutdown) { + while (!gbShutdown) sleep(1); - } LOG(NOTICE) << "Shutting down transceivers..."; - for (i = 0; i < numARFCN; i++) { + for (int i = 0; i < numARFCN; i++) trx[i]->shutdown(); - } - /* - * Allow time for threads to end before we start freeing objects - */ + /* Allow time for threads to end before we start freeing objects */ sleep(2); - for (i = 0; i < numARFCN; i++) { + for (int i = 0; i < numARFCN; i++) delete trx[i]; - } - delete drive; delete radio; - delete usrp; + delete device; } diff --git a/Transceiver52M/radioDevice.h b/Transceiver52M/radioDevice.h index 39f1de2..35cc82b 100644 --- a/Transceiver52M/radioDevice.h +++ b/Transceiver52M/radioDevice.h @@ -65,10 +65,9 @@ class RadioDevice { @param RSSI The received signal strength of the read result @return The number of samples actually read */ - virtual int readSamples(short *buf, int len, bool *overrun, - TIMESTAMP timestamp = 0xffffffff, - bool *underrun = 0, - unsigned *RSSI = 0)=0; + virtual int readSamples(short **buf, int chans, int len, TIMESTAMP timestamp, + bool *overrun = NULL, bool *underrun = NULL, + unsigned *RSSI = NULL)=0; /** Write samples to the radio. @param buf Contains the data to be written. @@ -78,18 +77,17 @@ class RadioDevice { @param isControl Set if data is a control packet, e.g. a ping command @return The number of samples actually written */ - virtual int writeSamples(short *buf, int len, bool *underrun, - TIMESTAMP timestamp, - bool isControl=false)=0; + virtual int writeSamples(short **buf, int chans, int len, TIMESTAMP timestamp, + bool *underrun = NULL, bool isControl = false)=0; /** Update the alignment between the read and write timestamps */ virtual bool updateAlignment(TIMESTAMP timestamp)=0; /** Set the transmitter frequency */ - virtual bool setTxFreq(double wFreq)=0; + virtual bool setTxFreq(double wFreq, int chan = 0)=0; /** Set the receiver frequency */ - virtual bool setRxFreq(double wFreq)=0; + virtual bool setRxFreq(double wFreq, int chan = 0)=0; /** Returns the starting write Timestamp*/ virtual TIMESTAMP initialWriteTimestamp(void)=0; diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp index b3bc07c..40826e9 100644 --- a/Transceiver52M/radioInterface.cpp +++ b/Transceiver52M/radioInterface.cpp @@ -28,8 +28,8 @@ bool started = false; /* Device side buffers */ -static short rx_buf[OUTCHUNK * 2 * 2]; -static short tx_buf[INCHUNK * 2 * 2]; +static short *rx_buf[CHAN_MAX]; +static short *tx_buf[CHAN_MAX]; /* Complex float to short conversion */ static void floatToShort(short *out, float *in, int num) @@ -51,34 +51,25 @@ static void shortToFloat(float *out, short *in, int num) RadioInterface::RadioInterface(RadioDevice *wRadio, int wChanM, - int wReceiveOffset, int wSPS, + int wReceiveOffset, GSM::Time wStartTime) : mChanM(wChanM), underrun(false), sendCursor(0), rcvCursor(0), mOn(false), - mRadio(wRadio), receiveOffset(wReceiveOffset), - samplesPerSymbol(wSPS), powerScaling(1.0), - loadTest(false) + mRadio(wRadio), receiveOffset(wReceiveOffset), samplesPerSymbol(wSPS), + powerScaling(1.0), loadTest(false) { - int i; - mClock.set(wStartTime); - - for (i = 0; i < mChanM; i++) { - chanActive[i] = false; - } } RadioInterface::~RadioInterface(void) { - int i; - if (mOn) { mRadio->stop(); close(); delete mAlignRadioServiceLoopThread; - for (i = 0; i < mChanM; i++) { + for (int i = 0; i < mChanM; i++) { if (rcvBuffer[i] != NULL) delete rcvBuffer[i]; if (sendBuffer[i] != NULL) @@ -145,14 +136,14 @@ int RadioInterface::unRadioifyVector(float *floatVector, int offset, return newVector.size(); } -bool RadioInterface::tuneTx(double freq) +bool RadioInterface::tuneTx(double freq, int chan) { - return mRadio->setTxFreq(freq); + return mRadio->setTxFreq(freq, chan); } -bool RadioInterface::tuneRx(double freq) +bool RadioInterface::tuneRx(double freq, int chan) { - return mRadio->setRxFreq(freq); + return mRadio->setRxFreq(freq, chan); } @@ -220,10 +211,8 @@ void RadioInterface::driveTransmitRadio(signalVector **radioBurst, bool *zeroBur return; for (i = 0; i < mChanM; i++) { - if (chanActive[i]) { - radioifyVector(*radioBurst[i], sendBuffer[i] + 2 * sendCursor, - powerScaling, zeroBurst[i]); - } + radioifyVector(*radioBurst[i], sendBuffer[i] + 2 * sendCursor, + powerScaling, zeroBurst[i]); } /* @@ -235,15 +224,10 @@ void RadioInterface::driveTransmitRadio(signalVector **radioBurst, bool *zeroBur pushBuffer(); } -void shiftRxBuffers(float **buf, int offset, int len, int chanM, bool *active) +static inline void shiftRxBuffers(float **buf, int offset, int len, int chanM) { - int i; - - for (i = 0; i < chanM; i++) { - if (active[i]) { + for (int i = 0; i < chanM; i++) memmove(buf[i], buf[i] + offset, sizeof(float) * len); - } - } } void RadioInterface::loadVectors(unsigned tN, int samplesPerBurst, @@ -252,12 +236,10 @@ void RadioInterface::loadVectors(unsigned tN, int samplesPerBurst, int i; for (i = 0; i < mChanM; i++) { - if (chanActive[i]) { - signalVector rxVector(samplesPerBurst); - unRadioifyVector(rcvBuffer[i], idx * 2, rxVector); - radioVector *rxBurst = new radioVector(rxVector, rxClock); - mReceiveFIFO[i].write(rxBurst); - } + signalVector rxVector(samplesPerBurst); + unRadioifyVector(rcvBuffer[i], idx * 2, rxVector); + radioVector *rxBurst = new radioVector(rxVector, rxClock); + mReceiveFIFO[i].write(rxBurst); } } @@ -299,18 +281,10 @@ void RadioInterface::driveReceiveRadio() if (readSz > 0) { rcvCursor -= readSz; - shiftRxBuffers(rcvBuffer, 2 * readSz, 2 * rcvCursor, mChanM, chanActive); + shiftRxBuffers(rcvBuffer, 2 * readSz, 2 * rcvCursor, mChanM); } } -bool RadioInterface::isUnderrun() -{ - bool retVal = underrun; - underrun = false; - - return retVal; -} - double RadioInterface::setRxGain(double dB) { if (mRadio) @@ -327,14 +301,29 @@ double RadioInterface::getRxGain() return -1; } +bool RadioInterface::init() +{ + for (int i = 0; i < CHAN_MAX; i++) { + rx_buf[i] = new short[2 * OUTCHUNK]; + tx_buf[i] = new short[4 * 2 * INCHUNK]; + } +} + +void RadioInterface::close() +{ + for (int i = 0; i < CHAN_MAX; i++) { + delete rx_buf[i]; + delete tx_buf[i]; + } +} + /* Receive a timestamped chunk from the device */ void RadioInterface::pullBuffer() { bool local_underrun; /* Read samples. Fail if we don't get what we want. */ - int num_rd = mRadio->readSamples(rx_buf, OUTCHUNK, &overrun, - readTimestamp, &local_underrun); + int num_rd = mRadio->readSamples(rx_buf, mChanM, OUTCHUNK, readTimestamp); LOG(DEBUG) << "Rx read " << num_rd << " samples from device"; assert(num_rd == OUTCHUNK); @@ -342,7 +331,9 @@ void RadioInterface::pullBuffer() underrun |= local_underrun; readTimestamp += (TIMESTAMP) num_rd; - shortToFloat(rcvBuffer + 2 * rcvCursor, rx_buf, num_rd); + for (int i = 0; i < mChanM; i++) + shortToFloat(rcvBuffer[i] + 2 * rcvCursor, rx_buf[i], num_rd); + rcvCursor += num_rd; } @@ -352,13 +343,12 @@ void RadioInterface::pushBuffer() if (sendCursor < INCHUNK) return; - floatToShort(tx_buf, sendBuffer, sendCursor); + for (int i = 0; i < mChanM; i++) + floatToShort(tx_buf[i], sendBuffer[i], sendCursor); /* Write samples. Fail if we don't get what we want. */ - int num_smpls = mRadio->writeSamples(tx_buf, - sendCursor, - &underrun, - writeTimestamp); + int num_smpls = mRadio->writeSamples(tx_buf, mChanM, sendCursor, + writeTimestamp, &underrun); assert(num_smpls == sendCursor); writeTimestamp += (TIMESTAMP) num_smpls; diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h index f301511..b02cadc 100644 --- a/Transceiver52M/radioInterface.h +++ b/Transceiver52M/radioInterface.h @@ -26,7 +26,7 @@ #define SAMPSPERSYM 1 #define INCHUNK (625) #define OUTCHUNK (625) -#define CHAN_M 5 +#define CHAN_MAX 2 static const unsigned gSlotLen = 148; ///< number of symbols per slot, not counting guard periods @@ -49,8 +49,6 @@ protected: float *rcvBuffer[CHAN_MAX]; unsigned rcvCursor; - bool chanActive[CHAN_MAX]; - bool underrun; ///< indicates writes to USRP are too slow bool overrun; ///< indicates reads from USRP are too slow TIMESTAMP writeTimestamp; ///< sample timestamp of next packet written to USRP @@ -103,11 +101,11 @@ public: void close(); /** constructor */ - RadioInterface(RadioDevice* wRadio = NULL, + RadioInterface(RadioDevice* wRadio, int wChanM = 1, - int receiveOffset = 3, int wSPS = SAMPSPERSYM, - GSM::Time wStartTime = GSM::Time(0)); + int receiveOffset = 3, + GSM::Time wStartTime = GSM::Time(0, 0)); /** destructor */ ~RadioInterface(); @@ -115,10 +113,7 @@ public: void setSamplesPerSymbol(int wSamplesPerSymbol) {if (!mOn) samplesPerSymbol = wSamplesPerSymbol;} int getSamplesPerSymbol() { return samplesPerSymbol;} - - /** check for underrun, resets underrun value */ - bool isUnderrun(); - + /** return the receive FIFO */ VectorFIFO* receiveFIFO(int num) { return &mReceiveFIFO[num];} @@ -126,10 +121,10 @@ public: RadioClock* getClock(void) { return &mClock;}; /** set transmit frequency */ - bool tuneTx(double freq); + bool tuneTx(double freq, int chan = 0); /** set receive frequency */ - bool tuneRx(double freq); + bool tuneRx(double freq, int chan = 0); /** set receive gain */ double setRxGain(double dB); @@ -156,41 +151,6 @@ public: /** get transport window type of attached device */ enum RadioDevice::TxWindowType getWindowType() { return mRadio->getWindowType(); } - -#if USRP1 -protected: - - /** drive synchronization of Tx/Rx of USRP */ - void alignRadio(); - - /** reset the interface */ - void reset(); - - /** interface status */ - bool on() { return mOn; } - - friend void *AlignRadioServiceLoopAdapter(RadioInterface*); -#endif -}; - -#if USRP1 -/** synchronization thread loop */ -void *AlignRadioServiceLoopAdapter(RadioInterface*); -#endif - -class RadioInterfaceResamp : public RadioInterface { - -private: - - void pushBuffer(); - void pullBuffer(); - -public: - - RadioInterfaceResamp(RadioDevice* wRadio = NULL, - int receiveOffset = 3, - int wSPS = SAMPSPERSYM, - GSM::Time wStartTime = GSM::Time(0)); }; #endif /* _RADIOINTEFACE_H_ */ diff --git a/Transceiver52M/radioInterfaceResamp.cpp b/Transceiver52M/radioInterfaceResamp.cpp deleted file mode 100644 index c7f17ea..0000000 --- a/Transceiver52M/radioInterfaceResamp.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Radio device interface with sample rate conversion - * Written by Thomas Tsou <ttsou@vt.edu> - * - * Copyright 2011 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * See the COPYING file in the main directory for details. - */ - -#include <radioInterface.h> -#include <Logger.h> - -/* New chunk sizes for resampled rate */ -#ifdef INCHUNK - #undef INCHUNK -#endif -#ifdef OUTCHUNK - #undef OUTCHUNK -#endif - -/* Resampling parameters */ -#define INRATE 65 * SAMPSPERSYM -#define INHISTORY INRATE * 2 -#define INCHUNK INRATE * 9 - -#define OUTRATE 96 * SAMPSPERSYM -#define OUTHISTORY OUTRATE * 2 -#define OUTCHUNK OUTRATE * 9 - -/* Resampler low pass filters */ -signalVector *tx_lpf = 0; -signalVector *rx_lpf = 0; - -/* Resampler history */ -signalVector *tx_hist = 0; -signalVector *rx_hist = 0; - -/* Resampler input buffer */ -signalVector *tx_vec = 0; -signalVector *rx_vec = 0; - -/* - * High rate (device facing) buffers - * - * Transmit side samples are pushed after each burst so accomodate - * a resampled burst plus up to a chunk left over from the previous - * resampling operation. - * - * Receive side samples always pulled with a fixed size. - */ -short tx_buf[INCHUNK * 2 * 4]; -short rx_buf[OUTCHUNK * 2 * 2]; - -/* - * Utilities and Conversions - * - * Manipulate signal vectors dynamically for two reasons. For one, - * it's simpler. And two, it doesn't make any reasonable difference - * relative to the high overhead generated by the resampling. - */ - -/* Concatenate signal vectors. Deallocate input vectors. */ -signalVector *concat(signalVector *a, signalVector *b) -{ - signalVector *vec = new signalVector(*a, *b); - delete a; - delete b; - - return vec; -} - -/* Segment a signal vector. Deallocate the input vector. */ -signalVector *segment(signalVector *a, int indx, int sz) -{ - signalVector *vec = new signalVector(sz); - a->segmentCopyTo(*vec, indx, sz); - delete a; - - return vec; -} - -/* Create a new signal vector from a short array. */ -signalVector *short_to_sigvec(short *smpls, size_t sz) -{ - int i; - signalVector *vec = new signalVector(sz); - signalVector::iterator itr = vec->begin(); - - for (i = 0; i < sz; i++) { - *itr++ = Complex<float>(smpls[2 * i + 0], smpls[2 * i + 1]); - } - - return vec; -} - -/* Convert and deallocate a signal vector into a short array. */ -int sigvec_to_short(signalVector *vec, short *smpls) -{ - int i; - signalVector::iterator itr = vec->begin(); - - for (i = 0; i < vec->size(); i++) { - smpls[2 * i + 0] = itr->real(); - smpls[2 * i + 1] = itr->imag(); - itr++; - } - delete vec; - - return i; -} - -/* Create a new signal vector from a float array. */ -signalVector *float_to_sigvec(float *smpls, int sz) -{ - int i; - signalVector *vec = new signalVector(sz); - signalVector::iterator itr = vec->begin(); - - for (i = 0; i < sz; i++) { - *itr++ = Complex<float>(smpls[2 * i + 0], smpls[2 * i + 1]); - } - - return vec; -} - -/* Convert and deallocate a signal vector into a float array. */ -int sigvec_to_float(signalVector *vec, float *smpls) -{ - int i; - signalVector::iterator itr = vec->begin(); - - for (i = 0; i < vec->size(); i++) { - smpls[2 * i + 0] = itr->real(); - smpls[2 * i + 1] = itr->imag(); - itr++; - } - delete vec; - - return i; -} - -/* Initialize resampling signal vectors */ -void init_resampler(signalVector **lpf, - signalVector **buf, - signalVector **hist, - int tx) -{ - int P, Q, taps, hist_len; - float cutoff_freq; - - if (tx) { - LOG(INFO) << "Initializing Tx resampler"; - P = OUTRATE; - Q = INRATE; - taps = 651; - hist_len = INHISTORY; - } else { - LOG(INFO) << "Initializing Rx resampler"; - P = INRATE; - Q = OUTRATE; - taps = 961; - hist_len = OUTHISTORY; - } - - if (!*lpf) { - cutoff_freq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P); - *lpf = createLPF(cutoff_freq, taps, P); - } - - if (!*buf) { - *buf = new signalVector(); - } - - if (!*hist); - *hist = new signalVector(hist_len); -} - -/* Resample a signal vector - * - * The input vector is deallocated and the pointer returned with a vector - * of any unconverted samples. - */ -signalVector *resmpl_sigvec(signalVector *hist, signalVector **vec, - signalVector *lpf, double in_rate, - double out_rate, int chunk_sz) -{ - signalVector *resamp_vec; - int num_chunks = (*vec)->size() / chunk_sz; - - /* Truncate to a chunk multiple */ - signalVector trunc_vec(num_chunks * chunk_sz); - (*vec)->segmentCopyTo(trunc_vec, 0, num_chunks * chunk_sz); - - /* Update sample buffer with remainder */ - *vec = segment(*vec, trunc_vec.size(), (*vec)->size() - trunc_vec.size()); - - /* Add history and resample */ - signalVector input_vec(*hist, trunc_vec); - resamp_vec = polyphaseResampleVector(input_vec, in_rate, - out_rate, lpf); - - /* Update history */ - trunc_vec.segmentCopyTo(*hist, trunc_vec.size() - hist->size(), - hist->size()); - return resamp_vec; -} - -/* Wrapper for receive-side integer-to-float array resampling */ - int rx_resmpl_int_flt(float *smpls_out, short *smpls_in, int num_smpls) -{ - int num_resmpld, num_chunks; - signalVector *convert_vec, *resamp_vec, *trunc_vec; - - if (!rx_lpf || !rx_vec || !rx_hist) - init_resampler(&rx_lpf, &rx_vec, &rx_hist, false); - - /* Convert and add samples to the receive buffer */ - convert_vec = short_to_sigvec(smpls_in, num_smpls); - rx_vec = concat(rx_vec, convert_vec); - - num_chunks = rx_vec->size() / OUTCHUNK; - if (num_chunks < 1) - return 0; - - /* Resample */ - resamp_vec = resmpl_sigvec(rx_hist, &rx_vec, rx_lpf, - INRATE, OUTRATE, OUTCHUNK); - /* Truncate */ - trunc_vec = segment(resamp_vec, INHISTORY, - resamp_vec->size() - INHISTORY); - /* Convert */ - num_resmpld = sigvec_to_float(trunc_vec, smpls_out); - - return num_resmpld; -} - -/* Wrapper for transmit-side float-to-int array resampling */ -int tx_resmpl_flt_int(short *smpls_out, float *smpls_in, int num_smpls) -{ - int num_resmpl, num_chunks; - signalVector *convert_vec, *resamp_vec; - - if (!tx_lpf || !tx_vec || !tx_hist) - init_resampler(&tx_lpf, &tx_vec, &tx_hist, true); - - /* Convert and add samples to the transmit buffer */ - convert_vec = float_to_sigvec(smpls_in, num_smpls); - tx_vec = concat(tx_vec, convert_vec); - - num_chunks = tx_vec->size() / INCHUNK; - if (num_chunks < 1) - return 0; - - /* Resample and convert to an integer array */ - resamp_vec = resmpl_sigvec(tx_hist, &tx_vec, tx_lpf, - OUTRATE, INRATE, INCHUNK); - num_resmpl = sigvec_to_short(resamp_vec, smpls_out); - - return num_resmpl; -} - -RadioInterfaceResamp::RadioInterfaceResamp(RadioDevice *wRadio, - int wReceiveOffset, - int wSPS, - GSM::Time wStartTime) - : RadioInterface(wRadio, wReceiveOffset, wSPS, wStartTime) -{ -} - -/* Receive a timestamped chunk from the device */ -void RadioInterfaceResamp::pullBuffer() -{ - int num_cv, num_rd; - bool local_underrun; - - /* Read samples. Fail if we don't get what we want. */ - num_rd = mRadio->readSamples(rx_buf, OUTCHUNK, &overrun, - readTimestamp, &local_underrun); - - LOG(DEBUG) << "Rx read " << num_rd << " samples from device"; - assert(num_rd == OUTCHUNK); - - underrun |= local_underrun; - readTimestamp += (TIMESTAMP) num_rd; - - /* Convert and resample */ - num_cv = rx_resmpl_int_flt(rcvBuffer + 2 * rcvCursor, - rx_buf, num_rd); - - LOG(DEBUG) << "Rx read " << num_cv << " samples from resampler"; - - rcvCursor += num_cv; -} - -/* Send a timestamped chunk to the device */ -void RadioInterfaceResamp::pushBuffer() -{ - int num_cv, num_wr; - - if (sendCursor < INCHUNK) - return; - - LOG(DEBUG) << "Tx wrote " << sendCursor << " samples to resampler"; - - /* Resample and convert */ - num_cv = tx_resmpl_flt_int(tx_buf, sendBuffer, sendCursor); - assert(num_cv > sendCursor); - - /* Write samples. Fail if we don't get what we want. */ - num_wr = mRadio->writeSamples(tx_buf + OUTHISTORY * 2, - num_cv - OUTHISTORY, - &underrun, - writeTimestamp); - - LOG(DEBUG) << "Tx wrote " << num_wr << " samples to device"; - assert(num_wr == num_wr); - - writeTimestamp += (TIMESTAMP) num_wr; - sendCursor = 0; -} diff --git a/Transceiver52M/runTransceiver.cpp b/Transceiver52M/runTransceiver.cpp index acbea72..6a05100 100644 --- a/Transceiver52M/runTransceiver.cpp +++ b/Transceiver52M/runTransceiver.cpp @@ -109,8 +109,6 @@ int main(int argc, char *argv[]) radio = new RadioInterface(usrp, 3, SAMPSPERSYM, false); break; case RadioDevice::RESAMP: - radio = new RadioInterfaceResamp(usrp, 3, SAMPSPERSYM, false); - break; default: LOG(ALERT) << "Unsupported configuration"; return EXIT_FAILURE; |