blob: a3c933fa1eb8e7e3513bfe86cc725f2e53af1547 [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,
31 int wReceiveOffset,
32 int wRadioOversampling,
33 int wTransceiverOversampling,
34 GSM::Time wStartTime)
35
36{
37 underrun = false;
38
39 sendCursor = 0;
40 rcvCursor = 0;
41 mOn = false;
42
43 mRadio = wRadio;
44 receiveOffset = wReceiveOffset;
45 samplesPerSymbol = wRadioOversampling;
46 mClock.set(wStartTime);
kurtis.heimerlf5eef202011-11-26 03:16:45 +000047 loadTest = false;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000048 powerScaling = 1.0;
dburgessb3a0ca42011-10-12 07:44:40 +000049}
50
51RadioInterface::~RadioInterface(void) {
52 if (rcvBuffer!=NULL) delete rcvBuffer;
53 //mReceiveFIFO.clear();
54}
55
56double RadioInterface::fullScaleInputValue(void) {
57 return mRadio->fullScaleInputValue();
58}
59
60double RadioInterface::fullScaleOutputValue(void) {
61 return mRadio->fullScaleOutputValue();
62}
63
64
kurtis.heimerl58d6a012011-11-26 03:17:38 +000065void RadioInterface::setPowerAttenuation(double atten)
dburgessb3a0ca42011-10-12 07:44:40 +000066{
kurtis.heimerl16c65402011-11-26 03:18:11 +000067 double rfGain, digAtten;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000068
kurtis.heimerl16c65402011-11-26 03:18:11 +000069 rfGain = mRadio->setTxGain(mRadio->maxTxGain() - atten);
70 digAtten = atten - mRadio->maxTxGain() + rfGain;
kurtis.heimerlee5347a2011-11-26 03:18:05 +000071
72 if (digAtten < 1.0)
73 powerScaling = 1.0;
74 else
75 powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0)));
dburgessb3a0ca42011-10-12 07:44:40 +000076}
77
kurtis.heimerl9b557832011-11-26 03:18:34 +000078int RadioInterface::radioifyVector(signalVector &wVector,
79 float *retVector,
80 float scale,
81 bool zero)
dburgessb3a0ca42011-10-12 07:44:40 +000082{
kurtis.heimerl9b557832011-11-26 03:18:34 +000083 int i;
dburgessb3a0ca42011-10-12 07:44:40 +000084 signalVector::iterator itr = wVector.begin();
kurtis.heimerl9b557832011-11-26 03:18:34 +000085
86 if (zero) {
87 memset(retVector, 0, wVector.size() * 2 * sizeof(float));
88 return wVector.size();
dburgessb3a0ca42011-10-12 07:44:40 +000089 }
90
kurtis.heimerl9b557832011-11-26 03:18:34 +000091 for (i = 0; i < wVector.size(); i++) {
92 retVector[2 * i + 0] = itr->real() * scale;
93 retVector[2 * i + 1] = itr->imag() * scale;
94 itr++;
95 }
96
97 return wVector.size();
dburgessb3a0ca42011-10-12 07:44:40 +000098}
99
kurtis.heimerl9b557832011-11-26 03:18:34 +0000100int RadioInterface::unRadioifyVector(float *floatVector,
101 signalVector& newVector)
dburgessb3a0ca42011-10-12 07:44:40 +0000102{
kurtis.heimerl9b557832011-11-26 03:18:34 +0000103 int i;
dburgessb3a0ca42011-10-12 07:44:40 +0000104 signalVector::iterator itr = newVector.begin();
kurtis.heimerl9b557832011-11-26 03:18:34 +0000105
106 for (i = 0; i < newVector.size(); i++) {
107 *itr++ = Complex<float>(floatVector[2 * i + 0],
108 floatVector[2 * i + 1]);
dburgessb3a0ca42011-10-12 07:44:40 +0000109 }
110
kurtis.heimerl9b557832011-11-26 03:18:34 +0000111 return newVector.size();
dburgessb3a0ca42011-10-12 07:44:40 +0000112}
113
114bool RadioInterface::tuneTx(double freq)
115{
116 return mRadio->setTxFreq(freq);
117}
118
119bool RadioInterface::tuneRx(double freq)
120{
121 return mRadio->setRxFreq(freq);
122}
123
124
125void RadioInterface::start()
126{
127 LOG(INFO) << "starting radio interface...";
128 mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
129 (void*)this);
130 writeTimestamp = mRadio->initialWriteTimestamp();
131 readTimestamp = mRadio->initialReadTimestamp();
132 mRadio->start();
133 LOG(DEBUG) << "Radio started";
134 mRadio->updateAlignment(writeTimestamp-10000);
135 mRadio->updateAlignment(writeTimestamp-10000);
136
kurtis.heimerl9b557832011-11-26 03:18:34 +0000137 sendBuffer = new float[2*2*INCHUNK*samplesPerSymbol];
138 rcvBuffer = new float[2*2*OUTCHUNK*samplesPerSymbol];
dburgessb3a0ca42011-10-12 07:44:40 +0000139
140 mOn = true;
141
142}
143
144void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
145{
146 while (1) {
147 radioInterface->alignRadio();
148 pthread_testcancel();
149 }
150 return NULL;
151}
152
153void RadioInterface::alignRadio() {
154 sleep(60);
155 mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
156}
157
158void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {
159
160 if (!mOn) return;
161
kurtis.heimerl9b557832011-11-26 03:18:34 +0000162 radioifyVector(radioBurst, sendBuffer + 2 * sendCursor, powerScaling, zeroBurst);
dburgessb3a0ca42011-10-12 07:44:40 +0000163
kurtis.heimerl9b557832011-11-26 03:18:34 +0000164 sendCursor += radioBurst.size();
dburgessb3a0ca42011-10-12 07:44:40 +0000165
166 pushBuffer();
167}
168
169void RadioInterface::driveReceiveRadio() {
170
171 if (!mOn) return;
172
173 if (mReceiveFIFO.size() > 8) return;
174
175 pullBuffer();
176
177 GSM::Time rcvClock = mClock.get();
178 rcvClock.decTN(receiveOffset);
179 unsigned tN = rcvClock.TN();
kurtis.heimerl9b557832011-11-26 03:18:34 +0000180 int rcvSz = rcvCursor;
dburgessb3a0ca42011-10-12 07:44:40 +0000181 int readSz = 0;
182 const int symbolsPerSlot = gSlotLen + 8;
183
184 // while there's enough data in receive buffer, form received
185 // GSM bursts and pass up to Transceiver
186 // Using the 157-156-156-156 symbols per timeslot format.
187 while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
188 signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
189 unRadioifyVector(rcvBuffer+readSz*2,rxVector);
190 GSM::Time tmpTime = rcvClock;
191 if (rcvClock.FN() >= 0) {
192 //LOG(DEBUG) << "FN: " << rcvClock.FN();
193 radioVector *rxBurst = NULL;
194 if (!loadTest)
195 rxBurst = new radioVector(rxVector,tmpTime);
196 else {
197 if (tN % 4 == 0)
198 rxBurst = new radioVector(*finalVec9,tmpTime);
199 else
200 rxBurst = new radioVector(*finalVec,tmpTime);
201 }
202 mReceiveFIFO.put(rxBurst);
203 }
204 mClock.incTN();
205 rcvClock.incTN();
206 //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
207 //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
208 readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
209 rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
210
211 tN = rcvClock.TN();
212 }
213
kurtis.heimerl9b557832011-11-26 03:18:34 +0000214 if (readSz > 0) {
215 rcvCursor -= readSz;
216 memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(float) * 2 * rcvCursor);
dburgessb3a0ca42011-10-12 07:44:40 +0000217 }
kurtis.heimerle724d6d2011-11-26 03:18:46 +0000218}
219
220bool RadioInterface::isUnderrun()
221{
222 bool retVal = underrun;
223 underrun = false;
224
225 return retVal;
226}
227
228void RadioInterface::attach(RadioDevice *wRadio, int wRadioOversampling)
229{
230 if (!mOn) {
231 mRadio = wRadio;
232 mRadioOversampling = SAMPSPERSYM;
233 }
234}
235
236double RadioInterface::setRxGain(double dB)
237{
238 if (mRadio)
239 return mRadio->setRxGain(dB);
240 else
241 return -1;
242}
243
244double RadioInterface::getRxGain()
245{
246 if (mRadio)
247 return mRadio->getRxGain();
248 else
249 return -1;
250}