blob: b733d0ed2d2cc844988a74506fc10b5086ebf4a0 [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...";
121 mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
122 (void*)this);
123 writeTimestamp = mRadio->initialWriteTimestamp();
124 readTimestamp = mRadio->initialReadTimestamp();
125 mRadio->start();
126 LOG(DEBUG) << "Radio started";
127 mRadio->updateAlignment(writeTimestamp-10000);
128 mRadio->updateAlignment(writeTimestamp-10000);
129
kurtis.heimerl9b557832011-11-26 03:18:34 +0000130 sendBuffer = new float[2*2*INCHUNK*samplesPerSymbol];
131 rcvBuffer = new float[2*2*OUTCHUNK*samplesPerSymbol];
dburgessb3a0ca42011-10-12 07:44:40 +0000132
133 mOn = true;
134
135}
136
137void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
138{
139 while (1) {
140 radioInterface->alignRadio();
141 pthread_testcancel();
142 }
143 return NULL;
144}
145
146void RadioInterface::alignRadio() {
147 sleep(60);
148 mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
149}
150
151void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {
152
153 if (!mOn) return;
154
kurtis.heimerl9b557832011-11-26 03:18:34 +0000155 radioifyVector(radioBurst, sendBuffer + 2 * sendCursor, powerScaling, zeroBurst);
dburgessb3a0ca42011-10-12 07:44:40 +0000156
kurtis.heimerl9b557832011-11-26 03:18:34 +0000157 sendCursor += radioBurst.size();
dburgessb3a0ca42011-10-12 07:44:40 +0000158
159 pushBuffer();
160}
161
162void RadioInterface::driveReceiveRadio() {
163
164 if (!mOn) return;
165
166 if (mReceiveFIFO.size() > 8) return;
167
168 pullBuffer();
169
170 GSM::Time rcvClock = mClock.get();
171 rcvClock.decTN(receiveOffset);
172 unsigned tN = rcvClock.TN();
kurtis.heimerl9b557832011-11-26 03:18:34 +0000173 int rcvSz = rcvCursor;
dburgessb3a0ca42011-10-12 07:44:40 +0000174 int readSz = 0;
175 const int symbolsPerSlot = gSlotLen + 8;
176
177 // while there's enough data in receive buffer, form received
178 // GSM bursts and pass up to Transceiver
179 // Using the 157-156-156-156 symbols per timeslot format.
180 while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
181 signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
182 unRadioifyVector(rcvBuffer+readSz*2,rxVector);
183 GSM::Time tmpTime = rcvClock;
184 if (rcvClock.FN() >= 0) {
185 //LOG(DEBUG) << "FN: " << rcvClock.FN();
186 radioVector *rxBurst = NULL;
187 if (!loadTest)
188 rxBurst = new radioVector(rxVector,tmpTime);
189 else {
190 if (tN % 4 == 0)
191 rxBurst = new radioVector(*finalVec9,tmpTime);
192 else
193 rxBurst = new radioVector(*finalVec,tmpTime);
194 }
195 mReceiveFIFO.put(rxBurst);
196 }
197 mClock.incTN();
198 rcvClock.incTN();
199 //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
200 //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
201 readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
202 rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
203
204 tN = rcvClock.TN();
205 }
206
kurtis.heimerl9b557832011-11-26 03:18:34 +0000207 if (readSz > 0) {
208 rcvCursor -= readSz;
209 memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(float) * 2 * rcvCursor);
dburgessb3a0ca42011-10-12 07:44:40 +0000210 }
kurtis.heimerle724d6d2011-11-26 03:18:46 +0000211}
212
213bool RadioInterface::isUnderrun()
214{
215 bool retVal = underrun;
216 underrun = false;
217
218 return retVal;
219}
220
221void RadioInterface::attach(RadioDevice *wRadio, int wRadioOversampling)
222{
223 if (!mOn) {
224 mRadio = wRadio;
225 mRadioOversampling = SAMPSPERSYM;
226 }
227}
228
229double RadioInterface::setRxGain(double dB)
230{
231 if (mRadio)
232 return mRadio->setRxGain(dB);
233 else
234 return -1;
235}
236
237double RadioInterface::getRxGain()
238{
239 if (mRadio)
240 return mRadio->getRxGain();
241 else
242 return -1;
243}