aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tsou <tom.tsou@ettus.com>2016-03-06 03:44:34 -0800
committerTom Tsou <tom.tsou@ettus.com>2016-03-08 17:44:53 -0800
commitb0aefcbf47ed2eec1e4f3fd9bed72dde999913bf (patch)
treec9c605a9cca3890fc9c5c9e64c42279465bc1b3f
parentd325343ecca5c6484eeda5ebf9e230c810ea4b82 (diff)
EDGE: Add interfaces to enable EDGE transceiver
Create EDGE slot type in the Transceiver. When EDGE mode is enabled for a particular slot, blind detection will be performed by correlating against EDGE followed by normal bursts if no EDGE burst is found. Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
-rw-r--r--Transceiver52M/Transceiver.cpp105
-rw-r--r--Transceiver52M/Transceiver.h5
-rw-r--r--Transceiver52M/osmo-trx.cpp23
-rw-r--r--Transceiver52M/sigProcLib.h5
4 files changed, 99 insertions, 39 deletions
diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp
index 2be7ab0..255e120 100644
--- a/Transceiver52M/Transceiver.cpp
+++ b/Transceiver52M/Transceiver.cpp
@@ -367,7 +367,12 @@ void Transceiver::addRadioVector(size_t chan, BitVector &bits,
return;
}
- burst = modulateBurst(bits, 8 + (wTime.TN() % 4 == 0), mSPSTx);
+ /* Use the number of bits as the EDGE burst indicator */
+ if (bits.size() == EDGE_BURST_NBITS)
+ burst = modulateEdgeBurst(bits, mSPSTx);
+ else
+ burst = modulateBurst(bits, 8 + (wTime.TN() % 4 == 0), mSPSTx);
+
scaleVector(*burst, txFullScale * pow(10, -RSSI / 10));
radio_burst = new radioVector(wTime, burst);
@@ -561,6 +566,13 @@ int Transceiver::detectBurst(TransceiverState *state, signalVector &burst,
float threshold = 5.0, rc = 0;
switch (type) {
+ case EDGE:
+ rc = detectEdgeBurst(burst, mTSC, threshold, mSPSRx,
+ amp, toa, mMaxExpectedDelay);
+ if (rc > 0)
+ break;
+ else
+ type = TSC;
case TSC:
rc = analyzeTrafficBurst(burst, mTSC, threshold, mSPSRx,
amp, toa, mMaxExpectedDelay);
@@ -573,6 +585,8 @@ int Transceiver::detectBurst(TransceiverState *state, signalVector &burst,
LOG(ERR) << "Invalid correlation type";
}
+ if (rc > 0)
+ return type;
return rc;
}
@@ -583,8 +597,11 @@ int Transceiver::detectBurst(TransceiverState *state, signalVector &burst,
*/
SoftVector *Transceiver::demodulate(TransceiverState *state,
signalVector &burst, complex amp,
- float toa)
+ float toa, CorrType type)
{
+ if (type == EDGE)
+ return demodEdgeBurst(burst, mSPSRx, amp, toa);
+
return demodulateBurst(burst, mSPSRx, amp, toa);
}
@@ -606,7 +623,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
double &timingOffset, double &noise,
size_t chan)
{
- int success;
+ int rc;
complex amp;
float toa, pow, max = -1.0, avg = 0.0;
int max_i = -1;
@@ -677,13 +694,14 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
}
/* Detect normal or RACH bursts */
- success = detectBurst(state, *burst, amp, toa, type);
+ rc = detectBurst(state, *burst, amp, toa, type);
- /* Alert an error and exit */
- if (success <= 0) {
- if (success == -SIGERR_CLIP) {
+ if (rc > 0) {
+ type = (CorrType) rc;
+ } else if (rc <= 0) {
+ if (rc == -SIGERR_CLIP) {
LOG(WARNING) << "Clipping detected on received RACH or Normal Burst";
- } else if (success != SIGERR_NONE) {
+ } else if (rc != SIGERR_NONE) {
LOG(WARNING) << "Unhandled RACH or Normal Burst detection error";
}
@@ -693,7 +711,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
timingOffset = toa / mSPSRx;
- bits = demodulate(state, *burst, amp, toa);
+ bits = demodulate(state, *burst, amp, toa, type);
delete radio_burst;
return bits;
@@ -916,6 +934,19 @@ void Transceiver::driveReceiveRadio()
}
}
+void Transceiver::logRxBurst(SoftVector *burst, GSM::Time time, double dbm,
+ double rssi, double noise, double toa)
+{
+ LOG(DEBUG) << std::fixed << std::right
+ << " time: " << time
+ << " RSSI: " << std::setw(5) << std::setprecision(1) << rssi
+ << "dBFS/" << std::setw(6) << -dbm << "dBm"
+ << " noise: " << std::setw(5) << std::setprecision(1) << noise
+ << "dBFS/" << std::setw(6) << -(noise + rssiOffset) << "dBm"
+ << " TOA: " << std::setw(5) << std::setprecision(2) << toa
+ << " bits: " << *burst;
+}
+
void Transceiver::driveReceiveFIFO(size_t chan)
{
SoftVector *rxBurst = NULL;
@@ -926,37 +957,39 @@ void Transceiver::driveReceiveFIFO(size_t chan)
double noise; // noise level in dBFS
GSM::Time burstTime;
bool isRssiValid; // are RSSI, noise and burstTime valid
+ unsigned nbits = gSlotLen;
rxBurst = pullRadioVector(burstTime, RSSI, isRssiValid, TOA, noise, chan);
+ if (!rxBurst)
+ return;
- if (rxBurst) {
- dBm = RSSI+rssiOffset;
- TOAint = (int) (TOA * 256.0 + 0.5); // round to closest integer
-
- LOG(DEBUG) << std::fixed << std::right
- << " time: " << burstTime
- << " RSSI: " << std::setw(5) << std::setprecision(1) << RSSI << "dBFS/" << std::setw(6) << -dBm << "dBm"
- << " noise: " << std::setw(5) << std::setprecision(1) << noise << "dBFS/" << std::setw(6) << -(noise+rssiOffset) << "dBm"
- << " TOA: " << std::setw(5) << std::setprecision(2) << TOA
- << " bits: " << *rxBurst;
-
- char burstString[gSlotLen+10];
- burstString[0] = burstTime.TN();
- for (int i = 0; i < 4; i++)
- burstString[1+i] = (burstTime.FN() >> ((3-i)*8)) & 0x0ff;
- burstString[5] = (int)dBm;
- burstString[6] = (TOAint >> 8) & 0x0ff;
- burstString[7] = TOAint & 0x0ff;
- SoftVector::iterator burstItr = rxBurst->begin();
-
- for (unsigned int i = 0; i < gSlotLen; i++) {
- burstString[8+i] =(char) round((*burstItr++)*255.0);
- }
- burstString[gSlotLen+9] = '\0';
- delete rxBurst;
+ /*
+ * EDGE demodulator returns 444 (148 * 3) bits
+ */
+ if (rxBurst->size() == gSlotLen * 3)
+ nbits = gSlotLen * 3;
- mDataSockets[chan]->write(burstString,gSlotLen+10);
- }
+ dBm = RSSI + rssiOffset;
+ logRxBurst(rxBurst, burstTime, dBm, RSSI, noise, TOA);
+
+ TOAint = (int) (TOA * 256.0 + 0.5); // round to closest integer
+
+ char burstString[nbits + 10];
+ burstString[0] = burstTime.TN();
+ for (int i = 0; i < 4; i++)
+ burstString[1+i] = (burstTime.FN() >> ((3-i)*8)) & 0x0ff;
+ burstString[5] = (int)dBm;
+ burstString[6] = (TOAint >> 8) & 0x0ff;
+ burstString[7] = TOAint & 0x0ff;
+ SoftVector::iterator burstItr = rxBurst->begin();
+
+ for (unsigned i = 0; i < nbits; i++)
+ burstString[8 + i] = (char) round((*burstItr++) * 255.0);
+
+ burstString[nbits + 9] = '\0';
+ delete rxBurst;
+
+ mDataSockets[chan]->write(burstString, nbits + 10);
}
void Transceiver::driveTxFIFO()
diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h
index 2fd1aea..fa58053 100644
--- a/Transceiver52M/Transceiver.h
+++ b/Transceiver52M/Transceiver.h
@@ -147,6 +147,7 @@ public:
OFF, ///< timeslot is off
TSC, ///< timeslot should contain a normal burst
RACH, ///< timeslot should contain an access burst
+ EDGE, ///< timeslot should contain an EDGE burst
IDLE ///< timeslot is an idle (or dummy) burst
} CorrType;
@@ -214,7 +215,7 @@ private:
/** Demodulate burst and output soft bits */
SoftVector *demodulate(TransceiverState *state, signalVector &burst,
- complex amp, float toa);
+ complex amp, float toa, CorrType type);
int mSPSTx; ///< number of samples per Tx symbol
int mSPSRx; ///< number of samples per Rx symbol
@@ -272,6 +273,8 @@ protected:
/** set priority on current thread */
void setPriority(float prio = 0.5) { mRadioInterface->setPriority(prio); }
+ void logRxBurst(SoftVector *burst, GSM::Time time, double dbm,
+ double rssi, double noise, double toa);
};
void *RxUpperLoopAdapter(TransceiverChannel *);
diff --git a/Transceiver52M/osmo-trx.cpp b/Transceiver52M/osmo-trx.cpp
index c8fd9a8..e7b2a16 100644
--- a/Transceiver52M/osmo-trx.cpp
+++ b/Transceiver52M/osmo-trx.cpp
@@ -81,6 +81,7 @@ struct trx_config {
double offset;
double rssi_offset;
bool swap_channels;
+ bool edge;
};
ConfigurationTable gConfig;
@@ -130,7 +131,7 @@ bool testConfig()
*/
bool trx_setup_config(struct trx_config *config)
{
- std::string refstr, fillstr, divstr;
+ std::string refstr, fillstr, divstr, edgestr;
if (!testConfig())
return false;
@@ -170,6 +171,7 @@ bool trx_setup_config(struct trx_config *config)
if (config->diversity)
config->chans = 2;
+ edgestr = config->edge ? "Enabled" : "Disabled";
refstr = config->extref ? "Enabled" : "Disabled";
divstr = config->diversity ? "Enabled" : "Disabled";
switch (config->filler) {
@@ -192,6 +194,7 @@ bool trx_setup_config(struct trx_config *config)
ost << " TRX Address............. " << config->addr << std::endl;
ost << " Channels................ " << config->chans << std::endl;
ost << " Tx Samples-per-Symbol... " << config->tx_sps << std::endl;
+ ost << " EDGE support............ " << edgestr << std::endl;
ost << " External Reference...... " << refstr << std::endl;
ost << " C0 Filler Table......... " << fillstr << std::endl;
ost << " Diversity............... " << divstr << std::endl;
@@ -215,6 +218,10 @@ RadioInterface *makeRadioInterface(struct trx_config *config,
{
RadioInterface *radio = NULL;
+ if ((config->rx_sps != 1) && (type != RadioDevice::NORMAL)) {
+ LOG(ALERT) << "Unsupported radio interface configuration";
+ }
+
switch (type) {
case RadioDevice::NORMAL:
radio = new RadioInterface(usrp, config->tx_sps,
@@ -301,6 +308,7 @@ static void print_help()
" -l Logging level (%s)\n"
" -i IP address of GSM core\n"
" -p Base port number\n"
+ " -e Enable EDGE receiver\n"
" -d Enable dual channel diversity receiver\n"
" -x Enable external 10 MHz reference\n"
" -s Samples-per-symbol (1 or 4)\n"
@@ -328,8 +336,9 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
config->offset = 0.0;
config->rssi_offset = 0.0;
config->swap_channels = false;
+ config->edge = false;
- while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:r:R:S")) != -1) {
+ while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:r:R:Se")) != -1) {
switch (option) {
case 'h':
print_help();
@@ -375,6 +384,10 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
case 'S':
config->swap_channels = true;
break;
+ case 'e':
+ config->edge = true;
+ config->rx_sps = 4;
+ break;
default:
print_help();
exit(0);
@@ -387,6 +400,12 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
exit(0);
}
+ if (config->edge && (config->tx_sps != 4)) {
+ printf("EDGE only supported at 4 samples per symbol\n\n");
+ print_help();
+ exit(0);
+ }
+
if (config->rtsc > 7) {
printf("Invalid training sequence %i\n\n", config->rtsc);
print_help();
diff --git a/Transceiver52M/sigProcLib.h b/Transceiver52M/sigProcLib.h
index 2dcc97d..4f9f849 100644
--- a/Transceiver52M/sigProcLib.h
+++ b/Transceiver52M/sigProcLib.h
@@ -20,6 +20,11 @@
#include "BitVector.h"
#include "signalVector.h"
+/* Burst lengths */
+#define NORMAL_BURST_NBITS 148
+#define EDGE_BURST_NBITS 444
+#define EDGE_BURST_NSYMS (EDGE_BURST_NBITS / 3)
+
/** Convolution type indicator */
enum ConvType {
START_ONLY,