aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/Transceiver.h
blob: 91c34eebd228cb4f845400af625e502f57dfcf5f (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
/*
* Copyright 2008, 2012 Free Software Foundation, Inc.
* Copyright 2013 Alexander Chemeris <Alexander.Chemeris@fairwaves.ru>
*
* 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/>.

*/



/*
	Compilation switches
	TRANSMIT_LOGGING	write every burst on the given slot to a log
*/

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

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

/** Define this to be the slot number to be logged. */
//#define TRANSMIT_LOGGING 1

/** FIFO thread loop */
class FIFOServiceLoopThread : public Thread {
public:
  FIFOServiceLoopThread() : Thread("FIFOServiceLoopThread") {}
  Thread::ReturnStatus shutdown();

protected:
  virtual void runThread();
};

/** control message handler thread loop */
class ControlServiceLoopThread : public Thread {
public:
  ControlServiceLoopThread() : Thread("ControlServiceLoopThread") {}
  Thread::ReturnStatus shutdown();

protected:
  virtual void runThread();
};

/** transmit queueing thread loop */
class TransmitPriorityQueueServiceLoopThread : public Thread {
public:
  TransmitPriorityQueueServiceLoopThread() : Thread("TransmitPriorityQueueServiceLoopThread") {}
  Thread::ReturnStatus shutdown();

protected:
  virtual void runThread();
};

/** The Transceiver class, responsible for physical layer of basestation */
class Transceiver {
  
private:
  DriveLoop *mDriveLoop;

  int mBasePort;                  ///< Base port address for all our ports
  std::string mTRXAddress;        ///< Address of the BTS TRX control interface
  UDPSocket mDataSocket;	  ///< socket for writing to/reading from GSM core
  UDPSocket mControlSocket;	  ///< socket for writing/reading control commands from GSM core

  VectorQueue  *mTransmitPriorityQueue;   ///< priority queue of transmit bursts received from GSM core
  VectorFIFO*  mReceiveFIFO;      ///< radioInterface FIFO of receive bursts 

  friend class FIFOServiceLoopThread;
  FIFOServiceLoopThread mFIFOServiceLoop;      ///< thread to push/pull bursts into transmit/receive FIFO
  friend class ControlServiceLoopThread;
  ControlServiceLoopThread mControlServiceLoop;   ///< thread to process control messages from GSM core
  friend class TransmitPriorityQueueServiceLoopThread;
  TransmitPriorityQueueServiceLoopThread mTransmitPriorityQueueServiceLoop;///< thread to process transmit bursts from GSM core

  int mChannel;                           ///< channelizer attach number between 0 and 'M-1'

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

  /** unmodulate a modulated burst */
#ifdef TRANSMIT_LOGGING
  void unModulateVector(signalVector wVector); 
#endif

  /** modulate and add a burst to the transmit queue */
  void addRadioVector(BitVector &burst,
		      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);
   
  /** send messages over the clock socket */
  void writeClockInterface(void);

  void pullFIFO(void);                 ///< blocking call on receive FIFO 

  signalVector *gsmPulse;              ///< the GSM shaping pulse for modulation

  int mSamplesPerSymbol;               ///< number of samples per GSM symbol

  bool mOn;			       ///< flag to indicate that transceiver is powered on
  bool mRunning;                       ///< flag to indicate control loop is running
  bool mPrimary;                       ///< flag to indicate C0 channel 
  double mTxFreq;                      ///< the transmit frequency
  double mRxFreq;                      ///< the receive frequency
  double mFreqOffset;                  ///< RF frequency offset
  int mPower;                          ///< the transmit power in dB
  double mEnergyThreshold;             ///< threshold to determine if received data is potentially a GSM burst
  GSM::Time prevFalseDetectionTime;    ///< last timestamp of a false energy detection
  unsigned mMaxExpectedDelay;            ///< maximum expected time-of-arrival offset in GSM symbols

  GSM::Time    channelEstimateTime[8]; ///< last timestamp of each timeslot's channel estimate
  signalVector *channelResponse[8];    ///< most recent channel estimate of all timeslots
  float        SNRestimate[8];         ///< most recent SNR estimate of all timeslots
  signalVector *DFEForward[8];         ///< most recent DFE feedforward filter of all timeslots
  signalVector *DFEFeedback[8];        ///< most recent DFE feedback filter of all timeslots
  float        chanRespOffset[8];      ///< most recent timing offset, e.g. TOA, of all timeslots
  complex      chanRespAmplitude[8];   ///< most recent channel amplitude of all timeslots

  static int mTSC;                     ///< the midamble sequence code

public:

  /** Transceiver constructor 
      @param wBasePort base port number of UDP sockets
      @param TRXAddress IP address of the TRX manager, as a string
      @param wSamplesPerSymbol number of samples per GSM symbol
      @param wTransmitLatency initial setting of transmit latency
      @param radioInterface associated radioInterface object
  */
  Transceiver(int wBasePort, const char *TRXAddress,
	      DriveLoop *wDriveLoop, RadioInterface *wRadioInterface,
	      int wSamplesPerSymbol = SAMPSPERSYM,
	      int wChannel = 0, bool wPrimary = true);

  /** Destructor */
  ~Transceiver();

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

  /** shutdown (teardown threads) the Transceiver */
  void shutdown();

protected:

  /** drive reception and demodulation of GSM bursts */ 
  void driveReceiveFIFO();

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

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

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

  void reset();

  /** return transceiver on/off status */ 
  bool on() { return mOn; }

  /** return control loop operational status */ 
  bool running() { return mRunning; }

  /** return the drive loop pointer */
  DriveLoop *getDriveLoop() { return mDriveLoop; }
  
  /** set priority on current thread */
  void setPriority() { mRadioInterface->setPriority(); }
};