aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tsou <tom.tsou@ettus.com>2015-05-19 18:26:31 -0700
committerTom Tsou <tom.tsou@ettus.com>2015-05-19 18:26:31 -0700
commit64ad712daac0a9125e8827ed5d3eac0afcf369ce (patch)
tree85ccf47b217a927571fc9c65e12caf20da20d73f
parent5c7c1783697bea21f77d64338157bb26c5e5c255 (diff)
test: Add command line random normal burst option
-rw-r--r--Transceiver52M/Transceiver.cpp88
-rw-r--r--Transceiver52M/Transceiver.h132
-rw-r--r--Transceiver52M/osmo-trx.cpp44
3 files changed, 164 insertions, 100 deletions
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[])