mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
synced 2025-11-02 13:13:17 +00:00
Compare commits
23 Commits
fairwaves/
...
ttsou/mast
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5463584a9f | ||
|
|
047956259b | ||
|
|
d2b070369d | ||
|
|
9664c3a6e7 | ||
|
|
1ab5e7f7bc | ||
|
|
5efe05021a | ||
|
|
78d1fc9a13 | ||
|
|
a8cf208616 | ||
|
|
f84232d30a | ||
|
|
9bd649ec73 | ||
|
|
871b87829f | ||
|
|
d17b189cbc | ||
|
|
7fec3030d4 | ||
|
|
af717b2d3c | ||
|
|
8ee2f38a87 | ||
|
|
4dfd64aa9e | ||
|
|
b0aefcbf47 | ||
|
|
d325343ecc | ||
|
|
5cd70dc4ec | ||
|
|
465694027b | ||
|
|
2079a3c664 | ||
|
|
99cf930f9a | ||
|
|
283b22dbce |
@@ -35,7 +35,7 @@
|
||||
#ifdef DEBUG_CONFIG
|
||||
#define debugLogEarly gLogEarly
|
||||
#else
|
||||
#define debugLogEarly
|
||||
#define debugLogEarly(x,y,z)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,14 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Switches to enable/disable logging targets
|
||||
// MUST BE DEFINED BEFORE gConfig FOR gLogEarly() TO WORK CORRECTLY
|
||||
bool gLogToConsole = true;
|
||||
bool gLogToSyslog = false;
|
||||
FILE *gLogToFile = NULL;
|
||||
Mutex gLogToLock;
|
||||
|
||||
|
||||
// Reference to a global config table, used all over the system.
|
||||
extern ConfigurationTable gConfig;
|
||||
|
||||
@@ -67,10 +75,6 @@ const char *levelNames[] = {
|
||||
"EMERG", "ALERT", "CRIT", "ERR", "WARNING", "NOTICE", "INFO", "DEBUG"
|
||||
};
|
||||
int numLevels = 8;
|
||||
bool gLogToConsole = true;
|
||||
bool gLogToSyslog = false;
|
||||
FILE *gLogToFile = NULL;
|
||||
Mutex gLogToLock;
|
||||
|
||||
|
||||
int levelStringToInt(const string& name)
|
||||
@@ -269,9 +273,32 @@ void gLogInit(const char* name, const char* level, int facility)
|
||||
void gLogEarly(int level, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
||||
va_start(args, fmt);
|
||||
vsyslog(level | LOG_USER, fmt, args);
|
||||
|
||||
if (gLogToSyslog) {
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
vsyslog(level | LOG_USER, fmt, args_copy);
|
||||
va_end(args_copy);
|
||||
}
|
||||
|
||||
if (gLogToConsole) {
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
vprintf(fmt, args_copy);
|
||||
printf("\n");
|
||||
va_end(args_copy);
|
||||
}
|
||||
|
||||
if (gLogToFile) {
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
vfprintf(gLogToFile, fmt, args_copy);
|
||||
fprintf(gLogToFile, "\n");
|
||||
va_end(args_copy);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,10 +41,24 @@ const BitVector GSM::gTrainingSequence[] = {
|
||||
BitVector("11101111000100101110111100"),
|
||||
};
|
||||
|
||||
const BitVector GSM::gEdgeTrainingSequence[] = {
|
||||
BitVector("111111001111111001111001001001111111111111001111111111001111111001111001001001"),
|
||||
BitVector("111111001111001001111001001001111001001001001111111111001111001001111001001001"),
|
||||
BitVector("111001111111111111001001001111001001001111001111111001111111111111001001001111"),
|
||||
BitVector("111001111111111001001001001111001001111001111111111001111111111001001001001111"),
|
||||
BitVector("111111111001001111001111001001001111111001111111111111111001001111001111001001"),
|
||||
BitVector("111001111111001001001111001111001001111111111111111001111111001001001111001111"),
|
||||
BitVector("001111001111111001001001001001111001001111111111001111001111111001001001001001"),
|
||||
BitVector("001001001111001001001001111111111001111111001111001001001111001001001001111111"),
|
||||
};
|
||||
|
||||
const BitVector GSM::gDummyBurst("0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000");
|
||||
|
||||
const BitVector GSM::gRACHSynchSequence("01001011011111111001100110101010001111000");
|
||||
|
||||
// |-head-||---------midamble----------------------||--------------data----------------||t|
|
||||
const BitVector GSM::gRACHBurst("0011101001001011011111111001100110101010001111000110111101111110000111001001010110011000");
|
||||
|
||||
|
||||
int32_t GSM::FNDelta(int32_t v1, int32_t v2)
|
||||
{
|
||||
|
||||
@@ -46,12 +46,15 @@ namespace GSM {
|
||||
|
||||
/** GSM Training sequences from GSM 05.02 5.2.3. */
|
||||
extern const BitVector gTrainingSequence[];
|
||||
extern const BitVector gEdgeTrainingSequence[];
|
||||
|
||||
/** C0T0 filler burst, GSM 05.02, 5.2.6 */
|
||||
extern const BitVector gDummyBurst;
|
||||
|
||||
/** Random access burst synch. sequence */
|
||||
extern const BitVector gRACHSynchSequence;
|
||||
/** Random access burst synch. sequence, GSM 05.02 5.2.7 */
|
||||
extern const BitVector gRACHBurst;
|
||||
|
||||
|
||||
/**@name Modulus operations for frame numbers. */
|
||||
|
||||
@@ -173,10 +173,15 @@ int Resampler::rotate(float *in, size_t in_len, float *out, size_t out_len)
|
||||
int hist_len = filt_len - 1;
|
||||
|
||||
if (!check_vec_len(in_len, out_len, p, q))
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
/* Insert history */
|
||||
memcpy(&in[-2 * hist_len], history, hist_len * 2 * sizeof(float));
|
||||
if (history_on) {
|
||||
memcpy(&in[-2 * hist_len],
|
||||
history, hist_len * 2 * sizeof(float));
|
||||
} else {
|
||||
memset(&in[-2 * hist_len], 0,
|
||||
hist_len * 2 * sizeof(float));
|
||||
}
|
||||
|
||||
/* Generate output from precomputed input/output paths */
|
||||
for (size_t i = 0; i < out_len; i++) {
|
||||
@@ -190,8 +195,10 @@ int Resampler::rotate(float *in, size_t in_len, float *out, size_t out_len)
|
||||
}
|
||||
|
||||
/* Save history */
|
||||
memcpy(history, &in[2 * (in_len - hist_len)],
|
||||
hist_len * 2 * sizeof(float));
|
||||
if (history_on) {
|
||||
memcpy(history, &in[2 * (in_len - hist_len)],
|
||||
hist_len * 2 * sizeof(float));
|
||||
}
|
||||
|
||||
return out_len;
|
||||
}
|
||||
@@ -221,8 +228,14 @@ size_t Resampler::len()
|
||||
return filt_len;
|
||||
}
|
||||
|
||||
void Resampler::enableHistory(bool on)
|
||||
{
|
||||
history_on = on;
|
||||
}
|
||||
|
||||
Resampler::Resampler(size_t p, size_t q, size_t filt_len)
|
||||
: in_index(NULL), out_path(NULL), partitions(NULL), history(NULL)
|
||||
: in_index(NULL), out_path(NULL), partitions(NULL),
|
||||
history(NULL), history_on(true)
|
||||
{
|
||||
this->p = p;
|
||||
this->q = q;
|
||||
|
||||
@@ -59,6 +59,11 @@ public:
|
||||
*/
|
||||
size_t len();
|
||||
|
||||
/*
|
||||
* Enable/disable history
|
||||
*/
|
||||
void enableHistory(bool on);
|
||||
|
||||
private:
|
||||
size_t p;
|
||||
size_t q;
|
||||
@@ -68,6 +73,7 @@ private:
|
||||
|
||||
float **partitions;
|
||||
float *history;
|
||||
bool history_on;
|
||||
|
||||
bool initFilters(float bw);
|
||||
void releaseFilters();
|
||||
|
||||
@@ -71,71 +71,41 @@ TransceiverState::~TransceiverState()
|
||||
}
|
||||
}
|
||||
|
||||
static BitVector *genRandNormalBurst(size_t tsc)
|
||||
{
|
||||
if (tsc > 7)
|
||||
return NULL;
|
||||
|
||||
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 (int j = 0; i < 87; i++, j++)
|
||||
(*bits)[i] = GSM::gTrainingSequence[tsc][j];
|
||||
|
||||
/* 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);
|
||||
burst = generateDummyBurst(sps, n);
|
||||
break;
|
||||
case Transceiver::FILLER_RAND:
|
||||
bits = genRandNormalBurst(rtsc);
|
||||
burst = modulateBurst(*bits, guard, sps);
|
||||
delete bits;
|
||||
case Transceiver::FILLER_NORM_RAND:
|
||||
burst = genRandNormalBurst(rtsc, sps, n);
|
||||
break;
|
||||
case Transceiver::FILLER_EDGE_RAND:
|
||||
burst = generateEdgeBurst(rtsc);
|
||||
break;
|
||||
case Transceiver::FILLER_ACCESS_RAND:
|
||||
burst = genRandAccessBurst(sps, n);
|
||||
break;
|
||||
case Transceiver::FILLER_ZERO:
|
||||
default:
|
||||
burst = new signalVector(len);
|
||||
burst = generateEmptyBurst(sps, n);
|
||||
}
|
||||
|
||||
scaleVector(*burst, scale);
|
||||
fillerTable[i][n] = burst;
|
||||
}
|
||||
|
||||
if (filler == Transceiver::FILLER_RAND)
|
||||
chanType[n] = Transceiver::TSC;
|
||||
if ((filler == Transceiver::FILLER_NORM_RAND) ||
|
||||
(filler == Transceiver::FILLER_EDGE_RAND)) {
|
||||
chanType[n] = Transceiver::TSC;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -143,7 +113,7 @@ bool TransceiverState::init(int filler, size_t sps, float scale, size_t rtsc)
|
||||
|
||||
Transceiver::Transceiver(int wBasePort,
|
||||
const char *wTRXAddress,
|
||||
size_t wSPS, size_t wChans,
|
||||
size_t tx_sps, size_t rx_sps, size_t chans,
|
||||
GSM::Time wTransmitLatency,
|
||||
RadioInterface *wRadioInterface,
|
||||
double wRssiOffset)
|
||||
@@ -151,8 +121,9 @@ Transceiver::Transceiver(int wBasePort,
|
||||
mClockSocket(wBasePort, wTRXAddress, mBasePort + 100),
|
||||
mTransmitLatency(wTransmitLatency), mRadioInterface(wRadioInterface),
|
||||
rssiOffset(wRssiOffset),
|
||||
mSPSTx(wSPS), mSPSRx(1), mChans(wChans), mOn(false),
|
||||
mTxFreq(0.0), mRxFreq(0.0), mTSC(0), mMaxExpectedDelay(0), mWriteBurstToDiskMask(0)
|
||||
mSPSTx(tx_sps), mSPSRx(rx_sps), mChans(chans), mOn(false),
|
||||
mTxFreq(0.0), mRxFreq(0.0), mTSC(0), mMaxExpectedDelayAB(0), mMaxExpectedDelayNB(0),
|
||||
mWriteBurstToDiskMask(0)
|
||||
{
|
||||
txFullScale = mRadioInterface->fullScaleInputValue();
|
||||
rxFullScale = mRadioInterface->fullScaleOutputValue();
|
||||
@@ -198,7 +169,7 @@ bool Transceiver::init(int filler, size_t rtsc)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sigProcLibSetup(mSPSTx)) {
|
||||
if (!sigProcLibSetup()) {
|
||||
LOG(ALERT) << "Failed to initialize signal processing library";
|
||||
return false;
|
||||
}
|
||||
@@ -300,7 +271,6 @@ bool Transceiver::start()
|
||||
TxUpperLoopAdapter, (void*) chan);
|
||||
}
|
||||
|
||||
writeClockInterface();
|
||||
mOn = true;
|
||||
return true;
|
||||
}
|
||||
@@ -367,7 +337,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);
|
||||
@@ -555,88 +530,47 @@ Transceiver::CorrType Transceiver::expectedCorrType(GSM::Time currTime,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect RACH synchronization sequence within a burst. No equalization
|
||||
* is used or available on the RACH channel.
|
||||
*/
|
||||
int Transceiver::detectRACH(TransceiverState *state,
|
||||
signalVector &burst,
|
||||
complex &, float &toa)
|
||||
int Transceiver::detectBurst(signalVector &burst,
|
||||
complex &, float &toa, CorrType type)
|
||||
{
|
||||
float threshold = 6.0;
|
||||
float threshold = 5.0, rc = 0;
|
||||
|
||||
return detectRACHBurst(burst, threshold, mSPSRx, amp, toa);
|
||||
switch (type) {
|
||||
case EDGE:
|
||||
rc = detectEdgeBurst(burst, mTSC, threshold, mSPSRx,
|
||||
amp, toa, mMaxExpectedDelayNB);
|
||||
if (rc > 0)
|
||||
break;
|
||||
else
|
||||
type = TSC;
|
||||
case TSC:
|
||||
rc = analyzeTrafficBurst(burst, mTSC, threshold, mSPSRx,
|
||||
amp, toa, mMaxExpectedDelayNB);
|
||||
break;
|
||||
case RACH:
|
||||
threshold = 6.0;
|
||||
rc = detectRACHBurst(burst, threshold, mSPSRx, amp, toa,
|
||||
mMaxExpectedDelayAB);
|
||||
break;
|
||||
default:
|
||||
LOG(ERR) << "Invalid correlation type";
|
||||
}
|
||||
|
||||
if (rc > 0)
|
||||
return type;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect normal burst training sequence midamble. Update equalization
|
||||
* state information and channel estimate if necessary. Equalization
|
||||
* is currently disabled.
|
||||
*/
|
||||
int Transceiver::detectTSC(TransceiverState *state, signalVector &burst,
|
||||
complex &, float &toa, GSM::Time &time)
|
||||
{
|
||||
int success;
|
||||
int tn = time.TN();
|
||||
float chanOffset, threshold = 5.0;
|
||||
bool needDFE = false, estimateChan = false;
|
||||
double elapsed = time - state->chanEstimateTime[tn];
|
||||
signalVector *chanResp;
|
||||
|
||||
/* Check equalization update state */
|
||||
if (needDFE && ((elapsed > 50) || (!state->chanResponse[tn]))) {
|
||||
delete state->DFEForward[tn];
|
||||
delete state->DFEFeedback[tn];
|
||||
state->DFEForward[tn] = NULL;
|
||||
state->DFEFeedback[tn] = NULL;
|
||||
|
||||
estimateChan = true;
|
||||
}
|
||||
|
||||
/* Detect normal burst midambles */
|
||||
success = analyzeTrafficBurst(burst, mTSC, threshold, mSPSRx, amp,
|
||||
toa, mMaxExpectedDelay, estimateChan,
|
||||
&chanResp, &chanOffset);
|
||||
if (success <= 0) {
|
||||
return success;
|
||||
}
|
||||
|
||||
/* Set equalizer if unabled */
|
||||
if (needDFE && estimateChan) {
|
||||
float noise = state->mNoiseLev;
|
||||
state->SNRestimate[tn] = amp.norm2() / (noise * noise + 1.0);
|
||||
|
||||
state->chanResponse[tn] = chanResp;
|
||||
state->chanRespOffset[tn] = chanOffset;
|
||||
state->chanRespAmplitude[tn] = amp;
|
||||
|
||||
scaleVector(*chanResp, complex(1.0, 0.0) / amp);
|
||||
|
||||
designDFE(*chanResp, state->SNRestimate[tn],
|
||||
7, &state->DFEForward[tn], &state->DFEFeedback[tn]);
|
||||
|
||||
state->chanEstimateTime[tn] = time;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Demodulate GMSK burst using equalization if requested. Otherwise
|
||||
* demodulate by direct rotation and soft slicing.
|
||||
* Demodulate GMSK by direct rotation and soft slicing.
|
||||
*/
|
||||
SoftVector *Transceiver::demodulate(TransceiverState *state,
|
||||
signalVector &burst, complex amp,
|
||||
float toa, size_t tn, bool equalize)
|
||||
SoftVector *Transceiver::demodulate(signalVector &burst, complex amp,
|
||||
float toa, CorrType type)
|
||||
{
|
||||
if (equalize) {
|
||||
scaleVector(burst, complex(1.0, 0.0) / amp);
|
||||
return equalizeBurst(burst,
|
||||
toa - state->chanRespOffset[tn],
|
||||
mSPSRx,
|
||||
*state->DFEForward[tn],
|
||||
*state->DFEFeedback[tn]);
|
||||
}
|
||||
if (type == EDGE)
|
||||
return demodEdgeBurst(burst, mSPSRx, amp, toa);
|
||||
|
||||
return demodulateBurst(burst, mSPSRx, amp, toa);
|
||||
}
|
||||
@@ -659,8 +593,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
|
||||
double &timingOffset, double &noise,
|
||||
size_t chan)
|
||||
{
|
||||
int success;
|
||||
bool equalize = false;
|
||||
int rc;
|
||||
complex amp;
|
||||
float toa, pow, max = -1.0, avg = 0.0;
|
||||
int max_i = -1;
|
||||
@@ -731,16 +664,14 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
|
||||
}
|
||||
|
||||
/* Detect normal or RACH bursts */
|
||||
if (type == TSC)
|
||||
success = detectTSC(state, *burst, amp, toa, time);
|
||||
else
|
||||
success = detectRACH(state, *burst, amp, toa);
|
||||
rc = detectBurst(*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";
|
||||
}
|
||||
|
||||
@@ -750,11 +681,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
|
||||
|
||||
timingOffset = toa / mSPSRx;
|
||||
|
||||
/* Demodulate and set output info */
|
||||
if (equalize && (type != TSC))
|
||||
equalize = false;
|
||||
|
||||
bits = demodulate(state, *burst, amp, toa, time.TN(), equalize);
|
||||
bits = demodulate(*burst, amp, toa, type);
|
||||
|
||||
delete radio_burst;
|
||||
return bits;
|
||||
@@ -788,9 +715,6 @@ void Transceiver::driveControl(size_t chan)
|
||||
|
||||
sscanf(buffer,"%3s %s",cmdcheck,command);
|
||||
|
||||
if (!chan)
|
||||
writeClockInterface();
|
||||
|
||||
if (strcmp(cmdcheck,"CMD")!=0) {
|
||||
LOG(WARNING) << "bogus message on control interface";
|
||||
return;
|
||||
@@ -829,9 +753,16 @@ void Transceiver::driveControl(size_t chan)
|
||||
//set expected maximum time-of-arrival
|
||||
int maxDelay;
|
||||
sscanf(buffer,"%3s %s %d",cmdcheck,command,&maxDelay);
|
||||
mMaxExpectedDelay = maxDelay; // 1 GSM symbol is approx. 1 km
|
||||
mMaxExpectedDelayAB = maxDelay; // 1 GSM symbol is approx. 1 km
|
||||
sprintf(response,"RSP SETMAXDLY 0 %d",maxDelay);
|
||||
}
|
||||
else if (strcmp(command,"SETMAXDLYNB")==0) {
|
||||
//set expected maximum time-of-arrival
|
||||
int maxDelay;
|
||||
sscanf(buffer,"%3s %s %d",cmdcheck,command,&maxDelay);
|
||||
mMaxExpectedDelayNB = maxDelay; // 1 GSM symbol is approx. 1 km
|
||||
sprintf(response,"RSP SETMAXDLYNB 0 %d",maxDelay);
|
||||
}
|
||||
else if (strcmp(command,"SETRXGAIN")==0) {
|
||||
//set expected maximum time-of-arrival
|
||||
int newGain;
|
||||
@@ -898,7 +829,6 @@ void Transceiver::driveControl(size_t chan)
|
||||
sprintf(response, "RSP SETTSC 1 %d", TSC);
|
||||
else {
|
||||
mTSC = TSC;
|
||||
generateMidamble(mSPSRx, TSC);
|
||||
sprintf(response,"RSP SETTSC 0 %d", TSC);
|
||||
}
|
||||
}
|
||||
@@ -978,6 +908,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;
|
||||
@@ -988,37 +931,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
|
||||
/*
|
||||
* EDGE demodulator returns 444 (148 * 3) bits
|
||||
*/
|
||||
if (rxBurst->size() == gSlotLen * 3)
|
||||
nbits = gSlotLen * 3;
|
||||
|
||||
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;
|
||||
dBm = RSSI + rssiOffset;
|
||||
logRxBurst(rxBurst, burstTime, dBm, RSSI, noise, TOA);
|
||||
|
||||
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();
|
||||
TOAint = (int) (TOA * 256.0 + 0.5); // round to closest integer
|
||||
|
||||
for (unsigned int i = 0; i < gSlotLen; i++) {
|
||||
burstString[8+i] =(char) round((*burstItr++)*255.0);
|
||||
}
|
||||
burstString[gSlotLen+9] = '\0';
|
||||
delete rxBurst;
|
||||
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();
|
||||
|
||||
mDataSockets[chan]->write(burstString,gSlotLen+10);
|
||||
}
|
||||
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()
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
*/
|
||||
Transceiver(int wBasePort,
|
||||
const char *TRXAddress,
|
||||
size_t wSPS, size_t chans,
|
||||
size_t tx_sps, size_t rx_sps, size_t chans,
|
||||
GSM::Time wTransmitLatency,
|
||||
RadioInterface *wRadioInterface,
|
||||
double wRssiOffset);
|
||||
@@ -147,13 +147,16 @@ 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;
|
||||
|
||||
enum FillerType {
|
||||
FILLER_DUMMY,
|
||||
FILLER_ZERO,
|
||||
FILLER_RAND,
|
||||
FILLER_NORM_RAND,
|
||||
FILLER_EDGE_RAND,
|
||||
FILLER_ACCESS_RAND,
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -208,20 +211,13 @@ private:
|
||||
/** send messages over the clock socket */
|
||||
void writeClockInterface(void);
|
||||
|
||||
/** Detect RACH bursts */
|
||||
int detectRACH(TransceiverState *state,
|
||||
signalVector &burst,
|
||||
complex &, float &toa);
|
||||
/** Detectbursts */
|
||||
int detectBurst(signalVector &burst,
|
||||
complex &, float &toa, CorrType type);
|
||||
|
||||
/** Detect normal bursts */
|
||||
int detectTSC(TransceiverState *state,
|
||||
signalVector &burst,
|
||||
complex &, float &toa, GSM::Time &time);
|
||||
|
||||
/** Demodulat burst and output soft bits */
|
||||
SoftVector *demodulate(TransceiverState *state,
|
||||
signalVector &burst, complex amp,
|
||||
float toa, size_t tn, bool equalize);
|
||||
/** Demodulate burst and output soft bits */
|
||||
SoftVector *demodulate(signalVector &burst,
|
||||
complex amp, float toa, CorrType type);
|
||||
|
||||
int mSPSTx; ///< number of samples per Tx symbol
|
||||
int mSPSRx; ///< number of samples per Rx symbol
|
||||
@@ -232,7 +228,8 @@ private:
|
||||
double mTxFreq; ///< the transmit frequency
|
||||
double mRxFreq; ///< the receive frequency
|
||||
unsigned mTSC; ///< the midamble sequence code
|
||||
unsigned mMaxExpectedDelay; ///< maximum expected time-of-arrival offset in GSM symbols
|
||||
unsigned mMaxExpectedDelayAB; ///< maximum expected time-of-arrival offset in GSM symbols for Access Bursts (RACH)
|
||||
unsigned mMaxExpectedDelayNB; ///< maximum expected time-of-arrival offset in GSM symbols for Normal Bursts
|
||||
unsigned mWriteBurstToDiskMask; ///< debug: bitmask to indicate which timeslots to dump to disk
|
||||
|
||||
std::vector<TransceiverState> mStates;
|
||||
@@ -279,6 +276,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 *);
|
||||
|
||||
@@ -58,7 +58,6 @@ enum uhd_dev_type {
|
||||
USRP2,
|
||||
B100,
|
||||
B200,
|
||||
B205,
|
||||
B210,
|
||||
E1XX,
|
||||
E3XX,
|
||||
@@ -69,7 +68,8 @@ enum uhd_dev_type {
|
||||
|
||||
struct uhd_dev_offset {
|
||||
enum uhd_dev_type type;
|
||||
int sps;
|
||||
int tx_sps;
|
||||
int rx_sps;
|
||||
double offset;
|
||||
const std::string desc;
|
||||
};
|
||||
@@ -80,9 +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 6.18462e-5
|
||||
#else
|
||||
#define B2XX_TIMING_1SPS 9.9692e-5
|
||||
#define B2XX_TIMING_4SPS 6.9248e-5
|
||||
#define B2XX_TIMING_4_4SPS 4.52308e-5
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -95,40 +97,42 @@ struct uhd_dev_offset {
|
||||
* Notes:
|
||||
* USRP1 with timestamps is not supported by UHD.
|
||||
*/
|
||||
static struct uhd_dev_offset uhd_offsets[NUM_USRP_TYPES * 2] = {
|
||||
{ USRP1, 1, 0.0, "USRP1 not supported" },
|
||||
{ USRP1, 4, 0.0, "USRP1 not supported"},
|
||||
{ USRP2, 1, 1.2184e-4, "N2XX 1 SPS" },
|
||||
{ USRP2, 4, 8.0230e-5, "N2XX 4 SPS" },
|
||||
{ B100, 1, 1.2104e-4, "B100 1 SPS" },
|
||||
{ B100, 4, 7.9307e-5, "B100 4 SPS" },
|
||||
{ B200, 1, B2XX_TIMING_1SPS, "B200 1 SPS" },
|
||||
{ B200, 4, B2XX_TIMING_4SPS, "B200 4 SPS" },
|
||||
{ B205, 1, B2XX_TIMING_1SPS, "B200-mini 1 SPS" },
|
||||
{ B205, 4, B2XX_TIMING_4SPS, "B200-mini 4 SPS" },
|
||||
{ B210, 1, B2XX_TIMING_1SPS, "B210 1 SPS" },
|
||||
{ B210, 4, B2XX_TIMING_4SPS, "B210 4 SPS" },
|
||||
{ E1XX, 1, 9.5192e-5, "E1XX 1 SPS" },
|
||||
{ E1XX, 4, 6.5571e-5, "E1XX 4 SPS" },
|
||||
{ E3XX, 1, 1.5000e-4, "E3XX 1 SPS" },
|
||||
{ E3XX, 4, 1.2740e-4, "E3XX 4 SPS" },
|
||||
{ X3XX, 1, 1.5360e-4, "X3XX 1 SPS"},
|
||||
{ X3XX, 4, 1.1264e-4, "X3XX 4 SPS"},
|
||||
{ UMTRX, 1, 9.9692e-5, "UmTRX 1 SPS" },
|
||||
{ UMTRX, 4, 7.3846e-5, "UmTRX 4 SPS" },
|
||||
static struct uhd_dev_offset uhd_offsets[] = {
|
||||
{ USRP1, 1, 1, 0.0, "USRP1 not supported" },
|
||||
{ USRP1, 4, 1, 0.0, "USRP1 not supported"},
|
||||
{ USRP2, 1, 1, 1.2184e-4, "N2XX 1 SPS" },
|
||||
{ USRP2, 4, 1, 8.0230e-5, "N2XX 4 SPS" },
|
||||
{ B100, 1, 1, 1.2104e-4, "B100 1 SPS" },
|
||||
{ B100, 4, 1, 7.9307e-5, "B100 4 SPS" },
|
||||
{ B200, 1, 1, B2XX_TIMING_1SPS, "B200 1 SPS" },
|
||||
{ B200, 4, 1, B2XX_TIMING_4SPS, "B200 4 SPS" },
|
||||
{ B210, 1, 1, B2XX_TIMING_1SPS, "B210 1 SPS" },
|
||||
{ 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" },
|
||||
{ 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" },
|
||||
{ UMTRX, 4, 1, 7.3846e-5, "UmTRX 4 SPS" },
|
||||
{ B200, 4, 4, B2XX_TIMING_4_4SPS, "B200/B210 EDGE mode (4 SPS TX/RX)" },
|
||||
{ B210, 4, 4, B2XX_TIMING_4_4SPS, "B200/B210 EDGE mode (4 SPS TX/RX)" },
|
||||
{ UMTRX, 4, 4, 5.1503e-5, "UmTRX EDGE mode (4 SPS TX/RX)" },
|
||||
};
|
||||
#define NUM_UHD_OFFSETS (sizeof(uhd_offsets)/sizeof(uhd_offsets[0]))
|
||||
|
||||
/*
|
||||
* Offset handling for special cases. Currently used for UmTRX dual channel
|
||||
* diversity receiver only.
|
||||
*/
|
||||
static struct uhd_dev_offset special_offsets[] = {
|
||||
{ UMTRX, 1, 8.0875e-5, "UmTRX diversity, 1 SPS" },
|
||||
{ UMTRX, 4, 5.2103e-5, "UmTRX diversity, 4 SPS" },
|
||||
{ UMTRX, 1, 1, 8.0875e-5, "UmTRX diversity, 1 SPS" },
|
||||
{ UMTRX, 4, 1, 5.2103e-5, "UmTRX diversity, 4 SPS" },
|
||||
};
|
||||
|
||||
static double get_dev_offset(enum uhd_dev_type type,
|
||||
int sps, bool diversity = false)
|
||||
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;
|
||||
|
||||
@@ -138,6 +142,16 @@ static double get_dev_offset(enum uhd_dev_type 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) {
|
||||
@@ -145,7 +159,7 @@ static double get_dev_offset(enum uhd_dev_type type,
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
switch (sps) {
|
||||
switch (tx_sps) {
|
||||
case 1:
|
||||
offset = &special_offsets[0];
|
||||
break;
|
||||
@@ -155,9 +169,10 @@ static double get_dev_offset(enum uhd_dev_type type,
|
||||
}
|
||||
} else {
|
||||
/* Search for matching offset value */
|
||||
for (int i = 0; i < NUM_USRP_TYPES * 2; i++) {
|
||||
for (size_t i = 0; i < NUM_UHD_OFFSETS; i++) {
|
||||
if ((type == uhd_offsets[i].type) &&
|
||||
(sps == uhd_offsets[i].sps)) {
|
||||
(tx_sps == uhd_offsets[i].tx_sps) &&
|
||||
(rx_sps == uhd_offsets[i].rx_sps)) {
|
||||
offset = &uhd_offsets[i];
|
||||
break;
|
||||
}
|
||||
@@ -198,7 +213,6 @@ static double select_rate(uhd_dev_type type, int sps, bool diversity = false)
|
||||
case B100:
|
||||
return B100_BASE_RT * sps;
|
||||
case B200:
|
||||
case B205:
|
||||
case B210:
|
||||
case E1XX:
|
||||
case E3XX:
|
||||
@@ -285,7 +299,8 @@ private:
|
||||
*/
|
||||
class uhd_device : public RadioDevice {
|
||||
public:
|
||||
uhd_device(size_t sps, size_t chans, bool diversity, double offset);
|
||||
uhd_device(size_t tx_sps, size_t rx_sps,
|
||||
size_t chans, bool diversity, double offset);
|
||||
~uhd_device();
|
||||
|
||||
int open(const std::string &args, bool extref, bool swap_channels);
|
||||
@@ -306,8 +321,8 @@ public:
|
||||
bool setTxFreq(double wFreq, size_t chan);
|
||||
bool setRxFreq(double wFreq, size_t chan);
|
||||
|
||||
inline TIMESTAMP initialWriteTimestamp() { return ts_initial * sps; }
|
||||
inline TIMESTAMP initialReadTimestamp() { return ts_initial; }
|
||||
inline TIMESTAMP initialWriteTimestamp();
|
||||
inline TIMESTAMP initialReadTimestamp();
|
||||
|
||||
double fullScaleInputValue();
|
||||
double fullScaleOutputValue();
|
||||
@@ -348,7 +363,7 @@ private:
|
||||
enum TxWindowType tx_window;
|
||||
enum uhd_dev_type dev_type;
|
||||
|
||||
size_t sps, chans;
|
||||
size_t tx_sps, rx_sps, chans;
|
||||
double tx_rate, rx_rate;
|
||||
|
||||
double tx_gain_min, tx_gain_max;
|
||||
@@ -427,14 +442,16 @@ static void thread_enable_cancel(bool cancel)
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||
}
|
||||
|
||||
uhd_device::uhd_device(size_t sps, size_t chans, bool diversity, double offset)
|
||||
uhd_device::uhd_device(size_t tx_sps, size_t rx_sps,
|
||||
size_t chans, bool diversity, double offset)
|
||||
: tx_gain_min(0.0), tx_gain_max(0.0),
|
||||
rx_gain_min(0.0), rx_gain_max(0.0),
|
||||
tx_spp(0), rx_spp(0),
|
||||
started(false), aligned(false), rx_pkt_cnt(0), drop_cnt(0),
|
||||
prev_ts(0,0), ts_initial(0), ts_offset(0)
|
||||
{
|
||||
this->sps = sps;
|
||||
this->tx_sps = tx_sps;
|
||||
this->rx_sps = rx_sps;
|
||||
this->chans = chans;
|
||||
this->offset = offset;
|
||||
this->diversity = diversity;
|
||||
@@ -527,7 +544,7 @@ int uhd_device::set_rates(double tx_rate, double rx_rate)
|
||||
double tx_offset, rx_offset;
|
||||
|
||||
/* B2XX and E1xx are the only device where we set FPGA clocking */
|
||||
if ((dev_type == B200) || (dev_type == B205) || (dev_type == B210) || (dev_type == E3XX)) {
|
||||
if ((dev_type == B200) || (dev_type == B210) || (dev_type == E3XX)) {
|
||||
if (set_master_clk(B2XX_CLK_RT) < 0)
|
||||
return -1;
|
||||
}
|
||||
@@ -627,7 +644,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,
|
||||
b100_str, b200_str, b205_str, b210_str, x300_str, x310_str, umtrx_str;
|
||||
b100_str, b200_str, b210_str, x300_str, x310_str, umtrx_str;
|
||||
|
||||
prop_tree = usrp_dev->get_device()->get_tree();
|
||||
dev_str = prop_tree->access<std::string>("/name").get();
|
||||
@@ -637,7 +654,6 @@ bool uhd_device::parse_dev_type()
|
||||
usrp2_str = dev_str.find("USRP2");
|
||||
b100_str = mboard_str.find("B100");
|
||||
b200_str = mboard_str.find("B200");
|
||||
b205_str = mboard_str.find("B205");
|
||||
b210_str = mboard_str.find("B210");
|
||||
e100_str = mboard_str.find("E100");
|
||||
e110_str = mboard_str.find("E110");
|
||||
@@ -659,9 +675,6 @@ bool uhd_device::parse_dev_type()
|
||||
} else if (b200_str != std::string::npos) {
|
||||
tx_window = TX_WINDOW_USRP1;
|
||||
dev_type = B200;
|
||||
} else if (b205_str != std::string::npos) {
|
||||
tx_window = TX_WINDOW_USRP1;
|
||||
dev_type = B205;
|
||||
} else if (b210_str != std::string::npos) {
|
||||
tx_window = TX_WINDOW_USRP1;
|
||||
dev_type = B210;
|
||||
@@ -746,12 +759,8 @@ int uhd_device::open(const std::string &args, bool extref, bool swap_channels)
|
||||
usrp_dev->set_clock_source("external");
|
||||
|
||||
// Set rates
|
||||
double _rx_rate;
|
||||
double _tx_rate = select_rate(dev_type, sps);
|
||||
if (diversity)
|
||||
_rx_rate = select_rate(dev_type, 1, true);
|
||||
else
|
||||
_rx_rate = _tx_rate / sps;
|
||||
double _tx_rate = select_rate(dev_type, tx_sps);
|
||||
double _rx_rate = select_rate(dev_type, rx_sps, diversity);
|
||||
|
||||
if ((_tx_rate < 0.0) || (_rx_rate < 0.0))
|
||||
return -1;
|
||||
@@ -785,8 +794,14 @@ int uhd_device::open(const std::string &args, bool extref, bool swap_channels)
|
||||
for (size_t i = 0; i < rx_buffers.size(); i++)
|
||||
rx_buffers[i] = new smpl_buf(buf_len, rx_rate);
|
||||
|
||||
// Set receive chain sample offset
|
||||
double offset = get_dev_offset(dev_type, sps, diversity);
|
||||
// Set receive chain sample offset. Trigger the EDGE offset
|
||||
// table by checking for 4 SPS on the receive path. No other
|
||||
// configuration supports using 4 SPS.
|
||||
bool edge = false;
|
||||
if (rx_sps == 4)
|
||||
edge = true;
|
||||
|
||||
double offset = get_dev_offset(dev_type, tx_sps, rx_sps, edge, diversity);
|
||||
if (offset == 0.0) {
|
||||
LOG(ERR) << "Unsupported configuration, no correction applied";
|
||||
ts_offset = 0;
|
||||
@@ -810,7 +825,6 @@ int uhd_device::open(const std::string &args, bool extref, bool swap_channels)
|
||||
case X3XX:
|
||||
return RESAMP_100M;
|
||||
case B200:
|
||||
case B205:
|
||||
case B210:
|
||||
case E1XX:
|
||||
case E3XX:
|
||||
@@ -1252,6 +1266,24 @@ double uhd_device::getRxFreq(size_t chan)
|
||||
return rx_freqs[chan];
|
||||
}
|
||||
|
||||
/*
|
||||
* Only allow sampling the Rx path lower than Tx and not vice-versa.
|
||||
* Using Tx with 4 SPS and Rx at 1 SPS is the only allowed mixed
|
||||
* combination.
|
||||
*/
|
||||
TIMESTAMP uhd_device::initialWriteTimestamp()
|
||||
{
|
||||
if (rx_sps == tx_sps)
|
||||
return ts_initial;
|
||||
else
|
||||
return ts_initial * tx_sps;
|
||||
}
|
||||
|
||||
TIMESTAMP uhd_device::initialReadTimestamp()
|
||||
{
|
||||
return ts_initial;
|
||||
}
|
||||
|
||||
double uhd_device::fullScaleInputValue()
|
||||
{
|
||||
if (dev_type == UMTRX)
|
||||
@@ -1517,8 +1549,8 @@ std::string smpl_buf::str_code(ssize_t code)
|
||||
}
|
||||
}
|
||||
|
||||
RadioDevice *RadioDevice::make(size_t sps, size_t chans,
|
||||
bool diversity, double offset)
|
||||
RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps,
|
||||
size_t chans, bool diversity, double offset)
|
||||
{
|
||||
return new uhd_device(sps, chans, diversity, offset);
|
||||
return new uhd_device(tx_sps, rx_sps, chans, diversity, offset);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ const dboardConfigType dboardConfig = TXA_RXB;
|
||||
|
||||
const double USRPDevice::masterClockRate = 52.0e6;
|
||||
|
||||
USRPDevice::USRPDevice(size_t sps, size_t, bool)
|
||||
USRPDevice::USRPDevice(size_t sps)
|
||||
{
|
||||
LOG(INFO) << "creating USRP device...";
|
||||
|
||||
@@ -600,7 +600,8 @@ bool USRPDevice::setTxFreq(double wFreq) { return true;};
|
||||
bool USRPDevice::setRxFreq(double wFreq) { return true;};
|
||||
#endif
|
||||
|
||||
RadioDevice *RadioDevice::make(size_t sps, size_t chans, bool diversity, double)
|
||||
RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps,
|
||||
size_t chans, bool diversity, double)
|
||||
{
|
||||
return new USRPDevice(sps, chans, diversity);
|
||||
return new USRPDevice(tx_sps);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ private:
|
||||
public:
|
||||
|
||||
/** Object constructor */
|
||||
USRPDevice(size_t sps, size_t chans = 1, bool diversity = false);
|
||||
USRPDevice(size_t sps);
|
||||
|
||||
/** Instantiate the USRP */
|
||||
int open(const std::string &, bool, bool);
|
||||
|
||||
@@ -25,25 +25,25 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
void neon_convert_ps_si16_4n(short *, float *, float *, int);
|
||||
void neon_convert_si16_ps_4n(float *, short *, int);
|
||||
void neon_convert_ps_si16_4n(short *, const float *, const float *, int);
|
||||
void neon_convert_si16_ps_4n(float *, const short *, int);
|
||||
|
||||
#ifndef HAVE_NEON
|
||||
static void convert_si16_ps(float *out, short *in, int len)
|
||||
static void convert_si16_ps(float *out, const short *in, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
out[i] = in[i];
|
||||
}
|
||||
|
||||
static void convert_ps_si16(short *out, float *in, float scale, int len)
|
||||
static void convert_ps_si16(short *out, const float *in, float scale, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
out[i] = in[i] * scale;
|
||||
}
|
||||
#else
|
||||
/* 4*N 16-bit signed integer conversion with remainder */
|
||||
static void neon_convert_si16_ps(float *restrict out,
|
||||
short *restrict in,
|
||||
static void neon_convert_si16_ps(float *out,
|
||||
const short *in,
|
||||
int len)
|
||||
{
|
||||
int start = len / 4 * 4;
|
||||
@@ -55,9 +55,9 @@ static void neon_convert_si16_ps(float *restrict out,
|
||||
}
|
||||
|
||||
/* 4*N 16-bit signed integer conversion with remainder */
|
||||
static void neon_convert_ps_si16(short *restrict out,
|
||||
float *restrict in,
|
||||
float *restrict scale,
|
||||
static void neon_convert_ps_si16(short *out,
|
||||
const float *in,
|
||||
const float *scale,
|
||||
int len)
|
||||
{
|
||||
int start = len / 4 * 4;
|
||||
@@ -69,7 +69,7 @@ static void neon_convert_ps_si16(short *restrict out,
|
||||
}
|
||||
#endif
|
||||
|
||||
void convert_float_short(short *out, float *in, float scale, int len)
|
||||
void convert_float_short(short *out, const float *in, float scale, int len)
|
||||
{
|
||||
#ifdef HAVE_NEON
|
||||
float q[4] = { scale, scale, scale, scale };
|
||||
@@ -83,7 +83,7 @@ void convert_float_short(short *out, float *in, float scale, int len)
|
||||
#endif
|
||||
}
|
||||
|
||||
void convert_short_float(float *out, short *in, int len)
|
||||
void convert_short_float(float *out, const short *in, int len)
|
||||
{
|
||||
#ifdef HAVE_NEON
|
||||
if (len % 4)
|
||||
|
||||
@@ -41,11 +41,19 @@
|
||||
* ARM and non-SIMD enabled architectures.
|
||||
*/
|
||||
#if defined(HAVE_NEON) || !defined(HAVE_SSE3)
|
||||
#define DEFAULT_SPS 1
|
||||
#define DEFAULT_TX_SPS 1
|
||||
#else
|
||||
#define DEFAULT_SPS 4
|
||||
#define DEFAULT_TX_SPS 4
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Samples-per-symbol for uplink (receiver) path
|
||||
* Do not modify this value. EDGE configures 4 sps automatically on
|
||||
* B200/B210 devices only. Use of 4 sps on the receive path for other
|
||||
* configurations is not supported.
|
||||
*/
|
||||
#define DEFAULT_RX_SPS 1
|
||||
|
||||
/* Default configuration parameters
|
||||
* Note that these values are only used if the particular key does not
|
||||
* exist in the configuration database. IP port and address values will
|
||||
@@ -63,7 +71,8 @@ struct trx_config {
|
||||
std::string addr;
|
||||
std::string dev_args;
|
||||
unsigned port;
|
||||
unsigned sps;
|
||||
unsigned tx_sps;
|
||||
unsigned rx_sps;
|
||||
unsigned chans;
|
||||
unsigned rtsc;
|
||||
bool extref;
|
||||
@@ -72,6 +81,7 @@ struct trx_config {
|
||||
double offset;
|
||||
double rssi_offset;
|
||||
bool swap_channels;
|
||||
bool edge;
|
||||
};
|
||||
|
||||
ConfigurationTable gConfig;
|
||||
@@ -121,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;
|
||||
@@ -161,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) {
|
||||
@@ -170,9 +181,15 @@ bool trx_setup_config(struct trx_config *config)
|
||||
case Transceiver::FILLER_ZERO:
|
||||
fillstr = "Disabled";
|
||||
break;
|
||||
case Transceiver::FILLER_RAND:
|
||||
case Transceiver::FILLER_NORM_RAND:
|
||||
fillstr = "Normal busrts with random payload";
|
||||
break;
|
||||
case Transceiver::FILLER_EDGE_RAND:
|
||||
fillstr = "EDGE busrts with random payload";
|
||||
break;
|
||||
case Transceiver::FILLER_ACCESS_RAND:
|
||||
fillstr = "Access busrts with random payload";
|
||||
break;
|
||||
}
|
||||
|
||||
std::ostringstream ost("");
|
||||
@@ -182,7 +199,9 @@ bool trx_setup_config(struct trx_config *config)
|
||||
ost << " TRX Base Port........... " << config->port << std::endl;
|
||||
ost << " TRX Address............. " << config->addr << std::endl;
|
||||
ost << " Channels................ " << config->chans << std::endl;
|
||||
ost << " Samples-per-Symbol...... " << config->sps << 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;
|
||||
ost << " Diversity............... " << divstr << std::endl;
|
||||
@@ -206,18 +225,23 @@ 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->sps, config->chans);
|
||||
radio = new RadioInterface(usrp, config->tx_sps,
|
||||
config->rx_sps, config->chans);
|
||||
break;
|
||||
case RadioDevice::RESAMP_64M:
|
||||
case RadioDevice::RESAMP_100M:
|
||||
radio = new RadioInterfaceResamp(usrp,
|
||||
config->sps, config->chans);
|
||||
radio = new RadioInterfaceResamp(usrp, config->tx_sps,
|
||||
config->chans);
|
||||
break;
|
||||
case RadioDevice::DIVERSITY:
|
||||
radio = new RadioInterfaceDiversity(usrp,
|
||||
config->sps, config->chans);
|
||||
radio = new RadioInterfaceDiversity(usrp, config->tx_sps,
|
||||
config->chans);
|
||||
break;
|
||||
default:
|
||||
LOG(ALERT) << "Unsupported radio interface configuration";
|
||||
@@ -243,8 +267,9 @@ Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
|
||||
Transceiver *trx;
|
||||
VectorFIFO *fifo;
|
||||
|
||||
trx = new Transceiver(config->port, config->addr.c_str(), config->sps,
|
||||
config->chans, GSM::Time(3,0), radio, config->rssi_offset);
|
||||
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)) {
|
||||
LOG(ALERT) << "Failed to initialize transceiver";
|
||||
delete trx;
|
||||
@@ -290,6 +315,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"
|
||||
@@ -297,6 +323,7 @@ static void print_help()
|
||||
" -f Enable C0 filler table\n"
|
||||
" -o Set baseband frequency offset (default=auto)\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");
|
||||
@@ -307,7 +334,8 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
|
||||
int option;
|
||||
|
||||
config->port = 0;
|
||||
config->sps = DEFAULT_SPS;
|
||||
config->tx_sps = DEFAULT_TX_SPS;
|
||||
config->rx_sps = DEFAULT_RX_SPS;
|
||||
config->chans = DEFAULT_CHANS;
|
||||
config->rtsc = 0;
|
||||
config->extref = false;
|
||||
@@ -316,8 +344,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:AR:Se")) != -1) {
|
||||
switch (option) {
|
||||
case 'h':
|
||||
print_help();
|
||||
@@ -351,11 +380,14 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
|
||||
config->offset = atof(optarg);
|
||||
break;
|
||||
case 's':
|
||||
config->sps = atoi(optarg);
|
||||
config->tx_sps = atoi(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
config->rtsc = atoi(optarg);
|
||||
config->filler = Transceiver::FILLER_RAND;
|
||||
config->filler = Transceiver::FILLER_NORM_RAND;
|
||||
break;
|
||||
case 'A':
|
||||
config->filler = Transceiver::FILLER_ACCESS_RAND;
|
||||
break;
|
||||
case 'R':
|
||||
config->rssi_offset = atof(optarg);
|
||||
@@ -363,14 +395,27 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
if ((config->sps != 1) && (config->sps != 4)) {
|
||||
printf("Unsupported samples-per-symbol %i\n\n", config->sps);
|
||||
if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND))
|
||||
config->filler = Transceiver::FILLER_EDGE_RAND;
|
||||
|
||||
if ((config->tx_sps != 1) && (config->tx_sps != 4)) {
|
||||
printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps);
|
||||
print_help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (config->edge && (config->tx_sps != 4)) {
|
||||
printf("EDGE only supported at 4 samples per symbol\n\n");
|
||||
print_help();
|
||||
exit(0);
|
||||
}
|
||||
@@ -405,7 +450,7 @@ int main(int argc, char *argv[])
|
||||
srandom(time(NULL));
|
||||
|
||||
/* Create the low level device object */
|
||||
usrp = RadioDevice::make(config.sps, config.chans,
|
||||
usrp = RadioDevice::make(config.tx_sps, config.rx_sps, config.chans,
|
||||
config.diversity, config.offset);
|
||||
type = usrp->open(config.dev_args, config.extref, config.swap_channels);
|
||||
if (type < 0) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class RadioDevice {
|
||||
/* Radio interface types */
|
||||
enum RadioInterfaceType { NORMAL, RESAMP_64M, RESAMP_100M, DIVERSITY };
|
||||
|
||||
static RadioDevice *make(size_t sps, size_t chans = 1,
|
||||
static RadioDevice *make(size_t tx_sps, size_t rx_sps = 1, size_t chans = 1,
|
||||
bool diversity = false, double offset = 0.0);
|
||||
|
||||
/** Initialize the USRP */
|
||||
|
||||
@@ -33,12 +33,12 @@ extern "C" {
|
||||
#define CHUNK 625
|
||||
#define NUMCHUNKS 4
|
||||
|
||||
RadioInterface::RadioInterface(RadioDevice *wRadio,
|
||||
size_t sps, size_t chans, size_t diversity,
|
||||
RadioInterface::RadioInterface(RadioDevice *wRadio, size_t tx_sps,
|
||||
size_t rx_sps, size_t chans, size_t diversity,
|
||||
int wReceiveOffset, GSM::Time wStartTime)
|
||||
: mRadio(wRadio), mSPSTx(sps), mSPSRx(1), mChans(chans), mMIMO(diversity),
|
||||
sendCursor(0), recvCursor(0), underrun(false), overrun(false),
|
||||
receiveOffset(wReceiveOffset), mOn(false)
|
||||
: mRadio(wRadio), mSPSTx(tx_sps), mSPSRx(rx_sps), mChans(chans),
|
||||
mMIMO(diversity), sendCursor(0), recvCursor(0), underrun(false),
|
||||
overrun(false), receiveOffset(wReceiveOffset), mOn(false)
|
||||
{
|
||||
mClock.set(wStartTime);
|
||||
}
|
||||
@@ -262,7 +262,12 @@ bool RadioInterface::driveReceiveRadio()
|
||||
int recvSz = recvCursor;
|
||||
int readSz = 0;
|
||||
const int symbolsPerSlot = gSlotLen + 8;
|
||||
int burstSize = (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx;
|
||||
int burstSize;
|
||||
|
||||
if (mSPSRx == 4)
|
||||
burstSize = 625;
|
||||
else
|
||||
burstSize = symbolsPerSlot + (tN % 4 == 0);
|
||||
|
||||
/*
|
||||
* Pre-allocate head room for the largest correlation size
|
||||
@@ -297,7 +302,8 @@ bool RadioInterface::driveReceiveRadio()
|
||||
|
||||
tN = rcvClock.TN();
|
||||
|
||||
burstSize = (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx;
|
||||
if (mSPSRx != 4)
|
||||
burstSize = (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx;
|
||||
}
|
||||
|
||||
if (readSz > 0) {
|
||||
|
||||
@@ -87,7 +87,8 @@ public:
|
||||
|
||||
/** constructor */
|
||||
RadioInterface(RadioDevice* wRadio = NULL,
|
||||
size_t sps = 4, size_t chans = 1, size_t diversity = 1,
|
||||
size_t tx_sps = 4, size_t rx_sps = 1,
|
||||
size_t chans = 1, size_t diversity = 1,
|
||||
int receiveOffset = 3, GSM::Time wStartTime = GSM::Time(0));
|
||||
|
||||
/** destructor */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
@@ -49,7 +54,7 @@ float vectorNorm2(const signalVector &x);
|
||||
float vectorPower(const signalVector &x);
|
||||
|
||||
/** Setup the signal processing library */
|
||||
bool sigProcLibSetup(int sps);
|
||||
bool sigProcLibSetup();
|
||||
|
||||
/** Destroy the signal processing library */
|
||||
void sigProcLibDestroy(void);
|
||||
@@ -104,6 +109,25 @@ signalVector *modulateBurst(const BitVector &wBurst,
|
||||
int guardPeriodLength,
|
||||
int sps, bool emptyPulse = false);
|
||||
|
||||
/** 8-PSK modulate a burst of bits */
|
||||
signalVector *modulateEdgeBurst(const BitVector &bits,
|
||||
int sps, bool emptyPulse = false);
|
||||
|
||||
/** Generate a EDGE burst with random payload - 4 SPS (625 samples) only */
|
||||
signalVector *generateEdgeBurst(int tsc);
|
||||
|
||||
/** Generate an empty burst - 4 or 1 SPS */
|
||||
signalVector *generateEmptyBurst(int sps, int tn);
|
||||
|
||||
/** Generate a normal GSM burst with random payload - 4 or 1 SPS */
|
||||
signalVector *genRandNormalBurst(int tsc, int sps, int tn);
|
||||
|
||||
/** Generate an access GSM burst with random payload - 4 or 1 SPS */
|
||||
signalVector *genRandAccessBurst(int sps, int tn);
|
||||
|
||||
/** Generate a dummy GSM burst - 4 or 1 SPS */
|
||||
signalVector *generateDummyBurst(int sps, int tn);
|
||||
|
||||
/** Sinc function */
|
||||
float sinc(float x);
|
||||
|
||||
@@ -151,22 +175,6 @@ complex peakDetect(const signalVector &rxBurst,
|
||||
void scaleVector(signalVector &x,
|
||||
complex scale);
|
||||
|
||||
/**
|
||||
Generate a modulated GSM midamble, stored within the library.
|
||||
@param gsmPulse The GSM pulse used for modulation.
|
||||
@param sps The number of samples per GSM symbol.
|
||||
@param TSC The training sequence [0..7]
|
||||
@return Success.
|
||||
*/
|
||||
bool generateMidamble(int sps, int tsc);
|
||||
/**
|
||||
Generate a modulated RACH sequence, stored within the library.
|
||||
@param gsmPulse The GSM pulse used for modulation.
|
||||
@param sps The number of samples per GSM symbol.
|
||||
@return Success.
|
||||
*/
|
||||
bool generateRACHSequence(int sps);
|
||||
|
||||
/**
|
||||
Energy detector, checks to see if received burst energy is above a threshold.
|
||||
@param rxBurst The received GSM burst of interest.
|
||||
@@ -187,13 +195,15 @@ bool energyDetect(signalVector &rxBurst,
|
||||
@param sps The number of samples per GSM symbol.
|
||||
@param amplitude The estimated amplitude of received RACH burst.
|
||||
@param TOA The estimate time-of-arrival of received RACH burst.
|
||||
@param maxTOA The maximum expected time-of-arrival
|
||||
@return positive if threshold value is reached, negative on error, zero otherwise
|
||||
*/
|
||||
int detectRACHBurst(signalVector &rxBurst,
|
||||
float detectThreshold,
|
||||
int sps,
|
||||
complex &litude,
|
||||
float &TOA);
|
||||
float &TOA,
|
||||
unsigned maxTOA);
|
||||
|
||||
/**
|
||||
Normal burst correlator, detector, channel estimator.
|
||||
@@ -215,10 +225,34 @@ int analyzeTrafficBurst(signalVector &rxBurst,
|
||||
int sps,
|
||||
complex &litude,
|
||||
float &TOA,
|
||||
unsigned maxTOA,
|
||||
bool requestChannel = false,
|
||||
signalVector** channelResponse = NULL,
|
||||
float *channelResponseOffset = NULL);
|
||||
unsigned maxTOA);
|
||||
|
||||
/**
|
||||
EDGE burst detector
|
||||
@param burst The received GSM burst of interest
|
||||
|
||||
@param detectThreshold The threshold that the received burst's post-correlator SNR is compared against to determine validity.
|
||||
@param sps The number of samples per GSM symbol.
|
||||
@param amplitude The estimated amplitude of received TSC burst.
|
||||
@param TOA The estimate time-of-arrival of received TSC burst.
|
||||
@param maxTOA The maximum expected time-of-arrival
|
||||
@return positive if threshold value is reached, negative on error, zero otherwise
|
||||
*/
|
||||
int detectEdgeBurst(signalVector &burst,
|
||||
unsigned TSC,
|
||||
float detectThreshold,
|
||||
int sps,
|
||||
complex &litude,
|
||||
float &TOA,
|
||||
unsigned maxTOA);
|
||||
|
||||
/**
|
||||
Downsample 4 SPS to 1 SPS using a polyphase filterbank
|
||||
@param burst Input burst of at least 624 symbols
|
||||
@return Decimated signal vector of 156 symbols
|
||||
*/
|
||||
|
||||
signalVector *downsampleBurst(signalVector &burst);
|
||||
|
||||
/**
|
||||
Decimate a vector.
|
||||
@@ -241,33 +275,14 @@ SoftVector *demodulateBurst(signalVector &rxBurst, int sps,
|
||||
complex channel, float TOA);
|
||||
|
||||
/**
|
||||
Design the necessary filters for a decision-feedback equalizer.
|
||||
@param channelResponse The multipath channel that we're mitigating.
|
||||
@param SNRestimate The signal-to-noise estimate of the channel, a linear value
|
||||
@param Nf The number of taps in the feedforward filter.
|
||||
@param feedForwardFilter The designed feed forward filter.
|
||||
@param feedbackFilter The designed feedback filter.
|
||||
@return True if DFE can be designed.
|
||||
Demodulate 8-PSK EDGE burst with soft symbol ooutput
|
||||
@param rxBurst The burst to be demodulated.
|
||||
@param sps The number of samples per GSM symbol.
|
||||
@param channel The amplitude estimate of the received burst.
|
||||
@param TOA The time-of-arrival of the received burst.
|
||||
@return The demodulated bit sequence.
|
||||
*/
|
||||
bool designDFE(signalVector &channelResponse,
|
||||
float SNRestimate,
|
||||
int Nf,
|
||||
signalVector **feedForwardFilter,
|
||||
signalVector **feedbackFilter);
|
||||
|
||||
/**
|
||||
Equalize/demodulate a received burst via a decision-feedback equalizer.
|
||||
@param rxBurst The received burst to be demodulated.
|
||||
@param TOA The time-of-arrival of the received burst.
|
||||
@param sps The number of samples per GSM symbol.
|
||||
@param w The feed forward filter of the DFE.
|
||||
@param b The feedback filter of the DFE.
|
||||
@return The demodulated bit sequence.
|
||||
*/
|
||||
SoftVector *equalizeBurst(signalVector &rxBurst,
|
||||
float TOA,
|
||||
int sps,
|
||||
signalVector &w,
|
||||
signalVector &b);
|
||||
SoftVector *demodEdgeBurst(signalVector &rxBurst, int sps,
|
||||
complex channel, float TOA);
|
||||
|
||||
#endif /* SIGPROCLIB_H */
|
||||
|
||||
11
debian/changelog
vendored
Normal file
11
debian/changelog
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
osmo-trx (0.1.9) trusty; urgency=medium
|
||||
|
||||
* Ask Ivan, really
|
||||
|
||||
-- Kirill Zakharenko <earwin@gmail.com> Thu, 16 Jul 2015 12:13:46 +0000
|
||||
|
||||
osmo-trx (0.1.8) precise; urgency=low
|
||||
|
||||
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP
|
||||
|
||||
-- Ivan Klyuchnikov <Ivan.Kluchnikov@fairwaves.ru> Sun, 9 Mar 2014 14:10:10 +0400
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
9
|
||||
24
debian/control
vendored
Normal file
24
debian/control
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
Source: osmo-trx
|
||||
Maintainer: Ivan Klyuchnikov <ivan.kluchnikov@fairwaves.ru>
|
||||
Section: net
|
||||
Priority: optional
|
||||
Standards-Version: 3.9.3
|
||||
Build-Depends: debhelper (>= 9), autotools-dev, libdbd-sqlite3, pkg-config, dh-autoreconf, libuhd-dev, libusb-1.0-0-dev, libboost-all-dev, hardening-wrapper
|
||||
Homepage: http://openbsc.osmocom.org/trac/wiki/OsmoTRX
|
||||
Vcs-Git: git://git.osmocom.org/osmo-trx
|
||||
Vcs-Browser: http://cgit.osmocom.org/osmo-trx
|
||||
|
||||
Package: osmo-trx
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libdbd-sqlite3
|
||||
Description: OsmoTRX is a software-defined radio transceiver that implements the Layer 1 physical layer of a BTS
|
||||
|
||||
Package: osmo-trx-dbg
|
||||
Architecture: any
|
||||
Section: debug
|
||||
Priority: extra
|
||||
Depends: osmo-trx (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Debug symbols for the osmo-trx
|
||||
Make debugging possible
|
||||
|
||||
|
||||
25
debian/copyright
vendored
Normal file
25
debian/copyright
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
The Debian packaging is:
|
||||
|
||||
Copyright (C) 2014 Max <max.suraev@fairwaves.ru>
|
||||
|
||||
It was downloaded from:
|
||||
|
||||
git://git.osmocom.org/osmo-trx
|
||||
|
||||
Upstream Authors:
|
||||
|
||||
Thomas Tsou <tom@tsou.cc>
|
||||
David A. Burgess <dburgess@kestrelsp.com>
|
||||
Harvind S. Samra <hssamra@kestrelsp.com>
|
||||
Raffi Sevlian <raffisev@gmail.com>
|
||||
|
||||
Copyright:
|
||||
|
||||
Copyright (C) 2012-2013 Thomas Tsou <tom@tsou.cc>
|
||||
Copyright (C) 2011 Range Networks, Inc.
|
||||
Copyright (C) 2008-2011 Free Software Foundation, Inc.
|
||||
|
||||
License:
|
||||
|
||||
GNU Affero General Public License, Version 3
|
||||
|
||||
1
debian/osmo-trx.install
vendored
Normal file
1
debian/osmo-trx.install
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/usr/bin/osmo-trx
|
||||
12
debian/rules
vendored
Executable file
12
debian/rules
vendored
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
DEB_BUILD_HARDENING=1
|
||||
|
||||
%:
|
||||
dh $@ --with autoreconf
|
||||
|
||||
override_dh_shlibdeps:
|
||||
dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
|
||||
|
||||
override_dh_strip:
|
||||
dh_strip --dbg-package=osmo-trx-dbg
|
||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (native)
|
||||
Reference in New Issue
Block a user