blob: 1dfb37c65e788d203f1a0bbd3bf53e32767d0d52 [file] [log] [blame]
dburgessb3a0ca42011-10-12 07:44:40 +00001/*
2* Copyright 2008 Free Software Foundation, Inc.
3*
4* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
5*
6* This use of this software may be subject to additional restrictions.
7* See the LEGAL file in the main directory for details.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13*/
14
15
16
17#include "sigProcLib.h"
18#include "GSMCommon.h"
19#include "LinkedLists.h"
20#include "radioDevice.h"
21
22/** samples per GSM symbol */
23#define SAMPSPERSYM 1
24#define INCHUNK (625)
25#define OUTCHUNK (625)
26
27/** class used to organize GSM bursts by GSM timestamps */
28class radioVector : public signalVector {
29
30private:
31
32 GSM::Time mTime; ///< the burst's GSM timestamp
33
34public:
35 /** constructor */
36 radioVector(const signalVector& wVector,
37 GSM::Time& wTime): signalVector(wVector),mTime(wTime) {};
38
39 /** timestamp read and write operators */
40 GSM::Time time() const { return mTime;}
41 void time(const GSM::Time& wTime) { mTime = wTime;}
42
43 /** comparison operator, used for sorting */
44 bool operator>(const radioVector& other) const {return mTime > other.mTime;}
45
46};
47
48/** a priority queue of radioVectors, i.e. GSM bursts, sorted so that earliest element is at top */
49class VectorQueue : public InterthreadPriorityQueue<radioVector> {
50
51public:
52
53 /** the top element of the queue */
54 GSM::Time nextTime() const;
55
56 /**
57 Get stale burst, if any.
58 @param targTime The target time.
59 @return Pointer to burst older than target time, removed from queue, or NULL.
60 */
61 radioVector* getStaleBurst(const GSM::Time& targTime);
62
63 /**
64 Get current burst, if any.
65 @param targTime The target time.
66 @return Pointer to burst at the target time, removed from queue, or NULL.
67 */
68 radioVector* getCurrentBurst(const GSM::Time& targTime);
69
70
71};
72
73/** a FIFO of radioVectors */
74class VectorFIFO {
75
76private:
77
78 PointerFIFO mQ;
79 Mutex mLock;
80
81public:
82
83 unsigned size() {return mQ.size();}
84
85 void put(radioVector *ptr) {ScopedLock lock(mLock); mQ.put((void*) ptr);}
86
87 radioVector *get() { ScopedLock lock(mLock); return (radioVector*) mQ.get();}
88
89};
90
91
92/** the basestation clock class */
93class RadioClock {
94
95private:
96
97 GSM::Time mClock;
98 Mutex mLock;
99 Signal updateSignal;
100
101public:
102
103 /** Set clock */
104 //void set(const GSM::Time& wTime) { ScopedLock lock(mLock); mClock = wTime; updateSignal.signal();}
105 void set(const GSM::Time& wTime) { ScopedLock lock(mLock); mClock = wTime; updateSignal.broadcast();;}
106
107 /** Increment clock */
108 //void incTN() { ScopedLock lock(mLock); mClock.incTN(); updateSignal.signal();}
109 void incTN() { ScopedLock lock(mLock); mClock.incTN(); updateSignal.broadcast();}
110
111 /** Get clock value */
112 GSM::Time get() { ScopedLock lock(mLock); return mClock; }
113
114 /** Wait until clock has changed */
115 //void wait() {ScopedLock lock(mLock); updateSignal.wait(mLock,1);}
116 // FIXME -- If we take away the timeout, a lot of threads don't start. Why?
117 void wait() {ScopedLock lock(mLock); updateSignal.wait(mLock);}
118
119};
120
121
122/** class to interface the transceiver with the USRP */
123class RadioInterface {
124
125private:
126
127 Thread mAlignRadioServiceLoopThread; ///< thread that synchronizes transmit and receive sections
128
129 VectorFIFO mReceiveFIFO; ///< FIFO that holds receive bursts
130
131 RadioDevice *mRadio; ///< the USRP object
132
133 short *sendBuffer; //[2*2*INCHUNK];
134 unsigned sendCursor;
135
136 short *rcvBuffer; //[2*2*OUTCHUNK];
137 unsigned rcvCursor;
138
139 bool underrun; ///< indicates writes to USRP are too slow
140 bool overrun; ///< indicates reads from USRP are too slow
141 TIMESTAMP writeTimestamp; ///< sample timestamp of next packet written to USRP
142 TIMESTAMP readTimestamp; ///< sample timestamp of next packet read from USRP
143
144 RadioClock mClock; ///< the basestation clock!
145
146 int samplesPerSymbol; ///< samples per GSM symbol
147 int receiveOffset; ///< offset b/w transmit and receive GSM timestamps, in timeslots
148 int mRadioOversampling;
149 int mTransceiverOversampling;
150
151 bool mOn; ///< indicates radio is on
152
153 double powerScaling;
154
155 bool loadTest;
156 int mNumARFCNs;
157 signalVector *finalVec, *finalVec9;
158
159 /** format samples to USRP */
160 short *radioifyVector(signalVector &wVector, short *shortVector, double scale, bool zeroOut);
161
162 /** format samples from USRP */
163 void unRadioifyVector(short *shortVector, signalVector &wVector);
164
165 /** push GSM bursts into the transmit buffer */
166 void pushBuffer(void);
167
168 /** pull GSM bursts from the receive buffer */
169 void pullBuffer(void);
170
171public:
172
173 /** start the interface */
174 void start();
175
176 /** constructor */
177 RadioInterface(RadioDevice* wRadio = NULL,
178 int receiveOffset = 3,
179 int wRadioOversampling = SAMPSPERSYM,
180 int wTransceiverOversampling = SAMPSPERSYM,
181 GSM::Time wStartTime = GSM::Time(0));
182
183 /** destructor */
184 ~RadioInterface();
185
186 void setSamplesPerSymbol(int wSamplesPerSymbol) {if (!mOn) samplesPerSymbol = wSamplesPerSymbol;}
187
188 int getSamplesPerSymbol() { return samplesPerSymbol;}
189
190 /** check for underrun, resets underrun value */
191 bool isUnderrun() { bool retVal = underrun; underrun = false; return retVal;}
192
193 /** attach an existing USRP to this interface */
194 void attach(RadioDevice *wRadio, int wRadioOversampling) {if (!mOn) {mRadio = wRadio; mRadioOversampling = SAMPSPERSYM;} }
195
196 /** return the receive FIFO */
197 VectorFIFO* receiveFIFO() { return &mReceiveFIFO;}
198
199 /** return the basestation clock */
200 RadioClock* getClock(void) { return &mClock;};
201
202 /** set receive gain */
203 double setRxGain(double dB) {if (mRadio) return mRadio->setRxGain(dB); else return -1;}
204
205 /** get receive gain */
206 double getRxGain(void) {if (mRadio) return mRadio->getRxGain(); else return -1;}
207
208
209 /** set transmit frequency */
210 bool tuneTx(double freq);
211
212 /** set receive frequency */
213 bool tuneRx(double freq);
214
215 /** drive transmission of GSM bursts */
216 void driveTransmitRadio(signalVector &radioBurst, bool zeroBurst);
217
218 /** drive reception of GSM bursts */
219 void driveReceiveRadio();
220
221 void setPowerAttenuation(double atten);
222
223 /** returns the full-scale transmit amplitude **/
224 double fullScaleInputValue();
225
226 /** returns the full-scale receive amplitude **/
227 double fullScaleOutputValue();
228
229
230protected:
231
232 /** drive synchronization of Tx/Rx of USRP */
233 void alignRadio();
234
235 /** reset the interface */
236 void reset();
237
238 friend void *AlignRadioServiceLoopAdapter(RadioInterface*);
239
240};
241
242/** synchronization thread loop */
243void *AlignRadioServiceLoopAdapter(RadioInterface*);