blob: e4d04409f857fb778eb8f13dfea47115028c79ae [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"
dburgessb3a0ca42011-10-12 07:44:40 +000028
29#include <sys/types.h>
30#include <sys/socket.h>
31
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010032extern "C" {
Pau Espin Pedroldb936b92018-09-03 16:50:49 +020033#include <osmocom/core/signal.h>
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010034#include "config_defs.h"
35}
36
Pau Espin Pedrol7dc07b92019-07-01 17:55:01 +020037#define MAX_RX_BURST_BUF_SIZE EDGE_BURST_NBITS
38
Pau Espin Pedrolddd18a52019-06-28 17:01:16 +020039struct trx_ul_burst_ind {
Pau Espin Pedrol7dc07b92019-07-01 17:55:01 +020040 float rx_burst[MAX_RX_BURST_BUF_SIZE]; /* soft bits normalized 0..1 */
Pau Espin Pedrol0e67cf22019-07-02 14:59:47 +020041 unsigned nbits; // number of symbols per slot in rxBurst, not counting guard periods
Pau Espin Pedrol07ddce52019-07-01 16:36:10 +020042 uint32_t fn; // TDMA frame number
43 uint8_t tn; // TDMA time-slot number
Pau Espin Pedrolddd18a52019-06-28 17:01:16 +020044 double rssi; // in dBFS
45 double toa; // in symbols
46 double noise; // noise level in dBFS
Pau Espin Pedrolddd18a52019-06-28 17:01:16 +020047};
48
Thomas Tsouf0782732013-10-29 15:55:47 -040049class Transceiver;
50
51/** Channel descriptor for transceiver object and channel number pair */
52struct TransceiverChannel {
53 TransceiverChannel(Transceiver *trx, int num)
54 {
55 this->trx = trx;
56 this->num = num;
57 }
58
59 ~TransceiverChannel()
60 {
61 }
62
63 Transceiver *trx;
64 size_t num;
65};
66
67/** Internal transceiver state variables */
68struct TransceiverState {
69 TransceiverState();
70 ~TransceiverState();
71
72 /* Initialize a multiframe slot in the filler table */
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010073 bool init(FillerType filler, size_t sps, float scale, size_t rtsc, unsigned rach_delay);
Thomas Tsouf0782732013-10-29 15:55:47 -040074
75 int chanType[8];
76
77 /* Last timestamp of each timeslot's channel estimate */
78 GSM::Time chanEstimateTime[8];
79
80 /* The filler table */
81 signalVector *fillerTable[102][8];
82 int fillerModulus[8];
Thomas Tsou15d743e2014-01-25 02:34:03 -050083 bool mRetrans;
Thomas Tsouf0782732013-10-29 15:55:47 -040084
85 /* Most recent channel estimate of all timeslots */
86 signalVector *chanResponse[8];
87
88 /* Most recent DFE feedback filter of all timeslots */
89 signalVector *DFEForward[8];
90 signalVector *DFEFeedback[8];
91
92 /* Most recent SNR, timing, and channel amplitude estimates */
93 float SNRestimate[8];
94 float chanRespOffset[8];
95 complex chanRespAmplitude[8];
Thomas Tsoua0179e32013-11-14 15:52:04 -050096
97 /* Received noise energy levels */
98 float mNoiseLev;
99 noiseVector mNoises;
Tom Tsoua4d1a412014-11-25 15:46:56 -0800100
101 /* Shadowed downlink attenuation */
102 int mPower;
Thomas Tsouf0782732013-10-29 15:55:47 -0400103};
104
dburgessb3a0ca42011-10-12 07:44:40 +0000105/** The Transceiver class, responsible for physical layer of basestation */
106class Transceiver {
Tom Tsou64ad7122015-05-19 18:26:31 -0700107public:
Pau Espin Pedrol7c405a02017-07-04 16:24:06 +0200108 /** Transceiver constructor
Tom Tsou64ad7122015-05-19 18:26:31 -0700109 @param wBasePort base port number of UDP sockets
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200110 @param TRXAddress IP address of the TRX, as a string
111 @param GSMcoreAddress IP address of the GSM core, as a string
Tom Tsou64ad7122015-05-19 18:26:31 -0700112 @param wSPS number of samples per GSM symbol
113 @param wTransmitLatency initial setting of transmit latency
114 @param radioInterface associated radioInterface object
115 */
116 Transceiver(int wBasePort,
Alexander Chemerise8905a02015-06-03 23:47:56 -0400117 const char *TRXAddress,
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200118 const char *GSMcoreAddress,
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800119 size_t tx_sps, size_t rx_sps, size_t chans,
Alexander Chemerise8905a02015-06-03 23:47:56 -0400120 GSM::Time wTransmitLatency,
121 RadioInterface *wRadioInterface,
Eric Wildac0487e2019-06-17 13:02:44 +0200122 double wRssiOffset, int stackSize);
Tom Tsou64ad7122015-05-19 18:26:31 -0700123
124 /** Destructor */
125 ~Transceiver();
126
127 /** Start the control loop */
Vadim Yanitskiya8b35652018-10-22 02:52:18 +0200128 bool init(FillerType filler, size_t rtsc, unsigned rach_delay,
129 bool edge, bool ext_rach);
Tom Tsou64ad7122015-05-19 18:26:31 -0700130
131 /** attach the radioInterface receive FIFO */
132 bool receiveFIFO(VectorFIFO *wFIFO, size_t chan)
133 {
134 if (chan >= mReceiveFIFO.size())
135 return false;
136
137 mReceiveFIFO[chan] = wFIFO;
138 return true;
139 }
140
141 /** accessor for number of channels */
142 size_t numChans() const { return mChans; };
143
144 /** Codes for channel combinations */
145 typedef enum {
146 FILL, ///< Channel is transmitted, but unused
147 I, ///< TCH/FS
148 II, ///< TCH/HS, idle every other slot
149 III, ///< TCH/HS
150 IV, ///< FCCH+SCH+CCCH+BCCH, uplink RACH
151 V, ///< FCCH+SCH+CCCH+BCCH+SDCCH/4+SACCH/4, uplink RACH+SDCCH/4
152 VI, ///< CCCH+BCCH, uplink RACH
153 VII, ///< SDCCH/8 + SACCH/8
154 VIII, ///< TCH/F + FACCH/F + SACCH/M
155 IX, ///< TCH/F + SACCH/M
156 X, ///< TCH/FD + SACCH/MD
157 XI, ///< PBCCH+PCCCH+PDTCH+PACCH+PTCCH
158 XII, ///< PCCCH+PDTCH+PACCH+PTCCH
159 XIII, ///< PDTCH+PACCH+PTCCH
160 NONE, ///< Channel is inactive, default
161 LOOPBACK ///< similar go VII, used in loopback testing
162 } ChannelCombination;
163
dburgessb3a0ca42011-10-12 07:44:40 +0000164private:
Thomas Tsoud647ec52013-10-29 15:17:34 -0400165 int mBasePort;
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200166 std::string mLocalAddr;
167 std::string mRemoteAddr;
dburgessb3a0ca42011-10-12 07:44:40 +0000168
Pau Espin Pedrolb9d25152019-07-01 19:03:49 +0200169 std::vector<int> mDataSockets; ///< socket for writing to/reading from GSM core
170 std::vector<int> mCtrlSockets; ///< socket for writing/reading control commands from GSM core
171 int mClockSocket; ///< socket for writing clock updates to GSM core
dburgessb3a0ca42011-10-12 07:44:40 +0000172
Thomas Tsou204a9f12013-10-29 18:34:16 -0400173 std::vector<VectorQueue> mTxPriorityQueues; ///< priority queue of transmit bursts received from GSM core
174 std::vector<VectorFIFO *> mReceiveFIFO; ///< radioInterface FIFO of receive bursts
dburgessb3a0ca42011-10-12 07:44:40 +0000175
Thomas Tsou204a9f12013-10-29 18:34:16 -0400176 std::vector<Thread *> mRxServiceLoopThreads; ///< thread to pull bursts into receive FIFO
177 Thread *mRxLowerLoopThread; ///< thread to pull bursts into receive FIFO
178 Thread *mTxLowerLoopThread; ///< thread to push bursts into transmit FIFO
179 std::vector<Thread *> mControlServiceLoopThreads; ///< thread to process control messages from GSM core
180 std::vector<Thread *> mTxPriorityQueueServiceLoopThreads; ///< thread to process transmit bursts from GSM core
dburgessb3a0ca42011-10-12 07:44:40 +0000181
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800182 GSM::Time mTransmitLatency; ///< latency between basestation clock and transmit deadline clock
183 GSM::Time mLatencyUpdateTime; ///< last time latency was updated
Pau Espin Pedrol7c405a02017-07-04 16:24:06 +0200184 GSM::Time mTransmitDeadlineClock; ///< deadline for pushing bursts into transmit FIFO
dburgessb3a0ca42011-10-12 07:44:40 +0000185 GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core
186
187 RadioInterface *mRadioInterface; ///< associated radioInterface object
188 double txFullScale; ///< full scale input to radio
189 double rxFullScale; ///< full scale output to radio
190
Alexander Chemerise8905a02015-06-03 23:47:56 -0400191 double rssiOffset; ///< RSSI to dBm conversion offset
Eric Wildac0487e2019-06-17 13:02:44 +0200192 int stackSize; ///< stack size for threads, 0 = OS default
Alexander Chemerise8905a02015-06-03 23:47:56 -0400193
dburgessb3a0ca42011-10-12 07:44:40 +0000194 /** modulate and add a burst to the transmit queue */
Thomas Tsoua2fe91a2013-11-13 22:48:11 -0500195 void addRadioVector(size_t chan, BitVector &bits,
Thomas Tsou204a9f12013-10-29 18:34:16 -0400196 int RSSI, GSM::Time &wTime);
dburgessb3a0ca42011-10-12 07:44:40 +0000197
Thomas Tsou15d743e2014-01-25 02:34:03 -0500198 /** Update filler table */
199 void updateFillerTable(size_t chan, radioVector *burst);
200
dburgessb3a0ca42011-10-12 07:44:40 +0000201 /** Push modulated burst into transmit FIFO corresponding to a particular timestamp */
202 void pushRadioVector(GSM::Time &nowTime);
203
Thomas Tsou204a9f12013-10-29 18:34:16 -0400204 /** Pull and demodulate a burst from the receive FIFO */
Pau Espin Pedrolddd18a52019-06-28 17:01:16 +0200205 bool pullRadioVector(size_t chan, struct trx_ul_burst_ind *ind);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400206
dburgessb3a0ca42011-10-12 07:44:40 +0000207 /** Set modulus for specific timeslot */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400208 void setModulus(size_t timeslot, size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000209
210 /** return the expected burst type for the specified timestamp */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400211 CorrType expectedCorrType(GSM::Time currTime, size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000212
213 /** send messages over the clock socket */
214 void writeClockInterface(void);
215
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400216 int mSPSTx; ///< number of samples per Tx symbol
217 int mSPSRx; ///< number of samples per Rx symbol
Thomas Tsou204a9f12013-10-29 18:34:16 -0400218 size_t mChans;
dburgessb3a0ca42011-10-12 07:44:40 +0000219
Vadim Yanitskiya8b35652018-10-22 02:52:18 +0200220 bool mExtRACH;
Tom Tsou64464e62016-07-01 03:46:46 -0700221 bool mEdge;
Alexander Chemeris37229202015-06-20 01:37:54 +0300222 bool mOn; ///< flag to indicate that transceiver is powered on
Pau Espin Pedrol934da482017-07-04 16:25:20 +0200223 bool mForceClockInterface; ///< flag to indicate whether IND CLOCK shall be sent unconditionally after transceiver is started
Alexander Chemeris5a068062015-06-20 01:38:47 +0300224 bool mHandover[8][8]; ///< expect handover to the timeslot/subslot
dburgessb3a0ca42011-10-12 07:44:40 +0000225 double mTxFreq; ///< the transmit frequency
226 double mRxFreq; ///< the receive frequency
dburgessb3a0ca42011-10-12 07:44:40 +0000227 unsigned mTSC; ///< the midamble sequence code
Alexander Chemeris78d1fc92016-03-19 21:16:22 +0300228 unsigned mMaxExpectedDelayAB; ///< maximum expected time-of-arrival offset in GSM symbols for Access Bursts (RACH)
229 unsigned mMaxExpectedDelayNB; ///< maximum expected time-of-arrival offset in GSM symbols for Normal Bursts
Alexander Chemerise692ce92015-06-12 00:15:31 -0400230 unsigned mWriteBurstToDiskMask; ///< debug: bitmask to indicate which timeslots to dump to disk
dburgessb3a0ca42011-10-12 07:44:40 +0000231
Thomas Tsou204a9f12013-10-29 18:34:16 -0400232 std::vector<TransceiverState> mStates;
dburgessb3a0ca42011-10-12 07:44:40 +0000233
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800234 /** Start and stop I/O threads through the control socket API */
235 bool start();
236 void stop();
237
238 /** Protect destructor accessable stop call */
239 Mutex mLock;
240
dburgessb3a0ca42011-10-12 07:44:40 +0000241protected:
Thomas Tsou204a9f12013-10-29 18:34:16 -0400242 /** drive lower receive I/O and burst generation */
243 void driveReceiveRadio();
dburgessb3a0ca42011-10-12 07:44:40 +0000244
Thomas Tsou204a9f12013-10-29 18:34:16 -0400245 /** drive demodulation of GSM bursts */
246 void driveReceiveFIFO(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000247
248 /** drive transmission of GSM bursts */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400249 void driveTxFIFO();
dburgessb3a0ca42011-10-12 07:44:40 +0000250
251 /** drive handling of control messages from GSM core */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400252 void driveControl(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000253
254 /**
255 drive modulation and sorting of GSM bursts from GSM core
256 @return true if a burst was transferred successfully
257 */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400258 bool driveTxPriorityQueue(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000259
Thomas Tsou204a9f12013-10-29 18:34:16 -0400260 friend void *RxUpperLoopAdapter(TransceiverChannel *);
Thomas Tsou92c16df2013-09-28 18:04:19 -0400261
Thomas Tsou204a9f12013-10-29 18:34:16 -0400262 friend void *TxUpperLoopAdapter(TransceiverChannel *);
dburgessb3a0ca42011-10-12 07:44:40 +0000263
Thomas Tsou204a9f12013-10-29 18:34:16 -0400264 friend void *RxLowerLoopAdapter(Transceiver *);
dburgessb3a0ca42011-10-12 07:44:40 +0000265
Thomas Tsou204a9f12013-10-29 18:34:16 -0400266 friend void *TxLowerLoopAdapter(Transceiver *);
267
268 friend void *ControlServiceLoopAdapter(TransceiverChannel *);
269
dburgessb3a0ca42011-10-12 07:44:40 +0000270
271 void reset();
kurtis.heimerl6b495a52011-11-26 03:17:21 +0000272
273 /** set priority on current thread */
Thomas Tsou7553aa92013-11-08 12:50:03 -0500274 void setPriority(float prio = 0.5) { mRadioInterface->setPriority(prio); }
kurtis.heimerl6b495a52011-11-26 03:17:21 +0000275
Pau Espin Pedrol607a4142019-07-01 13:56:17 +0200276 void logRxBurst(size_t chan, const struct trx_ul_burst_ind *bi);
dburgessb3a0ca42011-10-12 07:44:40 +0000277};
278
Thomas Tsou204a9f12013-10-29 18:34:16 -0400279void *RxUpperLoopAdapter(TransceiverChannel *);
280
Thomas Tsou92c16df2013-09-28 18:04:19 -0400281/** Main drive threads */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400282void *RxLowerLoopAdapter(Transceiver *);
283void *TxLowerLoopAdapter(Transceiver *);
dburgessb3a0ca42011-10-12 07:44:40 +0000284
285/** control message handler thread loop */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400286void *ControlServiceLoopAdapter(TransceiverChannel *);
dburgessb3a0ca42011-10-12 07:44:40 +0000287
288/** transmit queueing thread loop */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400289void *TxUpperLoopAdapter(TransceiverChannel *);