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:
parent
c88d8d53f8
commit
865bca42d6
|
@ -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,
|
||||||
&litude,
|
&litude,
|
||||||
&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,
|
||||||
&litude,
|
&litude,
|
||||||
&TOA);
|
&TOA);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue