blob: 3e654b1f9ec1547c20158a4856d97b1303f8171f [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;
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.heimerl7ac54b12011-11-26 03:17:49 +0000105 mRadio->setTxGain(mRadio->maxTxGain() - atten);
dburgessb3a0ca42011-10-12 07:44:40 +0000106}
107
kurtis.heimerl7ac54b12011-11-26 03:17:49 +0000108short *RadioInterface::radioifyVector(signalVector &wVector, short *retVector, bool zeroOut)
dburgessb3a0ca42011-10-12 07:44:40 +0000109{
dburgessb3a0ca42011-10-12 07:44:40 +0000110 signalVector::iterator itr = wVector.begin();
111 short *shortItr = retVector;
112 if (zeroOut) {
113 while (itr < wVector.end()) {
114 *shortItr++ = 0;
115 *shortItr++ = 0;
116 itr++;
117 }
118 }
dburgessb3a0ca42011-10-12 07:44:40 +0000119 else {
120 while (itr < wVector.end()) {
121 *shortItr++ = (short) (itr->real());
122 *shortItr++ = (short) (itr->imag());
123 itr++;
124 }
125 }
126
127 return retVector;
dburgessb3a0ca42011-10-12 07:44:40 +0000128}
129
130void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector)
131{
132
133 signalVector::iterator itr = newVector.begin();
134 short *shortItr = shortVector;
135 while (itr < newVector.end()) {
136 *itr++ = Complex<float>(*shortItr,*(shortItr+1));
137 //LOG(DEBUG) << (*(itr-1));
138 shortItr += 2;
139 }
140
141}
142
143
144bool started = false;
145
146void RadioInterface::pushBuffer(void) {
147
148 if (sendCursor < 2*INCHUNK*samplesPerSymbol) return;
149
150 // send resampleVector
151 int samplesWritten = mRadio->writeSamples(sendBuffer,
152 INCHUNK*samplesPerSymbol,
153 &underrun,
154 writeTimestamp);
155 //LOG(DEBUG) << "writeTimestamp: " << writeTimestamp << ", samplesWritten: " << samplesWritten;
156
157 writeTimestamp += (TIMESTAMP) samplesWritten;
158
159 if (sendCursor > 2*samplesWritten)
160 memcpy(sendBuffer,sendBuffer+samplesWritten*2,sizeof(short)*2*(sendCursor-2*samplesWritten));
161 sendCursor = sendCursor - 2*samplesWritten;
162}
163
164
165void RadioInterface::pullBuffer(void)
166{
167
168 bool localUnderrun;
169
170 // receive receiveVector
171 short* shortVector = rcvBuffer+rcvCursor;
172 //LOG(DEBUG) << "Reading USRP samples at timestamp " << readTimestamp;
173 int samplesRead = mRadio->readSamples(shortVector,OUTCHUNK*samplesPerSymbol,&overrun,readTimestamp,&localUnderrun);
174 underrun |= localUnderrun;
175 readTimestamp += (TIMESTAMP) samplesRead;
176 while (samplesRead < OUTCHUNK*samplesPerSymbol) {
177 int oldSamplesRead = samplesRead;
178 samplesRead += mRadio->readSamples(shortVector+2*samplesRead,
179 OUTCHUNK*samplesPerSymbol-samplesRead,
180 &overrun,
181 readTimestamp,
182 &localUnderrun);
183 underrun |= localUnderrun;
184 readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead);
185 }
186 //LOG(DEBUG) << "samplesRead " << samplesRead;
187
188 rcvCursor += samplesRead*2;
189
190}
191
192bool RadioInterface::tuneTx(double freq)
193{
194 return mRadio->setTxFreq(freq);
195}
196
197bool RadioInterface::tuneRx(double freq)
198{
199 return mRadio->setRxFreq(freq);
200}
201
202
203void RadioInterface::start()
204{
205 LOG(INFO) << "starting radio interface...";
206 mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
207 (void*)this);
208 writeTimestamp = mRadio->initialWriteTimestamp();
209 readTimestamp = mRadio->initialReadTimestamp();
210 mRadio->start();
211 LOG(DEBUG) << "Radio started";
212 mRadio->updateAlignment(writeTimestamp-10000);
213 mRadio->updateAlignment(writeTimestamp-10000);
214
215 sendBuffer = new short[2*2*INCHUNK*samplesPerSymbol];
216 rcvBuffer = new short[2*2*OUTCHUNK*samplesPerSymbol];
217
218 mOn = true;
219
220}
221
222void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
223{
224 while (1) {
225 radioInterface->alignRadio();
226 pthread_testcancel();
227 }
228 return NULL;
229}
230
231void RadioInterface::alignRadio() {
232 sleep(60);
233 mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
234}
235
236void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {
237
238 if (!mOn) return;
239
kurtis.heimerl7ac54b12011-11-26 03:17:49 +0000240 radioifyVector(radioBurst, sendBuffer+sendCursor, zeroBurst);
dburgessb3a0ca42011-10-12 07:44:40 +0000241
242 sendCursor += (radioBurst.size()*2);
243
244 pushBuffer();
245}
246
247void RadioInterface::driveReceiveRadio() {
248
249 if (!mOn) return;
250
251 if (mReceiveFIFO.size() > 8) return;
252
253 pullBuffer();
254
255 GSM::Time rcvClock = mClock.get();
256 rcvClock.decTN(receiveOffset);
257 unsigned tN = rcvClock.TN();
258 int rcvSz = rcvCursor/2;
259 int readSz = 0;
260 const int symbolsPerSlot = gSlotLen + 8;
261
262 // while there's enough data in receive buffer, form received
263 // GSM bursts and pass up to Transceiver
264 // Using the 157-156-156-156 symbols per timeslot format.
265 while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
266 signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
267 unRadioifyVector(rcvBuffer+readSz*2,rxVector);
268 GSM::Time tmpTime = rcvClock;
269 if (rcvClock.FN() >= 0) {
270 //LOG(DEBUG) << "FN: " << rcvClock.FN();
271 radioVector *rxBurst = NULL;
272 if (!loadTest)
273 rxBurst = new radioVector(rxVector,tmpTime);
274 else {
275 if (tN % 4 == 0)
276 rxBurst = new radioVector(*finalVec9,tmpTime);
277 else
278 rxBurst = new radioVector(*finalVec,tmpTime);
279 }
280 mReceiveFIFO.put(rxBurst);
281 }
282 mClock.incTN();
283 rcvClock.incTN();
284 //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
285 //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
286 readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
287 rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
288
289 tN = rcvClock.TN();
290 }
291
292 if (readSz > 0) {
293 memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor-readSz));
294 rcvCursor = rcvCursor-2*readSz;
295 }
296}
297