blob: 568f0e5077be232b373eb5c3680bf3c6bf7240ef [file] [log] [blame]
dburgessb3a0ca42011-10-12 07:44:40 +00001/*
2* Copyright 2008, 2009 Free Software Foundation, Inc.
3*
4* This software is distributed under the terms of the GNU Affero Public License.
5* See the COPYING file in the main directory for details.
6*
7* This use of this software may be subject to additional restrictions.
8* See the LEGAL file in the main directory for details.
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Affero General Public License for more details.
19
20 You should have received a copy of the GNU Affero General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22
23*/
24
25
26/*
27 Compilation Flags
28
29 SWLOOPBACK compile for software loopback testing
30*/
31
32
33#include <stdint.h>
34#include <string.h>
35#include <stdlib.h>
36#include "Threads.h"
37#include "USRPDevice.h"
38
39#include <Logger.h>
40
kurtis.heimerl3758b162011-11-26 03:19:22 +000041#ifdef HAVE_CONFIG_H
42#include "config.h"
43#endif
dburgessb3a0ca42011-10-12 07:44:40 +000044
45using namespace std;
46
kurtis.heimerl79e71c92011-11-26 03:16:48 +000047enum dboardConfigType {
48 TXA_RXB,
49 TXB_RXA,
50 TXA_RXA,
51 TXB_RXB
52};
dburgessb3a0ca42011-10-12 07:44:40 +000053
kurtis.heimerl3758b162011-11-26 03:19:22 +000054#ifdef SINGLEDB
55const dboardConfigType dboardConfig = TXA_RXA;
56#else
kurtis.heimerl79e71c92011-11-26 03:16:48 +000057const dboardConfigType dboardConfig = TXA_RXB;
kurtis.heimerl3758b162011-11-26 03:19:22 +000058#endif
59
kurtis.heimerl79e71c92011-11-26 03:16:48 +000060const double USRPDevice::masterClockRate = 52.0e6;
dburgessb3a0ca42011-10-12 07:44:40 +000061
Thomas Tsoue90a42b2013-11-13 23:38:09 -050062USRPDevice::USRPDevice(size_t sps, size_t, bool)
dburgessb3a0ca42011-10-12 07:44:40 +000063{
64 LOG(INFO) << "creating USRP device...";
Thomas Tsouc1f7c422013-10-11 13:49:55 -040065
66 this->sps = sps;
Thomas Tsoucb69f082013-04-08 14:18:26 -040067 decimRate = (unsigned int) round(masterClockRate/((GSMRATE) * (double) sps));
dburgessb3a0ca42011-10-12 07:44:40 +000068 actualSampleRate = masterClockRate/decimRate;
69 rxGain = 0;
70
Thomas Tsouc1f7c422013-10-11 13:49:55 -040071 /*
72 * Undetermined delay b/w ping response timestamp and true
73 * receive timestamp. Values are empirically measured. With
74 * split sample rate Tx/Rx - 4/1 sps we need to need to
75 * compensate for advance rather than delay.
76 */
77 if (sps == 1)
78 pingOffset = 272;
79 else if (sps == 4)
80 pingOffset = 269 - 7500;
81 else
82 pingOffset = 0;
83
dburgessb3a0ca42011-10-12 07:44:40 +000084#ifdef SWLOOPBACK
85 samplePeriod = 1.0e6/actualSampleRate;
86 loopbackBufferSize = 0;
87 gettimeofday(&lastReadTime,NULL);
88 firstRead = false;
89#endif
90}
91
Alexander Chemerisdf127bc2015-06-07 01:07:45 -040092int USRPDevice::open(const std::string &, bool, bool)
dburgessb3a0ca42011-10-12 07:44:40 +000093{
dburgessb3a0ca42011-10-12 07:44:40 +000094 writeLock.unlock();
95
kurtis.heimerl965e7572011-11-26 03:16:54 +000096 LOG(INFO) << "opening USRP device..";
dburgessb3a0ca42011-10-12 07:44:40 +000097#ifndef SWLOOPBACK
98 string rbf = "std_inband.rbf";
99 //string rbf = "inband_1rxhb_1tx.rbf";
100 m_uRx.reset();
101 if (!skipRx) {
102 try {
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400103 m_uRx = usrp_standard_rx_sptr(usrp_standard_rx::make(
104 0, decimRate * sps, 1, -1,
105 usrp_standard_rx::FPGA_MODE_NORMAL,
106 1024, 16 * 8, rbf));
dburgessb3a0ca42011-10-12 07:44:40 +0000107 m_uRx->set_fpga_master_clock_freq(masterClockRate);
dburgessb3a0ca42011-10-12 07:44:40 +0000108 }
Thomas Tsouc0641242013-10-11 14:55:31 -0400109
dburgessb3a0ca42011-10-12 07:44:40 +0000110 catch(...) {
111 LOG(ALERT) << "make failed on Rx";
112 m_uRx.reset();
Thomas Tsoucb69f082013-04-08 14:18:26 -0400113 return -1;
dburgessb3a0ca42011-10-12 07:44:40 +0000114 }
115
116 if (m_uRx->fpga_master_clock_freq() != masterClockRate)
117 {
118 LOG(ALERT) << "WRONG FPGA clock freq = " << m_uRx->fpga_master_clock_freq()
119 << ", desired clock freq = " << masterClockRate;
120 m_uRx.reset();
Thomas Tsoucb69f082013-04-08 14:18:26 -0400121 return -1;
dburgessb3a0ca42011-10-12 07:44:40 +0000122 }
123 }
124
125 try {
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400126 m_uTx = usrp_standard_tx_sptr(usrp_standard_tx::make(
127 0, decimRate * 2, 1, -1,
128 1024, 16 * 8, rbf));
dburgessb3a0ca42011-10-12 07:44:40 +0000129 m_uTx->set_fpga_master_clock_freq(masterClockRate);
dburgessb3a0ca42011-10-12 07:44:40 +0000130 }
Thomas Tsouc0641242013-10-11 14:55:31 -0400131
dburgessb3a0ca42011-10-12 07:44:40 +0000132 catch(...) {
133 LOG(ALERT) << "make failed on Tx";
134 m_uTx.reset();
Thomas Tsoucb69f082013-04-08 14:18:26 -0400135 return -1;
dburgessb3a0ca42011-10-12 07:44:40 +0000136 }
137
138 if (m_uTx->fpga_master_clock_freq() != masterClockRate)
139 {
140 LOG(ALERT) << "WRONG FPGA clock freq = " << m_uTx->fpga_master_clock_freq()
141 << ", desired clock freq = " << masterClockRate;
142 m_uTx.reset();
Thomas Tsoucb69f082013-04-08 14:18:26 -0400143 return -1;
dburgessb3a0ca42011-10-12 07:44:40 +0000144 }
145
146 if (!skipRx) m_uRx->stop();
147 m_uTx->stop();
148
149#endif
150
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000151 switch (dboardConfig) {
152 case TXA_RXB:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000153 txSubdevSpec = usrp_subdev_spec(0,0);
154 rxSubdevSpec = usrp_subdev_spec(1,0);
155 break;
156 case TXB_RXA:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000157 txSubdevSpec = usrp_subdev_spec(1,0);
158 rxSubdevSpec = usrp_subdev_spec(0,0);
159 break;
160 case TXA_RXA:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000161 txSubdevSpec = usrp_subdev_spec(0,0);
162 rxSubdevSpec = usrp_subdev_spec(0,0);
163 break;
164 case TXB_RXB:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000165 txSubdevSpec = usrp_subdev_spec(1,0);
166 rxSubdevSpec = usrp_subdev_spec(1,0);
167 break;
168 default:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000169 txSubdevSpec = usrp_subdev_spec(0,0);
170 rxSubdevSpec = usrp_subdev_spec(1,0);
171 }
172
kurtis.heimerlb9e237e2011-11-26 03:17:59 +0000173 m_dbTx = m_uTx->selected_subdev(txSubdevSpec);
174 m_dbRx = m_uRx->selected_subdev(rxSubdevSpec);
175
dburgessb3a0ca42011-10-12 07:44:40 +0000176 samplesRead = 0;
177 samplesWritten = 0;
178 started = false;
179
Thomas Tsoucb69f082013-04-08 14:18:26 -0400180 return NORMAL;
dburgessb3a0ca42011-10-12 07:44:40 +0000181}
182
183
184
185bool USRPDevice::start()
186{
187 LOG(INFO) << "starting USRP...";
188#ifndef SWLOOPBACK
189 if (!m_uRx && !skipRx) return false;
190 if (!m_uTx) return false;
191
192 if (!skipRx) m_uRx->stop();
193 m_uTx->stop();
194
195 writeLock.lock();
196 // power up and configure daughterboards
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000197 m_dbTx->set_enable(true);
198 m_uTx->set_mux(m_uTx->determine_tx_mux_value(txSubdevSpec));
199 m_uRx->set_mux(m_uRx->determine_rx_mux_value(rxSubdevSpec));
200
201 if (!m_dbRx->select_rx_antenna(1))
202 m_dbRx->select_rx_antenna(0);
203
dburgessb3a0ca42011-10-12 07:44:40 +0000204 writeLock.unlock();
205
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000206 // Set gains to midpoint
207 setTxGain((minTxGain() + maxTxGain()) / 2);
208 setRxGain((minRxGain() + maxRxGain()) / 2);
dburgessb3a0ca42011-10-12 07:44:40 +0000209
210 data = new short[currDataSize];
211 dataStart = 0;
212 dataEnd = 0;
213 timeStart = 0;
214 timeEnd = 0;
215 timestampOffset = 0;
216 latestWriteTimestamp = 0;
217 lastPktTimestamp = 0;
218 hi32Timestamp = 0;
219 isAligned = false;
220
221
222 if (!skipRx)
223 started = (m_uRx->start() && m_uTx->start());
224 else
225 started = m_uTx->start();
226 return started;
227#else
228 gettimeofday(&lastReadTime,NULL);
229 return true;
230#endif
231}
232
233bool USRPDevice::stop()
234{
235#ifndef SWLOOPBACK
236 if (!m_uRx) return false;
237 if (!m_uTx) return false;
238
dburgessb3a0ca42011-10-12 07:44:40 +0000239 delete[] currData;
240
241 started = !(m_uRx->stop() && m_uTx->stop());
242 return !started;
243#else
244 return true;
245#endif
246}
247
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000248double USRPDevice::maxTxGain()
249{
250 return m_dbTx->gain_max();
251}
252
253double USRPDevice::minTxGain()
254{
255 return m_dbTx->gain_min();
256}
257
258double USRPDevice::maxRxGain()
259{
260 return m_dbRx->gain_max();
261}
262
263double USRPDevice::minRxGain()
264{
265 return m_dbRx->gain_min();
266}
267
Thomas Tsou204a9f12013-10-29 18:34:16 -0400268double USRPDevice::setTxGain(double dB, size_t chan)
269{
270 if (chan) {
271 LOG(ALERT) << "Invalid channel " << chan;
272 return 0.0;
273 }
dburgessb3a0ca42011-10-12 07:44:40 +0000274
Thomas Tsou204a9f12013-10-29 18:34:16 -0400275 writeLock.lock();
276 if (dB > maxTxGain())
277 dB = maxTxGain();
278 if (dB < minTxGain())
279 dB = minTxGain();
dburgessb3a0ca42011-10-12 07:44:40 +0000280
Thomas Tsou204a9f12013-10-29 18:34:16 -0400281 LOG(NOTICE) << "Setting TX gain to " << dB << " dB.";
dburgessb3a0ca42011-10-12 07:44:40 +0000282
Thomas Tsou204a9f12013-10-29 18:34:16 -0400283 if (!m_dbTx->set_gain(dB))
284 LOG(ERR) << "Error setting TX gain";
285
286 writeLock.unlock();
287
288 return dB;
dburgessb3a0ca42011-10-12 07:44:40 +0000289}
290
291
Thomas Tsou204a9f12013-10-29 18:34:16 -0400292double USRPDevice::setRxGain(double dB, size_t chan)
293{
294 if (chan) {
295 LOG(ALERT) << "Invalid channel " << chan;
296 return 0.0;
297 }
dburgessb3a0ca42011-10-12 07:44:40 +0000298
Thomas Tsou204a9f12013-10-29 18:34:16 -0400299 dB = 47.0;
dburgessb3a0ca42011-10-12 07:44:40 +0000300
Thomas Tsou204a9f12013-10-29 18:34:16 -0400301 writeLock.lock();
302 if (dB > maxRxGain())
303 dB = maxRxGain();
304 if (dB < minRxGain())
305 dB = minRxGain();
306
307 LOG(NOTICE) << "Setting RX gain to " << dB << " dB.";
308
309 if (!m_dbRx->set_gain(dB))
310 LOG(ERR) << "Error setting RX gain";
311
312 writeLock.unlock();
313
314 return dB;
dburgessb3a0ca42011-10-12 07:44:40 +0000315}
316
317
318// NOTE: Assumes sequential reads
Thomas Tsou204a9f12013-10-29 18:34:16 -0400319int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
320 TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
dburgessb3a0ca42011-10-12 07:44:40 +0000321{
322#ifndef SWLOOPBACK
Thomas Tsou204a9f12013-10-29 18:34:16 -0400323 if (!m_uRx)
324 return 0;
325
326 short *buf = bufs[0];
327
dburgessb3a0ca42011-10-12 07:44:40 +0000328 timestamp += timestampOffset;
329
330 if (timestamp + len < timeStart) {
331 memset(buf,0,len*2*sizeof(short));
332 return len;
333 }
334
335 if (underrun) *underrun = false;
336
337 uint32_t readBuf[2000];
338
339 while (1) {
340 //guestimate USB read size
341 int readLen=0;
342 {
343 int numSamplesNeeded = timestamp + len - timeEnd;
344 if (numSamplesNeeded <=0) break;
345 readLen = 512 * ((int) ceil((float) numSamplesNeeded/126.0));
346 if (readLen > 8000) readLen= (8000/512)*512;
347 }
348
349 // read USRP packets, parse and save A/D data as needed
350 readLen = m_uRx->read((void *)readBuf,readLen,overrun);
351 for(int pktNum = 0; pktNum < (readLen/512); pktNum++) {
352 // tmpBuf points to start of a USB packet
353 uint32_t* tmpBuf = (uint32_t *) (readBuf+pktNum*512/4);
354 TIMESTAMP pktTimestamp = usrp_to_host_u32(tmpBuf[1]);
355 uint32_t word0 = usrp_to_host_u32(tmpBuf[0]);
356 uint32_t chan = (word0 >> 16) & 0x1f;
357 unsigned payloadSz = word0 & 0x1ff;
358 LOG(DEBUG) << "first two bytes: " << hex << word0 << " " << dec << pktTimestamp;
359
360 bool incrementHi32 = ((lastPktTimestamp & 0x0ffffffffll) > pktTimestamp);
361 if (incrementHi32 && (timeStart!=0)) {
362 LOG(DEBUG) << "high 32 increment!!!";
363 hi32Timestamp++;
364 }
365 pktTimestamp = (((TIMESTAMP) hi32Timestamp) << 32) | pktTimestamp;
366 lastPktTimestamp = pktTimestamp;
367
368 if (chan == 0x01f) {
369 // control reply, check to see if its ping reply
370 uint32_t word2 = usrp_to_host_u32(tmpBuf[2]);
371 if ((word2 >> 16) == ((0x01 << 8) | 0x02)) {
372 timestamp -= timestampOffset;
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400373 timestampOffset = pktTimestamp - pingTimestamp + pingOffset;
dburgessb3a0ca42011-10-12 07:44:40 +0000374 LOG(DEBUG) << "updating timestamp offset to: " << timestampOffset;
375 timestamp += timestampOffset;
376 isAligned = true;
377 }
378 continue;
379 }
380 if (chan != 0) {
381 LOG(DEBUG) << "chan: " << chan << ", timestamp: " << pktTimestamp << ", sz:" << payloadSz;
382 continue;
383 }
384 if ((word0 >> 28) & 0x04) {
385 if (underrun) *underrun = true;
386 LOG(DEBUG) << "UNDERRUN in TRX->USRP interface";
387 }
388 if (RSSI) *RSSI = (word0 >> 21) & 0x3f;
389
390 if (!isAligned) continue;
391
392 unsigned cursorStart = pktTimestamp - timeStart + dataStart;
393 while (cursorStart*2 > currDataSize) {
394 cursorStart -= currDataSize/2;
395 }
396 if (cursorStart*2 + payloadSz/2 > currDataSize) {
397 // need to circle around buffer
398 memcpy(data+cursorStart*2,tmpBuf+2,(currDataSize-cursorStart*2)*sizeof(short));
399 memcpy(data,tmpBuf+2+(currDataSize/2-cursorStart),payloadSz-(currDataSize-cursorStart*2)*sizeof(short));
400 }
401 else {
402 memcpy(data+cursorStart*2,tmpBuf+2,payloadSz);
403 }
404 if (pktTimestamp + payloadSz/2/sizeof(short) > timeEnd)
405 timeEnd = pktTimestamp+payloadSz/2/sizeof(short);
406
407 LOG(DEBUG) << "timeStart: " << timeStart << ", timeEnd: " << timeEnd << ", pktTimestamp: " << pktTimestamp;
408
409 }
410 }
411
412 // copy desired data to buf
413 unsigned bufStart = dataStart+(timestamp-timeStart);
414 if (bufStart + len < currDataSize/2) {
415 LOG(DEBUG) << "bufStart: " << bufStart;
416 memcpy(buf,data+bufStart*2,len*2*sizeof(short));
417 memset(data+bufStart*2,0,len*2*sizeof(short));
418 }
419 else {
420 LOG(DEBUG) << "len: " << len << ", currDataSize/2: " << currDataSize/2 << ", bufStart: " << bufStart;
421 unsigned firstLength = (currDataSize/2-bufStart);
422 LOG(DEBUG) << "firstLength: " << firstLength;
423 memcpy(buf,data+bufStart*2,firstLength*2*sizeof(short));
424 memset(data+bufStart*2,0,firstLength*2*sizeof(short));
425 memcpy(buf+firstLength*2,data,(len-firstLength)*2*sizeof(short));
426 memset(data,0,(len-firstLength)*2*sizeof(short));
427 }
428 dataStart = (bufStart + len) % (currDataSize/2);
429 timeStart = timestamp + len;
430
dburgessb3a0ca42011-10-12 07:44:40 +0000431 return len;
432
433#else
434 if (loopbackBufferSize < 2) return 0;
435 int numSamples = 0;
436 struct timeval currTime;
437 gettimeofday(&currTime,NULL);
438 double timeElapsed = (currTime.tv_sec - lastReadTime.tv_sec)*1.0e6 +
439 (currTime.tv_usec - lastReadTime.tv_usec);
440 if (timeElapsed < samplePeriod) {return 0;}
441 int numSamplesToRead = (int) floor(timeElapsed/samplePeriod);
442 if (numSamplesToRead < len) return 0;
443
444 if (numSamplesToRead > len) numSamplesToRead = len;
445 if (numSamplesToRead > loopbackBufferSize/2) {
446 firstRead =false;
447 numSamplesToRead = loopbackBufferSize/2;
448 }
449 memcpy(buf,loopbackBuffer,sizeof(short)*2*numSamplesToRead);
450 loopbackBufferSize -= 2*numSamplesToRead;
451 memcpy(loopbackBuffer,loopbackBuffer+2*numSamplesToRead,
452 sizeof(short)*loopbackBufferSize);
453 numSamples = numSamplesToRead;
454 if (firstRead) {
455 int new_usec = lastReadTime.tv_usec + (int) round((double) numSamplesToRead * samplePeriod);
456 lastReadTime.tv_sec = lastReadTime.tv_sec + new_usec/1000000;
457 lastReadTime.tv_usec = new_usec % 1000000;
458 }
459 else {
460 gettimeofday(&lastReadTime,NULL);
461 firstRead = true;
462 }
463 samplesRead += numSamples;
464
465 return numSamples;
466#endif
467}
468
Thomas Tsou204a9f12013-10-29 18:34:16 -0400469int USRPDevice::writeSamples(std::vector<short *> &bufs, int len,
470 bool *underrun, unsigned long long timestamp,
471 bool isControl)
dburgessb3a0ca42011-10-12 07:44:40 +0000472{
473 writeLock.lock();
474
475#ifndef SWLOOPBACK
Thomas Tsou204a9f12013-10-29 18:34:16 -0400476 if (!m_uTx)
477 return 0;
478
479 short *buf = bufs[0];
480
kurtis.heimerlc8739b82011-11-02 00:06:34 +0000481 static uint32_t outData[128*20];
Thomas Tsou204a9f12013-10-29 18:34:16 -0400482
dburgessb3a0ca42011-10-12 07:44:40 +0000483 for (int i = 0; i < len*2; i++) {
484 buf[i] = host_to_usrp_short(buf[i]);
485 }
486
487 int numWritten = 0;
488 unsigned isStart = 1;
489 unsigned RSSI = 0;
490 unsigned CHAN = (isControl) ? 0x01f : 0x00;
491 len = len*2*sizeof(short);
492 int numPkts = (int) ceil((float)len/(float)504);
493 unsigned isEnd = (numPkts < 2);
494 uint32_t *outPkt = outData;
495 int pktNum = 0;
496 while (numWritten < len) {
497 // pkt is pointer to start of a USB packet
498 uint32_t *pkt = outPkt + pktNum*128;
499 isEnd = (len - numWritten <= 504);
500 unsigned payloadLen = ((len - numWritten) < 504) ? (len-numWritten) : 504;
501 pkt[0] = (isStart << 12 | isEnd << 11 | (RSSI & 0x3f) << 5 | CHAN) << 16 | payloadLen;
502 pkt[1] = timestamp & 0x0ffffffffll;
503 memcpy(pkt+2,buf+(numWritten/sizeof(short)),payloadLen);
504 numWritten += payloadLen;
505 timestamp += payloadLen/2/sizeof(short);
506 isStart = 0;
507 pkt[0] = host_to_usrp_u32(pkt[0]);
508 pkt[1] = host_to_usrp_u32(pkt[1]);
509 pktNum++;
510 }
511 m_uTx->write((const void*) outPkt,sizeof(uint32_t)*128*numPkts,NULL);
512
513 samplesWritten += len/2/sizeof(short);
514 writeLock.unlock();
515
516 return len/2/sizeof(short);
517#else
518 int retVal = len;
519 memcpy(loopbackBuffer+loopbackBufferSize,buf,sizeof(short)*2*len);
520 samplesWritten += retVal;
521 loopbackBufferSize += retVal*2;
522
523 return retVal;
524#endif
525}
526
527bool USRPDevice::updateAlignment(TIMESTAMP timestamp)
528{
529#ifndef SWLOOPBACK
530 short data[] = {0x00,0x02,0x00,0x00};
531 uint32_t *wordPtr = (uint32_t *) data;
kurtis.heimerlc8739b82011-11-02 00:06:34 +0000532 *wordPtr = host_to_usrp_u32(*wordPtr);
dburgessb3a0ca42011-10-12 07:44:40 +0000533 bool tmpUnderrun;
Thomas Tsou204a9f12013-10-29 18:34:16 -0400534
535 std::vector<short *> buf(1, data);
536 if (writeSamples(buf, 1, &tmpUnderrun, timestamp & 0x0ffffffffll, true)) {
dburgessb3a0ca42011-10-12 07:44:40 +0000537 pingTimestamp = timestamp;
538 return true;
539 }
540 return false;
541#else
542 return true;
543#endif
544}
545
546#ifndef SWLOOPBACK
Thomas Tsou204a9f12013-10-29 18:34:16 -0400547bool USRPDevice::setTxFreq(double wFreq, size_t chan)
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000548{
549 usrp_tune_result result;
dburgessb3a0ca42011-10-12 07:44:40 +0000550
Thomas Tsou204a9f12013-10-29 18:34:16 -0400551 if (chan) {
552 LOG(ALERT) << "Invalid channel " << chan;
553 return false;
554 }
555
kurtis.heimerlb9e237e2011-11-26 03:17:59 +0000556 if (m_uTx->tune(txSubdevSpec.side, m_dbTx, wFreq, &result)) {
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000557 LOG(INFO) << "set TX: " << wFreq << std::endl
558 << " baseband freq: " << result.baseband_freq << std::endl
559 << " DDC freq: " << result.dxc_freq << std::endl
560 << " residual freq: " << result.residual_freq;
561 return true;
562 }
563 else {
kurtis.heimerle3320322011-11-28 06:26:08 +0000564 LOG(ALERT) << "set TX: " << wFreq << "failed" << std::endl
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000565 << " baseband freq: " << result.baseband_freq << std::endl
566 << " DDC freq: " << result.dxc_freq << std::endl
567 << " residual freq: " << result.residual_freq;
568 return false;
569 }
570}
571
Thomas Tsou204a9f12013-10-29 18:34:16 -0400572bool USRPDevice::setRxFreq(double wFreq, size_t chan)
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000573{
574 usrp_tune_result result;
575
Thomas Tsou204a9f12013-10-29 18:34:16 -0400576 if (chan) {
577 LOG(ALERT) << "Invalid channel " << chan;
578 return false;
579 }
580
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000581 if (m_uRx->tune(0, m_dbRx, wFreq, &result)) {
582 LOG(INFO) << "set RX: " << wFreq << std::endl
583 << " baseband freq: " << result.baseband_freq << std::endl
584 << " DDC freq: " << result.dxc_freq << std::endl
585 << " residual freq: " << result.residual_freq;
586 return true;
587 }
588 else {
kurtis.heimerle3320322011-11-28 06:26:08 +0000589 LOG(ALERT) << "set RX: " << wFreq << "failed" << std::endl
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000590 << " baseband freq: " << result.baseband_freq << std::endl
591 << " DDC freq: " << result.dxc_freq << std::endl
592 << " residual freq: " << result.residual_freq;
593 return false;
594 }
595
596}
dburgessb3a0ca42011-10-12 07:44:40 +0000597
598#else
599bool USRPDevice::setTxFreq(double wFreq) { return true;};
600bool USRPDevice::setRxFreq(double wFreq) { return true;};
601#endif
kurtis.heimerl965e7572011-11-26 03:16:54 +0000602
Tom Tsou722d4f72015-01-19 09:54:17 -0800603RadioDevice *RadioDevice::make(size_t sps, size_t chans, bool diversity, double)
kurtis.heimerl965e7572011-11-26 03:16:54 +0000604{
Thomas Tsoue90a42b2013-11-13 23:38:09 -0500605 return new USRPDevice(sps, chans, diversity);
kurtis.heimerl965e7572011-11-26 03:16:54 +0000606}