aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/Transceiver.h
blob: 671603e56741033ce7174cc248bf8119248e9847 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "radioInterface.h"
#include "Interthread.h"
#include "GSMCommon.h"
#include "Sockets.h"

#include <sys/types.h>
#include <sys/socket.h>

class Transceiver;

/** Channel descriptor for transceiver object and channel number pair */
struct TransceiverChannel {
  TransceiverChannel(Transceiver *trx, int num)
  {
    this->trx = trx;
    this->num = num;
  }

  ~TransceiverChannel()
  {
  }

  Transceiver *trx;
  size_t num;
};

/** Internal transceiver state variables */
struct TransceiverState {
  TransceiverState();
  ~TransceiverState();

  /* Initialize a multiframe slot in the filler table */
  void init(size_t slot, signalVector *burst);

  int chanType[8];

  /* Last timestamp of each timeslot's channel estimate */
  GSM::Time chanEstimateTime[8];

  /* The filler table */
  signalVector *fillerTable[102][8];
  int fillerModulus[8];

  /* Most recent channel estimate of all timeslots */
  signalVector *chanResponse[8];

  /* Most recent DFE feedback filter of all timeslots */
  signalVector *DFEForward[8];
  signalVector *DFEFeedback[8];

  /* Most recent SNR, timing, and channel amplitude estimates */
  float SNRestimate[8];
  float chanRespOffset[8];
  complex chanRespAmplitude[8];
};

/** The Transceiver class, responsible for physical layer of basestation */
class Transceiver {
private:
  int mBasePort;
  std::string mAddr;
  GSM::Time mTransmitLatency;     ///< latency between basestation clock and transmit deadline clock
  GSM::Time mLatencyUpdateTime;   ///< last time latency was updated

  std::vector<UDPSocket *> mDataSockets;  ///< socket for writing to/reading from GSM core
  std::vector<UDPSocket *> mCtrlSockets;  ///< socket for writing/reading control commands from GSM core
  UDPSocket *mClockSocket;                ///< socket for writing clock updates to GSM core

  std::vector<VectorQueue> mTxPriorityQueues;   ///< priority queue of transmit bursts received from GSM core
  std::vector<VectorFIFO *>  mReceiveFIFO;      ///< radioInterface FIFO of receive bursts

  std::vector<Thread *> mRxServiceLoopThreads;  ///< thread to pull bursts into receive FIFO
  Thread *mRxLowerLoopThread;                   ///< thread to pull bursts into receive FIFO
  Thread *mTxLowerLoopThread;                   ///< thread to push bursts into transmit FIFO
  std::vector<Thread *> mControlServiceLoopThreads;         ///< thread to process control messages from GSM core
  std::vector<Thread *> mTxPriorityQueueServiceLoopThreads; ///< thread to process transmit bursts from GSM core

  GSM::Time mTransmitDeadlineClock;       ///< deadline for pushing bursts into transmit FIFO 
  GSM::Time mLastClockUpdateTime;         ///< last time clock update was sent up to core

  RadioInterface *mRadioInterface;	  ///< associated radioInterface object
  double txFullScale;                     ///< full scale input to radio
  double rxFullScale;                     ///< full scale output to radio

  /** Codes for burst types of received bursts*/
  typedef enum {
    OFF,               ///< timeslot is off
    TSC,	       ///< timeslot should contain a normal burst
    RACH,	       ///< timeslot should contain an access burst
    IDLE	       ///< timeslot is an idle (or dummy) burst
  } CorrType;

  float mNoiseLev;      ///< Average noise level
  noiseVector mNoises;  ///< Vector holding running noise measurements

  /** modulate and add a burst to the transmit queue */
  void addRadioVector(size_t chan, BitVector &bits,
                      int RSSI, GSM::Time &wTime);

  /** Push modulated burst into transmit FIFO corresponding to a particular timestamp */
  void pushRadioVector(GSM::Time &nowTime);

  /** Pull and demodulate a burst from the receive FIFO */
  SoftVector *pullRadioVector(GSM::Time &wTime, int &RSSI,
                              int &timingOffset, size_t chan = 0);

  /** Set modulus for specific timeslot */
  void setModulus(size_t timeslot, size_t chan);

  /** return the expected burst type for the specified timestamp */
  CorrType expectedCorrType(GSM::Time currTime, size_t chan);

  /** send messages over the clock socket */
  void writeClockInterface(void);

  int mSPSTx;                          ///< number of samples per Tx symbol
  int mSPSRx;                          ///< number of samples per Rx symbol
  size_t mChans;

  bool mOn;			       ///< flag to indicate that transceiver is powered on
  double mTxFreq;                      ///< the transmit frequency
  double mRxFreq;                      ///< the receive frequency
  int mPower;                          ///< the transmit power in dB
  unsigned mTSC;                       ///< the midamble sequence code
  unsigned mMaxExpectedDelay;            ///< maximum expected time-of-arrival offset in GSM symbols

  std::vector<TransceiverState> mStates;

public:

  /** Transceiver constructor 
      @param wBasePort base port number of UDP sockets
      @param TRXAddress IP address of the TRX manager, as a string
      @param wSPS number of samples per GSM symbol
      @param wTransmitLatency initial setting of transmit latency
      @param radioInterface associated radioInterface object
  */
  Transceiver(int wBasePort,
	      const char *TRXAddress,
	      size_t wSPS, size_t chans,
	      GSM::Time wTransmitLatency,
	      RadioInterface *wRadioInterface);

  /** Destructor */
  ~Transceiver();

  /** start the Transceiver */
  void start();
  bool init();

  /** attach the radioInterface receive FIFO */
  bool receiveFIFO(VectorFIFO *wFIFO, size_t chan)
  {
    if (chan >= mReceiveFIFO.size())
      return false;

    mReceiveFIFO[chan] = wFIFO;
    return true;
  }

  /** Codes for channel combinations */
  typedef enum {
    FILL,               ///< Channel is transmitted, but unused
    I,                  ///< TCH/FS
    II,                 ///< TCH/HS, idle every other slot
    III,                ///< TCH/HS
    IV,                 ///< FCCH+SCH+CCCH+BCCH, uplink RACH
    V,                  ///< FCCH+SCH+CCCH+BCCH+SDCCH/4+SACCH/4, uplink RACH+SDCCH/4
    VI,                 ///< CCCH+BCCH, uplink RACH
    VII,                ///< SDCCH/8 + SACCH/8
    VIII,               ///< TCH/F + FACCH/F + SACCH/M
    IX,                 ///< TCH/F + SACCH/M
    X,                  ///< TCH/FD + SACCH/MD
    XI,                 ///< PBCCH+PCCCH+PDTCH+PACCH+PTCCH
    XII,                ///< PCCCH+PDTCH+PACCH+PTCCH
    XIII,               ///< PDTCH+PACCH+PTCCH
    NONE,               ///< Channel is inactive, default
    LOOPBACK            ///< similar go VII, used in loopback testing
  } ChannelCombination;

protected:
  /** drive lower receive I/O and burst generation */
  void driveReceiveRadio();

  /** drive demodulation of GSM bursts */
  void driveReceiveFIFO(size_t chan);

  /** drive transmission of GSM bursts */
  void driveTxFIFO();

  /** drive handling of control messages from GSM core */
  void driveControl(size_t chan);

  /**
    drive modulation and sorting of GSM bursts from GSM core
    @return true if a burst was transferred successfully
  */
  bool driveTxPriorityQueue(size_t chan);

  friend void *RxUpperLoopAdapter(TransceiverChannel *);

  friend void *TxUpperLoopAdapter(TransceiverChannel *);

  friend void *RxLowerLoopAdapter(Transceiver *);

  friend void *TxLowerLoopAdapter(Transceiver *);

  friend void *ControlServiceLoopAdapter(TransceiverChannel *);


  void reset();

  /** set priority on current thread */
  void setPriority(float prio = 0.5) { mRadioInterface->setPriority(prio); }

};

void *RxUpperLoopAdapter(TransceiverChannel *);

/** Main drive threads */
void *RxLowerLoopAdapter(Transceiver *);
void *TxLowerLoopAdapter(Transceiver *);

/** control message handler thread loop */
void *ControlServiceLoopAdapter(TransceiverChannel *);

/** transmit queueing thread loop */
void *TxUpperLoopAdapter(TransceiverChannel *);