blob: 034ccd8e0e9718a3cc3bf9db93fbe1e9a7fb048f [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
kurtis.heimerl3758b162011-11-26 03:19:22 +000039#ifdef HAVE_CONFIG_H
40#include "config.h"
41#endif
dburgessb3a0ca42011-10-12 07:44:40 +000042
43using namespace std;
44
kurtis.heimerl79e71c92011-11-26 03:16:48 +000045enum dboardConfigType {
46 TXA_RXB,
47 TXB_RXA,
48 TXA_RXA,
49 TXB_RXB
50};
dburgessb3a0ca42011-10-12 07:44:40 +000051
kurtis.heimerl3758b162011-11-26 03:19:22 +000052#ifdef SINGLEDB
53const dboardConfigType dboardConfig = TXA_RXA;
54#else
kurtis.heimerl79e71c92011-11-26 03:16:48 +000055const dboardConfigType dboardConfig = TXA_RXB;
kurtis.heimerl3758b162011-11-26 03:19:22 +000056#endif
57
kurtis.heimerl79e71c92011-11-26 03:16:48 +000058const double USRPDevice::masterClockRate = 52.0e6;
dburgessb3a0ca42011-10-12 07:44:40 +000059
Tom Tsou5cd70dc2016-03-06 01:28:40 -080060USRPDevice::USRPDevice(size_t sps)
dburgessb3a0ca42011-10-12 07:44:40 +000061{
62 LOG(INFO) << "creating USRP device...";
Thomas Tsouc1f7c422013-10-11 13:49:55 -040063
64 this->sps = sps;
Thomas Tsoucb69f082013-04-08 14:18:26 -040065 decimRate = (unsigned int) round(masterClockRate/((GSMRATE) * (double) sps));
dburgessb3a0ca42011-10-12 07:44:40 +000066 actualSampleRate = masterClockRate/decimRate;
67 rxGain = 0;
68
Thomas Tsouc1f7c422013-10-11 13:49:55 -040069 /*
70 * Undetermined delay b/w ping response timestamp and true
71 * receive timestamp. Values are empirically measured. With
72 * split sample rate Tx/Rx - 4/1 sps we need to need to
73 * compensate for advance rather than delay.
74 */
75 if (sps == 1)
76 pingOffset = 272;
77 else if (sps == 4)
78 pingOffset = 269 - 7500;
79 else
80 pingOffset = 0;
81
dburgessb3a0ca42011-10-12 07:44:40 +000082#ifdef SWLOOPBACK
83 samplePeriod = 1.0e6/actualSampleRate;
84 loopbackBufferSize = 0;
85 gettimeofday(&lastReadTime,NULL);
86 firstRead = false;
87#endif
88}
89
Tom Tsou2f3e60b2016-07-17 19:29:08 -070090int USRPDevice::open(const std::string &, int, bool)
dburgessb3a0ca42011-10-12 07:44:40 +000091{
dburgessb3a0ca42011-10-12 07:44:40 +000092 writeLock.unlock();
93
kurtis.heimerl965e7572011-11-26 03:16:54 +000094 LOG(INFO) << "opening USRP device..";
dburgessb3a0ca42011-10-12 07:44:40 +000095#ifndef SWLOOPBACK
96 string rbf = "std_inband.rbf";
97 //string rbf = "inband_1rxhb_1tx.rbf";
98 m_uRx.reset();
99 if (!skipRx) {
100 try {
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400101 m_uRx = usrp_standard_rx_sptr(usrp_standard_rx::make(
102 0, decimRate * sps, 1, -1,
103 usrp_standard_rx::FPGA_MODE_NORMAL,
104 1024, 16 * 8, rbf));
dburgessb3a0ca42011-10-12 07:44:40 +0000105 m_uRx->set_fpga_master_clock_freq(masterClockRate);
dburgessb3a0ca42011-10-12 07:44:40 +0000106 }
Thomas Tsouc0641242013-10-11 14:55:31 -0400107
dburgessb3a0ca42011-10-12 07:44:40 +0000108 catch(...) {
109 LOG(ALERT) << "make failed on Rx";
110 m_uRx.reset();
Thomas Tsoucb69f082013-04-08 14:18:26 -0400111 return -1;
dburgessb3a0ca42011-10-12 07:44:40 +0000112 }
113
114 if (m_uRx->fpga_master_clock_freq() != masterClockRate)
115 {
116 LOG(ALERT) << "WRONG FPGA clock freq = " << m_uRx->fpga_master_clock_freq()
117 << ", desired clock freq = " << masterClockRate;
118 m_uRx.reset();
Thomas Tsoucb69f082013-04-08 14:18:26 -0400119 return -1;
dburgessb3a0ca42011-10-12 07:44:40 +0000120 }
121 }
122
123 try {
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400124 m_uTx = usrp_standard_tx_sptr(usrp_standard_tx::make(
125 0, decimRate * 2, 1, -1,
126 1024, 16 * 8, rbf));
dburgessb3a0ca42011-10-12 07:44:40 +0000127 m_uTx->set_fpga_master_clock_freq(masterClockRate);
dburgessb3a0ca42011-10-12 07:44:40 +0000128 }
Thomas Tsouc0641242013-10-11 14:55:31 -0400129
dburgessb3a0ca42011-10-12 07:44:40 +0000130 catch(...) {
131 LOG(ALERT) << "make failed on Tx";
132 m_uTx.reset();
Thomas Tsoucb69f082013-04-08 14:18:26 -0400133 return -1;
dburgessb3a0ca42011-10-12 07:44:40 +0000134 }
135
136 if (m_uTx->fpga_master_clock_freq() != masterClockRate)
137 {
138 LOG(ALERT) << "WRONG FPGA clock freq = " << m_uTx->fpga_master_clock_freq()
139 << ", desired clock freq = " << masterClockRate;
140 m_uTx.reset();
Thomas Tsoucb69f082013-04-08 14:18:26 -0400141 return -1;
dburgessb3a0ca42011-10-12 07:44:40 +0000142 }
143
144 if (!skipRx) m_uRx->stop();
145 m_uTx->stop();
146
147#endif
148
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000149 switch (dboardConfig) {
150 case TXA_RXB:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000151 txSubdevSpec = usrp_subdev_spec(0,0);
152 rxSubdevSpec = usrp_subdev_spec(1,0);
153 break;
154 case TXB_RXA:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000155 txSubdevSpec = usrp_subdev_spec(1,0);
156 rxSubdevSpec = usrp_subdev_spec(0,0);
157 break;
158 case TXA_RXA:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000159 txSubdevSpec = usrp_subdev_spec(0,0);
160 rxSubdevSpec = usrp_subdev_spec(0,0);
161 break;
162 case TXB_RXB:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000163 txSubdevSpec = usrp_subdev_spec(1,0);
164 rxSubdevSpec = usrp_subdev_spec(1,0);
165 break;
166 default:
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000167 txSubdevSpec = usrp_subdev_spec(0,0);
168 rxSubdevSpec = usrp_subdev_spec(1,0);
169 }
170
kurtis.heimerlb9e237e2011-11-26 03:17:59 +0000171 m_dbTx = m_uTx->selected_subdev(txSubdevSpec);
172 m_dbRx = m_uRx->selected_subdev(rxSubdevSpec);
173
dburgessb3a0ca42011-10-12 07:44:40 +0000174 samplesRead = 0;
175 samplesWritten = 0;
176 started = false;
177
Thomas Tsoucb69f082013-04-08 14:18:26 -0400178 return NORMAL;
dburgessb3a0ca42011-10-12 07:44:40 +0000179}
180
181
182
183bool USRPDevice::start()
184{
185 LOG(INFO) << "starting USRP...";
186#ifndef SWLOOPBACK
187 if (!m_uRx && !skipRx) return false;
188 if (!m_uTx) return false;
189
190 if (!skipRx) m_uRx->stop();
191 m_uTx->stop();
192
193 writeLock.lock();
194 // power up and configure daughterboards
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000195 m_dbTx->set_enable(true);
196 m_uTx->set_mux(m_uTx->determine_tx_mux_value(txSubdevSpec));
197 m_uRx->set_mux(m_uRx->determine_rx_mux_value(rxSubdevSpec));
198
199 if (!m_dbRx->select_rx_antenna(1))
200 m_dbRx->select_rx_antenna(0);
201
dburgessb3a0ca42011-10-12 07:44:40 +0000202 writeLock.unlock();
203
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000204 // Set gains to midpoint
205 setTxGain((minTxGain() + maxTxGain()) / 2);
206 setRxGain((minRxGain() + maxRxGain()) / 2);
dburgessb3a0ca42011-10-12 07:44:40 +0000207
208 data = new short[currDataSize];
209 dataStart = 0;
210 dataEnd = 0;
211 timeStart = 0;
212 timeEnd = 0;
213 timestampOffset = 0;
214 latestWriteTimestamp = 0;
215 lastPktTimestamp = 0;
216 hi32Timestamp = 0;
217 isAligned = false;
218
219
220 if (!skipRx)
221 started = (m_uRx->start() && m_uTx->start());
222 else
223 started = m_uTx->start();
224 return started;
225#else
226 gettimeofday(&lastReadTime,NULL);
227 return true;
228#endif
229}
230
231bool USRPDevice::stop()
232{
233#ifndef SWLOOPBACK
234 if (!m_uRx) return false;
235 if (!m_uTx) return false;
236
dburgessb3a0ca42011-10-12 07:44:40 +0000237 delete[] currData;
238
239 started = !(m_uRx->stop() && m_uTx->stop());
240 return !started;
241#else
242 return true;
243#endif
244}
245
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000246double USRPDevice::maxTxGain()
247{
248 return m_dbTx->gain_max();
249}
250
251double USRPDevice::minTxGain()
252{
253 return m_dbTx->gain_min();
254}
255
256double USRPDevice::maxRxGain()
257{
258 return m_dbRx->gain_max();
259}
260
261double USRPDevice::minRxGain()
262{
263 return m_dbRx->gain_min();
264}
265
Thomas Tsou204a9f12013-10-29 18:34:16 -0400266double USRPDevice::setTxGain(double dB, size_t chan)
267{
268 if (chan) {
269 LOG(ALERT) << "Invalid channel " << chan;
270 return 0.0;
271 }
dburgessb3a0ca42011-10-12 07:44:40 +0000272
Thomas Tsou204a9f12013-10-29 18:34:16 -0400273 writeLock.lock();
274 if (dB > maxTxGain())
275 dB = maxTxGain();
276 if (dB < minTxGain())
277 dB = minTxGain();
dburgessb3a0ca42011-10-12 07:44:40 +0000278
Thomas Tsou204a9f12013-10-29 18:34:16 -0400279 LOG(NOTICE) << "Setting TX gain to " << dB << " dB.";
dburgessb3a0ca42011-10-12 07:44:40 +0000280
Thomas Tsou204a9f12013-10-29 18:34:16 -0400281 if (!m_dbTx->set_gain(dB))
282 LOG(ERR) << "Error setting TX gain";
283
284 writeLock.unlock();
285
286 return dB;
dburgessb3a0ca42011-10-12 07:44:40 +0000287}
288
289
Thomas Tsou204a9f12013-10-29 18:34:16 -0400290double USRPDevice::setRxGain(double dB, size_t chan)
291{
292 if (chan) {
293 LOG(ALERT) << "Invalid channel " << chan;
294 return 0.0;
295 }
dburgessb3a0ca42011-10-12 07:44:40 +0000296
Thomas Tsou204a9f12013-10-29 18:34:16 -0400297 dB = 47.0;
dburgessb3a0ca42011-10-12 07:44:40 +0000298
Thomas Tsou204a9f12013-10-29 18:34:16 -0400299 writeLock.lock();
300 if (dB > maxRxGain())
301 dB = maxRxGain();
302 if (dB < minRxGain())
303 dB = minRxGain();
304
305 LOG(NOTICE) << "Setting RX gain to " << dB << " dB.";
306
307 if (!m_dbRx->set_gain(dB))
308 LOG(ERR) << "Error setting RX gain";
309
310 writeLock.unlock();
311
312 return dB;
dburgessb3a0ca42011-10-12 07:44:40 +0000313}
314
315
316// NOTE: Assumes sequential reads
Thomas Tsou204a9f12013-10-29 18:34:16 -0400317int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
318 TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
dburgessb3a0ca42011-10-12 07:44:40 +0000319{
320#ifndef SWLOOPBACK
Thomas Tsou204a9f12013-10-29 18:34:16 -0400321 if (!m_uRx)
322 return 0;
323
324 short *buf = bufs[0];
325
dburgessb3a0ca42011-10-12 07:44:40 +0000326 timestamp += timestampOffset;
327
328 if (timestamp + len < timeStart) {
329 memset(buf,0,len*2*sizeof(short));
330 return len;
331 }
332
333 if (underrun) *underrun = false;
334
335 uint32_t readBuf[2000];
336
337 while (1) {
338 //guestimate USB read size
339 int readLen=0;
340 {
341 int numSamplesNeeded = timestamp + len - timeEnd;
342 if (numSamplesNeeded <=0) break;
343 readLen = 512 * ((int) ceil((float) numSamplesNeeded/126.0));
344 if (readLen > 8000) readLen= (8000/512)*512;
345 }
346
347 // read USRP packets, parse and save A/D data as needed
348 readLen = m_uRx->read((void *)readBuf,readLen,overrun);
349 for(int pktNum = 0; pktNum < (readLen/512); pktNum++) {
350 // tmpBuf points to start of a USB packet
351 uint32_t* tmpBuf = (uint32_t *) (readBuf+pktNum*512/4);
352 TIMESTAMP pktTimestamp = usrp_to_host_u32(tmpBuf[1]);
353 uint32_t word0 = usrp_to_host_u32(tmpBuf[0]);
354 uint32_t chan = (word0 >> 16) & 0x1f;
355 unsigned payloadSz = word0 & 0x1ff;
356 LOG(DEBUG) << "first two bytes: " << hex << word0 << " " << dec << pktTimestamp;
357
358 bool incrementHi32 = ((lastPktTimestamp & 0x0ffffffffll) > pktTimestamp);
359 if (incrementHi32 && (timeStart!=0)) {
360 LOG(DEBUG) << "high 32 increment!!!";
361 hi32Timestamp++;
362 }
363 pktTimestamp = (((TIMESTAMP) hi32Timestamp) << 32) | pktTimestamp;
364 lastPktTimestamp = pktTimestamp;
365
366 if (chan == 0x01f) {
367 // control reply, check to see if its ping reply
368 uint32_t word2 = usrp_to_host_u32(tmpBuf[2]);
369 if ((word2 >> 16) == ((0x01 << 8) | 0x02)) {
370 timestamp -= timestampOffset;
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400371 timestampOffset = pktTimestamp - pingTimestamp + pingOffset;
dburgessb3a0ca42011-10-12 07:44:40 +0000372 LOG(DEBUG) << "updating timestamp offset to: " << timestampOffset;
373 timestamp += timestampOffset;
374 isAligned = true;
375 }
376 continue;
377 }
378 if (chan != 0) {
379 LOG(DEBUG) << "chan: " << chan << ", timestamp: " << pktTimestamp << ", sz:" << payloadSz;
380 continue;
381 }
382 if ((word0 >> 28) & 0x04) {
383 if (underrun) *underrun = true;
384 LOG(DEBUG) << "UNDERRUN in TRX->USRP interface";
385 }
386 if (RSSI) *RSSI = (word0 >> 21) & 0x3f;
387
388 if (!isAligned) continue;
389
390 unsigned cursorStart = pktTimestamp - timeStart + dataStart;
391 while (cursorStart*2 > currDataSize) {
392 cursorStart -= currDataSize/2;
393 }
394 if (cursorStart*2 + payloadSz/2 > currDataSize) {
395 // need to circle around buffer
396 memcpy(data+cursorStart*2,tmpBuf+2,(currDataSize-cursorStart*2)*sizeof(short));
397 memcpy(data,tmpBuf+2+(currDataSize/2-cursorStart),payloadSz-(currDataSize-cursorStart*2)*sizeof(short));
398 }
399 else {
400 memcpy(data+cursorStart*2,tmpBuf+2,payloadSz);
401 }
402 if (pktTimestamp + payloadSz/2/sizeof(short) > timeEnd)
403 timeEnd = pktTimestamp+payloadSz/2/sizeof(short);
404
405 LOG(DEBUG) << "timeStart: " << timeStart << ", timeEnd: " << timeEnd << ", pktTimestamp: " << pktTimestamp;
406
407 }
408 }
409
410 // copy desired data to buf
411 unsigned bufStart = dataStart+(timestamp-timeStart);
412 if (bufStart + len < currDataSize/2) {
413 LOG(DEBUG) << "bufStart: " << bufStart;
414 memcpy(buf,data+bufStart*2,len*2*sizeof(short));
415 memset(data+bufStart*2,0,len*2*sizeof(short));
416 }
417 else {
418 LOG(DEBUG) << "len: " << len << ", currDataSize/2: " << currDataSize/2 << ", bufStart: " << bufStart;
419 unsigned firstLength = (currDataSize/2-bufStart);
420 LOG(DEBUG) << "firstLength: " << firstLength;
421 memcpy(buf,data+bufStart*2,firstLength*2*sizeof(short));
422 memset(data+bufStart*2,0,firstLength*2*sizeof(short));
423 memcpy(buf+firstLength*2,data,(len-firstLength)*2*sizeof(short));
424 memset(data,0,(len-firstLength)*2*sizeof(short));
425 }
426 dataStart = (bufStart + len) % (currDataSize/2);
427 timeStart = timestamp + len;
428
dburgessb3a0ca42011-10-12 07:44:40 +0000429 return len;
430
431#else
432 if (loopbackBufferSize < 2) return 0;
433 int numSamples = 0;
434 struct timeval currTime;
435 gettimeofday(&currTime,NULL);
436 double timeElapsed = (currTime.tv_sec - lastReadTime.tv_sec)*1.0e6 +
437 (currTime.tv_usec - lastReadTime.tv_usec);
438 if (timeElapsed < samplePeriod) {return 0;}
439 int numSamplesToRead = (int) floor(timeElapsed/samplePeriod);
440 if (numSamplesToRead < len) return 0;
441
442 if (numSamplesToRead > len) numSamplesToRead = len;
443 if (numSamplesToRead > loopbackBufferSize/2) {
444 firstRead =false;
445 numSamplesToRead = loopbackBufferSize/2;
446 }
447 memcpy(buf,loopbackBuffer,sizeof(short)*2*numSamplesToRead);
448 loopbackBufferSize -= 2*numSamplesToRead;
449 memcpy(loopbackBuffer,loopbackBuffer+2*numSamplesToRead,
450 sizeof(short)*loopbackBufferSize);
451 numSamples = numSamplesToRead;
452 if (firstRead) {
453 int new_usec = lastReadTime.tv_usec + (int) round((double) numSamplesToRead * samplePeriod);
454 lastReadTime.tv_sec = lastReadTime.tv_sec + new_usec/1000000;
455 lastReadTime.tv_usec = new_usec % 1000000;
456 }
457 else {
458 gettimeofday(&lastReadTime,NULL);
459 firstRead = true;
460 }
461 samplesRead += numSamples;
462
463 return numSamples;
464#endif
465}
466
Thomas Tsou204a9f12013-10-29 18:34:16 -0400467int USRPDevice::writeSamples(std::vector<short *> &bufs, int len,
468 bool *underrun, unsigned long long timestamp,
469 bool isControl)
dburgessb3a0ca42011-10-12 07:44:40 +0000470{
471 writeLock.lock();
472
473#ifndef SWLOOPBACK
Thomas Tsou204a9f12013-10-29 18:34:16 -0400474 if (!m_uTx)
475 return 0;
476
477 short *buf = bufs[0];
478
kurtis.heimerlc8739b82011-11-02 00:06:34 +0000479 static uint32_t outData[128*20];
Thomas Tsou204a9f12013-10-29 18:34:16 -0400480
dburgessb3a0ca42011-10-12 07:44:40 +0000481 for (int i = 0; i < len*2; i++) {
482 buf[i] = host_to_usrp_short(buf[i]);
483 }
484
485 int numWritten = 0;
486 unsigned isStart = 1;
487 unsigned RSSI = 0;
488 unsigned CHAN = (isControl) ? 0x01f : 0x00;
489 len = len*2*sizeof(short);
490 int numPkts = (int) ceil((float)len/(float)504);
491 unsigned isEnd = (numPkts < 2);
492 uint32_t *outPkt = outData;
493 int pktNum = 0;
494 while (numWritten < len) {
495 // pkt is pointer to start of a USB packet
496 uint32_t *pkt = outPkt + pktNum*128;
497 isEnd = (len - numWritten <= 504);
498 unsigned payloadLen = ((len - numWritten) < 504) ? (len-numWritten) : 504;
499 pkt[0] = (isStart << 12 | isEnd << 11 | (RSSI & 0x3f) << 5 | CHAN) << 16 | payloadLen;
500 pkt[1] = timestamp & 0x0ffffffffll;
501 memcpy(pkt+2,buf+(numWritten/sizeof(short)),payloadLen);
502 numWritten += payloadLen;
503 timestamp += payloadLen/2/sizeof(short);
504 isStart = 0;
505 pkt[0] = host_to_usrp_u32(pkt[0]);
506 pkt[1] = host_to_usrp_u32(pkt[1]);
507 pktNum++;
508 }
509 m_uTx->write((const void*) outPkt,sizeof(uint32_t)*128*numPkts,NULL);
510
511 samplesWritten += len/2/sizeof(short);
512 writeLock.unlock();
513
514 return len/2/sizeof(short);
515#else
516 int retVal = len;
517 memcpy(loopbackBuffer+loopbackBufferSize,buf,sizeof(short)*2*len);
518 samplesWritten += retVal;
519 loopbackBufferSize += retVal*2;
520
521 return retVal;
522#endif
523}
524
525bool USRPDevice::updateAlignment(TIMESTAMP timestamp)
526{
527#ifndef SWLOOPBACK
528 short data[] = {0x00,0x02,0x00,0x00};
529 uint32_t *wordPtr = (uint32_t *) data;
kurtis.heimerlc8739b82011-11-02 00:06:34 +0000530 *wordPtr = host_to_usrp_u32(*wordPtr);
dburgessb3a0ca42011-10-12 07:44:40 +0000531 bool tmpUnderrun;
Thomas Tsou204a9f12013-10-29 18:34:16 -0400532
533 std::vector<short *> buf(1, data);
534 if (writeSamples(buf, 1, &tmpUnderrun, timestamp & 0x0ffffffffll, true)) {
dburgessb3a0ca42011-10-12 07:44:40 +0000535 pingTimestamp = timestamp;
536 return true;
537 }
538 return false;
539#else
540 return true;
541#endif
542}
543
544#ifndef SWLOOPBACK
Thomas Tsou204a9f12013-10-29 18:34:16 -0400545bool USRPDevice::setTxFreq(double wFreq, size_t chan)
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000546{
547 usrp_tune_result result;
dburgessb3a0ca42011-10-12 07:44:40 +0000548
Thomas Tsou204a9f12013-10-29 18:34:16 -0400549 if (chan) {
550 LOG(ALERT) << "Invalid channel " << chan;
551 return false;
552 }
553
kurtis.heimerlb9e237e2011-11-26 03:17:59 +0000554 if (m_uTx->tune(txSubdevSpec.side, m_dbTx, wFreq, &result)) {
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000555 LOG(INFO) << "set TX: " << wFreq << std::endl
556 << " baseband freq: " << result.baseband_freq << std::endl
557 << " DDC freq: " << result.dxc_freq << std::endl
558 << " residual freq: " << result.residual_freq;
559 return true;
560 }
561 else {
kurtis.heimerle3320322011-11-28 06:26:08 +0000562 LOG(ALERT) << "set TX: " << wFreq << "failed" << std::endl
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000563 << " baseband freq: " << result.baseband_freq << std::endl
564 << " DDC freq: " << result.dxc_freq << std::endl
565 << " residual freq: " << result.residual_freq;
566 return false;
567 }
568}
569
Thomas Tsou204a9f12013-10-29 18:34:16 -0400570bool USRPDevice::setRxFreq(double wFreq, size_t chan)
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000571{
572 usrp_tune_result result;
573
Thomas Tsou204a9f12013-10-29 18:34:16 -0400574 if (chan) {
575 LOG(ALERT) << "Invalid channel " << chan;
576 return false;
577 }
578
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000579 if (m_uRx->tune(0, m_dbRx, wFreq, &result)) {
580 LOG(INFO) << "set RX: " << wFreq << std::endl
581 << " baseband freq: " << result.baseband_freq << std::endl
582 << " DDC freq: " << result.dxc_freq << std::endl
583 << " residual freq: " << result.residual_freq;
584 return true;
585 }
586 else {
kurtis.heimerle3320322011-11-28 06:26:08 +0000587 LOG(ALERT) << "set RX: " << wFreq << "failed" << std::endl
kurtis.heimerl79e71c92011-11-26 03:16:48 +0000588 << " baseband freq: " << result.baseband_freq << std::endl
589 << " DDC freq: " << result.dxc_freq << std::endl
590 << " residual freq: " << result.residual_freq;
591 return false;
592 }
593
594}
dburgessb3a0ca42011-10-12 07:44:40 +0000595
596#else
597bool USRPDevice::setTxFreq(double wFreq) { return true;};
598bool USRPDevice::setRxFreq(double wFreq) { return true;};
599#endif
kurtis.heimerl965e7572011-11-26 03:16:54 +0000600
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800601RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps,
Tom Tsoud6ae8642017-03-30 17:22:58 -0700602 size_t chans, double)
kurtis.heimerl965e7572011-11-26 03:16:54 +0000603{
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800604 return new USRPDevice(tx_sps);
kurtis.heimerl965e7572011-11-26 03:16:54 +0000605}