blob: 2b56f9ac112651df14b3f124518235de8a1277f8 [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
dburgessb3a0ca42011-10-12 07:44:40 +000025#include "radioInterface.h"
26#include <Logger.h>
27
28
29GSM::Time VectorQueue::nextTime() const
30{
31 GSM::Time retVal;
32 ScopedLock lock(mLock);
33 while (mQ.size()==0) mWriteSignal.wait(mLock);
34 return mQ.top()->time();
35}
36
37radioVector* VectorQueue::getStaleBurst(const GSM::Time& targTime)
38{
39 ScopedLock lock(mLock);
40 if ((mQ.size()==0)) {
41 return NULL;
42 }
43 if (mQ.top()->time() < targTime) {
44 radioVector* retVal = mQ.top();
45 mQ.pop();
46 return retVal;
47 }
48 return NULL;
49}
50
51
52radioVector* VectorQueue::getCurrentBurst(const GSM::Time& targTime)
53{
54 ScopedLock lock(mLock);
55 if ((mQ.size()==0)) {
56 return NULL;
57 }
58 if (mQ.top()->time() == targTime) {
59 radioVector* retVal = mQ.top();
60 mQ.pop();
61 return retVal;
62 }
63 return NULL;
64}
65
66
67
68RadioInterface::RadioInterface(RadioDevice *wRadio,
69 int wReceiveOffset,
70 int wRadioOversampling,
71 int wTransceiverOversampling,
72 GSM::Time wStartTime)
73
74{
75 underrun = false;
76
77 sendCursor = 0;
78 rcvCursor = 0;
79 mOn = false;
80
81 mRadio = wRadio;
82 receiveOffset = wReceiveOffset;
83 samplesPerSymbol = wRadioOversampling;
84 mClock.set(wStartTime);
kurtis.heimerlf5eef202011-11-26 03:16:45 +000085 loadTest = false;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000086 powerScaling = 1.0;
dburgessb3a0ca42011-10-12 07:44:40 +000087}
88
89RadioInterface::~RadioInterface(void) {
90 if (rcvBuffer!=NULL) delete rcvBuffer;
91 //mReceiveFIFO.clear();
92}
93
94double RadioInterface::fullScaleInputValue(void) {
95 return mRadio->fullScaleInputValue();
96}
97
98double RadioInterface::fullScaleOutputValue(void) {
99 return mRadio->fullScaleOutputValue();
100}
101
102
kurtis.heimerl58d6a012011-11-26 03:17:38 +0000103void RadioInterface::setPowerAttenuation(double atten)
dburgessb3a0ca42011-10-12 07:44:40 +0000104{
kurtis.heimerl16c65402011-11-26 03:18:11 +0000105 double rfGain, digAtten;
kurtis.heimerlee5347a2011-11-26 03:18:05 +0000106
kurtis.heimerl16c65402011-11-26 03:18:11 +0000107 rfGain = mRadio->setTxGain(mRadio->maxTxGain() - atten);
108 digAtten = atten - mRadio->maxTxGain() + rfGain;
kurtis.heimerlee5347a2011-11-26 03:18:05 +0000109
110 if (digAtten < 1.0)
111 powerScaling = 1.0;
112 else
113 powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0)));
dburgessb3a0ca42011-10-12 07:44:40 +0000114}
115
kurtis.heimerlee5347a2011-11-26 03:18:05 +0000116short *RadioInterface::radioifyVector(signalVector &wVector,
117 short *retVector,
118 float scale,
119 bool zeroOut)
dburgessb3a0ca42011-10-12 07:44:40 +0000120{
dburgessb3a0ca42011-10-12 07:44:40 +0000121 signalVector::iterator itr = wVector.begin();
122 short *shortItr = retVector;
123 if (zeroOut) {
124 while (itr < wVector.end()) {
125 *shortItr++ = 0;
126 *shortItr++ = 0;
127 itr++;
128 }
kurtis.heimerlee5347a2011-11-26 03:18:05 +0000129 } else if (scale != 1.0) {
130 while (itr < wVector.end()) {
131 *shortItr++ = (short) (itr->real() * scale);
132 *shortItr++ = (short) (itr->imag() * scale);
133 itr++;
134 }
135 } else {
dburgessb3a0ca42011-10-12 07:44:40 +0000136 while (itr < wVector.end()) {
137 *shortItr++ = (short) (itr->real());
138 *shortItr++ = (short) (itr->imag());
139 itr++;
140 }
141 }
142
143 return retVector;
dburgessb3a0ca42011-10-12 07:44:40 +0000144}
145
146void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector)
147{
148
149 signalVector::iterator itr = newVector.begin();
150 short *shortItr = shortVector;
151 while (itr < newVector.end()) {
152 *itr++ = Complex<float>(*shortItr,*(shortItr+1));
dburgessb3a0ca42011-10-12 07:44:40 +0000153 shortItr += 2;
154 }
155
156}
157
158
159bool started = false;
160
161void RadioInterface::pushBuffer(void) {
162
163 if (sendCursor < 2*INCHUNK*samplesPerSymbol) return;
164
165 // send resampleVector
166 int samplesWritten = mRadio->writeSamples(sendBuffer,
167 INCHUNK*samplesPerSymbol,
168 &underrun,
169 writeTimestamp);
kurtis.heimerlbe1decc2011-11-26 03:18:21 +0000170<<<<<<< HEAD
dburgessb3a0ca42011-10-12 07:44:40 +0000171 //LOG(DEBUG) << "writeTimestamp: " << writeTimestamp << ", samplesWritten: " << samplesWritten;
kurtis.heimerlbe1decc2011-11-26 03:18:21 +0000172=======
173>>>>>>> 957b9c5... transceiver: remove extraneous comments
dburgessb3a0ca42011-10-12 07:44:40 +0000174
175 writeTimestamp += (TIMESTAMP) samplesWritten;
176
177 if (sendCursor > 2*samplesWritten)
178 memcpy(sendBuffer,sendBuffer+samplesWritten*2,sizeof(short)*2*(sendCursor-2*samplesWritten));
179 sendCursor = sendCursor - 2*samplesWritten;
180}
181
182
183void RadioInterface::pullBuffer(void)
184{
185
186 bool localUnderrun;
187
188 // receive receiveVector
189 short* shortVector = rcvBuffer+rcvCursor;
190 //LOG(DEBUG) << "Reading USRP samples at timestamp " << readTimestamp;
191 int samplesRead = mRadio->readSamples(shortVector,OUTCHUNK*samplesPerSymbol,&overrun,readTimestamp,&localUnderrun);
192 underrun |= localUnderrun;
193 readTimestamp += (TIMESTAMP) samplesRead;
194 while (samplesRead < OUTCHUNK*samplesPerSymbol) {
195 int oldSamplesRead = samplesRead;
196 samplesRead += mRadio->readSamples(shortVector+2*samplesRead,
197 OUTCHUNK*samplesPerSymbol-samplesRead,
198 &overrun,
199 readTimestamp,
200 &localUnderrun);
201 underrun |= localUnderrun;
202 readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead);
203 }
204 //LOG(DEBUG) << "samplesRead " << samplesRead;
205
206 rcvCursor += samplesRead*2;
207
208}
209
210bool RadioInterface::tuneTx(double freq)
211{
212 return mRadio->setTxFreq(freq);
213}
214
215bool RadioInterface::tuneRx(double freq)
216{
217 return mRadio->setRxFreq(freq);
218}
219
220
221void RadioInterface::start()
222{
223 LOG(INFO) << "starting radio interface...";
224 mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
225 (void*)this);
226 writeTimestamp = mRadio->initialWriteTimestamp();
227 readTimestamp = mRadio->initialReadTimestamp();
228 mRadio->start();
229 LOG(DEBUG) << "Radio started";
230 mRadio->updateAlignment(writeTimestamp-10000);
231 mRadio->updateAlignment(writeTimestamp-10000);
232
233 sendBuffer = new short[2*2*INCHUNK*samplesPerSymbol];
234 rcvBuffer = new short[2*2*OUTCHUNK*samplesPerSymbol];
235
236 mOn = true;
237
238}
239
240void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
241{
242 while (1) {
243 radioInterface->alignRadio();
244 pthread_testcancel();
245 }
246 return NULL;
247}
248
249void RadioInterface::alignRadio() {
250 sleep(60);
251 mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
252}
253
254void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {
255
256 if (!mOn) return;
257
kurtis.heimerlee5347a2011-11-26 03:18:05 +0000258 radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst);
dburgessb3a0ca42011-10-12 07:44:40 +0000259
260 sendCursor += (radioBurst.size()*2);
261
262 pushBuffer();
263}
264
265void RadioInterface::driveReceiveRadio() {
266
267 if (!mOn) return;
268
269 if (mReceiveFIFO.size() > 8) return;
270
271 pullBuffer();
272
273 GSM::Time rcvClock = mClock.get();
274 rcvClock.decTN(receiveOffset);
275 unsigned tN = rcvClock.TN();
276 int rcvSz = rcvCursor/2;
277 int readSz = 0;
278 const int symbolsPerSlot = gSlotLen + 8;
279
280 // while there's enough data in receive buffer, form received
281 // GSM bursts and pass up to Transceiver
282 // Using the 157-156-156-156 symbols per timeslot format.
283 while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
284 signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
285 unRadioifyVector(rcvBuffer+readSz*2,rxVector);
286 GSM::Time tmpTime = rcvClock;
287 if (rcvClock.FN() >= 0) {
288 //LOG(DEBUG) << "FN: " << rcvClock.FN();
289 radioVector *rxBurst = NULL;
290 if (!loadTest)
291 rxBurst = new radioVector(rxVector,tmpTime);
292 else {
293 if (tN % 4 == 0)
294 rxBurst = new radioVector(*finalVec9,tmpTime);
295 else
296 rxBurst = new radioVector(*finalVec,tmpTime);
297 }
298 mReceiveFIFO.put(rxBurst);
299 }
300 mClock.incTN();
301 rcvClock.incTN();
302 //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
303 //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
304 readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
305 rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
306
307 tN = rcvClock.TN();
308 }
309
310 if (readSz > 0) {
311 memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor-readSz));
312 rcvCursor = rcvCursor-2*readSz;
313 }
314}
315