blob: 6e0d157690e60f1e307e9f967202897d18aa9eed [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>
Erica7143bf2020-04-08 01:39:17 +020036#include <osmocom/core/select.h>
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010037#include "config_defs.h"
38}
39
Thomas Tsouf0782732013-10-29 15:55:47 -040040class Transceiver;
41
Erica7143bf2020-04-08 01:39:17 +020042extern Transceiver *transceiver;
43
Thomas Tsouf0782732013-10-29 15:55:47 -040044/** Channel descriptor for transceiver object and channel number pair */
Pau Espin Pedrol720b9122019-07-22 18:10:52 +020045struct TrxChanThParams {
46 Transceiver *trx;
47 size_t num;
Thomas Tsouf0782732013-10-29 15:55:47 -040048};
49
50/** Internal transceiver state variables */
51struct TransceiverState {
52 TransceiverState();
53 ~TransceiverState();
54
55 /* Initialize a multiframe slot in the filler table */
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010056 bool init(FillerType filler, size_t sps, float scale, size_t rtsc, unsigned rach_delay);
Thomas Tsouf0782732013-10-29 15:55:47 -040057
58 int chanType[8];
59
60 /* Last timestamp of each timeslot's channel estimate */
61 GSM::Time chanEstimateTime[8];
62
63 /* The filler table */
64 signalVector *fillerTable[102][8];
65 int fillerModulus[8];
Thomas Tsou15d743e2014-01-25 02:34:03 -050066 bool mRetrans;
Thomas Tsouf0782732013-10-29 15:55:47 -040067
68 /* Most recent channel estimate of all timeslots */
69 signalVector *chanResponse[8];
70
71 /* Most recent DFE feedback filter of all timeslots */
72 signalVector *DFEForward[8];
73 signalVector *DFEFeedback[8];
74
75 /* Most recent SNR, timing, and channel amplitude estimates */
76 float SNRestimate[8];
77 float chanRespOffset[8];
78 complex chanRespAmplitude[8];
Thomas Tsoua0179e32013-11-14 15:52:04 -050079
80 /* Received noise energy levels */
81 float mNoiseLev;
82 noiseVector mNoises;
Tom Tsoua4d1a412014-11-25 15:46:56 -080083
84 /* Shadowed downlink attenuation */
85 int mPower;
Thomas Tsouf0782732013-10-29 15:55:47 -040086};
87
dburgessb3a0ca42011-10-12 07:44:40 +000088/** The Transceiver class, responsible for physical layer of basestation */
89class Transceiver {
Tom Tsou64ad7122015-05-19 18:26:31 -070090public:
Pau Espin Pedrol7c405a02017-07-04 16:24:06 +020091 /** Transceiver constructor
Tom Tsou64ad7122015-05-19 18:26:31 -070092 @param wBasePort base port number of UDP sockets
Pau Espin Pedrol8c800952017-08-16 16:53:23 +020093 @param TRXAddress IP address of the TRX, as a string
94 @param GSMcoreAddress IP address of the GSM core, as a string
Tom Tsou64ad7122015-05-19 18:26:31 -070095 @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 Chemerise8905a02015-06-03 23:47:56 -0400100 const char *TRXAddress,
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200101 const char *GSMcoreAddress,
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800102 size_t tx_sps, size_t rx_sps, size_t chans,
Alexander Chemerise8905a02015-06-03 23:47:56 -0400103 GSM::Time wTransmitLatency,
104 RadioInterface *wRadioInterface,
Eric Wildac0487e2019-06-17 13:02:44 +0200105 double wRssiOffset, int stackSize);
Tom Tsou64ad7122015-05-19 18:26:31 -0700106
107 /** Destructor */
108 ~Transceiver();
109
110 /** Start the control loop */
Vadim Yanitskiya8b35652018-10-22 02:52:18 +0200111 bool init(FillerType filler, size_t rtsc, unsigned rach_delay,
112 bool edge, bool ext_rach);
Tom Tsou64ad7122015-05-19 18:26:31 -0700113
114 /** attach the radioInterface receive FIFO */
115 bool receiveFIFO(VectorFIFO *wFIFO, size_t chan)
116 {
117 if (chan >= mReceiveFIFO.size())
118 return false;
119
120 mReceiveFIFO[chan] = wFIFO;
121 return true;
122 }
123
124 /** accessor for number of channels */
125 size_t numChans() const { return mChans; };
126
127 /** Codes for channel combinations */
128 typedef enum {
129 FILL, ///< Channel is transmitted, but unused
130 I, ///< TCH/FS
131 II, ///< TCH/HS, idle every other slot
132 III, ///< TCH/HS
133 IV, ///< FCCH+SCH+CCCH+BCCH, uplink RACH
134 V, ///< FCCH+SCH+CCCH+BCCH+SDCCH/4+SACCH/4, uplink RACH+SDCCH/4
135 VI, ///< CCCH+BCCH, uplink RACH
136 VII, ///< SDCCH/8 + SACCH/8
137 VIII, ///< TCH/F + FACCH/F + SACCH/M
138 IX, ///< TCH/F + SACCH/M
139 X, ///< TCH/FD + SACCH/MD
140 XI, ///< PBCCH+PCCCH+PDTCH+PACCH+PTCCH
141 XII, ///< PCCCH+PDTCH+PACCH+PTCCH
142 XIII, ///< PDTCH+PACCH+PTCCH
143 NONE, ///< Channel is inactive, default
144 LOOPBACK ///< similar go VII, used in loopback testing
145 } ChannelCombination;
146
dburgessb3a0ca42011-10-12 07:44:40 +0000147private:
Erica7143bf2020-04-08 01:39:17 +0200148
149struct ctrl_msg {
150 char data[101];
151 ctrl_msg() {};
152};
153
154struct ctrl_sock_state {
155 osmo_fd conn_bfd;
156 std::deque<ctrl_msg> txmsgqueue;
157 ctrl_sock_state() {
158 conn_bfd.fd = -1;
159 }
160 ~ctrl_sock_state() {
161 if(conn_bfd.fd >= 0) {
162 close(conn_bfd.fd);
163 conn_bfd.fd = -1;
164 osmo_fd_unregister(&conn_bfd);
165 }
166 }
167};
168
Thomas Tsoud647ec52013-10-29 15:17:34 -0400169 int mBasePort;
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200170 std::string mLocalAddr;
171 std::string mRemoteAddr;
dburgessb3a0ca42011-10-12 07:44:40 +0000172
Pau Espin Pedrolb9d25152019-07-01 19:03:49 +0200173 std::vector<int> mDataSockets; ///< socket for writing to/reading from GSM core
Erica7143bf2020-04-08 01:39:17 +0200174 std::vector<ctrl_sock_state> mCtrlSockets; ///< socket for writing/reading control commands from GSM core
Pau Espin Pedrolb9d25152019-07-01 19:03:49 +0200175 int mClockSocket; ///< socket for writing clock updates to GSM core
dburgessb3a0ca42011-10-12 07:44:40 +0000176
Thomas Tsou204a9f12013-10-29 18:34:16 -0400177 std::vector<VectorQueue> mTxPriorityQueues; ///< priority queue of transmit bursts received from GSM core
178 std::vector<VectorFIFO *> mReceiveFIFO; ///< radioInterface FIFO of receive bursts
dburgessb3a0ca42011-10-12 07:44:40 +0000179
Thomas Tsou204a9f12013-10-29 18:34:16 -0400180 std::vector<Thread *> mRxServiceLoopThreads; ///< thread to pull bursts into receive FIFO
181 Thread *mRxLowerLoopThread; ///< thread to pull bursts into receive FIFO
182 Thread *mTxLowerLoopThread; ///< thread to push bursts into transmit FIFO
Thomas Tsou204a9f12013-10-29 18:34:16 -0400183 std::vector<Thread *> mTxPriorityQueueServiceLoopThreads; ///< thread to process transmit bursts from GSM core
dburgessb3a0ca42011-10-12 07:44:40 +0000184
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800185 GSM::Time mTransmitLatency; ///< latency between basestation clock and transmit deadline clock
186 GSM::Time mLatencyUpdateTime; ///< last time latency was updated
Pau Espin Pedrol7c405a02017-07-04 16:24:06 +0200187 GSM::Time mTransmitDeadlineClock; ///< deadline for pushing bursts into transmit FIFO
dburgessb3a0ca42011-10-12 07:44:40 +0000188 GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core
189
190 RadioInterface *mRadioInterface; ///< associated radioInterface object
191 double txFullScale; ///< full scale input to radio
192 double rxFullScale; ///< full scale output to radio
193
Alexander Chemerise8905a02015-06-03 23:47:56 -0400194 double rssiOffset; ///< RSSI to dBm conversion offset
Eric Wildac0487e2019-06-17 13:02:44 +0200195 int stackSize; ///< stack size for threads, 0 = OS default
Alexander Chemerise8905a02015-06-03 23:47:56 -0400196
dburgessb3a0ca42011-10-12 07:44:40 +0000197 /** modulate and add a burst to the transmit queue */
Thomas Tsoua2fe91a2013-11-13 22:48:11 -0500198 void addRadioVector(size_t chan, BitVector &bits,
Thomas Tsou204a9f12013-10-29 18:34:16 -0400199 int RSSI, GSM::Time &wTime);
dburgessb3a0ca42011-10-12 07:44:40 +0000200
Thomas Tsou15d743e2014-01-25 02:34:03 -0500201 /** Update filler table */
202 void updateFillerTable(size_t chan, radioVector *burst);
203
dburgessb3a0ca42011-10-12 07:44:40 +0000204 /** Push modulated burst into transmit FIFO corresponding to a particular timestamp */
205 void pushRadioVector(GSM::Time &nowTime);
206
Thomas Tsou204a9f12013-10-29 18:34:16 -0400207 /** Pull and demodulate a burst from the receive FIFO */
Pau Espin Pedrol923b4bc2019-09-06 15:01:26 +0200208 int pullRadioVector(size_t chan, struct trx_ul_burst_ind *ind);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400209
dburgessb3a0ca42011-10-12 07:44:40 +0000210 /** Set modulus for specific timeslot */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400211 void setModulus(size_t timeslot, size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000212
213 /** return the expected burst type for the specified timestamp */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400214 CorrType expectedCorrType(GSM::Time currTime, size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000215
216 /** send messages over the clock socket */
Pau Espin Pedrol76ff96e2019-08-26 12:05:48 +0200217 bool writeClockInterface(void);
dburgessb3a0ca42011-10-12 07:44:40 +0000218
Erica7143bf2020-04-08 01:39:17 +0200219 static int ctrl_sock_cb(struct osmo_fd *bfd, unsigned int flags);
220 int ctrl_sock_write(int chan);
221 void ctrl_sock_send(ctrl_msg& m, int chan);
222 /** drive handling of control messages from GSM core */
223 int ctrl_sock_handle_rx(int chan);
224
Thomas Tsouc1f7c422013-10-11 13:49:55 -0400225 int mSPSTx; ///< number of samples per Tx symbol
226 int mSPSRx; ///< number of samples per Rx symbol
Thomas Tsou204a9f12013-10-29 18:34:16 -0400227 size_t mChans;
dburgessb3a0ca42011-10-12 07:44:40 +0000228
Vadim Yanitskiya8b35652018-10-22 02:52:18 +0200229 bool mExtRACH;
Tom Tsou64464e62016-07-01 03:46:46 -0700230 bool mEdge;
Alexander Chemeris37229202015-06-20 01:37:54 +0300231 bool mOn; ///< flag to indicate that transceiver is powered on
Pau Espin Pedrol934da482017-07-04 16:25:20 +0200232 bool mForceClockInterface; ///< flag to indicate whether IND CLOCK shall be sent unconditionally after transceiver is started
Alexander Chemeris5a068062015-06-20 01:38:47 +0300233 bool mHandover[8][8]; ///< expect handover to the timeslot/subslot
dburgessb3a0ca42011-10-12 07:44:40 +0000234 double mTxFreq; ///< the transmit frequency
235 double mRxFreq; ///< the receive frequency
dburgessb3a0ca42011-10-12 07:44:40 +0000236 unsigned mTSC; ///< the midamble sequence code
Alexander Chemeris78d1fc92016-03-19 21:16:22 +0300237 unsigned mMaxExpectedDelayAB; ///< maximum expected time-of-arrival offset in GSM symbols for Access Bursts (RACH)
238 unsigned mMaxExpectedDelayNB; ///< maximum expected time-of-arrival offset in GSM symbols for Normal Bursts
Alexander Chemerise692ce92015-06-12 00:15:31 -0400239 unsigned mWriteBurstToDiskMask; ///< debug: bitmask to indicate which timeslots to dump to disk
dburgessb3a0ca42011-10-12 07:44:40 +0000240
Pau Espin Pedrolc3325b92019-07-22 17:47:02 +0200241 std::vector<unsigned> mVersionTRXD; ///< Format version to use for TRXD protocol communication, per channel
Thomas Tsou204a9f12013-10-29 18:34:16 -0400242 std::vector<TransceiverState> mStates;
dburgessb3a0ca42011-10-12 07:44:40 +0000243
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800244 /** Start and stop I/O threads through the control socket API */
245 bool start();
246 void stop();
247
Martin Hauke066fd042019-10-13 19:08:00 +0200248 /** Protect destructor accessible stop call */
Tom Tsoueb54bdd2014-11-25 16:06:32 -0800249 Mutex mLock;
250
dburgessb3a0ca42011-10-12 07:44:40 +0000251protected:
Thomas Tsou204a9f12013-10-29 18:34:16 -0400252 /** drive lower receive I/O and burst generation */
Pau Espin Pedrol76ff96e2019-08-26 12:05:48 +0200253 bool driveReceiveRadio();
dburgessb3a0ca42011-10-12 07:44:40 +0000254
Thomas Tsou204a9f12013-10-29 18:34:16 -0400255 /** drive demodulation of GSM bursts */
Pau Espin Pedrol76ff96e2019-08-26 12:05:48 +0200256 bool driveReceiveFIFO(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000257
258 /** drive transmission of GSM bursts */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400259 void driveTxFIFO();
dburgessb3a0ca42011-10-12 07:44:40 +0000260
dburgessb3a0ca42011-10-12 07:44:40 +0000261 /**
262 drive modulation and sorting of GSM bursts from GSM core
263 @return true if a burst was transferred successfully
264 */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400265 bool driveTxPriorityQueue(size_t chan);
dburgessb3a0ca42011-10-12 07:44:40 +0000266
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200267 friend void *RxUpperLoopAdapter(TrxChanThParams *params);
268 friend void *TxUpperLoopAdapter(TrxChanThParams *params);
269 friend void *RxLowerLoopAdapter(Transceiver *transceiver);
270 friend void *TxLowerLoopAdapter(Transceiver *transceiver);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400271
dburgessb3a0ca42011-10-12 07:44:40 +0000272
273 void reset();
kurtis.heimerl6b495a52011-11-26 03:17:21 +0000274
Pau Espin Pedrol607a4142019-07-01 13:56:17 +0200275 void logRxBurst(size_t chan, const struct trx_ul_burst_ind *bi);
dburgessb3a0ca42011-10-12 07:44:40 +0000276};
277
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200278void *RxUpperLoopAdapter(TrxChanThParams *params);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400279
Thomas Tsou92c16df2013-09-28 18:04:19 -0400280/** Main drive threads */
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200281void *RxLowerLoopAdapter(Transceiver *transceiver);
282void *TxLowerLoopAdapter(Transceiver *transceiver);
dburgessb3a0ca42011-10-12 07:44:40 +0000283
dburgessb3a0ca42011-10-12 07:44:40 +0000284/** transmit queueing thread loop */
Pau Espin Pedrol720b9122019-07-22 18:10:52 +0200285void *TxUpperLoopAdapter(TrxChanThParams *params);