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