Compare commits

..

15 Commits

Author SHA1 Message Date
Max
f38a0c06dc Add .gitignore 2016-06-15 16:53:49 +02:00
Tom Tsou
3b093bb13b uhd: Set minimum UHD version requirement for E3XX
Create runtime version check for minimum supported UHD driver
when using USRP E3XX devices. The minimum version, 3.9.0, matches
supported version on current E3XX release images.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-05-03 19:06:56 -07:00
Tom Tsou
3f4a13f049 uhd: Make device offset check a private method
Removes extra arguments and a static call.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-05-03 19:04:00 -07:00
Tom Tsou
0fe41a583c uhd: Set default Tx sampling to 4 sps
The majority of GSM host platforms are capable of operating with
the 4x oversampled modulator, which justifies the new default
setting. The small number exceptions (e.g. Raspberry Pi) can still
use the lower complexity 1 sps modulator with the '-s 1' command
line option if required.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-05-03 15:17:39 -07:00
Tom Tsou
a5e0f1cdba uhd: Update default E3XX settings
Tune timing values after testing on UHD 003.009.002 for E3XX.
Table value for 1 sps was off by 10 samples causing improper
operation. Table value for 4 sps was shifted by 1 sample for
more accurate timing.

Also update E3XX description string detection.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-05-03 15:14:06 -07:00
Tom Tsou
2c650a6895 common: Add mandatory length field to UDP receive calls
Current UDP receive reads up to MAX_UDP_LENGTH bytes into the
passed in buffer, which may lead to buffer overflow if the
write buffer is of insufficient size.

Add mandatory length argument to UDP socket receive calls.

Reported-by: Simone Margaritelli <simone@zimperium.com>
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-05-02 17:37:05 -07:00
Tom Tsou
d4555f267e common: Restrict UDP binding to localhost only
Reported security vulnerability where control and data UDP
packets can be injected into the transceiver externally due
to socket binding to all interfaces using INADDR_ANY.

Existing socket interface does not allow specifying local
address; only the local port and remote address/port are
arguments.

Restrict socket bind to localhost with INADDR_LOOPBACK. If
external interfaces do need to be used, the API should be
modified to allow specifying the local socket address.

Reported-by: Simone Margaritelli <simone@zimperium.com>
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-05-02 17:35:01 -07:00
Tom Tsou
047956259b EDGE: Fix demodulation slicer input
EDGE 8-PSK soft slicer was receiving input from the output of the
downsampler. Equalization and derotation were missing causing the
soft symbol output to be invalid.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-04-26 21:20:43 -07:00
Tom Tsou
d2b070369d uhd: Correct timing alignment in 8-PSK and GMSK downlink bursts
Delay the EDGE downlink bursts by one symbol in order to match GMSK
pulse shaping group delay. The difference in group delay arises from
the dual pulse filter combination of the GMSK Laurent represenation
whereas 8-PSK uses a single pulse linear filter.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-04-26 19:31:14 -07:00
Alexander Chemeris
9664c3a6e7 transceiver: Do not pass transceiver state struct to function where it's not used. 2016-04-26 12:03:20 -07:00
Alexander Chemeris
1ab5e7f7bc osmo-trx: Output Rx SPS as a part of configuration output. 2016-04-26 12:02:51 -07:00
Alexander Chemeris
5efe05021a transceiver: Add an option to generate random Access Bursts. 2016-04-20 13:46:02 -07:00
Alexander Chemeris
78d1fc9a13 transceiver: Properly handle MAXDLY.
Previously MAXDLY value was applied to Normal Bursts, which was nice
when working with sloppy test equipment like CMD57, but useless for
real world usage. At the same time documentation and de facto usage
of MAXDLY in OsmoBTS and OpenBTS assumed that it actually applies to
Access Bursts (RACH). So this patch changes osmo-rx behavior to apply
MAXDLY to RACH bursts and introduces a new command MAXDLYNB for the
old behavior.
2016-04-20 13:45:00 -07:00
Alexander Chemeris
a8cf208616 Common: Make sure gLogEarly() log to the same facilities as the normal log. 2016-04-20 12:33:41 -07:00
Alexander Chemeris
f84232d30a Common: Get rid of a compilation warning.
debugLogEarly was replaced to an empty space and arguments of the function
became operators, grouped together by ():
Configuration.cpp: In member function 'bool ConfigurationTable::defines(const string&)':
Configuration.cpp:272:28: warning: left operand of comma operator has no effect [-Wunused-value]
   debugLogEarly(LOG_ALERT, "configuration parameter %s not found", key.c_str());
                            ^

This fix removes debugLogEarly together with its arguments.
2016-04-20 12:26:57 -07:00
12 changed files with 216 additions and 156 deletions

56
.gitignore vendored Normal file
View File

@@ -0,0 +1,56 @@
.deps
.libs
*.o
*.lo
CommonLibs/BitVectorTest
CommonLibs/ConfigurationTest
CommonLibs/F16Test
CommonLibs/InterthreadTest
CommonLibs/LogTest
CommonLibs/Makefile
CommonLibs/Makefile.in
CommonLibs/RegexpTest
CommonLibs/SocketsTest
CommonLibs/TimevalTest
CommonLibs/URLEncodeTest
CommonLibs/VectorTest
CommonLibs/libcommon.la
GSM/Makefile
GSM/Makefile.in
GSM/libGSM.la
Makefile
Makefile.in
Transceiver52M/Makefile
Transceiver52M/Makefile.in
Transceiver52M/arm/Makefile
Transceiver52M/arm/Makefile.in
Transceiver52M/common/.dirstamp
Transceiver52M/libtransceiver.la
Transceiver52M/osmo-trx
Transceiver52M/x86/Makefile
Transceiver52M/x86/Makefile.in
Transceiver52M/x86/libarch.la
aclocal.m4
autom4te.cache/
compile
config.guess
config.h
config.h.in
config.log
config.status
config.sub
config/libtool.m4
config/ltoptions.m4
config/ltsugar.m4
config/ltversion.m4
config/lt~obsolete.m4
configure
depcomp
install-sh
libtool
ltmain.sh
missing
sqlite3/Makefile
sqlite3/Makefile.in
sqlite3/libsqlite.la
stamp-h1

View File

@@ -187,24 +187,20 @@ int DatagramSocket::send(const struct sockaddr* dest, const char * message)
return send(dest,message,length);
}
int DatagramSocket::read(char* buffer)
int DatagramSocket::read(char* buffer, size_t length)
{
socklen_t temp_len = sizeof(mSource);
int length = recvfrom(mSocketFD, (void*)buffer, MAX_UDP_LENGTH, 0,
(struct sockaddr*)&mSource,&temp_len);
if ((length==-1) && (errno!=EAGAIN)) {
socklen_t addr_len = sizeof(mSource);
int rd_length = recvfrom(mSocketFD, (void *) buffer, length, 0,
(struct sockaddr*) &mSource, &addr_len);
if ((rd_length==-1) && (errno!=EAGAIN)) {
perror("DatagramSocket::read() failed");
throw SocketError();
}
return length;
return rd_length;
}
int DatagramSocket::read(char* buffer, unsigned timeout)
int DatagramSocket::read(char* buffer, size_t length, unsigned timeout)
{
fd_set fds;
FD_ZERO(&fds);
@@ -218,7 +214,7 @@ int DatagramSocket::read(char* buffer, unsigned timeout)
throw SocketError();
}
if (sel==0) return -1;
if (FD_ISSET(mSocketFD,&fds)) return read(buffer);
if (FD_ISSET(mSocketFD,&fds)) return read(buffer, length);
return -1;
}
@@ -269,7 +265,7 @@ void UDPSocket::open(unsigned short localPort)
size_t length = sizeof(address);
bzero(&address,length);
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
address.sin_port = htons(localPort);
if (bind(mSocketFD,(struct sockaddr*)&address,length)<0) {
perror("bind() failed");

View File

@@ -108,7 +108,7 @@ public:
@param buffer A char[MAX_UDP_LENGTH] procured by the caller.
@return The number of bytes received or -1 on non-blocking pass.
*/
int read(char* buffer);
int read(char* buffer, size_t length);
/**
Receive a packet with a timeout.
@@ -116,7 +116,7 @@ public:
@param maximum wait time in milliseconds
@return The number of bytes received or -1 on timeout.
*/
int read(char* buffer, unsigned timeout);
int read(char* buffer, size_t length, unsigned timeout);
/** Send a packet to a given destination, other than the default. */

View File

@@ -42,7 +42,7 @@ void *testReaderIP(void *)
int rc = 0;
while (rc<gNumToSend) {
char buf[MAX_UDP_LENGTH];
int count = readSocket.read(buf);
int count = readSocket.read(buf, MAX_UDP_LENGTH);
if (count>0) {
COUT("read: " << buf);
rc++;
@@ -62,7 +62,7 @@ void *testReaderUnix(void *)
int rc = 0;
while (rc<gNumToSend) {
char buf[MAX_UDP_LENGTH];
int count = readSocket.read(buf);
int count = readSocket.read(buf, MAX_UDP_LENGTH);
if (count>0) {
COUT("read: " << buf);
rc++;

View File

@@ -71,7 +71,7 @@ TransceiverState::~TransceiverState()
}
}
bool TransceiverState::init(int filler, size_t sps, float scale, size_t rtsc, unsigned rach_delay)
bool TransceiverState::init(int filler, size_t sps, float scale, size_t rtsc)
{
signalVector *burst;
@@ -91,7 +91,7 @@ bool TransceiverState::init(int filler, size_t sps, float scale, size_t rtsc, un
burst = generateEdgeBurst(rtsc);
break;
case Transceiver::FILLER_ACCESS_RAND:
burst = genRandAccessBurst(rach_delay, sps, n);
burst = genRandAccessBurst(sps, n);
break;
case Transceiver::FILLER_ZERO:
default:
@@ -122,7 +122,7 @@ Transceiver::Transceiver(int wBasePort,
mTransmitLatency(wTransmitLatency), mRadioInterface(wRadioInterface),
rssiOffset(wRssiOffset),
mSPSTx(tx_sps), mSPSRx(rx_sps), mChans(chans), mOn(false),
mTxFreq(0.0), mRxFreq(0.0), mTSC(0), mMaxExpectedDelayAB(2*rx_sps), mMaxExpectedDelayNB(2*rx_sps),
mTxFreq(0.0), mRxFreq(0.0), mTSC(0), mMaxExpectedDelayAB(0), mMaxExpectedDelayNB(0),
mWriteBurstToDiskMask(0)
{
txFullScale = mRadioInterface->fullScaleInputValue();
@@ -160,7 +160,7 @@ Transceiver::~Transceiver()
* are still expected to report clock indications through control channel
* activity.
*/
bool Transceiver::init(int filler, size_t rtsc, unsigned rach_delay)
bool Transceiver::init(int filler, size_t rtsc)
{
int d_srcport, d_dstport, c_srcport, c_dstport;
@@ -216,7 +216,7 @@ bool Transceiver::init(int filler, size_t rtsc, unsigned rach_delay)
if (i && filler == FILLER_DUMMY)
filler = FILLER_ZERO;
mStates[i].init(filler, mSPSTx, txFullScale, rtsc, rach_delay);
mStates[i].init(filler, mSPSTx, txFullScale, rtsc);
}
return true;
@@ -531,8 +531,8 @@ Transceiver::CorrType Transceiver::expectedCorrType(GSM::Time currTime,
}
}
int Transceiver::detectBurst(TransceiverState *state, signalVector &burst,
complex &amp, float &toa, CorrType type)
int Transceiver::detectBurst(signalVector &burst,
complex &amp, float &toa, CorrType type)
{
float threshold = 5.0, rc = 0;
@@ -567,8 +567,7 @@ int Transceiver::detectBurst(TransceiverState *state, signalVector &burst,
/*
* Demodulate GMSK by direct rotation and soft slicing.
*/
SoftVector *Transceiver::demodulate(TransceiverState *state,
signalVector &burst, complex amp,
SoftVector *Transceiver::demodulate(signalVector &burst, complex amp,
float toa, CorrType type)
{
if (type == EDGE)
@@ -666,7 +665,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
}
/* Detect normal or RACH bursts */
rc = detectBurst(state, *burst, amp, toa, type);
rc = detectBurst(*burst, amp, toa, type);
if (rc > 0) {
type = (CorrType) rc;
@@ -683,7 +682,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
timingOffset = toa / mSPSRx;
bits = demodulate(state, *burst, amp, toa, type);
bits = demodulate(*burst, amp, toa, type);
delete radio_burst;
return bits;
@@ -705,7 +704,7 @@ void Transceiver::driveControl(size_t chan)
int msgLen = -1;
buffer[0] = '\0';
msgLen = mCtrlSockets[chan]->read(buffer);
msgLen = mCtrlSockets[chan]->read(buffer, sizeof(buffer));
if (msgLen < 1) {
return;
@@ -873,7 +872,7 @@ bool Transceiver::driveTxPriorityQueue(size_t chan)
char buffer[gSlotLen+50];
// check data socket
size_t msgLen = mDataSockets[chan]->read(buffer);
size_t msgLen = mDataSockets[chan]->read(buffer, sizeof(buffer));
if (msgLen!=gSlotLen+1+4+1) {
LOG(ERR) << "badly formatted packet on GSM->TRX interface";
@@ -913,11 +912,10 @@ void Transceiver::driveReceiveRadio()
}
}
void Transceiver::logRxBurst(size_t chan, SoftVector *burst, GSM::Time time, double dbm,
void Transceiver::logRxBurst(SoftVector *burst, GSM::Time time, double dbm,
double rssi, double noise, double toa)
{
LOG(DEBUG) << std::fixed << std::right
<< " chan: " << chan
<< " time: " << time
<< " RSSI: " << std::setw(5) << std::setprecision(1) << rssi
<< "dBFS/" << std::setw(6) << -dbm << "dBm"
@@ -950,7 +948,7 @@ void Transceiver::driveReceiveFIFO(size_t chan)
nbits = gSlotLen * 3;
dBm = RSSI + rssiOffset;
logRxBurst(chan, rxBurst, burstTime, dBm, RSSI, noise, TOA);
logRxBurst(rxBurst, burstTime, dBm, RSSI, noise, TOA);
TOAint = (int) (TOA * 256.0 + 0.5); // round to closest integer

View File

@@ -54,7 +54,7 @@ struct TransceiverState {
~TransceiverState();
/* Initialize a multiframe slot in the filler table */
bool init(int filler, size_t sps, float scale, size_t rtsc, unsigned rach_delay);
bool init(int filler, size_t sps, float scale, size_t rtsc);
int chanType[8];
@@ -107,7 +107,7 @@ public:
~Transceiver();
/** Start the control loop */
bool init(int filler, size_t rtsc, unsigned rach_delay);
bool init(int filler, size_t rtsc);
/** attach the radioInterface receive FIFO */
bool receiveFIFO(VectorFIFO *wFIFO, size_t chan)
@@ -212,11 +212,11 @@ private:
void writeClockInterface(void);
/** Detectbursts */
int detectBurst(TransceiverState *state, signalVector &burst,
int detectBurst(signalVector &burst,
complex &amp, float &toa, CorrType type);
/** Demodulate burst and output soft bits */
SoftVector *demodulate(TransceiverState *state, signalVector &burst,
SoftVector *demodulate(signalVector &burst,
complex amp, float toa, CorrType type);
int mSPSTx; ///< number of samples per Tx symbol
@@ -276,7 +276,7 @@ protected:
/** set priority on current thread */
void setPriority(float prio = 0.5) { mRadioInterface->setPriority(prio); }
void logRxBurst(size_t chan, SoftVector *burst, GSM::Time time, double dbm,
void logRxBurst(SoftVector *burst, GSM::Time time, double dbm,
double rssi, double noise, double toa);
};

View File

@@ -68,8 +68,8 @@ enum uhd_dev_type {
struct uhd_dev_offset {
enum uhd_dev_type type;
int tx_sps;
int rx_sps;
size_t tx_sps;
size_t rx_sps;
double offset;
const std::string desc;
};
@@ -80,11 +80,11 @@ struct uhd_dev_offset {
#ifdef USE_UHD_3_9
#define B2XX_TIMING_1SPS 1.7153e-4
#define B2XX_TIMING_4SPS 1.1696e-4
#define B2XX_TIMING_4_4SPS 5.89578e-5
#define B2XX_TIMING_4_4SPS 6.18462e-5
#else
#define B2XX_TIMING_1SPS 9.9692e-5
#define B2XX_TIMING_4SPS 6.9248e-5
#define B2XX_TIMING_4_4SPS 4.19034e-5
#define B2XX_TIMING_4_4SPS 4.52308e-5
#endif
/*
@@ -110,8 +110,8 @@ static struct uhd_dev_offset uhd_offsets[] = {
{ B210, 4, 1, B2XX_TIMING_4SPS, "B210 4 SPS" },
{ E1XX, 1, 1, 9.5192e-5, "E1XX 1 SPS" },
{ E1XX, 4, 1, 6.5571e-5, "E1XX 4 SPS" },
{ E3XX, 1, 1, 1.5000e-4, "E3XX 1 SPS" },
{ E3XX, 4, 1, 1.2740e-4, "E3XX 4 SPS" },
{ E3XX, 1, 1, 1.84616e-4, "E3XX 1 SPS" },
{ E3XX, 4, 1, 1.29231e-4, "E3XX 4 SPS" },
{ X3XX, 1, 1, 1.5360e-4, "X3XX 1 SPS"},
{ X3XX, 4, 1, 1.1264e-4, "X3XX 4 SPS"},
{ UMTRX, 1, 1, 9.9692e-5, "UmTRX 1 SPS" },
@@ -131,63 +131,6 @@ static struct uhd_dev_offset special_offsets[] = {
{ UMTRX, 4, 1, 5.2103e-5, "UmTRX diversity, 4 SPS" },
};
static double get_dev_offset(enum uhd_dev_type type, int tx_sps, int rx_sps,
bool edge = false, bool diversity = false)
{
struct uhd_dev_offset *offset = NULL;
/* Reject USRP1 */
if (type == USRP1) {
LOG(ERR) << "Invalid device type";
return 0.0;
}
if (edge && diversity) {
LOG(ERR) << "Unsupported configuration";
return 0.0;
}
if (edge && (type != B200) && (type != B210) && (type != UMTRX)) {
LOG(ALERT) << "EDGE is supported on B200/B210 and UmTRX only";
return 0.0;
}
/* Special cases (e.g. diversity receiver) */
if (diversity) {
if (type != UMTRX) {
LOG(ALERT) << "Diversity on UmTRX only";
return 0.0;
}
switch (tx_sps) {
case 1:
offset = &special_offsets[0];
break;
case 4:
default:
offset = &special_offsets[1];
}
} else {
/* Search for matching offset value */
for (size_t i = 0; i < NUM_UHD_OFFSETS; i++) {
if ((type == uhd_offsets[i].type) &&
(tx_sps == uhd_offsets[i].tx_sps) &&
(rx_sps == uhd_offsets[i].rx_sps)) {
offset = &uhd_offsets[i];
break;
}
}
}
if (!offset) {
LOG(ERR) << "Invalid device configuration";
return 0.0;
}
std::cout << "-- Setting " << offset->desc << std::endl;
return offset->offset;
}
/*
* Select sample rate based on device type and requested samples-per-symbol.
@@ -385,6 +328,7 @@ private:
std::vector<smpl_buf *> rx_buffers;
void init_gains();
double get_dev_offset(bool edge, bool diversity);
int set_master_clk(double rate);
int set_rates(double tx_rate, double rx_rate);
bool parse_dev_type();
@@ -513,6 +457,64 @@ void uhd_device::init_gains()
}
double uhd_device::get_dev_offset(bool edge, bool diversity)
{
struct uhd_dev_offset *offset = NULL;
/* Reject USRP1 */
if (dev_type == USRP1) {
LOG(ERR) << "Invalid device type";
return 0.0;
}
if (edge && diversity) {
LOG(ERR) << "Unsupported configuration";
return 0.0;
}
if (edge && (dev_type != B200) &&
(dev_type != B210) && (dev_type != UMTRX)) {
LOG(ALERT) << "EDGE is supported on B200/B210 and UmTRX only";
return 0.0;
}
/* Special cases (e.g. diversity receiver) */
if (diversity) {
if (dev_type != UMTRX) {
LOG(ALERT) << "Diversity on UmTRX only";
return 0.0;
}
switch (tx_sps) {
case 1:
offset = &special_offsets[0];
break;
case 4:
default:
offset = &special_offsets[1];
}
} else {
/* Search for matching offset value */
for (size_t i = 0; i < NUM_UHD_OFFSETS; i++) {
if ((dev_type == uhd_offsets[i].type) &&
(tx_sps == uhd_offsets[i].tx_sps) &&
(rx_sps == uhd_offsets[i].rx_sps)) {
offset = &uhd_offsets[i];
break;
}
}
}
if (!offset) {
LOG(ERR) << "Invalid device configuration";
return 0.0;
}
std::cout << "-- Setting " << offset->desc << std::endl;
return offset->offset;
}
int uhd_device::set_master_clk(double clk_rate)
{
double actual, offset, limit = 1.0;
@@ -643,7 +645,7 @@ bool uhd_device::parse_dev_type()
{
std::string mboard_str, dev_str;
uhd::property_tree::sptr prop_tree;
size_t usrp1_str, usrp2_str, e100_str, e110_str, e310_str,
size_t usrp1_str, usrp2_str, e100_str, e110_str, e310_str, e3xx_str,
b100_str, b200_str, b210_str, x300_str, x310_str, umtrx_str;
prop_tree = usrp_dev->get_device()->get_tree();
@@ -658,6 +660,7 @@ bool uhd_device::parse_dev_type()
e100_str = mboard_str.find("E100");
e110_str = mboard_str.find("E110");
e310_str = mboard_str.find("E310");
e3xx_str = mboard_str.find("E3XX");
x300_str = mboard_str.find("X300");
x310_str = mboard_str.find("X310");
umtrx_str = dev_str.find("UmTRX");
@@ -687,7 +690,8 @@ bool uhd_device::parse_dev_type()
} else if (usrp2_str != std::string::npos) {
tx_window = TX_WINDOW_FIXED;
dev_type = USRP2;
} else if (e310_str != std::string::npos) {
} else if ((e310_str != std::string::npos) ||
(e3xx_str != std::string::npos)) {
tx_window = TX_WINDOW_FIXED;
dev_type = E3XX;
} else if (x300_str != std::string::npos) {
@@ -700,7 +704,8 @@ bool uhd_device::parse_dev_type()
tx_window = TX_WINDOW_FIXED;
dev_type = UMTRX;
} else {
LOG(ALERT) << "Unknown UHD device type " << dev_str;
LOG(ALERT) << "Unknown UHD device type "
<< dev_str << " " << mboard_str;
return false;
}
@@ -715,6 +720,26 @@ bool uhd_device::parse_dev_type()
return true;
}
/*
* Check for UHD version > 3.9.0 for E3XX support
*/
static bool uhd_e3xx_version_chk()
{
std::string ver = uhd::get_version_string();
std::string major_str(ver.begin(), ver.begin() + 3);
std::string minor_str(ver.begin() + 4, ver.begin() + 7);
int major_val = atoi(major_str.c_str());
int minor_val = atoi(minor_str.c_str());
if (major_val < 3)
return false;
if (minor_val < 9)
return false;
return true;
}
int uhd_device::open(const std::string &args, bool extref, bool swap_channels)
{
// Find UHD devices
@@ -738,6 +763,11 @@ int uhd_device::open(const std::string &args, bool extref, bool swap_channels)
if (!parse_dev_type())
return -1;
if ((dev_type == E3XX) && !uhd_e3xx_version_chk()) {
LOG(ALERT) << "E3XX requires UHD 003.009.000 or greater";
return -1;
}
// Verify and set channels
if ((dev_type == B210) && (chans == 2)) {
} else if ((dev_type == UMTRX) && (chans == 2)) {
@@ -801,7 +831,7 @@ int uhd_device::open(const std::string &args, bool extref, bool swap_channels)
if (rx_sps == 4)
edge = true;
double offset = get_dev_offset(dev_type, tx_sps, rx_sps, edge, diversity);
double offset = get_dev_offset(edge, diversity);
if (offset == 0.0) {
LOG(ERR) << "Unsupported configuration, no correction applied";
ts_offset = 0;

View File

@@ -37,14 +37,9 @@
* 1 - Uses minimized modulator (less computation, more distortion)
*
* Other values are invalid. Receive path (uplink) is always
* downsampled to 1 sps. Default to 4 sps for all cases except for
* ARM and non-SIMD enabled architectures.
* downsampled to 1 sps. Default to 4 sps for all cases.
*/
#if defined(HAVE_NEON) || !defined(HAVE_SSE3)
#define DEFAULT_TX_SPS 1
#else
#define DEFAULT_TX_SPS 4
#endif
/*
* Samples-per-symbol for uplink (receiver) path
@@ -75,7 +70,6 @@ struct trx_config {
unsigned rx_sps;
unsigned chans;
unsigned rtsc;
unsigned rach_delay;
bool extref;
Transceiver::FillerType filler;
bool diversity;
@@ -201,6 +195,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 << " Rx Samples-per-Symbol... " << config->rx_sps << std::endl;
ost << " EDGE support............ " << edgestr << std::endl;
ost << " External Reference...... " << refstr << std::endl;
ost << " C0 Filler Table......... " << fillstr << std::endl;
@@ -270,7 +265,7 @@ Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
trx = new Transceiver(config->port, config->addr.c_str(),
config->tx_sps, config->rx_sps, config->chans,
GSM::Time(3,0), radio, config->rssi_offset);
if (!trx->init(config->filler, config->rtsc, config->rach_delay)) {
if (!trx->init(config->filler, config->rtsc)) {
LOG(ALERT) << "Failed to initialize transceiver";
delete trx;
return NULL;
@@ -322,8 +317,8 @@ static void print_help()
" -c Number of ARFCN channels (default=1)\n"
" -f Enable C0 filler table\n"
" -o Set baseband frequency offset (default=auto)\n"
" -r Random Normal Burst test mode with TSC\n"
" -A Random Access Burst test mode with delay\n"
" -r Random burst test mode with TSC\n"
" -A Random burst test mode with Access Bursts\n"
" -R RSSI to dBm offset in dB (default=0)\n"
" -S Swap channels (UmTRX only)\n",
"EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
@@ -338,7 +333,6 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
config->rx_sps = DEFAULT_RX_SPS;
config->chans = DEFAULT_CHANS;
config->rtsc = 0;
config->rach_delay = 0;
config->extref = false;
config->filler = Transceiver::FILLER_ZERO;
config->diversity = false;
@@ -347,7 +341,7 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
config->swap_channels = false;
config->edge = false;
while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:r:A:R:Se")) != -1) {
while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:r:AR:Se")) != -1) {
switch (option) {
case 'h':
print_help();
@@ -388,7 +382,6 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
config->filler = Transceiver::FILLER_NORM_RAND;
break;
case 'A':
config->rach_delay = atoi(optarg);
config->filler = Transceiver::FILLER_ACCESS_RAND;
break;
case 'R':
@@ -427,12 +420,6 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
print_help();
exit(0);
}
if (config->rach_delay > 68) {
printf("RACH delay is too big %i\n\n", config->rach_delay);
print_help();
exit(0);
}
}
int main(int argc, char *argv[])

View File

@@ -935,26 +935,35 @@ static signalVector *mapEdgeSymbols(const BitVector &bits)
return symbols;
}
/*
* EDGE 8-PSK rotate and pulse shape
*
* Delay the EDGE downlink bursts by one symbol in order to match GMSK pulse
* shaping group delay. The difference in group delay arises from the dual
* pulse filter combination of the GMSK Laurent represenation whereas 8-PSK
* uses a single pulse linear filter.
*/
static signalVector *shapeEdgeBurst(const signalVector &symbols)
{
size_t nsyms, nsamps = 625;
size_t nsyms, nsamps = 625, sps = 4;
signalVector *burst, *shape;
signalVector::iterator burst_itr;
nsyms = symbols.size();
if (nsyms * 4 > nsamps)
if (nsyms * sps > nsamps)
nsyms = 156;
burst = new signalVector(nsamps, GSMPulse4->c0->size());
burst_itr = burst->begin();
for (size_t i = 0; i < nsyms; i++) {
/* Delay burst by 1 symbol */
burst_itr = burst->begin() + sps;
for (size_t i = 0; i < nsyms - 1; i++) {
float phase = i * 3.0f * M_PI / 8.0f;
Complex<float> rot = Complex<float>(cos(phase), sin(phase));
*burst_itr = symbols[i] * rot;
burst_itr += 4;
burst_itr += sps;
}
/* Single Gaussian pulse approximation shaping */
@@ -1008,36 +1017,30 @@ signalVector *genRandNormalBurst(int tsc, int sps, int tn)
/*
* Generate a random GSM access burst.
*/
signalVector *genRandAccessBurst(int delay, int sps, int tn)
signalVector *genRandAccessBurst(int sps, int tn)
{
if ((tn < 0) || (tn > 7))
return NULL;
if ((sps != 1) && (sps != 4))
return NULL;
if (delay > 68)
return NULL;
int i = 0;
BitVector *bits = new BitVector(88+delay);
BitVector *bits = new BitVector(88);
signalVector *burst;
/* delay */
for (; i < delay; i++)
(*bits)[i] = 0;
/* head and synch bits */
for (int n = 0; i < 49+delay; i++, n++)
for (int n = 0; i < 49; i++, n++)
(*bits)[i] = gRACHBurst[n];
/* Random bits */
for (; i < 85+delay; i++)
for (; i < 85; i++)
(*bits)[i] = rand() % 2;
/* Tail bits */
for (; i < 88+delay; i++)
for (; i < 88; i++)
(*bits)[i] = 0;
int guard = 68-delay + !(tn % 4);
int guard = 68 + !(tn % 4);
burst = modulateBurst(*bits, guard, sps);
delete bits;
@@ -1855,7 +1858,7 @@ int detectGeneralBurst(signalVector &rxBurst,
*
* Correlation window parameters:
* target: Tail bits + RACH length (reduced from 41 to a multiple of 4)
* head: Search 8 symbols before target
* head: Search 4 symbols before target
* tail: Search 4 symbols + maximum expected delay
*/
int detectRACHBurst(signalVector &rxBurst,
@@ -1869,7 +1872,7 @@ int detectRACHBurst(signalVector &rxBurst,
CorrelationSequence *sync;
target = 8 + 40;
head = 8;
head = 4;
tail = 4 + maxTOA;
sync = gRACHSequence;
@@ -2086,7 +2089,7 @@ SoftVector *demodEdgeBurst(signalVector &burst, int sps,
rot = derotateEdgeBurst(*eq, 1);
/* Soft slice and normalize */
bits = softSliceEdgeBurst(*dec);
bits = softSliceEdgeBurst(*rot);
vectorSlicer(bits);
delete dec;

View File

@@ -123,7 +123,7 @@ signalVector *generateEmptyBurst(int sps, int tn);
signalVector *genRandNormalBurst(int tsc, int sps, int tn);
/** Generate an access GSM burst with random payload - 4 or 1 SPS */
signalVector *genRandAccessBurst(int delay, int sps, int tn);
signalVector *genRandAccessBurst(int sps, int tn);
/** Generate a dummy GSM burst - 4 or 1 SPS */
signalVector *generateDummyBurst(int sps, int tn);

7
debian/changelog vendored
View File

@@ -1,10 +1,3 @@
osmo-trx (0.1.10~1) trusty; urgency=medium
* some EDGE support in master
* fairwaves/rach-filler branch
-- Kirill Zakharenko <earwin@gmail.com> Sun, 27 Mar 2016 19:37:39 +0100
osmo-trx (0.1.9) trusty; urgency=medium
* Ask Ivan, really

3
debian/rules vendored
View File

@@ -5,9 +5,6 @@ DEB_BUILD_HARDENING=1
%:
dh $@ --with autoreconf
override_dh_auto_configure:
dh_auto_configure -- --without-sse CFLAGS="-DHAVE_SSE3 -march=atom -mtune=atom -O2" CXXFLAGS="-DHAVE_SSE3 -march=atom -mtune=atom -O2"
override_dh_shlibdeps:
dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info