aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/sigProcLib.cpp
diff options
context:
space:
mode:
authorThomas Tsou <tom@tsou.cc>2014-04-16 19:36:30 -0400
committerThomas Tsou <tom@tsou.cc>2014-10-06 10:35:29 -0700
commit1189019c30c1208c95868cb6998f6b7af25d2c45 (patch)
treeeef1039c2843cce3b570e2ef8f5dff20ea6ffab8 /Transceiver52M/sigProcLib.cpp
parent187225cf337244ad7061745b7834a027e44855be (diff)
Transceiver52M: Add SCH detection capability
Use similar approach for detecting normal and RACH bursts, but apply a sample shift after detection in order to gradually zero the measured timing offset. SCH synchronization sequence and setup are added similar to RACH detection with the main difference, aside being the SCH runs full length of the burst. History is also added to accommodate full length burst correlation. Signed-off-by: Thomas Tsou <tom@tsou.cc>
Diffstat (limited to 'Transceiver52M/sigProcLib.cpp')
-rw-r--r--Transceiver52M/sigProcLib.cpp134
1 files changed, 132 insertions, 2 deletions
diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp
index 54dd8fc..0db3a81 100644
--- a/Transceiver52M/sigProcLib.cpp
+++ b/Transceiver52M/sigProcLib.cpp
@@ -78,6 +78,7 @@ struct CorrelationSequence {
signalVector *sequence;
void *buffer;
+ void *history;
float toa;
complex gain;
};
@@ -111,6 +112,7 @@ struct PulseSequence {
CorrelationSequence *gMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
CorrelationSequence *gRACHSequence = NULL;
+CorrelationSequence *gSCHSequence = NULL;
PulseSequence *GSMPulse = NULL;
PulseSequence *GSMPulse1 = NULL;
@@ -131,6 +133,7 @@ void sigProcLibDestroy()
delete GMSKRotation1;
delete GMSKReverseRotation1;
delete gRACHSequence;
+ delete gSCHSequence;
delete GSMPulse;
delete GSMPulse1;
@@ -139,6 +142,7 @@ void sigProcLibDestroy()
GMSKReverseRotationN = NULL;
GMSKReverseRotation1 = NULL;
gRACHSequence = NULL;
+ gSCHSequence = NULL;
GSMPulse = NULL;
GSMPulse1 = NULL;
}
@@ -395,8 +399,10 @@ signalVector *convolve(const signalVector *x,
break;
case CUSTOM:
if (start < h->size() - 1) {
- head = h->size() - start;
- append = true;
+ if (x->getStart() < h->size() - 1) {
+ head = h->size() - start;
+ append = true;
+ }
}
if (start + len > x->size()) {
tail = start + len - x->size();
@@ -1274,6 +1280,69 @@ release:
return status;
}
+bool generateSCHSequence(int sps)
+{
+ bool status = true;
+ float toa;
+ complex *data = NULL;
+ signalVector *autocorr = NULL;
+ signalVector *seq0 = NULL, *seq1 = NULL, *_seq1 = NULL;
+
+ delete gSCHSequence;
+
+ seq0 = modulateBurst(gSCHSynchSequence, 0, sps, false);
+ if (!seq0)
+ return false;
+
+ seq1 = modulateBurst(gSCHSynchSequence, 0, sps, true);
+ if (!seq1) {
+ status = false;
+ goto release;
+ }
+
+ conjugateVector(*seq1);
+
+ /* For SSE alignment, reallocate the midamble sequence on 16-byte boundary */
+ data = (complex *) convolve_h_alloc(seq1->size());
+ _seq1 = new signalVector(data, 0, seq1->size());
+ _seq1->setAligned(true);
+ memcpy(_seq1->begin(), seq1->begin(), seq1->size() * sizeof(complex));
+
+ autocorr = convolve(seq0, _seq1, autocorr, NO_DELAY);
+ if (!autocorr) {
+ status = false;
+ goto release;
+ }
+
+ gSCHSequence = new CorrelationSequence;
+ gSCHSequence->sequence = _seq1;
+ gSCHSequence->buffer = data;
+ gSCHSequence->gain = peakDetect(*autocorr, &toa, NULL);
+ gSCHSequence->history = new complex[_seq1->size()];
+
+ /* For 1 sps only
+ * (Half of correlation length - 1) + midpoint of pulse shaping filer
+ * 20.5 = (64 / 2 - 1) + 1.5
+ */
+ if (sps == 1)
+ gSCHSequence->toa = toa - 32.5;
+ else
+ gSCHSequence->toa = 0.0;
+
+release:
+ delete autocorr;
+ delete seq0;
+ delete seq1;
+
+ if (!status) {
+ delete _seq1;
+ free(data);
+ gSCHSequence = NULL;
+ }
+
+ return status;
+}
+
static float computePeakRatio(signalVector *corr,
int sps, float toa, complex amp)
{
@@ -1424,6 +1493,62 @@ int detectRACHBurst(signalVector &rxBurst,
return 1;
}
+int detectSCHBurst(signalVector &burst,
+ float thresh,
+ int sps,
+ complex *amp,
+ float *toa)
+{
+ int rc, start, target, head, tail, len;
+ float _toa;
+ complex _amp;
+ signalVector *corr, *_burst;
+ CorrelationSequence *sync;
+
+ if ((sps != 1) && (sps != 4))
+ return -1;
+
+ /* Search full length */
+ target = 3 + 39 + 64;
+ head = target - 1;
+ tail = 39 + 3 + 9;
+
+ start = (target - head) * sps - 1;
+ len = (head + tail) * sps;
+ sync = gSCHSequence;
+ corr = new signalVector(len);
+
+ _burst = new signalVector(burst, sync->sequence->size(), 5);
+
+ memcpy(_burst->begin() - sync->sequence->size(), sync->history,
+ sync->sequence->size() * sizeof(complex));
+
+ memcpy(sync->history, &burst.begin()[burst.size() - sync->sequence->size()],
+ sync->sequence->size() * sizeof(complex));
+
+ rc = detectBurst(*_burst, *corr, sync,
+ thresh, sps, &_amp, &_toa, start, len);
+ delete corr;
+
+ 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 */
+ if (toa)
+ *toa = _toa - head * sps;
+ if (amp)
+ *amp = _amp;
+
+ return 1;
+}
+
/*
* Normal burst detection
*
@@ -1717,6 +1842,11 @@ bool sigProcLibSetup(int sps)
return false;
}
+ if (!generateSCHSequence(1)) {
+ sigProcLibDestroy();
+ return false;
+ }
+
generateDelayFilters();
return true;