mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
synced 2025-11-03 21:53:18 +00:00
Collect the slot information into an indpendent state object. This will allow us to easily create multiple instances of internal state variables without having to replicate the transceiver object itself. Signed-off-by: Thomas Tsou <tom@tsou.cc>
244 lines
8.2 KiB
C++
244 lines
8.2 KiB
C++
/*
|
|
* 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
|
|
|
|
UDPSocket *mDataSocket; ///< socket for writing to/reading from GSM core
|
|
UDPSocket *mCtrlSocket; ///< socket for writing/reading control commands from GSM core
|
|
UDPSocket *mClockSocket; ///< socket for writing clock updates to GSM core
|
|
|
|
VectorQueue mTransmitPriorityQueue; ///< priority queue of transmit bursts received from GSM core
|
|
VectorFIFO* mTransmitFIFO; ///< radioInterface FIFO of transmit bursts
|
|
VectorFIFO* mReceiveFIFO; ///< radioInterface FIFO of receive bursts
|
|
|
|
Thread *mRxServiceLoopThread; ///< thread to pull bursts into receive FIFO
|
|
Thread *mTxServiceLoopThread; ///< thread to push bursts into transmit FIFO
|
|
Thread *mControlServiceLoopThread; ///< thread to process control messages from GSM core
|
|
Thread *mTransmitPriorityQueueServiceLoopThread;///< 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(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);
|
|
|
|
/** Set modulus for specific timeslot */
|
|
void setModulus(int timeslot);
|
|
|
|
/** return the expected burst type for the specified timestamp */
|
|
CorrType expectedCorrType(GSM::Time currTime);
|
|
|
|
/** 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
|
|
|
|
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
|
|
|
|
TransceiverState mState;
|
|
|
|
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,
|
|
int wSPS,
|
|
GSM::Time wTransmitLatency,
|
|
RadioInterface *wRadioInterface);
|
|
|
|
/** Destructor */
|
|
~Transceiver();
|
|
|
|
/** start the Transceiver */
|
|
void start();
|
|
bool init();
|
|
|
|
/** attach the radioInterface receive FIFO */
|
|
void receiveFIFO(VectorFIFO *wFIFO) { mReceiveFIFO = wFIFO;}
|
|
|
|
/** attach the radioInterface transmit FIFO */
|
|
void transmitFIFO(VectorFIFO *wFIFO) { mTransmitFIFO = wFIFO;}
|
|
|
|
/** 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 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();
|
|
|
|
friend void *RxServiceLoopAdapter(Transceiver *);
|
|
|
|
friend void *TxServiceLoopAdapter(Transceiver *);
|
|
|
|
friend void *ControlServiceLoopAdapter(Transceiver *);
|
|
|
|
friend void *TransmitPriorityQueueServiceLoopAdapter(Transceiver *);
|
|
|
|
void reset();
|
|
|
|
/** set priority on current thread */
|
|
void setPriority() { mRadioInterface->setPriority(); }
|
|
|
|
};
|
|
|
|
/** Main drive threads */
|
|
void *RxServiceLoopAdapter(Transceiver *);
|
|
void *TxServiceLoopAdapter(Transceiver *);
|
|
|
|
/** control message handler thread loop */
|
|
void *ControlServiceLoopAdapter(Transceiver *);
|
|
|
|
/** transmit queueing thread loop */
|
|
void *TransmitPriorityQueueServiceLoopAdapter(Transceiver *);
|
|
|