Transceiver52M: Refactor RACH and normal burst detection

Both RACH and normal bursts are detected with the same approach of
midamble correlation combined with peak-to-average ratio. The
difference is the midamble placements and lengths. Thus, there is
no reason to have independent implementations.

This patch creates a common call burstDetect(), while leaving the
correlation window indexing in the original calls.

Signed-off-by: Thomas Tsou <tom@tsou.cc>
This commit is contained in:
Thomas Tsou 2013-08-21 20:58:00 -04:00
parent c88d8d53f8
commit 865bca42d6
2 changed files with 144 additions and 124 deletions

View File

@ -363,7 +363,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
float chanOffset; float chanOffset;
success = analyzeTrafficBurst(*vectorBurst, success = analyzeTrafficBurst(*vectorBurst,
mTSC, mTSC,
3.0, 5.0,
mSPS, mSPS,
&amplitude, &amplitude,
&TOA, &TOA,
@ -398,7 +398,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
else { else {
// RACH burst // RACH burst
success = detectRACHBurst(*vectorBurst, success = detectRACHBurst(*vectorBurst,
5.0, // detection threshold 6.0,
mSPS, mSPS,
&amplitude, &amplitude,
&TOA); &TOA);

View File

@ -259,7 +259,7 @@ void initGMSKRotationTables(int sps)
bool sigProcLibSetup(int sps) bool sigProcLibSetup(int sps)
{ {
if ((sps != 1) && (sps != 2) && (sps != 4)) if ((sps != 1) && (sps != 4))
return false; return false;
initTrigTables(); initTrigTables();
@ -955,77 +955,36 @@ release:
return status; return status;
} }
int detectRACHBurst(signalVector &rxBurst, static float computePeakRatio(signalVector *corr,
float thresh, int sps, float toa, complex amp)
int sps,
complex *amp,
float *toa)
{ {
int start, len, num = 0; int num = 0;
float _toa, rms, par, avg = 0.0f; complex *peak;
complex _amp, *peak; float rms, avg = 0.0;
signalVector corr, *sync = gRACHSequence->sequence;
if ((sps != 1) && (sps != 2) && (sps != 4)) peak = corr->begin() + (int) rint(toa);
return -1;
start = 40 * sps; /* Check for bogus results */
len = 24 * sps; if ((toa < 0.0) || (toa > corr->size()))
corr = signalVector(len); return 0.0;
if (!convolve(&rxBurst, sync, &corr,
CUSTOM, start, len, sps, 0)) {
return -1;
}
_amp = fastPeakDetect(corr, &_toa);
/* Restrict peak-to-average calculations at the edges */
if ((_toa < 3) || (_toa > len - 3))
goto notfound;
peak = corr.begin() + (int) rint(_toa);
/* Compute peak-to-average ratio. Reject if we don't have enough values */
for (int i = 2 * sps; i <= 5 * sps; i++) { for (int i = 2 * sps; i <= 5 * sps; i++) {
if (peak - i >= corr.begin()) { if (peak - i >= corr->begin()) {
avg += (peak - i)->norm2(); avg += (peak - i)->norm2();
num++; num++;
} }
if (peak + i < corr.end()) { if (peak + i < corr->end()) {
avg += (peak + i)->norm2(); avg += (peak + i)->norm2();
num++; num++;
} }
} }
if (num < 2) if (num < 2)
goto notfound; return 0.0;
rms = sqrtf(avg / (float) num) + 0.00001; rms = sqrtf(avg / (float) num) + 0.00001;
par = _amp.abs() / rms;
if (par < thresh)
goto notfound;
/* Run the full peak detection to obtain interpolated values */ return (amp.abs()) / rms;
_amp = peakDetect(corr, &_toa, NULL);
/* Subtract forward tail bits from delay */
if (toa)
*toa = _toa - 8 * sps;
/* Normalize our channel gain */
if (amp)
*amp = _amp / gRACHSequence->gain;
return 1;
notfound:
if (amp)
*amp = 0.0f;
if (toa)
*toa = 0.0f;
return 0;
} }
bool energyDetect(signalVector &rxBurst, bool energyDetect(signalVector &rxBurst,
@ -1046,94 +1005,155 @@ bool energyDetect(signalVector &rxBurst,
return (energy/windowLength > detectThreshold*detectThreshold); return (energy/windowLength > detectThreshold*detectThreshold);
} }
int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh, /*
int sps, complex *amp, float *toa, unsigned max_toa, * Detect a burst based on correlation and peak-to-average ratio
bool chan_req, signalVector **chan, float *chan_offset) *
* For one sampler-per-symbol, perform fast peak detection (no interpolation)
* for initial gating. We do this because energy detection should be disabled.
* For higher oversampling values, we assume the energy detector is in place
* and we run full interpolating peak detection.
*/
static int detectBurst(signalVector &burst,
signalVector &corr, CorrelationSequence *sync,
float thresh, int sps, complex *amp, float *toa,
int start, int len)
{ {
int start, target, len, num = 0; /* Correlate */
complex _amp, *peak; if (!convolve(&burst, sync->sequence, &corr,
float _toa, rms, par, avg = 0.0f;
signalVector corr, *sync, *_chan;
if ((tsc < 0) || (tsc > 7) || ((sps != 1) && (sps != 2) && (sps != 4)))
return -1;
target = 3 + 58 + 5 + 16;
start = (target - 8) * sps;
len = (8 + 8 + max_toa) * sps;
sync = gMidambles[tsc]->sequence;
sync = gMidambles[tsc]->sequence;
corr = signalVector(len);
if (!convolve(&rxBurst, sync, &corr,
CUSTOM, start, len, sps, 0)) { CUSTOM, start, len, sps, 0)) {
return -1; return -1;
} }
_amp = peakDetect(corr, &_toa, NULL); /* Peak detection - place restrictions at correlation edges */
peak = corr.begin() + (int) rint(_toa); *amp = fastPeakDetect(corr, toa);
/* Check for bogus results */ if ((*toa < 3 * sps) || (*toa > len - 3 * sps))
if ((_toa < 0.0) || (_toa > corr.size())) return 0;
goto notfound;
for (int i = 2 * sps; i <= 5 * sps; i++) { /* Peak -to-average ratio */
if (peak - i >= corr.begin()) { if (computePeakRatio(&corr, sps, *toa, *amp) < thresh)
avg += (peak - i)->norm2(); return 0;
num++;
} /* Compute peak-to-average ratio. Reject if we don't have enough values */
if (peak + i < corr.end()) { *amp = peakDetect(corr, toa, NULL);
avg += (peak + i)->norm2();
num++; /* Normalize our channel gain */
} *amp = *amp / sync->gain;
return 1;
}
/*
* RACH burst detection
*
* Correlation window parameters:
* target: Tail bits + RACH length (reduced from 41 to a multiple of 4)
* head: Search 8 symbols before target
* tail: Search 8 symbols after target
*/
int detectRACHBurst(signalVector &rxBurst,
float thresh,
int sps,
complex *amp,
float *toa)
{
int rc, start, target, head, tail, len;
float _toa;
complex _amp;
signalVector corr;
CorrelationSequence *sync;
if ((sps != 1) && (sps != 4))
return -1;
target = 8 + 40;
head = 8;
tail = head;
start = (target - head) * sps - 1;
len = (head + tail) * sps;
sync = gRACHSequence;
corr = signalVector(len);
rc = detectBurst(rxBurst, corr, sync,
thresh, sps, &_amp, &_toa, start, len);
if (rc < 0) {
return -1;
} else if (!rc) {
if (amp)
*amp = 0.0f;
if (toa)
*toa = 0.0f;
return 0;
} }
if (num < 2) /* Subtract forward search bits from delay */
goto notfound; if (toa)
*toa = _toa - head * sps;
rms = sqrtf(avg / (float) num) + 0.00001;
par = (_amp.abs()) / rms;
if (par < thresh)
goto notfound;
/*
* NOTE: Because ideal TSC is 66 symbols into burst,
* the ideal TSC has an +/- 180 degree phase shift,
* due to the pi/4 frequency shift, that
* needs to be accounted for.
*/
if (amp) if (amp)
*amp = _amp / gMidambles[tsc]->gain; *amp = _amp;
/* Delay one half of peak-centred correlation length */ return 1;
_toa -= sps * 8; }
/*
* Normal burst detection
*
* Correlation window parameters:
* target: Tail + data + mid-midamble + 1/2 remaining midamblebits
* head: Search 8 symbols before target
* tail: Search 8 symbols + maximum expected delay
*/
int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh,
int sps, complex *amp, float *toa, unsigned max_toa,
bool chan_req, signalVector **chan, float *chan_offset)
{
int rc, start, target, head, tail, len;
complex _amp;
float _toa;
signalVector corr;
CorrelationSequence *sync;
if ((tsc < 0) || (tsc > 7) || ((sps != 1) && (sps != 4)))
return -1;
target = 3 + 58 + 16 + 5;
head = 8;
tail = head + max_toa;
start = (target - head) * sps - 1;
len = (head + tail) * sps;
sync = gMidambles[tsc];
corr = signalVector(len);
rc = detectBurst(rxBurst, corr, sync,
thresh, sps, &_amp, &_toa, start, len);
if (rc < 0) {
return -1;
} else if (!rc) {
if (amp)
*amp = 0.0f;
if (toa)
*toa = 0.0f;
return 0;
}
/* Subtract forward search bits from delay */
_toa -= head * sps;
if (toa) if (toa)
*toa = _toa; *toa = _toa;
if (amp)
*amp = _amp;
/* Equalization not currently supported */
if (chan_req) { if (chan_req) {
_chan = new signalVector(6 * sps); *chan = new signalVector(6 * sps);
delayVector(corr, -_toa);
corr.segmentCopyTo(*_chan, target - 3, _chan->size());
scaleVector(*_chan, complex(1.0, 0.0) / gMidambles[tsc]->gain);
*chan = _chan;
if (chan_offset) if (chan_offset)
*chan_offset = 3.0 * sps;; *chan_offset = 0.0;
} }
return 1; return 1;
notfound:
if (amp)
*amp = 0.0f;
if (toa)
*toa = 0.0f;
return 0;
} }
signalVector *decimateVector(signalVector &wVector, signalVector *decimateVector(signalVector &wVector,