blob: ed063dde1ebe3bd5d604a0269b24edd08a1e0269 [file] [log] [blame]
dburgessb3a0ca42011-10-12 07:44:40 +00001/*
2* Copyright 2008 Free Software Foundation, Inc.
3*
Pau Espin Pedrol21d03d32019-07-22 12:05:52 +02004* SPDX-License-Identifier: GPL-3.0+
5*
dburgessb3a0ca42011-10-12 07:44:40 +00006* This software is distributed under the terms of the GNU Public License.
7* See the COPYING file in the main directory for details.
8*
9* This use of this software may be subject to additional restrictions.
10* See the LEGAL file in the main directory for details.
11
12 This program is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
24
25*/
26
dburgessb3a0ca42011-10-12 07:44:40 +000027#include "radioInterface.h"
28#include "Interthread.h"
29#include "GSMCommon.h"
dburgessb3a0ca42011-10-12 07:44:40 +000030
31#include <sys/types.h>
32#include <sys/socket.h>
33
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010034extern "C" {
Pau Espin Pedroldb936b92018-09-03 16:50:49 +020035#include <osmocom/core/signal.h>
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010036#include "config_defs.h"
37}
38
Thomas Tsouf0782732013-10-29 15:55:47 -040039class Transceiver;
40
41/** Channel descriptor for transceiver object and channel number pair */
Pau Espin Pedrol720b9122019-07-22 18:10:52 +020042struct TrxChanThParams {
43 Transceiver *trx;
44 size_t num;
Thomas Tsouf0782732013-10-29 15:55:47 -040045};
46
47/** Internal transceiver state variables */
48struct TransceiverState {
49 TransceiverState();
50 ~TransceiverState();
51
52 /* Initialize a multiframe slot in the filler table */
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010053 bool init(FillerType filler, size_t sps, float scale, size_t rtsc, unsigned rach_delay);
Thomas Tsouf0782732013-10-29 15:55:47 -040054
55 int chanType[8];
56
57 /* Last timestamp of each timeslot's channel estimate */
58 GSM::Time chanEstimateTime[8];
59
60 /* The filler table */
61 signalVector *fillerTable[102][8];
62 int fillerModulus[8];
Thomas Tsou15d743e2014-01-25 02:34:03 -050063 bool mRetrans;
Thomas Tsouf0782732013-10-29 15:55:47 -040064
65 /* Most recent channel estimate of all timeslots */
66 signalVector *chanResponse[8];
67
68 /* Most recent DFE feedback filter of all timeslots */
69 signalVector *DFEForward[8];
70 signalVector *DFEFeedback[8];
71
72 /* Most recent SNR, timing, and channel amplitude estimates */
73 float SNRestimate[8];
74 float chanRespOffset[8];
75 complex chanRespAmplitude[8];
Thomas Tsoua0179e32013-11-14 15:52:04 -050076
77 /* Received noise energy levels */
78 float mNoiseLev;
79 noiseVector mNoises;
Tom Tsoua4d1a412014-11-25 15:46:56 -080080
81 /* Shadowed downlink attenuation */
82 int mPower;
Thomas Tsouf0782732013-10-29 15:55:47 -040083};
84
dburgessb3a0ca42011-10-12 07:44:40 +000085/** The Transceiver class, responsible for physical layer of basestation */
86class Transceiver {
Tom Tsou64ad7122015-05-19 18:26:31 -070087public:
Pau Espin Pedrol7c405a02017-07-04 16:24:06 +020088 /** Transceiver constructor
Tom Tsou64ad7122015-05-19 18:26:31 -070089 @param wBasePort base port number of UDP sockets
Pau Espin Pedrol8c800952017-08-16 16:53:23 +020090 @param TRXAddress IP address of the TRX, as a string
91 @param GSMcoreAddress IP address of the GSM core, as a string
Tom Tsou64ad7122015-05-19 18:26:31 -070092 @param wSPS number of samples per GSM symbol
93 @param wTransmitLatency initial setting of transmit latency
94 @param radioInterface associated radioInterface object
95 */
96 Transceiver(int wBasePort,
Alexander Chemerise8905a02015-06-03 23:47:56 -040097 const char *TRXAddress,
Pau Espin Pedrol8c800952017-08-16 16:53:23 +020098 const char *GSMcoreAddress,
Tom Tsou5cd70dc2016-03-06 01:28:40 -080099 size_t tx_sps, size_t rx_sps, size_t chans,
Alexander Chemerise8905a02015-06-03 23:47:56 -0400100 GSM::Time wTransmitLatency,
101 RadioInterface *wRadioInterface,
Eric Wildac0487e2019-06-17 13:02:44 +0200102 double wRssiOffset, int stackSize);
Tom Tsou64ad7122015-05-19 18:26:31 -0700103
104 /** Destructor */
105 ~Transceiver();
106
107 /** Start the control loop */
Vadim Yanitskiya8b35652018-10-22 02:52:18 +0200108 bool init(FillerType filler, size_t rtsc, unsigned rach_delay,
109 bool edge, bool ext_rach);
Tom Tsou64ad7122015-05-19 18:26:31 -0700110
111 /** attach the radioInterface receive FIFO */
112 bool receiveFIFO(VectorFIFO *wFIFO, size_t chan)
113 {
114 if (chan >= mReceiveFIFO.size())
115 return false;
116
117 mReceiveFIFO[chan] = wFIFO;
118 return true;
119 }
120
121 /** accessor for number of channels */
122 size_t numChans() const { return mChans; };
123
124 /** Codes for channel combinations */
125 typedef enum {
126 FILL, ///< Channel is transmitted, but unused
127 I, ///< TCH/FS
128 II, ///< TCH/HS, idle every other slot
129 III, ///< TCH/HS
130 IV, ///< FCCH+SCH+CCCH+BCCH, uplink RACH
131 V, ///< FCCH+SCH+CCCH+BCCH+SDCCH/4+SACCH/4, uplink RACH+SDCCH/4
132 VI, ///< CCCH+BCCH, uplink RACH
133 VII, ///< SDCCH/8 + SACCH/8
134 VIII, ///< TCH/F + FACCH/F + SACCH/M
135 IX, ///< TCH/F + SACCH/M
136 X, ///< TCH/FD + SACCH/MD
137 XI, ///< PBCCH+PCCCH+PDTCH+PACCH+PTCCH
138 XII, ///< PCCCH+PDTCH+PACCH+PTCCH
139 XIII, ///< PDTCH+PACCH+PTCCH
140 NONE, ///< Channel is inactive, default
141 LOOPBACK ///< similar go VII, used in loopback testing
142 } ChannelCombination;
143
dburgessb3a0ca42011-10-12 07:44:40 +0000144private:
Thomas Tsoud647ec52013-10-29 15:17:34 -0400145 int mBasePort;
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200146 std::string mLocalAddr;
147 std::string mRemoteAddr;
dburgessb3a0ca42011-10-12 07:44:40 +0000148
Pau Espin Pedrolb9d25152019-07-01 19:03:49 +0200149 std::vector<int> mDataSockets; ///< socket for writing to/reading from GSM core
150 std::vector<int> mCtrlSockets; ///< socket for writing/reading control commands from GSM core
151 int mClockSocket; ///< socket for writing clock updates to GSM core
dburgessb3a0ca42011-10-12 07:44:40 +0000152
Thomas Tsou204a9f12013-10-29 18:34:16 -0400153 std::vector<VectorQueue> mTxPriorityQueues; ///< priority queue of transmit bursts received from GSM core
154 std::vector<VectorFIFO *> mReceiveFIFO; ///< radioInterface FIFO of receive bursts
dburgessb3a0ca42011-10-12 07:44:40 +0000155
Thomas Tsou204a9f12013-10-29 18:34:16 -0400156 std::vector<Thread *> mRxServiceLoopThreads; ///< thread to pull bursts into receive FIFO
157 Thread *mRxLowerLoopThread; ///< thread to pull bursts into receive FIFO
158 Thread *mTxLowerLoopThread; ///< thread to push bursts into transmit FIFO
159 std::vector<Thread *> mControlServiceLoopThreads; ///< thread to process control messages from GSM core
160 std::vector<Thread *> mTxPriorityQueueServiceLoopThreads; ///< thread to process transmit bursts from GSM core
dburgessb3a0ca42011-10-12 07:44:40 +0000161
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800162 GSM::Time mTransmitLatency; ///< latency between basestation clock and transmit deadline clock
163 GSM::Time mLatencyUpdateTime; ///< last time latency was updated
Pau Espin Pedrol7c405a02017-07-04 16:24:06 +0200164 GSM::Time mTransmitDeadlineClock; ///< deadline for pushing bursts into transmit FIFO
dburgessb3a0ca42011-10-12 07:44:40 +0000165 GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core
166
167 RadioInterface *mRadioInterface; ///< associated radioInterface object
168 double txFullScale; ///< full scale input to radio
169 double rxFullScale; ///< full scale output to radio
170
Alexander Chemerise8905a02015-06-03 23:47:56 -0400171 double rssiOffset; ///< RSSI to dBm conversion offset
Eric Wildac0487e2019-06-17 13:02:44 +0200172 int stackSize; ///< stack size for threads, 0 = OS default
Alexander Chemerise8905a02015-06-03 23:47:56 -0400173
dburgessb3a0ca42011-10-12 07:44:40 +0000174 /** modulate and add a burst to the transmit queue */
Thomas Tsoua2fe91a2013-11-13 22:48:11 -0500175 void addRadioVector(size_t chan, BitVector &bits,
Thomas Tsou204a9f12013-10-29 18:34:16 -0400176 int RSSI, GSM::Time &wTime);
dburgessb3a0ca42011-10-12 07:44:40 +0000177
Thomas Tsou15d743e2014-01-25 02:34:03 -0500178 /** Update filler table */
179 void updateFillerTable(size_t chan, radioVector *burst);
180
dburgessb3a0ca42011-10-12 07:44:40 +0000181 /** Push modulated burst into transmit FIFO corresponding to a particular timestamp */
182 void pushRadioVector(GSM::Time &nowTime);
183
Thomas Tsou204a9f12013-10-29 18:34:16 -0400184 /** Pull and demodulate a burst from the receive FIFO */
Pau Espin Pedrol923b4bc2019-09-06 15:01:26 +0200185 int pullRadioVector(size_t chan, struct trx_ul_burst_ind *ind);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400186
dburgessb3a0ca42011-10-12 07:44:40 +0000187 /** Set modulus for specific timeslot */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400188 void setModulus(size_t timeslot, size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000189
190 /** return the expected burst type for the specified timestamp */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400191 CorrType expectedCorrType(GSM::Time currTime, size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000192
193 /** send messages over the clock socket */
Pau Espin Pedrol76ff96e2019-08-26 12:05:48 +0200194 bool writeClockInterface(void);
dburgessb3a0ca42011-10-12 07:44:40 +0000195
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400196 int mSPSTx; ///< number of samples per Tx symbol
197 int mSPSRx; ///< number of samples per Rx symbol
Thomas Tsou204a9f12013-10-29 18:34:16 -0400198 size_t mChans;
dburgessb3a0ca42011-10-12 07:44:40 +0000199
Vadim Yanitskiya8b35652018-10-22 02:52:18 +0200200 bool mExtRACH;
Tom Tsou64464e62016-07-01 03:46:46 -0700201 bool mEdge;
Alexander Chemeris37229202015-06-20 01:37:54 +0300202 bool mOn; ///< flag to indicate that transceiver is powered on
Pau Espin Pedrol934da482017-07-04 16:25:20 +0200203 bool mForceClockInterface; ///< flag to indicate whether IND CLOCK shall be sent unconditionally after transceiver is started
Alexander Chemeris5a068062015-06-20 01:38:47 +0300204 bool mHandover[8][8]; ///< expect handover to the timeslot/subslot
dburgessb3a0ca42011-10-12 07:44:40 +0000205 double mTxFreq; ///< the transmit frequency
206 double mRxFreq; ///< the receive frequency
dburgessb3a0ca42011-10-12 07:44:40 +0000207 unsigned mTSC; ///< the midamble sequence code
Alexander Chemeris78d1fc92016-03-19 21:16:22 +0300208 unsigned mMaxExpectedDelayAB; ///< maximum expected time-of-arrival offset in GSM symbols for Access Bursts (RACH)
209 unsigned mMaxExpectedDelayNB; ///< maximum expected time-of-arrival offset in GSM symbols for Normal Bursts
Alexander Chemerise692ce92015-06-12 00:15:31 -0400210 unsigned mWriteBurstToDiskMask; ///< debug: bitmask to indicate which timeslots to dump to disk
dburgessb3a0ca42011-10-12 07:44:40 +0000211
Pau Espin Pedrolc3325b92019-07-22 17:47:02 +0200212 std::vector<unsigned> mVersionTRXD; ///< Format version to use for TRXD protocol communication, per channel
Thomas Tsou204a9f12013-10-29 18:34:16 -0400213 std::vector<TransceiverState> mStates;
dburgessb3a0ca42011-10-12 07:44:40 +0000214
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800215 /** Start and stop I/O threads through the control socket API */
216 bool start();
217 void stop();
218
Martin Hauke066fd042019-10-13 19:08:00 +0200219 /** Protect destructor accessible stop call */
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800220 Mutex mLock;
221
dburgessb3a0ca42011-10-12 07:44:40 +0000222protected:
Thomas Tsou204a9f12013-10-29 18:34:16 -0400223 /** drive lower receive I/O and burst generation */
Pau Espin Pedrol76ff96e2019-08-26 12:05:48 +0200224 bool driveReceiveRadio();
dburgessb3a0ca42011-10-12 07:44:40 +0000225
Thomas Tsou204a9f12013-10-29 18:34:16 -0400226 /** drive demodulation of GSM bursts */
Pau Espin Pedrol76ff96e2019-08-26 12:05:48 +0200227 bool driveReceiveFIFO(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000228
229 /** drive transmission of GSM bursts */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400230 void driveTxFIFO();
dburgessb3a0ca42011-10-12 07:44:40 +0000231
232 /** drive handling of control messages from GSM core */
Pau Espin Pedrol76ff96e2019-08-26 12:05:48 +0200233 bool driveControl(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000234
235 /**
236 drive modulation and sorting of GSM bursts from GSM core
237 @return true if a burst was transferred successfully
238 */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400239 bool driveTxPriorityQueue(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000240
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200241 friend void *RxUpperLoopAdapter(TrxChanThParams *params);
242 friend void *TxUpperLoopAdapter(TrxChanThParams *params);
243 friend void *RxLowerLoopAdapter(Transceiver *transceiver);
244 friend void *TxLowerLoopAdapter(Transceiver *transceiver);
245 friend void *ControlServiceLoopAdapter(TrxChanThParams *params);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400246
dburgessb3a0ca42011-10-12 07:44:40 +0000247
248 void reset();
kurtis.heimerl6b495a52011-11-26 03:17:21 +0000249
Pau Espin Pedrol607a4142019-07-01 13:56:17 +0200250 void logRxBurst(size_t chan, const struct trx_ul_burst_ind *bi);
dburgessb3a0ca42011-10-12 07:44:40 +0000251};
252
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200253void *RxUpperLoopAdapter(TrxChanThParams *params);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400254
Thomas Tsou92c16df2013-09-28 18:04:19 -0400255/** Main drive threads */
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200256void *RxLowerLoopAdapter(Transceiver *transceiver);
257void *TxLowerLoopAdapter(Transceiver *transceiver);
dburgessb3a0ca42011-10-12 07:44:40 +0000258
259/** control message handler thread loop */
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200260void *ControlServiceLoopAdapter(TrxChanThParams *params);
dburgessb3a0ca42011-10-12 07:44:40 +0000261
262/** transmit queueing thread loop */
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200263void *TxUpperLoopAdapter(TrxChanThParams *params);