blob: c981059bfa618af26dd309e4593f1476a37b36a5 [file] [log] [blame]
dburgessb3a0ca42011-10-12 07:44:40 +00001/*
2* Copyright 2008 Free Software Foundation, Inc.
3*
4* This software is distributed under the terms of the GNU 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 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 General Public License for more details.
19
20 You should have received a copy of the GNU 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 "Interthread.h"
27#include "GSMCommon.h"
28#include "Sockets.h"
29
30#include <sys/types.h>
31#include <sys/socket.h>
32
Thomas Tsouf0782732013-10-29 15:55:47 -040033class Transceiver;
34
35/** Channel descriptor for transceiver object and channel number pair */
36struct TransceiverChannel {
37 TransceiverChannel(Transceiver *trx, int num)
38 {
39 this->trx = trx;
40 this->num = num;
41 }
42
43 ~TransceiverChannel()
44 {
45 }
46
47 Transceiver *trx;
48 size_t num;
49};
50
51/** Internal transceiver state variables */
52struct TransceiverState {
53 TransceiverState();
54 ~TransceiverState();
55
56 /* Initialize a multiframe slot in the filler table */
Tom Tsou64ad7122015-05-19 18:26:31 -070057 bool init(int filler, size_t sps, float scale, size_t rtsc);
Thomas Tsouf0782732013-10-29 15:55:47 -040058
59 int chanType[8];
60
61 /* Last timestamp of each timeslot's channel estimate */
62 GSM::Time chanEstimateTime[8];
63
64 /* The filler table */
65 signalVector *fillerTable[102][8];
66 int fillerModulus[8];
Thomas Tsou15d743e2014-01-25 02:34:03 -050067 bool mRetrans;
Thomas Tsouf0782732013-10-29 15:55:47 -040068
69 /* Most recent channel estimate of all timeslots */
70 signalVector *chanResponse[8];
71
72 /* Most recent DFE feedback filter of all timeslots */
73 signalVector *DFEForward[8];
74 signalVector *DFEFeedback[8];
75
76 /* Most recent SNR, timing, and channel amplitude estimates */
77 float SNRestimate[8];
78 float chanRespOffset[8];
79 complex chanRespAmplitude[8];
Thomas Tsoua0179e32013-11-14 15:52:04 -050080
81 /* Received noise energy levels */
82 float mNoiseLev;
83 noiseVector mNoises;
Tom Tsoua4d1a412014-11-25 15:46:56 -080084
85 /* Shadowed downlink attenuation */
86 int mPower;
Thomas Tsouf0782732013-10-29 15:55:47 -040087};
88
dburgessb3a0ca42011-10-12 07:44:40 +000089/** The Transceiver class, responsible for physical layer of basestation */
90class Transceiver {
Tom Tsou64ad7122015-05-19 18:26:31 -070091public:
92 /** Transceiver constructor
93 @param wBasePort base port number of UDP sockets
94 @param TRXAddress IP address of the TRX manager, as a string
95 @param wSPS number of samples per GSM symbol
96 @param wTransmitLatency initial setting of transmit latency
97 @param radioInterface associated radioInterface object
98 */
99 Transceiver(int wBasePort,
Alexander Chemerisfdbf9142015-06-03 23:47:56 -0400100 const char *TRXAddress,
101 size_t wSPS, size_t chans,
102 GSM::Time wTransmitLatency,
103 RadioInterface *wRadioInterface,
104 double wRssiOffset);
Tom Tsou64ad7122015-05-19 18:26:31 -0700105
106 /** Destructor */
107 ~Transceiver();
108
109 /** Start the control loop */
110 bool init(int filler, size_t rtsc);
111
112 /** attach the radioInterface receive FIFO */
113 bool receiveFIFO(VectorFIFO *wFIFO, size_t chan)
114 {
115 if (chan >= mReceiveFIFO.size())
116 return false;
117
118 mReceiveFIFO[chan] = wFIFO;
119 return true;
120 }
121
122 /** accessor for number of channels */
123 size_t numChans() const { return mChans; };
124
125 /** Codes for channel combinations */
126 typedef enum {
127 FILL, ///< Channel is transmitted, but unused
128 I, ///< TCH/FS
129 II, ///< TCH/HS, idle every other slot
130 III, ///< TCH/HS
131 IV, ///< FCCH+SCH+CCCH+BCCH, uplink RACH
132 V, ///< FCCH+SCH+CCCH+BCCH+SDCCH/4+SACCH/4, uplink RACH+SDCCH/4
133 VI, ///< CCCH+BCCH, uplink RACH
134 VII, ///< SDCCH/8 + SACCH/8
135 VIII, ///< TCH/F + FACCH/F + SACCH/M
136 IX, ///< TCH/F + SACCH/M
137 X, ///< TCH/FD + SACCH/MD
138 XI, ///< PBCCH+PCCCH+PDTCH+PACCH+PTCCH
139 XII, ///< PCCCH+PDTCH+PACCH+PTCCH
140 XIII, ///< PDTCH+PACCH+PTCCH
141 NONE, ///< Channel is inactive, default
142 LOOPBACK ///< similar go VII, used in loopback testing
143 } ChannelCombination;
144
145 /** Codes for burst types of received bursts*/
146 typedef enum {
147 OFF, ///< timeslot is off
148 TSC, ///< timeslot should contain a normal burst
149 RACH, ///< timeslot should contain an access burst
150 IDLE ///< timeslot is an idle (or dummy) burst
151 } CorrType;
152
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400153 enum FillerType {
Tom Tsou64ad7122015-05-19 18:26:31 -0700154 FILLER_DUMMY,
155 FILLER_ZERO,
156 FILLER_RAND,
157 };
158
dburgessb3a0ca42011-10-12 07:44:40 +0000159private:
Thomas Tsoud647ec52013-10-29 15:17:34 -0400160 int mBasePort;
161 std::string mAddr;
dburgessb3a0ca42011-10-12 07:44:40 +0000162
Thomas Tsou204a9f12013-10-29 18:34:16 -0400163 std::vector<UDPSocket *> mDataSockets; ///< socket for writing to/reading from GSM core
164 std::vector<UDPSocket *> mCtrlSockets; ///< socket for writing/reading control commands from GSM core
Alexander Chemeriseac726b2015-06-30 22:37:12 -0400165 std::vector<UDPSocket *> mClockSockets; ///< socket for writing clock updates to GSM core
dburgessb3a0ca42011-10-12 07:44:40 +0000166
Thomas Tsou204a9f12013-10-29 18:34:16 -0400167 std::vector<VectorQueue> mTxPriorityQueues; ///< priority queue of transmit bursts received from GSM core
168 std::vector<VectorFIFO *> mReceiveFIFO; ///< radioInterface FIFO of receive bursts
dburgessb3a0ca42011-10-12 07:44:40 +0000169
Thomas Tsou204a9f12013-10-29 18:34:16 -0400170 std::vector<Thread *> mRxServiceLoopThreads; ///< thread to pull bursts into receive FIFO
171 Thread *mRxLowerLoopThread; ///< thread to pull bursts into receive FIFO
172 Thread *mTxLowerLoopThread; ///< thread to push bursts into transmit FIFO
173 std::vector<Thread *> mControlServiceLoopThreads; ///< thread to process control messages from GSM core
174 std::vector<Thread *> mTxPriorityQueueServiceLoopThreads; ///< thread to process transmit bursts from GSM core
dburgessb3a0ca42011-10-12 07:44:40 +0000175
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800176 GSM::Time mTransmitLatency; ///< latency between basestation clock and transmit deadline clock
177 GSM::Time mLatencyUpdateTime; ///< last time latency was updated
dburgessb3a0ca42011-10-12 07:44:40 +0000178 GSM::Time mTransmitDeadlineClock; ///< deadline for pushing bursts into transmit FIFO
179 GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core
180
181 RadioInterface *mRadioInterface; ///< associated radioInterface object
182 double txFullScale; ///< full scale input to radio
183 double rxFullScale; ///< full scale output to radio
184
Alexander Chemerisfdbf9142015-06-03 23:47:56 -0400185 double rssiOffset; ///< RSSI to dBm conversion offset
186
dburgessb3a0ca42011-10-12 07:44:40 +0000187 /** modulate and add a burst to the transmit queue */
Thomas Tsoua2fe91a2013-11-13 22:48:11 -0500188 void addRadioVector(size_t chan, BitVector &bits,
Thomas Tsou204a9f12013-10-29 18:34:16 -0400189 int RSSI, GSM::Time &wTime);
dburgessb3a0ca42011-10-12 07:44:40 +0000190
Thomas Tsou15d743e2014-01-25 02:34:03 -0500191 /** Update filler table */
192 void updateFillerTable(size_t chan, radioVector *burst);
193
dburgessb3a0ca42011-10-12 07:44:40 +0000194 /** Push modulated burst into transmit FIFO corresponding to a particular timestamp */
195 void pushRadioVector(GSM::Time &nowTime);
196
Thomas Tsou204a9f12013-10-29 18:34:16 -0400197 /** Pull and demodulate a burst from the receive FIFO */
Alexander Chemerisf0d8a582015-06-08 22:46:38 -0400198 SoftVector *pullRadioVector(GSM::Time &wTime, double &RSSI, bool &isRssiValid,
Alexander Chemeris37bbfa22015-06-04 00:14:51 -0400199 double &timingOffset, double &noise,
200 size_t chan = 0);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400201
dburgessb3a0ca42011-10-12 07:44:40 +0000202 /** Set modulus for specific timeslot */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400203 void setModulus(size_t timeslot, size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000204
205 /** return the expected burst type for the specified timestamp */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400206 CorrType expectedCorrType(GSM::Time currTime, size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000207
208 /** send messages over the clock socket */
209 void writeClockInterface(void);
210
Thomas Tsou30421a72013-11-13 23:14:48 -0500211 /** Detect RACH bursts */
Alexander Chemerisded68da2015-06-04 15:39:41 -0400212 int detectRACH(TransceiverState *state,
213 signalVector &burst,
214 complex &amp, float &toa);
Thomas Tsou30421a72013-11-13 23:14:48 -0500215
216 /** Detect normal bursts */
Alexander Chemerisded68da2015-06-04 15:39:41 -0400217 int detectTSC(TransceiverState *state,
218 signalVector &burst,
219 complex &amp, float &toa, GSM::Time &time);
Thomas Tsou30421a72013-11-13 23:14:48 -0500220
221 /** Demodulat burst and output soft bits */
222 SoftVector *demodulate(TransceiverState *state,
223 signalVector &burst, complex amp,
224 float toa, size_t tn, bool equalize);
225
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400226 int mSPSTx; ///< number of samples per Tx symbol
227 int mSPSRx; ///< number of samples per Rx symbol
Thomas Tsou204a9f12013-10-29 18:34:16 -0400228 size_t mChans;
dburgessb3a0ca42011-10-12 07:44:40 +0000229
Alexander Chemeris139c8452015-06-20 01:37:54 +0300230 bool mOn; ///< flag to indicate that transceiver is powered on
Alexander Chemeris3ac1cbf2015-06-20 01:38:47 +0300231 bool mHandover[8][8]; ///< expect handover to the timeslot/subslot
dburgessb3a0ca42011-10-12 07:44:40 +0000232 double mTxFreq; ///< the transmit frequency
233 double mRxFreq; ///< the receive frequency
dburgessb3a0ca42011-10-12 07:44:40 +0000234 unsigned mTSC; ///< the midamble sequence code
Alexander Chemeris139c8452015-06-20 01:37:54 +0300235 unsigned mMaxExpectedDelay; ///< maximum expected time-of-arrival offset in GSM symbols
Alexander Chemerisf2bdd1a2015-06-12 00:15:31 -0400236 unsigned mWriteBurstToDiskMask; ///< debug: bitmask to indicate which timeslots to dump to disk
dburgessb3a0ca42011-10-12 07:44:40 +0000237
Thomas Tsou204a9f12013-10-29 18:34:16 -0400238 std::vector<TransceiverState> mStates;
dburgessb3a0ca42011-10-12 07:44:40 +0000239
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800240 /** Start and stop I/O threads through the control socket API */
241 bool start();
242 void stop();
243
244 /** Protect destructor accessable stop call */
245 Mutex mLock;
246
dburgessb3a0ca42011-10-12 07:44:40 +0000247protected:
Thomas Tsou204a9f12013-10-29 18:34:16 -0400248 /** drive lower receive I/O and burst generation */
249 void driveReceiveRadio();
dburgessb3a0ca42011-10-12 07:44:40 +0000250
Thomas Tsou204a9f12013-10-29 18:34:16 -0400251 /** drive demodulation of GSM bursts */
252 void driveReceiveFIFO(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000253
254 /** drive transmission of GSM bursts */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400255 void driveTxFIFO();
dburgessb3a0ca42011-10-12 07:44:40 +0000256
257 /** drive handling of control messages from GSM core */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400258 void driveControl(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000259
260 /**
261 drive modulation and sorting of GSM bursts from GSM core
262 @return true if a burst was transferred successfully
263 */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400264 bool driveTxPriorityQueue(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000265
Thomas Tsou204a9f12013-10-29 18:34:16 -0400266 friend void *RxUpperLoopAdapter(TransceiverChannel *);
Thomas Tsou92c16df2013-09-28 18:04:19 -0400267
Thomas Tsou204a9f12013-10-29 18:34:16 -0400268 friend void *TxUpperLoopAdapter(TransceiverChannel *);
dburgessb3a0ca42011-10-12 07:44:40 +0000269
Thomas Tsou204a9f12013-10-29 18:34:16 -0400270 friend void *RxLowerLoopAdapter(Transceiver *);
dburgessb3a0ca42011-10-12 07:44:40 +0000271
Thomas Tsou204a9f12013-10-29 18:34:16 -0400272 friend void *TxLowerLoopAdapter(Transceiver *);
273
274 friend void *ControlServiceLoopAdapter(TransceiverChannel *);
275
dburgessb3a0ca42011-10-12 07:44:40 +0000276
277 void reset();
kurtis.heimerl6b495a52011-11-26 03:17:21 +0000278
279 /** set priority on current thread */
Thomas Tsou7553aa92013-11-08 12:50:03 -0500280 void setPriority(float prio = 0.5) { mRadioInterface->setPriority(prio); }
kurtis.heimerl6b495a52011-11-26 03:17:21 +0000281
dburgessb3a0ca42011-10-12 07:44:40 +0000282};
283
Thomas Tsou204a9f12013-10-29 18:34:16 -0400284void *RxUpperLoopAdapter(TransceiverChannel *);
285
Thomas Tsou92c16df2013-09-28 18:04:19 -0400286/** Main drive threads */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400287void *RxLowerLoopAdapter(Transceiver *);
288void *TxLowerLoopAdapter(Transceiver *);
dburgessb3a0ca42011-10-12 07:44:40 +0000289
290/** control message handler thread loop */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400291void *ControlServiceLoopAdapter(TransceiverChannel *);
dburgessb3a0ca42011-10-12 07:44:40 +0000292
293/** transmit queueing thread loop */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400294void *TxUpperLoopAdapter(TransceiverChannel *);
dburgessb3a0ca42011-10-12 07:44:40 +0000295