aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/DriveLoop.h
blob: eeabe036ccb602b0c8c0bfc14bbe64b394c3765d (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
/*
* 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
*/

#ifndef _DRIVELOOP_H_
#define _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

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

  int  mUseCount;                 ///< Use counter

  GSM::Time mTransmitLatency;     ///< latency between basestation clock and transmit deadline clock
  GSM::Time mLatencyUpdateTime;   ///< last time latency was updated
  GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core

  UDPSocket mClockSocket;	  ///< socket for writing clock updates to GSM core

  VectorQueue  mTransmitPriorityQueue[CHAN_MAX];   ///< priority queue of transmit bursts received from GSM core

  GSM::Time mTransmitDeadlineClock;       ///< deadline for pushing bursts into transmit FIFO 
  GSM::Time mStartTime;                   ///< random start time of the radio clock

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

  /** Number of channels supported by the channelizer */
  int mChanM;

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

  /** 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);
   
  signalVector *gsmPulse;              ///< the GSM shaping pulse for modulation

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

  int fillerModulus[CHAN_MAX][8];                ///< modulus values of all timeslots, in frames
  signalVector *fillerTable[CHAN_MAX][102][8];   ///< table of modulated filler waveforms for all timeslots

  /** Channelizer path for primary ARFCN */
  int mC0;

  signalVector *mTxBursts[CHAN_MAX];
  bool         mIsFiller[CHAN_MAX];
  bool         mIsZero[CHAN_MAX];

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
  */
  DriveLoop(int wBasePort, const char *TRXAddress,
	    RadioInterface *wRadioInterface,
	    int wChanM = 1, int wC0 = 0,
            int wSamplesPerSymbol = SAMPSPERSYM,
	    GSM::Time wTransmitLatency = GSM::Time(3, 0));
   
  /** Destructor */
  ~DriveLoop();

  /** Increase usage counter and start the thread if not started yet */
  bool start();
  /** Decrease usage counter and stop the thread if no users left */
  bool stop();

  VectorQueue *priorityQueue(int m) { return &mTransmitPriorityQueue[m]; }

  /** 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;

  /** 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
    NONE,               ///< Channel is inactive, default
    LOOPBACK            ///< similar go VII, used in loopback testing
  } ChannelCombination;

  /** Set modulus for specific timeslot */
  void setModulus(int channel, int timeslot);

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

  void setTimeslot(int m, int timeslot, ChannelCombination comb)
  {
    mChanType[m][timeslot] = comb;
  }

  GSM::Time getStartTime() { return mStartTime; }
  GSM::Time getLastClockUpdate() { return mLastClockUpdateTime; }
  GSM::Time getDeadlineClock() { return mTransmitDeadlineClock; }

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

private:

  ChannelCombination mChanType[CHAN_MAX][8];     ///< channel types for all timeslots

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();

  virtual void runThread();

  void reset();

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

};

/** FIFO thread loop */
void *RadioDriveLoopAdapter(DriveLoop *);

#endif /* _DRIVELOOP_H_ */