blob: 65d5738ccde9faf7feea715ad23faf9989d938c2 [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
kurtis.heimerl9b557832011-11-26 03:18:34 +000028bool started = false;
29
dburgessb3a0ca42011-10-12 07:44:40 +000030RadioInterface::RadioInterface(RadioDevice *wRadio,
kurtis.heimerl54354042011-11-26 03:18:49 +000031 int wReceiveOffset,
dburgessb3a0ca42011-10-12 07:44:40 +000032 int wRadioOversampling,
33 int wTransceiverOversampling,
34 GSM::Time wStartTime)
kurtis.heimerl54354042011-11-26 03:18:49 +000035 : underrun(false), sendCursor(0), rcvCursor(0), mOn(false),
36 mRadio(wRadio), receiveOffset(wReceiveOffset),
37 samplesPerSymbol(wRadioOversampling), powerScaling(1.0),
38 loadTest(false)
dburgessb3a0ca42011-10-12 07:44:40 +000039{
dburgessb3a0ca42011-10-12 07:44:40 +000040 mClock.set(wStartTime);
dburgessb3a0ca42011-10-12 07:44:40 +000041}
42
kurtis.heimerl54354042011-11-26 03:18:49 +000043
dburgessb3a0ca42011-10-12 07:44:40 +000044RadioInterface::~RadioInterface(void) {
45 if (rcvBuffer!=NULL) delete rcvBuffer;
46 //mReceiveFIFO.clear();
47}
48
49double RadioInterface::fullScaleInputValue(void) {
50 return mRadio->fullScaleInputValue();
51}
52
53double RadioInterface::fullScaleOutputValue(void) {
54 return mRadio->fullScaleOutputValue();
55}
56
57
kurtis.heimerl58d6a012011-11-26 03:17:38 +000058void RadioInterface::setPowerAttenuation(double atten)
dburgessb3a0ca42011-10-12 07:44:40 +000059{
kurtis.heimerl16c65402011-11-26 03:18:11 +000060 double rfGain, digAtten;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000061
kurtis.heimerl16c65402011-11-26 03:18:11 +000062 rfGain = mRadio->setTxGain(mRadio->maxTxGain() - atten);
63 digAtten = atten - mRadio->maxTxGain() + rfGain;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000064
65 if (digAtten < 1.0)
66 powerScaling = 1.0;
67 else
68 powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0)));
dburgessb3a0ca42011-10-12 07:44:40 +000069}
70
kurtis.heimerl9b557832011-11-26 03:18:34 +000071int RadioInterface::radioifyVector(signalVector &wVector,
72 float *retVector,
73 float scale,
74 bool zero)
dburgessb3a0ca42011-10-12 07:44:40 +000075{
kurtis.heimerl9b557832011-11-26 03:18:34 +000076 int i;
dburgessb3a0ca42011-10-12 07:44:40 +000077 signalVector::iterator itr = wVector.begin();
kurtis.heimerl9b557832011-11-26 03:18:34 +000078
79 if (zero) {
80 memset(retVector, 0, wVector.size() * 2 * sizeof(float));
81 return wVector.size();
dburgessb3a0ca42011-10-12 07:44:40 +000082 }
83
kurtis.heimerl9b557832011-11-26 03:18:34 +000084 for (i = 0; i < wVector.size(); i++) {
85 retVector[2 * i + 0] = itr->real() * scale;
86 retVector[2 * i + 1] = itr->imag() * scale;
87 itr++;
88 }
89
90 return wVector.size();
dburgessb3a0ca42011-10-12 07:44:40 +000091}
92
kurtis.heimerl9b557832011-11-26 03:18:34 +000093int RadioInterface::unRadioifyVector(float *floatVector,
94 signalVector& newVector)
dburgessb3a0ca42011-10-12 07:44:40 +000095{
kurtis.heimerl9b557832011-11-26 03:18:34 +000096 int i;
dburgessb3a0ca42011-10-12 07:44:40 +000097 signalVector::iterator itr = newVector.begin();
kurtis.heimerl9b557832011-11-26 03:18:34 +000098
99 for (i = 0; i < newVector.size(); i++) {
100 *itr++ = Complex<float>(floatVector[2 * i + 0],
101 floatVector[2 * i + 1]);
dburgessb3a0ca42011-10-12 07:44:40 +0000102 }
103
kurtis.heimerl9b557832011-11-26 03:18:34 +0000104 return newVector.size();
dburgessb3a0ca42011-10-12 07:44:40 +0000105}
106
107bool RadioInterface::tuneTx(double freq)
108{
109 return mRadio->setTxFreq(freq);
110}
111
112bool RadioInterface::tuneRx(double freq)
113{
114 return mRadio->setRxFreq(freq);
115}
116
117
118void RadioInterface::start()
119{
120 LOG(INFO) << "starting radio interface...";
Thomas Tsouf2293b82013-04-08 13:35:36 -0400121#ifdef USRP1
dburgessb3a0ca42011-10-12 07:44:40 +0000122 mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
123 (void*)this);
Thomas Tsouf2293b82013-04-08 13:35:36 -0400124#endif
dburgessb3a0ca42011-10-12 07:44:40 +0000125 writeTimestamp = mRadio->initialWriteTimestamp();
126 readTimestamp = mRadio->initialReadTimestamp();
127 mRadio->start();
128 LOG(DEBUG) << "Radio started";
129 mRadio->updateAlignment(writeTimestamp-10000);
130 mRadio->updateAlignment(writeTimestamp-10000);
131
kurtis.heimerl9b557832011-11-26 03:18:34 +0000132 sendBuffer = new float[2*2*INCHUNK*samplesPerSymbol];
133 rcvBuffer = new float[2*2*OUTCHUNK*samplesPerSymbol];
dburgessb3a0ca42011-10-12 07:44:40 +0000134
135 mOn = true;
136
137}
138
Thomas Tsouf2293b82013-04-08 13:35:36 -0400139#ifdef USRP1
dburgessb3a0ca42011-10-12 07:44:40 +0000140void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
141{
142 while (1) {
143 radioInterface->alignRadio();
144 pthread_testcancel();
145 }
146 return NULL;
147}
148
149void RadioInterface::alignRadio() {
150 sleep(60);
151 mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
152}
Thomas Tsouf2293b82013-04-08 13:35:36 -0400153#endif
dburgessb3a0ca42011-10-12 07:44:40 +0000154
155void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {
156
157 if (!mOn) return;
158
kurtis.heimerl9b557832011-11-26 03:18:34 +0000159 radioifyVector(radioBurst, sendBuffer + 2 * sendCursor, powerScaling, zeroBurst);
dburgessb3a0ca42011-10-12 07:44:40 +0000160
kurtis.heimerl9b557832011-11-26 03:18:34 +0000161 sendCursor += radioBurst.size();
dburgessb3a0ca42011-10-12 07:44:40 +0000162
163 pushBuffer();
164}
165
166void RadioInterface::driveReceiveRadio() {
167
168 if (!mOn) return;
169
170 if (mReceiveFIFO.size() > 8) return;
171
172 pullBuffer();
173
174 GSM::Time rcvClock = mClock.get();
175 rcvClock.decTN(receiveOffset);
176 unsigned tN = rcvClock.TN();
kurtis.heimerl9b557832011-11-26 03:18:34 +0000177 int rcvSz = rcvCursor;
dburgessb3a0ca42011-10-12 07:44:40 +0000178 int readSz = 0;
179 const int symbolsPerSlot = gSlotLen + 8;
180
181 // while there's enough data in receive buffer, form received
182 // GSM bursts and pass up to Transceiver
183 // Using the 157-156-156-156 symbols per timeslot format.
184 while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
185 signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
186 unRadioifyVector(rcvBuffer+readSz*2,rxVector);
187 GSM::Time tmpTime = rcvClock;
188 if (rcvClock.FN() >= 0) {
189 //LOG(DEBUG) << "FN: " << rcvClock.FN();
190 radioVector *rxBurst = NULL;
191 if (!loadTest)
192 rxBurst = new radioVector(rxVector,tmpTime);
193 else {
194 if (tN % 4 == 0)
195 rxBurst = new radioVector(*finalVec9,tmpTime);
196 else
197 rxBurst = new radioVector(*finalVec,tmpTime);
198 }
199 mReceiveFIFO.put(rxBurst);
200 }
201 mClock.incTN();
202 rcvClock.incTN();
203 //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
204 //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
205 readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
206 rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
207
208 tN = rcvClock.TN();
209 }
210
kurtis.heimerl9b557832011-11-26 03:18:34 +0000211 if (readSz > 0) {
212 rcvCursor -= readSz;
213 memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(float) * 2 * rcvCursor);
dburgessb3a0ca42011-10-12 07:44:40 +0000214 }
kurtis.heimerle724d6d2011-11-26 03:18:46 +0000215}
216
217bool RadioInterface::isUnderrun()
218{
219 bool retVal = underrun;
220 underrun = false;
221
222 return retVal;
223}
224
kurtis.heimerle724d6d2011-11-26 03:18:46 +0000225double RadioInterface::setRxGain(double dB)
226{
227 if (mRadio)
228 return mRadio->setRxGain(dB);
229 else
230 return -1;
231}
232
233double RadioInterface::getRxGain()
234{
235 if (mRadio)
236 return mRadio->getRxGain();
237 else
238 return -1;
239}