From 64ad712daac0a9125e8827ed5d3eac0afcf369ce Mon Sep 17 00:00:00 2001 From: Tom Tsou Date: Tue, 19 May 2015 18:26:31 -0700 Subject: test: Add command line random normal burst option --- Transceiver52M/Transceiver.cpp | 88 +++++++++++++++++++++------ Transceiver52M/Transceiver.h | 132 +++++++++++++++++++++-------------------- Transceiver52M/osmo-trx.cpp | 44 ++++++++------ 3 files changed, 164 insertions(+), 100 deletions(-) (limited to 'Transceiver52M') diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp index 31eea60..75d61f3 100644 --- a/Transceiver52M/Transceiver.cpp +++ b/Transceiver52M/Transceiver.cpp @@ -69,18 +69,74 @@ TransceiverState::~TransceiverState() } } -void TransceiverState::init(size_t slot, signalVector *burst, bool fill) +static BitVector *genRandNormalBurst(size_t tsc) { - signalVector *filler; + if (tsc > 7) + return NULL; - for (int i = 0; i < 102; i++) { - if (fill) - filler = new signalVector(*burst); - else - filler = new signalVector(burst->size()); + BitVector *bits = new BitVector(148); + + size_t i = 0; + + /* Tail bits */ + for (; i < 4; i++) + (*bits)[i] = 0; + + /* Random bits */ + for (; i < 61; i++) + (*bits)[i] = rand() % 2; + + /* Training sequence */ + for (; i < 87; i++) + (*bits)[i] = GSM::gTrainingSequence[tsc][i]; + + /* Random bits */ + for (; i < 144; i++) + (*bits)[i] = rand() % 2; + + /* Tail bits */ + for (; i < 148; i++) + (*bits)[i] = 0; + + return bits; +} + +bool TransceiverState::init(int filler, size_t sps, float scale, size_t rtsc) +{ + BitVector *bits; + signalVector *burst; + + if ((sps != 1) && (sps != 4)) + return false; + + for (size_t n = 0; n < 8; n++) { + size_t guard = 8 + !(n % 4); + size_t len = sps == 4 ? 625 : 148 + guard; + + for (size_t i = 0; i < 102; i++) { + switch (filler) { + case Transceiver::FILLER_DUMMY: + burst = modulateBurst(gDummyBurst, guard, sps); + break; + case Transceiver::FILLER_RAND: + bits = genRandNormalBurst(rtsc); + burst = modulateBurst(*bits, guard, sps); + delete bits; + break; + case Transceiver::FILLER_ZERO: + default: + burst = new signalVector(len); + } + + scaleVector(*burst, scale); + fillerTable[i][n] = burst; + } - fillerTable[i][slot] = filler; + if (filler == Transceiver::FILLER_RAND) + chanType[n] = Transceiver::TSC; } + + return false; } Transceiver::Transceiver(int wBasePort, @@ -124,10 +180,9 @@ Transceiver::~Transceiver() * are still expected to report clock indications through control channel * activity. */ -bool Transceiver::init(bool filler) +bool Transceiver::init(int filler, size_t rtsc) { int d_srcport, d_dstport, c_srcport, c_dstport; - signalVector *burst; if (!mChans) { LOG(ALERT) << "No channels assigned"; @@ -141,7 +196,6 @@ bool Transceiver::init(bool filler) mDataSockets.resize(mChans); mCtrlSockets.resize(mChans); - mControlServiceLoopThreads.resize(mChans); mTxPriorityQueueServiceLoopThreads.resize(mChans); mRxServiceLoopThreads.resize(mChans); @@ -151,7 +205,7 @@ bool Transceiver::init(bool filler) mStates.resize(mChans); /* Filler table retransmissions - support only on channel 0 */ - if (filler) + if (filler == FILLER_DUMMY) mStates[0].mRetrans = true; /* Setup sockets */ @@ -179,12 +233,10 @@ bool Transceiver::init(bool filler) mControlServiceLoopThreads[i]->start((void * (*)(void*)) ControlServiceLoopAdapter, (void*) chan); - for (size_t n = 0; n < 8; n++) { - burst = modulateBurst(gDummyBurst, 8 + (n % 4 == 0), mSPSTx); - scaleVector(*burst, txFullScale); - mStates[i].init(n, burst, filler && !i); - delete burst; - } + if (i && filler == FILLER_DUMMY) + filler = FILLER_ZERO; + + mStates[i].init(filler, mSPSTx, txFullScale, rtsc); } return true; diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h index 0b81511..8bcd8e5 100644 --- a/Transceiver52M/Transceiver.h +++ b/Transceiver52M/Transceiver.h @@ -54,7 +54,7 @@ struct TransceiverState { ~TransceiverState(); /* Initialize a multiframe slot in the filler table */ - void init(size_t slot, signalVector *burst, bool fill); + bool init(int filler, size_t sps, float scale, size_t rtsc); int chanType[8]; @@ -88,6 +88,73 @@ struct TransceiverState { /** The Transceiver class, responsible for physical layer of basestation */ class Transceiver { +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 control loop */ + bool init(int filler, size_t rtsc); + + /** attach the radioInterface receive FIFO */ + bool receiveFIFO(VectorFIFO *wFIFO, size_t chan) + { + if (chan >= mReceiveFIFO.size()) + return false; + + mReceiveFIFO[chan] = wFIFO; + return true; + } + + /** accessor for number of channels */ + size_t numChans() const { return mChans; }; + + /** 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; + + /** 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; + + enum { + FILLER_DUMMY, + FILLER_ZERO, + FILLER_RAND, + }; + private: int mBasePort; std::string mAddr; @@ -114,14 +181,6 @@ private: 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; - /** modulate and add a burst to the transmit queue */ void addRadioVector(size_t chan, BitVector &bits, int RSSI, GSM::Time &wTime); @@ -160,7 +219,6 @@ private: signalVector &burst, complex amp, float toa, size_t tn, bool equalize); - int mSPSTx; ///< number of samples per Tx symbol int mSPSRx; ///< number of samples per Rx symbol size_t mChans; @@ -180,60 +238,6 @@ private: /** Protect destructor accessable stop call */ Mutex mLock; -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 control loop */ - bool init(bool filler); - - /** attach the radioInterface receive FIFO */ - bool receiveFIFO(VectorFIFO *wFIFO, size_t chan) - { - if (chan >= mReceiveFIFO.size()) - return false; - - mReceiveFIFO[chan] = wFIFO; - return true; - } - - /** accessor for number of channels */ - size_t numChans() const { return mChans; }; - - /** 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(); diff --git a/Transceiver52M/osmo-trx.cpp b/Transceiver52M/osmo-trx.cpp index db0b2b1..b121e48 100644 --- a/Transceiver52M/osmo-trx.cpp +++ b/Transceiver52M/osmo-trx.cpp @@ -65,6 +65,7 @@ struct trx_config { unsigned port; unsigned sps; unsigned chans; + unsigned rtsc; bool extref; bool filler; bool diversity; @@ -154,12 +155,6 @@ bool trx_setup_config(struct trx_config *config) config->diversity = DEFAULT_DIVERSITY; } - if (!config->sps) - config->sps = DEFAULT_SPS; - - if (!config->chans) - config->chans = DEFAULT_CHANS; - /* Diversity only supported on 2 channels */ if (config->diversity) config->chans = 2; @@ -236,7 +231,7 @@ Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio) trx = new Transceiver(config->port, config->addr.c_str(), config->sps, config->chans, GSM::Time(3,0), radio); - if (!trx->init(config->filler)) { + if (!trx->init(config->filler, config->rtsc)) { LOG(ALERT) << "Failed to initialize transceiver"; delete trx; return NULL; @@ -286,7 +281,8 @@ static void print_help() " -s Samples-per-symbol (1 or 4)\n" " -c Number of ARFCN channels (default=1)\n" " -f Enable C0 filler table\n" - " -o Set baseband frequency offset (default=auto)\n", + " -o Set baseband frequency offset (default=auto)\n" + " -r Random burst test mode with TSC\n", "EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG"); } @@ -295,14 +291,15 @@ static void handle_options(int argc, char **argv, struct trx_config *config) int option; config->port = 0; - config->sps = 0; - config->chans = 0; + config->sps = DEFAULT_SPS; + config->chans = DEFAULT_CHANS; + config->rtsc = 0; config->extref = false; - config->filler = false; + config->filler = Transceiver::FILLER_ZERO; config->diversity = false; config->offset = 0.0; - while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:")) != -1) { + while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:r:")) != -1) { switch (option) { case 'h': print_help(); @@ -330,24 +327,35 @@ static void handle_options(int argc, char **argv, struct trx_config *config) config->extref = true; break; case 'f': - config->filler = true; + config->filler = Transceiver::FILLER_DUMMY; break; case 'o': config->offset = atof(optarg); break; case 's': config->sps = atoi(optarg); - if ((config->sps != 1) && (config->sps != 4)) { - printf("Unsupported samples-per-symbol\n\n"); - print_help(); - exit(0); - } + break; + case 'r': + config->rtsc = atoi(optarg); + config->filler = Transceiver::FILLER_RAND; break; default: print_help(); exit(0); } } + + if ((config->sps != 1) && (config->sps != 4)) { + printf("Unsupported samples-per-symbol %i\n\n", config->sps); + print_help(); + exit(0); + } + + if (config->rtsc > 7) { + printf("Invalid training sequence %i\n\n", config->rtsc); + print_help(); + exit(0); + } } int main(int argc, char *argv[]) -- cgit v1.2.3