blob: 4e261f72cc7018874b1448195ecfc84fa4ed15d3 [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
dburgessb3a0ca42011-10-12 07:44:40 +000028RadioInterface::RadioInterface(RadioDevice *wRadio,
29 int wReceiveOffset,
30 int wRadioOversampling,
31 int wTransceiverOversampling,
32 GSM::Time wStartTime)
33
34{
35 underrun = false;
36
37 sendCursor = 0;
38 rcvCursor = 0;
39 mOn = false;
40
41 mRadio = wRadio;
42 receiveOffset = wReceiveOffset;
43 samplesPerSymbol = wRadioOversampling;
44 mClock.set(wStartTime);
kurtis.heimerlf5eef202011-11-26 03:16:45 +000045 loadTest = false;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000046 powerScaling = 1.0;
dburgessb3a0ca42011-10-12 07:44:40 +000047}
48
49RadioInterface::~RadioInterface(void) {
50 if (rcvBuffer!=NULL) delete rcvBuffer;
51 //mReceiveFIFO.clear();
52}
53
54double RadioInterface::fullScaleInputValue(void) {
55 return mRadio->fullScaleInputValue();
56}
57
58double RadioInterface::fullScaleOutputValue(void) {
59 return mRadio->fullScaleOutputValue();
60}
61
62
kurtis.heimerl58d6a012011-11-26 03:17:38 +000063void RadioInterface::setPowerAttenuation(double atten)
dburgessb3a0ca42011-10-12 07:44:40 +000064{
kurtis.heimerl16c65402011-11-26 03:18:11 +000065 double rfGain, digAtten;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000066
kurtis.heimerl16c65402011-11-26 03:18:11 +000067 rfGain = mRadio->setTxGain(mRadio->maxTxGain() - atten);
68 digAtten = atten - mRadio->maxTxGain() + rfGain;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000069
70 if (digAtten < 1.0)
71 powerScaling = 1.0;
72 else
73 powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0)));
dburgessb3a0ca42011-10-12 07:44:40 +000074}
75
kurtis.heimerlee5347a2011-11-26 03:18:05 +000076short *RadioInterface::radioifyVector(signalVector &wVector,
77 short *retVector,
78 float scale,
79 bool zeroOut)
dburgessb3a0ca42011-10-12 07:44:40 +000080{
dburgessb3a0ca42011-10-12 07:44:40 +000081 signalVector::iterator itr = wVector.begin();
82 short *shortItr = retVector;
83 if (zeroOut) {
84 while (itr < wVector.end()) {
85 *shortItr++ = 0;
86 *shortItr++ = 0;
87 itr++;
88 }
kurtis.heimerlee5347a2011-11-26 03:18:05 +000089 } else if (scale != 1.0) {
90 while (itr < wVector.end()) {
91 *shortItr++ = (short) (itr->real() * scale);
92 *shortItr++ = (short) (itr->imag() * scale);
93 itr++;
94 }
95 } else {
dburgessb3a0ca42011-10-12 07:44:40 +000096 while (itr < wVector.end()) {
97 *shortItr++ = (short) (itr->real());
98 *shortItr++ = (short) (itr->imag());
99 itr++;
100 }
101 }
102
103 return retVector;
dburgessb3a0ca42011-10-12 07:44:40 +0000104}
105
106void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector)
107{
108
109 signalVector::iterator itr = newVector.begin();
110 short *shortItr = shortVector;
111 while (itr < newVector.end()) {
112 *itr++ = Complex<float>(*shortItr,*(shortItr+1));
dburgessb3a0ca42011-10-12 07:44:40 +0000113 shortItr += 2;
114 }
115
116}
117
118
119bool started = false;
120
121void RadioInterface::pushBuffer(void) {
122
123 if (sendCursor < 2*INCHUNK*samplesPerSymbol) return;
124
125 // send resampleVector
126 int samplesWritten = mRadio->writeSamples(sendBuffer,
127 INCHUNK*samplesPerSymbol,
128 &underrun,
129 writeTimestamp);
dburgessb3a0ca42011-10-12 07:44:40 +0000130
131 writeTimestamp += (TIMESTAMP) samplesWritten;
132
133 if (sendCursor > 2*samplesWritten)
134 memcpy(sendBuffer,sendBuffer+samplesWritten*2,sizeof(short)*2*(sendCursor-2*samplesWritten));
135 sendCursor = sendCursor - 2*samplesWritten;
136}
137
138
139void RadioInterface::pullBuffer(void)
140{
141
142 bool localUnderrun;
143
144 // receive receiveVector
145 short* shortVector = rcvBuffer+rcvCursor;
146 //LOG(DEBUG) << "Reading USRP samples at timestamp " << readTimestamp;
147 int samplesRead = mRadio->readSamples(shortVector,OUTCHUNK*samplesPerSymbol,&overrun,readTimestamp,&localUnderrun);
148 underrun |= localUnderrun;
149 readTimestamp += (TIMESTAMP) samplesRead;
150 while (samplesRead < OUTCHUNK*samplesPerSymbol) {
151 int oldSamplesRead = samplesRead;
152 samplesRead += mRadio->readSamples(shortVector+2*samplesRead,
153 OUTCHUNK*samplesPerSymbol-samplesRead,
154 &overrun,
155 readTimestamp,
156 &localUnderrun);
157 underrun |= localUnderrun;
158 readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead);
159 }
160 //LOG(DEBUG) << "samplesRead " << samplesRead;
161
162 rcvCursor += samplesRead*2;
163
164}
165
166bool RadioInterface::tuneTx(double freq)
167{
168 return mRadio->setTxFreq(freq);
169}
170
171bool RadioInterface::tuneRx(double freq)
172{
173 return mRadio->setRxFreq(freq);
174}
175
176
177void RadioInterface::start()
178{
179 LOG(INFO) << "starting radio interface...";
180 mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
181 (void*)this);
182 writeTimestamp = mRadio->initialWriteTimestamp();
183 readTimestamp = mRadio->initialReadTimestamp();
184 mRadio->start();
185 LOG(DEBUG) << "Radio started";
186 mRadio->updateAlignment(writeTimestamp-10000);
187 mRadio->updateAlignment(writeTimestamp-10000);
188
189 sendBuffer = new short[2*2*INCHUNK*samplesPerSymbol];
190 rcvBuffer = new short[2*2*OUTCHUNK*samplesPerSymbol];
191
192 mOn = true;
193
194}
195
196void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
197{
198 while (1) {
199 radioInterface->alignRadio();
200 pthread_testcancel();
201 }
202 return NULL;
203}
204
205void RadioInterface::alignRadio() {
206 sleep(60);
207 mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
208}
209
210void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {
211
212 if (!mOn) return;
213
kurtis.heimerlee5347a2011-11-26 03:18:05 +0000214 radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst);
dburgessb3a0ca42011-10-12 07:44:40 +0000215
216 sendCursor += (radioBurst.size()*2);
217
218 pushBuffer();
219}
220
221void RadioInterface::driveReceiveRadio() {
222
223 if (!mOn) return;
224
225 if (mReceiveFIFO.size() > 8) return;
226
227 pullBuffer();
228
229 GSM::Time rcvClock = mClock.get();
230 rcvClock.decTN(receiveOffset);
231 unsigned tN = rcvClock.TN();
232 int rcvSz = rcvCursor/2;
233 int readSz = 0;
234 const int symbolsPerSlot = gSlotLen + 8;
235
236 // while there's enough data in receive buffer, form received
237 // GSM bursts and pass up to Transceiver
238 // Using the 157-156-156-156 symbols per timeslot format.
239 while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
240 signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
241 unRadioifyVector(rcvBuffer+readSz*2,rxVector);
242 GSM::Time tmpTime = rcvClock;
243 if (rcvClock.FN() >= 0) {
244 //LOG(DEBUG) << "FN: " << rcvClock.FN();
245 radioVector *rxBurst = NULL;
246 if (!loadTest)
247 rxBurst = new radioVector(rxVector,tmpTime);
248 else {
249 if (tN % 4 == 0)
250 rxBurst = new radioVector(*finalVec9,tmpTime);
251 else
252 rxBurst = new radioVector(*finalVec,tmpTime);
253 }
254 mReceiveFIFO.put(rxBurst);
255 }
256 mClock.incTN();
257 rcvClock.incTN();
258 //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
259 //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
260 readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
261 rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
262
263 tN = rcvClock.TN();
264 }
265
266 if (readSz > 0) {
267 memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor-readSz));
268 rcvCursor = rcvCursor-2*readSz;
269 }
270}
271