blob: b7f35118c7e1a999766d7b0a150666af3fe5cf50 [file] [log] [blame]
dburgessb3a0ca42011-10-12 07:44:40 +00001/*
kurtis.heimerla198d452011-11-26 03:19:28 +00002* Copyright 2008, 2011 Free Software Foundation, Inc.
dburgessb3a0ca42011-10-12 07:44:40 +00003*
4* This software is distributed under the terms of the GNU Affero Public License.
5* See the COPYING file in the main directory for details.
6*
7* This use of this software may be subject to additional restrictions.
8* See the LEGAL file in the main directory for details.
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Affero General Public License for more details.
19
20 You should have received a copy of the GNU Affero General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22
23*/
24
25
26
27#define NDEBUG
28
29#include "sigProcLib.h"
30#include "GSMCommon.h"
kurtis.heimerla198d452011-11-26 03:19:28 +000031#include "sendLPF_961.h"
32#include "rcvLPF_651.h"
dburgessb3a0ca42011-10-12 07:44:40 +000033
34#include <Logger.h>
35
Alexander Chemerisd734e2d2013-06-16 14:30:58 +040036using namespace GSM;
37
dburgessb3a0ca42011-10-12 07:44:40 +000038#define TABLESIZE 1024
39
40/** Lookup tables for trigonometric approximation */
41float cosTable[TABLESIZE+1]; // add 1 element for wrap around
42float sinTable[TABLESIZE+1];
43
44/** Constants */
45static const float M_PI_F = (float)M_PI;
46static const float M_2PI_F = (float)(2.0*M_PI);
47static const float M_1_2PI_F = 1/M_2PI_F;
48
49/** Static vectors that contain a precomputed +/- f_b/4 sinusoid */
50signalVector *GMSKRotation = NULL;
51signalVector *GMSKReverseRotation = NULL;
52
53/** Static ideal RACH and midamble correlation waveforms */
54typedef struct {
55 signalVector *sequence;
56 signalVector *sequenceReversedConjugated;
57 float TOA;
58 complex gain;
59} CorrelationSequence;
60
61CorrelationSequence *gMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
62CorrelationSequence *gRACHSequence = NULL;
63
64void sigProcLibDestroy(void) {
65 if (GMSKRotation) {
66 delete GMSKRotation;
67 GMSKRotation = NULL;
68 }
69 if (GMSKReverseRotation) {
70 delete GMSKReverseRotation;
71 GMSKReverseRotation = NULL;
72 }
73 for (int i = 0; i < 8; i++) {
74 if (gMidambles[i]!=NULL) {
75 if (gMidambles[i]->sequence) delete gMidambles[i]->sequence;
76 if (gMidambles[i]->sequenceReversedConjugated) delete gMidambles[i]->sequenceReversedConjugated;
77 delete gMidambles[i];
78 gMidambles[i] = NULL;
79 }
80 }
81 if (gRACHSequence) {
82 if (gRACHSequence->sequence) delete gRACHSequence->sequence;
83 if (gRACHSequence->sequenceReversedConjugated) delete gRACHSequence->sequenceReversedConjugated;
84 delete gRACHSequence;
85 gRACHSequence = NULL;
86 }
87}
88
89
90
91// dB relative to 1.0.
92// if > 1.0, then return 0 dB
93float dB(float x) {
94
95 float arg = 1.0F;
96 float dB = 0.0F;
97
98 if (x >= 1.0F) return 0.0F;
99 if (x <= 0.0F) return -200.0F;
100
101 float prevArg = arg;
102 float prevdB = dB;
103 float stepSize = 16.0F;
104 float dBstepSize = 12.0F;
105 while (stepSize > 1.0F) {
106 do {
107 prevArg = arg;
108 prevdB = dB;
109 arg /= stepSize;
110 dB -= dBstepSize;
111 } while (arg > x);
112 arg = prevArg;
113 dB = prevdB;
114 stepSize *= 0.5F;
115 dBstepSize -= 3.0F;
116 }
117 return ((arg-x)*(dB-3.0F) + (x-arg*0.5F)*dB)/(arg - arg*0.5F);
118
119}
120
121// 10^(-dB/10), inverse of dB func.
122float dBinv(float x) {
123
124 float arg = 1.0F;
125 float dB = 0.0F;
126
127 if (x >= 0.0F) return 1.0F;
128 if (x <= -200.0F) return 0.0F;
129
130 float prevArg = arg;
131 float prevdB = dB;
132 float stepSize = 16.0F;
133 float dBstepSize = 12.0F;
134 while (stepSize > 1.0F) {
135 do {
136 prevArg = arg;
137 prevdB = dB;
138 arg /= stepSize;
139 dB -= dBstepSize;
140 } while (dB > x);
141 arg = prevArg;
142 dB = prevdB;
143 stepSize *= 0.5F;
144 dBstepSize -= 3.0F;
145 }
146
147 return ((dB-x)*(arg*0.5F)+(x-(dB-3.0F))*(arg))/3.0F;
148
149}
150
151float vectorNorm2(const signalVector &x)
152{
153 signalVector::const_iterator xPtr = x.begin();
154 float Energy = 0.0;
155 for (;xPtr != x.end();xPtr++) {
156 Energy += xPtr->norm2();
157 }
158 return Energy;
159}
160
161
162float vectorPower(const signalVector &x)
163{
164 return vectorNorm2(x)/x.size();
165}
166
167/** compute cosine via lookup table */
168float cosLookup(const float x)
169{
170 float arg = x*M_1_2PI_F;
171 while (arg > 1.0F) arg -= 1.0F;
172 while (arg < 0.0F) arg += 1.0F;
173
174 const float argT = arg*((float)TABLESIZE);
175 const int argI = (int)argT;
176 const float delta = argT-argI;
177 const float iDelta = 1.0F-delta;
178 return iDelta*cosTable[argI] + delta*cosTable[argI+1];
179}
180
181/** compute sine via lookup table */
182float sinLookup(const float x)
183{
184 float arg = x*M_1_2PI_F;
185 while (arg > 1.0F) arg -= 1.0F;
186 while (arg < 0.0F) arg += 1.0F;
187
188 const float argT = arg*((float)TABLESIZE);
189 const int argI = (int)argT;
190 const float delta = argT-argI;
191 const float iDelta = 1.0F-delta;
192 return iDelta*sinTable[argI] + delta*sinTable[argI+1];
193}
194
195
196/** compute e^(-jx) via lookup table. */
197complex expjLookup(float x)
198{
199 float arg = x*M_1_2PI_F;
200 while (arg > 1.0F) arg -= 1.0F;
201 while (arg < 0.0F) arg += 1.0F;
202
203 const float argT = arg*((float)TABLESIZE);
204 const int argI = (int)argT;
205 const float delta = argT-argI;
206 const float iDelta = 1.0F-delta;
207 return complex(iDelta*cosTable[argI] + delta*cosTable[argI+1],
208 iDelta*sinTable[argI] + delta*sinTable[argI+1]);
209}
210
211/** Library setup functions */
212void initTrigTables() {
213 for (int i = 0; i < TABLESIZE+1; i++) {
214 cosTable[i] = cos(2.0*M_PI*i/TABLESIZE);
215 sinTable[i] = sin(2.0*M_PI*i/TABLESIZE);
216 }
217}
218
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400219void initGMSKRotationTables(int sps)
220{
221 GMSKRotation = new signalVector(157 * sps);
222 GMSKReverseRotation = new signalVector(157 * sps);
dburgessb3a0ca42011-10-12 07:44:40 +0000223 signalVector::iterator rotPtr = GMSKRotation->begin();
224 signalVector::iterator revPtr = GMSKReverseRotation->begin();
225 float phase = 0.0;
226 while (rotPtr != GMSKRotation->end()) {
227 *rotPtr++ = expjLookup(phase);
228 *revPtr++ = expjLookup(-phase);
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400229 phase += M_PI_F / 2.0F / (float) sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000230 }
231}
232
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400233void sigProcLibSetup(int sps)
234{
dburgessb3a0ca42011-10-12 07:44:40 +0000235 initTrigTables();
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400236 initGMSKRotationTables(sps);
dburgessb3a0ca42011-10-12 07:44:40 +0000237}
238
239void GMSKRotate(signalVector &x) {
240 signalVector::iterator xPtr = x.begin();
241 signalVector::iterator rotPtr = GMSKRotation->begin();
242 if (x.isRealOnly()) {
243 while (xPtr < x.end()) {
244 *xPtr = *rotPtr++ * (xPtr->real());
245 xPtr++;
246 }
247 }
248 else {
249 while (xPtr < x.end()) {
250 *xPtr = *rotPtr++ * (*xPtr);
251 xPtr++;
252 }
253 }
254}
255
256void GMSKReverseRotate(signalVector &x) {
257 signalVector::iterator xPtr= x.begin();
258 signalVector::iterator rotPtr = GMSKReverseRotation->begin();
259 if (x.isRealOnly()) {
260 while (xPtr < x.end()) {
261 *xPtr = *rotPtr++ * (xPtr->real());
262 xPtr++;
263 }
264 }
265 else {
266 while (xPtr < x.end()) {
267 *xPtr = *rotPtr++ * (*xPtr);
268 xPtr++;
269 }
270 }
271}
272
273
274signalVector* convolve(const signalVector *a,
275 const signalVector *b,
276 signalVector *c,
277 ConvType spanType,
278 unsigned startIx,
279 unsigned len)
280{
281 if ((a==NULL) || (b==NULL)) return NULL;
282 int La = a->size();
283 int Lb = b->size();
284
285 int startIndex;
286 unsigned int outSize;
287 switch (spanType) {
288 case FULL_SPAN:
289 startIndex = 0;
290 outSize = La+Lb-1;
291 break;
292 case OVERLAP_ONLY:
293 startIndex = La;
294 outSize = abs(La-Lb)+1;
295 break;
296 case START_ONLY:
297 startIndex = 0;
298 outSize = La;
299 break;
300 case WITH_TAIL:
301 startIndex = Lb;
302 outSize = La;
303 break;
304 case NO_DELAY:
305 if (Lb % 2)
306 startIndex = Lb/2;
307 else
308 startIndex = Lb/2-1;
309 outSize = La;
310 break;
311 case CUSTOM:
312 startIndex = startIx;
313 outSize = len;
314 break;
315 default:
316 return NULL;
317 }
318
319
320 if (c==NULL)
321 c = new signalVector(outSize);
322 else if (c->size()!=outSize)
323 return NULL;
324
325 signalVector::const_iterator aStart = a->begin();
326 signalVector::const_iterator bStart = b->begin();
327 signalVector::const_iterator aEnd = a->end();
328 signalVector::const_iterator bEnd = b->end();
329 signalVector::iterator cPtr = c->begin();
330 int t = startIndex;
331 int stopIndex = startIndex + outSize;
332 switch (b->getSymmetry()) {
333 case NONE:
334 {
335 while (t < stopIndex) {
336 signalVector::const_iterator aP = aStart+t;
337 signalVector::const_iterator bP = bStart;
338 if (a->isRealOnly() && b->isRealOnly()) {
339 float sum = 0.0;
340 while (bP < bEnd) {
341 if (aP < aStart) break;
342 if (aP < aEnd) sum += (aP->real())*(bP->real());
343 aP--;
344 bP++;
345 }
346 *cPtr++ = sum;
347 }
348 else if (a->isRealOnly()) {
349 complex sum = 0.0;
350 while (bP < bEnd) {
351 if (aP < aStart) break;
352 if (aP < aEnd) sum += (*bP)*(aP->real());
353 aP--;
354 bP++;
355 }
356 *cPtr++ = sum;
357 }
358 else if (b->isRealOnly()) {
359 complex sum = 0.0;
360 while (bP < bEnd) {
361 if (aP < aStart) break;
362 if (aP < aEnd) sum += (*aP)*(bP->real());
363 aP--;
364 bP++;
365 }
366 *cPtr++ = sum;
367 }
368 else {
369 complex sum = 0.0;
370 while (bP < bEnd) {
371 if (aP < aStart) break;
372 if (aP < aEnd) sum += (*aP)*(*bP);
373 aP--;
374 bP++;
375 }
376 *cPtr++ = sum;
377 }
378 t++;
379 }
380 }
381 break;
382 case ABSSYM:
383 {
384 complex sum = 0.0;
385 bool isOdd = (bool) (Lb % 2);
386 if (isOdd)
387 bEnd = bStart + (Lb+1)/2;
388 else
389 bEnd = bStart + Lb/2;
390 while (t < stopIndex) {
391 signalVector::const_iterator aP = aStart+t;
392 signalVector::const_iterator aPsym = aP-Lb+1;
393 signalVector::const_iterator bP = bStart;
394 sum = 0.0;
395 if (!b->isRealOnly()) {
396 while (bP < bEnd) {
397 if (aP < aStart) break;
398 if (aP == aPsym)
399 sum+= (*aP)*(*bP);
400 else if ((aP < aEnd) && (aPsym >= aStart))
401 sum+= ((*aP)+(*aPsym))*(*bP);
402 else if (aP < aEnd)
403 sum += (*aP)*(*bP);
404 else if (aPsym >= aStart)
405 sum += (*aPsym)*(*bP);
406 aP--;
407 aPsym++;
408 bP++;
409 }
410 }
411 else {
412 while (bP < bEnd) {
413 if (aP < aStart) break;
414 if (aP == aPsym)
415 sum+= (*aP)*(bP->real());
416 else if ((aP < aEnd) && (aPsym >= aStart))
417 sum+= ((*aP)+(*aPsym))*(bP->real());
418 else if (aP < aEnd)
419 sum += (*aP)*(bP->real());
420 else if (aPsym >= aStart)
421 sum += (*aPsym)*(bP->real());
422 aP--;
423 aPsym++;
424 bP++;
425 }
426 }
427 *cPtr++ = sum;
428 t++;
429 }
430 }
431 break;
432 default:
433 return NULL;
434 break;
435 }
436
437
438 return c;
439}
440
441
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400442signalVector* generateGSMPulse(int sps, int symbolLength)
dburgessb3a0ca42011-10-12 07:44:40 +0000443{
444
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400445 int numSamples = sps * symbolLength + 1;
dburgessb3a0ca42011-10-12 07:44:40 +0000446 signalVector *x = new signalVector(numSamples);
447 signalVector::iterator xP = x->begin();
448 int centerPoint = (numSamples-1)/2;
449 for (int i = 0; i < numSamples; i++) {
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400450 float arg = (float) (i - centerPoint) / (float) sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000451 *xP++ = 0.96*exp(-1.1380*arg*arg-0.527*arg*arg*arg*arg); // GSM pulse approx.
452 }
453
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400454 float avgAbsval = sqrtf(vectorNorm2(*x) / sps);
dburgessb3a0ca42011-10-12 07:44:40 +0000455 xP = x->begin();
456 for (int i = 0; i < numSamples; i++)
457 *xP++ /= avgAbsval;
458 x->isRealOnly(true);
459 x->setSymmetry(ABSSYM);
460 return x;
461}
462
463signalVector* frequencyShift(signalVector *y,
464 signalVector *x,
465 float freq,
466 float startPhase,
467 float *finalPhase)
468{
469
470 if (!x) return NULL;
471
472 if (y==NULL) {
473 y = new signalVector(x->size());
474 y->isRealOnly(x->isRealOnly());
475 if (y==NULL) return NULL;
476 }
477
478 if (y->size() < x->size()) return NULL;
479
480 float phase = startPhase;
481 signalVector::iterator yP = y->begin();
482 signalVector::iterator xPEnd = x->end();
483 signalVector::iterator xP = x->begin();
484
485 if (x->isRealOnly()) {
486 while (xP < xPEnd) {
487 (*yP++) = expjLookup(phase)*( (xP++)->real() );
488 phase += freq;
489 }
490 }
491 else {
492 while (xP < xPEnd) {
493 (*yP++) = (*xP++)*expjLookup(phase);
494 phase += freq;
495 }
496 }
497
498
499 if (finalPhase) *finalPhase = phase;
500
501 return y;
502}
503
504signalVector* reverseConjugate(signalVector *b)
505{
506 signalVector *tmp = new signalVector(b->size());
507 tmp->isRealOnly(b->isRealOnly());
508 signalVector::iterator bP = b->begin();
509 signalVector::iterator bPEnd = b->end();
510 signalVector::iterator tmpP = tmp->end()-1;
511 if (!b->isRealOnly()) {
512 while (bP < bPEnd) {
513 *tmpP-- = bP->conj();
514 bP++;
515 }
516 }
517 else {
518 while (bP < bPEnd) {
519 *tmpP-- = bP->real();
520 bP++;
521 }
522 }
523
524 return tmp;
525}
526
527signalVector* correlate(signalVector *a,
528 signalVector *b,
529 signalVector *c,
530 ConvType spanType,
531 bool bReversedConjugated,
532 unsigned startIx,
533 unsigned len)
534{
535 signalVector *tmp = NULL;
536
537 if (!bReversedConjugated) {
538 tmp = reverseConjugate(b);
539 }
540 else {
541 tmp = b;
542 }
543
544 c = convolve(a,tmp,c,spanType,startIx,len);
545
546 if (!bReversedConjugated) delete tmp;
547
548 return c;
549}
550
551
552/* soft output slicer */
553bool vectorSlicer(signalVector *x)
554{
555
556 signalVector::iterator xP = x->begin();
557 signalVector::iterator xPEnd = x->end();
558 while (xP < xPEnd) {
559 *xP = (complex) (0.5*(xP->real()+1.0F));
560 if (xP->real() > 1.0) *xP = 1.0;
561 if (xP->real() < 0.0) *xP = 0.0;
562 xP++;
563 }
564 return true;
565}
566
567signalVector *modulateBurst(const BitVector &wBurst,
568 const signalVector &gsmPulse,
569 int guardPeriodLength,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400570 int sps)
dburgessb3a0ca42011-10-12 07:44:40 +0000571{
572
573 //static complex staticBurst[157];
574
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400575 int burstSize = sps * (wBurst.size() + guardPeriodLength);
dburgessb3a0ca42011-10-12 07:44:40 +0000576 //signalVector modBurst((complex *) staticBurst,0,burstSize);
577 signalVector modBurst(burstSize);// = new signalVector(burstSize);
578 modBurst.isRealOnly(true);
579 //memset(staticBurst,0,sizeof(complex)*burstSize);
580 modBurst.fill(0.0);
581 signalVector::iterator modBurstItr = modBurst.begin();
582
583#if 0
584 // if wBurst is already differentially decoded
585 *modBurstItr = 2.0*(wBurst[0] & 0x01)-1.0;
586 signalVector::iterator prevVal = modBurstItr;
587 for (unsigned int i = 1; i < wBurst.size(); i++) {
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400588 modBurstItr += sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000589 if (wBurst[i] & 0x01)
590 *modBurstItr = *prevVal * complex(0.0,1.0);
591 else
592 *modBurstItr = *prevVal * complex(0.0,-1.0);
593 prevVal = modBurstItr;
594 }
595#else
596 // if wBurst are the raw bits
597 for (unsigned int i = 0; i < wBurst.size(); i++) {
598 *modBurstItr = 2.0*(wBurst[i] & 0x01)-1.0;
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400599 modBurstItr += sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000600 }
601
602 // shift up pi/2
603 // ignore starting phase, since spec allows for discontinuous phase
604 GMSKRotate(modBurst);
605#endif
606 modBurst.isRealOnly(false);
607
608 // filter w/ pulse shape
609 signalVector *shapedBurst = convolve(&modBurst,&gsmPulse,NULL,NO_DELAY);
610
611 //delete modBurst;
612
613 return shapedBurst;
614
615}
616
617float sinc(float x)
618{
619 if ((x >= 0.01F) || (x <= -0.01F)) return (sinLookup(x)/x);
620 return 1.0F;
621}
622
623void delayVector(signalVector &wBurst,
624 float delay)
625{
626
627 int intOffset = (int) floor(delay);
628 float fracOffset = delay - intOffset;
629
630 // do fractional shift first, only do it for reasonable offsets
631 if (fabs(fracOffset) > 1e-2) {
632 // create sinc function
633 signalVector sincVector(21);
634 sincVector.isRealOnly(true);
635 signalVector::iterator sincBurstItr = sincVector.begin();
636 for (int i = 0; i < 21; i++)
637 *sincBurstItr++ = (complex) sinc(M_PI_F*(i-10-fracOffset));
638
639 signalVector shiftedBurst(wBurst.size());
640 convolve(&wBurst,&sincVector,&shiftedBurst,NO_DELAY);
641 wBurst.clone(shiftedBurst);
642 }
643
644 if (intOffset < 0) {
645 intOffset = -intOffset;
646 signalVector::iterator wBurstItr = wBurst.begin();
647 signalVector::iterator shiftedItr = wBurst.begin()+intOffset;
648 while (shiftedItr < wBurst.end())
649 *wBurstItr++ = *shiftedItr++;
650 while (wBurstItr < wBurst.end())
651 *wBurstItr++ = 0.0;
652 }
653 else {
654 signalVector::iterator wBurstItr = wBurst.end()-1;
655 signalVector::iterator shiftedItr = wBurst.end()-1-intOffset;
656 while (shiftedItr >= wBurst.begin())
657 *wBurstItr-- = *shiftedItr--;
658 while (wBurstItr >= wBurst.begin())
659 *wBurstItr-- = 0.0;
660 }
661}
662
663signalVector *gaussianNoise(int length,
664 float variance,
665 complex mean)
666{
667
668 signalVector *noise = new signalVector(length);
669 signalVector::iterator nPtr = noise->begin();
670 float stddev = sqrtf(variance);
671 while (nPtr < noise->end()) {
672 float u1 = (float) rand()/ (float) RAND_MAX;
673 while (u1==0.0)
674 u1 = (float) rand()/ (float) RAND_MAX;
675 float u2 = (float) rand()/ (float) RAND_MAX;
676 float arg = 2.0*M_PI*u2;
677 *nPtr = mean + stddev*complex(cos(arg),sin(arg))*sqrtf(-2.0*log(u1));
678 nPtr++;
679 }
680
681 return noise;
682}
683
684complex interpolatePoint(const signalVector &inSig,
685 float ix)
686{
687
688 int start = (int) (floor(ix) - 10);
689 if (start < 0) start = 0;
690 int end = (int) (floor(ix) + 11);
691 if ((unsigned) end > inSig.size()-1) end = inSig.size()-1;
692
693 complex pVal = 0.0;
694 if (!inSig.isRealOnly()) {
695 for (int i = start; i < end; i++)
696 pVal += inSig[i] * sinc(M_PI_F*(i-ix));
697 }
698 else {
699 for (int i = start; i < end; i++)
700 pVal += inSig[i].real() * sinc(M_PI_F*(i-ix));
701 }
702
703 return pVal;
704}
705
706
707
708complex peakDetect(const signalVector &rxBurst,
709 float *peakIndex,
710 float *avgPwr)
711{
712
713
714 complex maxVal = 0.0;
715 float maxIndex = -1;
716 float sumPower = 0.0;
717
718 for (unsigned int i = 0; i < rxBurst.size(); i++) {
719 float samplePower = rxBurst[i].norm2();
720 if (samplePower > maxVal.real()) {
721 maxVal = samplePower;
722 maxIndex = i;
723 }
724 sumPower += samplePower;
725 }
726
727 // interpolate around the peak
728 // to save computation, we'll use early-late balancing
729 float earlyIndex = maxIndex-1;
730 float lateIndex = maxIndex+1;
731
732 float incr = 0.5;
733 while (incr > 1.0/1024.0) {
734 complex earlyP = interpolatePoint(rxBurst,earlyIndex);
735 complex lateP = interpolatePoint(rxBurst,lateIndex);
736 if (earlyP < lateP)
737 earlyIndex += incr;
738 else if (earlyP > lateP)
739 earlyIndex -= incr;
740 else break;
741 incr /= 2.0;
742 lateIndex = earlyIndex + 2.0;
743 }
744
745 maxIndex = earlyIndex + 1.0;
746 maxVal = interpolatePoint(rxBurst,maxIndex);
747
748 if (peakIndex!=NULL)
749 *peakIndex = maxIndex;
750
751 if (avgPwr!=NULL)
752 *avgPwr = (sumPower-maxVal.norm2()) / (rxBurst.size()-1);
753
754 return maxVal;
755
756}
757
758void scaleVector(signalVector &x,
759 complex scale)
760{
761 signalVector::iterator xP = x.begin();
762 signalVector::iterator xPEnd = x.end();
763 if (!x.isRealOnly()) {
764 while (xP < xPEnd) {
765 *xP = *xP * scale;
766 xP++;
767 }
768 }
769 else {
770 while (xP < xPEnd) {
771 *xP = xP->real() * scale;
772 xP++;
773 }
774 }
775}
776
777/** in-place conjugation */
778void conjugateVector(signalVector &x)
779{
780 if (x.isRealOnly()) return;
781 signalVector::iterator xP = x.begin();
782 signalVector::iterator xPEnd = x.end();
783 while (xP < xPEnd) {
784 *xP = xP->conj();
785 xP++;
786 }
787}
788
789
790// in-place addition!!
791bool addVector(signalVector &x,
792 signalVector &y)
793{
794 signalVector::iterator xP = x.begin();
795 signalVector::iterator yP = y.begin();
796 signalVector::iterator xPEnd = x.end();
797 signalVector::iterator yPEnd = y.end();
798 while ((xP < xPEnd) && (yP < yPEnd)) {
799 *xP = *xP + *yP;
800 xP++; yP++;
801 }
802 return true;
803}
804
805// in-place multiplication!!
806bool multVector(signalVector &x,
807 signalVector &y)
808{
809 signalVector::iterator xP = x.begin();
810 signalVector::iterator yP = y.begin();
811 signalVector::iterator xPEnd = x.end();
812 signalVector::iterator yPEnd = y.end();
813 while ((xP < xPEnd) && (yP < yPEnd)) {
814 *xP = (*xP) * (*yP);
815 xP++; yP++;
816 }
817 return true;
818}
819
820
821void offsetVector(signalVector &x,
822 complex offset)
823{
824 signalVector::iterator xP = x.begin();
825 signalVector::iterator xPEnd = x.end();
826 if (!x.isRealOnly()) {
827 while (xP < xPEnd) {
828 *xP += offset;
829 xP++;
830 }
831 }
832 else {
833 while (xP < xPEnd) {
834 *xP = xP->real() + offset;
835 xP++;
836 }
837 }
838}
839
840bool generateMidamble(signalVector &gsmPulse,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400841 int sps,
dburgessb3a0ca42011-10-12 07:44:40 +0000842 int TSC)
843{
844
845 if ((TSC < 0) || (TSC > 7))
846 return false;
847
848 if (gMidambles[TSC]) {
849 if (gMidambles[TSC]->sequence!=NULL) delete gMidambles[TSC]->sequence;
850 if (gMidambles[TSC]->sequenceReversedConjugated!=NULL) delete gMidambles[TSC]->sequenceReversedConjugated;
851 }
852
853 signalVector emptyPulse(1);
854 *(emptyPulse.begin()) = 1.0;
855
856 // only use middle 16 bits of each TSC
857 signalVector *middleMidamble = modulateBurst(gTrainingSequence[TSC].segment(5,16),
858 emptyPulse,
859 0,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400860 sps);
dburgessb3a0ca42011-10-12 07:44:40 +0000861 signalVector *midamble = modulateBurst(gTrainingSequence[TSC],
862 gsmPulse,
863 0,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400864 sps);
dburgessb3a0ca42011-10-12 07:44:40 +0000865
866 if (midamble == NULL) return false;
867 if (middleMidamble == NULL) return false;
868
869 // NOTE: Because ideal TSC 16-bit midamble is 66 symbols into burst,
870 // the ideal TSC has an + 180 degree phase shift,
871 // due to the pi/2 frequency shift, that
872 // needs to be accounted for.
873 // 26-midamble is 61 symbols into burst, has +90 degree phase shift.
874 scaleVector(*middleMidamble,complex(-1.0,0.0));
875 scaleVector(*midamble,complex(0.0,1.0));
876
877 signalVector *autocorr = correlate(midamble,middleMidamble,NULL,NO_DELAY);
878
879 if (autocorr == NULL) return false;
880
881 gMidambles[TSC] = new CorrelationSequence;
882 gMidambles[TSC]->sequence = middleMidamble;
883 gMidambles[TSC]->sequenceReversedConjugated = reverseConjugate(middleMidamble);
884 gMidambles[TSC]->gain = peakDetect(*autocorr,&gMidambles[TSC]->TOA,NULL);
885
886 LOG(DEBUG) << "midamble autocorr: " << *autocorr;
887
888 LOG(DEBUG) << "TOA: " << gMidambles[TSC]->TOA;
889
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400890 //gMidambles[TSC]->TOA -= 5*sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000891
892 delete autocorr;
893 delete midamble;
894
895 return true;
896}
897
898bool generateRACHSequence(signalVector &gsmPulse,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400899 int sps)
dburgessb3a0ca42011-10-12 07:44:40 +0000900{
901
902 if (gRACHSequence) {
903 if (gRACHSequence->sequence!=NULL) delete gRACHSequence->sequence;
904 if (gRACHSequence->sequenceReversedConjugated!=NULL) delete gRACHSequence->sequenceReversedConjugated;
905 }
906
907 signalVector *RACHSeq = modulateBurst(gRACHSynchSequence,
908 gsmPulse,
909 0,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400910 sps);
dburgessb3a0ca42011-10-12 07:44:40 +0000911
912 assert(RACHSeq);
913
914 signalVector *autocorr = correlate(RACHSeq,RACHSeq,NULL,NO_DELAY);
915
916 assert(autocorr);
917
918 gRACHSequence = new CorrelationSequence;
919 gRACHSequence->sequence = RACHSeq;
920 gRACHSequence->sequenceReversedConjugated = reverseConjugate(RACHSeq);
921 gRACHSequence->gain = peakDetect(*autocorr,&gRACHSequence->TOA,NULL);
922
923 delete autocorr;
924
925 return true;
926
927}
928
929
930bool detectRACHBurst(signalVector &rxBurst,
931 float detectThreshold,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400932 int sps,
dburgessb3a0ca42011-10-12 07:44:40 +0000933 complex *amplitude,
934 float* TOA)
935{
936
937 //static complex staticData[500];
938
939 //signalVector correlatedRACH(staticData,0,rxBurst.size());
940 signalVector correlatedRACH(rxBurst.size());
941 correlate(&rxBurst,gRACHSequence->sequenceReversedConjugated,&correlatedRACH,NO_DELAY,true);
942
943 float meanPower;
944 complex peakAmpl = peakDetect(correlatedRACH,TOA,&meanPower);
945
946 float valleyPower = 0.0;
947
948 // check for bogus results
949 if ((*TOA < 0.0) || (*TOA > correlatedRACH.size())) {
950 *amplitude = 0.0;
951 return false;
952 }
953 complex *peakPtr = correlatedRACH.begin() + (int) rint(*TOA);
954
955 LOG(DEBUG) << "RACH corr: " << correlatedRACH;
956
957 float numSamples = 0.0;
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400958 for (int i = 57 * sps; i <= 107 * sps; i++) {
dburgessb3a0ca42011-10-12 07:44:40 +0000959 if (peakPtr+i >= correlatedRACH.end())
960 break;
961 valleyPower += (peakPtr+i)->norm2();
962 numSamples++;
963 }
964
965 if (numSamples < 2) {
966 *amplitude = 0.0;
967 return false;
968 }
969
970 float RMS = sqrtf(valleyPower/(float) numSamples)+0.00001;
971 float peakToMean = peakAmpl.abs()/RMS;
972
973 LOG(DEBUG) << "RACH peakAmpl=" << peakAmpl << " RMS=" << RMS << " peakToMean=" << peakToMean;
974 *amplitude = peakAmpl/(gRACHSequence->gain);
975
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400976 *TOA = (*TOA) - gRACHSequence->TOA - 8 * sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000977
978 LOG(DEBUG) << "RACH thresh: " << peakToMean;
979
980 return (peakToMean > detectThreshold);
981}
982
983bool energyDetect(signalVector &rxBurst,
984 unsigned windowLength,
985 float detectThreshold,
986 float *avgPwr)
987{
988
989 signalVector::const_iterator windowItr = rxBurst.begin(); //+rxBurst.size()/2 - 5*windowLength/2;
990 float energy = 0.0;
991 if (windowLength < 0) windowLength = 20;
992 if (windowLength > rxBurst.size()) windowLength = rxBurst.size();
993 for (unsigned i = 0; i < windowLength; i++) {
994 energy += windowItr->norm2();
995 windowItr+=4;
996 }
997 if (avgPwr) *avgPwr = energy/windowLength;
998 LOG(DEBUG) << "detected energy: " << energy/windowLength;
999 return (energy/windowLength > detectThreshold*detectThreshold);
1000}
1001
1002
1003bool analyzeTrafficBurst(signalVector &rxBurst,
1004 unsigned TSC,
1005 float detectThreshold,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001006 int sps,
dburgessb3a0ca42011-10-12 07:44:40 +00001007 complex *amplitude,
1008 float *TOA,
1009 unsigned maxTOA,
1010 bool requestChannel,
1011 signalVector **channelResponse,
1012 float *channelResponseOffset)
1013{
1014
1015 assert(TSC<8);
1016 assert(amplitude);
1017 assert(TOA);
1018 assert(gMidambles[TSC]);
1019
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001020 if (maxTOA < 3*sps) maxTOA = 3*sps;
dburgessb3a0ca42011-10-12 07:44:40 +00001021 unsigned spanTOA = maxTOA;
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001022 if (spanTOA < 5*sps) spanTOA = 5*sps;
dburgessb3a0ca42011-10-12 07:44:40 +00001023
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001024 unsigned startIx = 66*sps-spanTOA;
1025 unsigned endIx = (66+16)*sps+spanTOA;
dburgessb3a0ca42011-10-12 07:44:40 +00001026 unsigned windowLen = endIx - startIx;
1027 unsigned corrLen = 2*maxTOA+1;
1028
1029 unsigned expectedTOAPeak = (unsigned) round(gMidambles[TSC]->TOA + (gMidambles[TSC]->sequenceReversedConjugated->size()-1)/2);
1030
1031 signalVector burstSegment(rxBurst.begin(),startIx,windowLen);
1032
1033 //static complex staticData[200];
1034 //signalVector correlatedBurst(staticData,0,corrLen);
1035 signalVector correlatedBurst(corrLen);
1036 correlate(&burstSegment, gMidambles[TSC]->sequenceReversedConjugated,
1037 &correlatedBurst, CUSTOM,true,
1038 expectedTOAPeak-maxTOA,corrLen);
1039
1040 float meanPower;
1041 *amplitude = peakDetect(correlatedBurst,TOA,&meanPower);
1042 float valleyPower = 0.0; //amplitude->norm2();
1043 complex *peakPtr = correlatedBurst.begin() + (int) rint(*TOA);
1044
1045 // check for bogus results
1046 if ((*TOA < 0.0) || (*TOA > correlatedBurst.size())) {
1047 *amplitude = 0.0;
1048 return false;
1049 }
1050
1051 int numRms = 0;
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001052 for (int i = 2*sps; i <= 5*sps;i++) {
dburgessb3a0ca42011-10-12 07:44:40 +00001053 if (peakPtr - i >= correlatedBurst.begin()) {
1054 valleyPower += (peakPtr-i)->norm2();
1055 numRms++;
1056 }
1057 if (peakPtr + i < correlatedBurst.end()) {
1058 valleyPower += (peakPtr+i)->norm2();
1059 numRms++;
1060 }
1061 }
1062
1063 if (numRms < 2) {
1064 // check for bogus results
1065 *amplitude = 0.0;
1066 return false;
1067 }
1068
1069 float RMS = sqrtf(valleyPower/(float)numRms)+0.00001;
1070 float peakToMean = (amplitude->abs())/RMS;
1071
1072 // NOTE: Because ideal TSC is 66 symbols into burst,
1073 // the ideal TSC has an +/- 180 degree phase shift,
1074 // due to the pi/4 frequency shift, that
1075 // needs to be accounted for.
1076
1077 *amplitude = (*amplitude)/gMidambles[TSC]->gain;
1078 *TOA = (*TOA) - (maxTOA);
1079
1080 LOG(DEBUG) << "TCH peakAmpl=" << amplitude->abs() << " RMS=" << RMS << " peakToMean=" << peakToMean << " TOA=" << *TOA;
1081
1082 LOG(DEBUG) << "autocorr: " << correlatedBurst;
1083
1084 if (requestChannel && (peakToMean > detectThreshold)) {
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001085 float TOAoffset = maxTOA;
dburgessb3a0ca42011-10-12 07:44:40 +00001086 delayVector(correlatedBurst,-(*TOA));
1087 // midamble only allows estimation of a 6-tap channel
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001088 signalVector chanVector(6 * sps);
dburgessb3a0ca42011-10-12 07:44:40 +00001089 float maxEnergy = -1.0;
1090 int maxI = -1;
1091 for (int i = 0; i < 7; i++) {
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001092 if (TOAoffset + (i-5) * sps + chanVector.size() > correlatedBurst.size())
1093 continue;
1094 if (TOAoffset + (i-5) * sps < 0)
1095 continue;
1096 correlatedBurst.segmentCopyTo(chanVector,
1097 (int) floor(TOAoffset + (i - 5) * sps),
1098 chanVector.size());
1099 float energy = vectorNorm2(chanVector);
dburgessb3a0ca42011-10-12 07:44:40 +00001100 if (energy > 0.95*maxEnergy) {
1101 maxI = i;
1102 maxEnergy = energy;
1103 }
1104 }
1105
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001106 *channelResponse = new signalVector(chanVector.size());
1107 correlatedBurst.segmentCopyTo(**channelResponse,
1108 (int) floor(TOAoffset + (maxI - 5) * sps),
1109 (*channelResponse)->size());
1110 scaleVector(**channelResponse, complex(1.0, 0.0) / gMidambles[TSC]->gain);
dburgessb3a0ca42011-10-12 07:44:40 +00001111 LOG(DEBUG) << "channelResponse: " << **channelResponse;
1112
1113 if (channelResponseOffset)
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001114 *channelResponseOffset = 5 * sps - maxI;
dburgessb3a0ca42011-10-12 07:44:40 +00001115
1116 }
1117
1118 return (peakToMean > detectThreshold);
1119
1120}
1121
1122signalVector *decimateVector(signalVector &wVector,
1123 int decimationFactor)
1124{
1125
1126 if (decimationFactor <= 1) return NULL;
1127
1128 signalVector *decVector = new signalVector(wVector.size()/decimationFactor);
1129 decVector->isRealOnly(wVector.isRealOnly());
1130
1131 signalVector::iterator vecItr = decVector->begin();
1132 for (unsigned int i = 0; i < wVector.size();i+=decimationFactor)
1133 *vecItr++ = wVector[i];
1134
1135 return decVector;
1136}
1137
1138
1139SoftVector *demodulateBurst(signalVector &rxBurst,
1140 const signalVector &gsmPulse,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001141 int sps,
dburgessb3a0ca42011-10-12 07:44:40 +00001142 complex channel,
1143 float TOA)
1144
1145{
1146 scaleVector(rxBurst,((complex) 1.0)/channel);
1147 delayVector(rxBurst,-TOA);
1148
1149 signalVector *shapedBurst = &rxBurst;
1150
1151 // shift up by a quarter of a frequency
1152 // ignore starting phase, since spec allows for discontinuous phase
1153 GMSKReverseRotate(*shapedBurst);
1154
1155 // run through slicer
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001156 if (sps > 1) {
1157 signalVector *decShapedBurst = decimateVector(*shapedBurst, sps);
dburgessb3a0ca42011-10-12 07:44:40 +00001158 shapedBurst = decShapedBurst;
1159 }
1160
1161 LOG(DEBUG) << "shapedBurst: " << *shapedBurst;
1162
1163 vectorSlicer(shapedBurst);
1164
1165 SoftVector *burstBits = new SoftVector(shapedBurst->size());
1166
1167 SoftVector::iterator burstItr = burstBits->begin();
1168 signalVector::iterator shapedItr = shapedBurst->begin();
1169 for (; shapedItr < shapedBurst->end(); shapedItr++)
1170 *burstItr++ = shapedItr->real();
1171
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001172 if (sps > 1)
1173 delete shapedBurst;
dburgessb3a0ca42011-10-12 07:44:40 +00001174
1175 return burstBits;
1176
1177}
1178
1179
1180// 1.0 is sampling frequency
1181// must satisfy cutoffFreq > 1/filterLen
1182signalVector *createLPF(float cutoffFreq,
1183 int filterLen,
1184 float gainDC)
1185{
kurtis.heimerla198d452011-11-26 03:19:28 +00001186#if 0
dburgessb3a0ca42011-10-12 07:44:40 +00001187 signalVector *LPF = new signalVector(filterLen-1);
1188 LPF->isRealOnly(true);
1189 LPF->setSymmetry(ABSSYM);
1190 signalVector::iterator itr = LPF->begin();
1191 double sum = 0.0;
1192 for (int i = 1; i < filterLen; i++) {
1193 float ys = sinc(M_2PI_F*cutoffFreq*((float)i-(float)(filterLen)/2.0F));
1194 float yg = 4.0F * cutoffFreq;
1195 // Blackman -- less brickwall (sloping transition) but larger stopband attenuation
1196 float yw = 0.42 - 0.5*cos(((float)i)*M_2PI_F/(float)(filterLen)) + 0.08*cos(((float)i)*2*M_2PI_F/(float)(filterLen));
1197 // Hamming -- more brickwall with smaller stopband attenuation
1198 //float yw = 0.53836F - 0.46164F * cos(((float)i)*M_2PI_F/(float)(filterLen+1));
1199 *itr++ = (complex) ys*yg*yw;
1200 sum += ys*yg*yw;
1201 }
kurtis.heimerla198d452011-11-26 03:19:28 +00001202#else
1203 double sum = 0.0;
1204 signalVector *LPF;
1205 signalVector::iterator itr;
1206 if (filterLen == 651) { // receive LPF
1207 LPF = new signalVector(651);
1208 LPF->isRealOnly(true);
1209 itr = LPF->begin();
1210 for (int i = 0; i < filterLen; i++) {
1211 *itr++ = complex(rcvLPF_651[i],0.0);
1212 sum += rcvLPF_651[i];
1213 }
1214 }
1215 else {
1216 LPF = new signalVector(961);
1217 LPF->isRealOnly(true);
1218 itr = LPF->begin();
1219 for (int i = 0; i < filterLen; i++) {
1220 *itr++ = complex(sendLPF_961[i],0.0);
1221 sum += sendLPF_961[i];
1222 }
1223 }
1224#endif
1225
dburgessb3a0ca42011-10-12 07:44:40 +00001226 float normFactor = gainDC/sum; //sqrtf(gainDC/vectorNorm2(*LPF));
1227 // normalize power
1228 itr = LPF->begin();
kurtis.heimerla198d452011-11-26 03:19:28 +00001229 for (int i = 0; i < filterLen; i++) {
dburgessb3a0ca42011-10-12 07:44:40 +00001230 *itr = *itr*normFactor;
1231 itr++;
1232 }
1233 return LPF;
1234
1235}
1236
1237
1238
1239#define POLYPHASESPAN 10
1240
1241// assumes filter group delay is 0.5*(length of filter)
1242signalVector *polyphaseResampleVector(signalVector &wVector,
1243 int P, int Q,
1244 signalVector *LPF)
1245
1246{
1247
1248 bool deleteLPF = false;
1249
1250 if (LPF==NULL) {
1251 float cutoffFreq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P);
1252 LPF = createLPF(cutoffFreq/3.0,100*POLYPHASESPAN+1,Q);
1253 deleteLPF = true;
1254 }
1255
1256 signalVector *resampledVector = new signalVector((int) ceil(wVector.size()*(float) P / (float) Q));
1257 resampledVector->fill(0);
1258 resampledVector->isRealOnly(wVector.isRealOnly());
1259 signalVector::iterator newItr = resampledVector->begin();
1260
1261 //FIXME: need to update for real-only vectors
1262 int outputIx = (LPF->size()+1)/2/Q; //((P > Q) ? P : Q);
1263 while (newItr < resampledVector->end()) {
1264 int outputBranch = (outputIx*Q) % P;
1265 int inputOffset = (outputIx*Q - outputBranch)/P;
1266 signalVector::const_iterator inputItr = wVector.begin() + inputOffset;
1267 signalVector::const_iterator filtItr = LPF->begin() + outputBranch;
1268 while (inputItr >= wVector.end()) {
1269 inputItr--;
1270 filtItr+=P;
1271 }
1272 complex sum = 0.0;
1273 if ((LPF->getSymmetry()!=ABSSYM) || (P>1)) {
1274 if (!LPF->isRealOnly()) {
1275 while ( (inputItr >= wVector.begin()) && (filtItr < LPF->end()) ) {
1276 sum += (*inputItr)*(*filtItr);
1277 inputItr--;
1278 filtItr += P;
1279 }
1280 }
1281 else {
1282 while ( (inputItr >= wVector.begin()) && (filtItr < LPF->end()) ) {
1283 sum += (*inputItr)*(filtItr->real());
1284 inputItr--;
1285 filtItr += P;
1286 }
1287 }
1288 }
1289 else {
1290 signalVector::const_iterator revInputItr = inputItr- LPF->size() + 1;
1291 signalVector::const_iterator filtMidpoint = LPF->begin()+(LPF->size()-1)/2;
1292 if (!LPF->isRealOnly()) {
1293 while (filtItr <= filtMidpoint) {
1294 if (inputItr < revInputItr) break;
1295 if (inputItr == revInputItr)
1296 sum += (*inputItr)*(*filtItr);
1297 else if ( (inputItr < wVector.end()) && (revInputItr >= wVector.begin()) )
1298 sum += (*inputItr + *revInputItr)*(*filtItr);
1299 else if ( inputItr < wVector.end() )
1300 sum += (*inputItr)*(*filtItr);
1301 else if ( revInputItr >= wVector.begin() )
1302 sum += (*revInputItr)*(*filtItr);
1303 inputItr--;
1304 revInputItr++;
1305 filtItr++;
1306 }
1307 }
1308 else {
1309 while (filtItr <= filtMidpoint) {
1310 if (inputItr < revInputItr) break;
1311 if (inputItr == revInputItr)
1312 sum += (*inputItr)*(filtItr->real());
1313 else if ( (inputItr < wVector.end()) && (revInputItr >= wVector.begin()) )
1314 sum += (*inputItr + *revInputItr)*(filtItr->real());
1315 else if ( inputItr < wVector.end() )
1316 sum += (*inputItr)*(filtItr->real());
1317 else if ( revInputItr >= wVector.begin() )
1318 sum += (*revInputItr)*(filtItr->real());
1319 inputItr--;
1320 revInputItr++;
1321 filtItr++;
1322 }
1323 }
1324 }
1325 *newItr = sum;
1326 newItr++;
1327 outputIx++;
1328 }
1329
1330 if (deleteLPF) delete LPF;
1331
1332 return resampledVector;
1333}
1334
1335
1336signalVector *resampleVector(signalVector &wVector,
1337 float expFactor,
1338 complex endPoint)
1339
1340{
1341
1342 if (expFactor < 1.0) return NULL;
1343
1344 signalVector *retVec = new signalVector((int) ceil(wVector.size()*expFactor));
1345
1346 float t = 0.0;
1347
1348 signalVector::iterator retItr = retVec->begin();
1349 while (retItr < retVec->end()) {
1350 unsigned tLow = (unsigned int) floor(t);
1351 unsigned tHigh = tLow + 1;
1352 if (tLow > wVector.size()-1) break;
1353 if (tHigh > wVector.size()) break;
1354 complex lowPoint = wVector[tLow];
1355 complex highPoint = (tHigh == wVector.size()) ? endPoint : wVector[tHigh];
1356 complex a = (tHigh-t);
1357 complex b = (t-tLow);
1358 *retItr = (a*lowPoint + b*highPoint);
1359 t += 1.0/expFactor;
1360 }
1361
1362 return retVec;
1363
1364}
1365
1366
1367// Assumes symbol-spaced sampling!!!
1368// Based upon paper by Al-Dhahir and Cioffi
1369bool designDFE(signalVector &channelResponse,
1370 float SNRestimate,
1371 int Nf,
1372 signalVector **feedForwardFilter,
1373 signalVector **feedbackFilter)
1374{
1375
1376 signalVector G0(Nf);
1377 signalVector G1(Nf);
1378 signalVector::iterator G0ptr = G0.begin();
1379 signalVector::iterator G1ptr = G1.begin();
1380 signalVector::iterator chanPtr = channelResponse.begin();
1381
1382 int nu = channelResponse.size()-1;
1383
1384 *G0ptr = 1.0/sqrtf(SNRestimate);
1385 for(int j = 0; j <= nu; j++) {
1386 *G1ptr = chanPtr->conj();
1387 G1ptr++; chanPtr++;
1388 }
1389
1390 signalVector *L[Nf];
1391 signalVector::iterator Lptr;
1392 float d;
1393 for(int i = 0; i < Nf; i++) {
1394 d = G0.begin()->norm2() + G1.begin()->norm2();
1395 L[i] = new signalVector(Nf+nu);
1396 Lptr = L[i]->begin()+i;
1397 G0ptr = G0.begin(); G1ptr = G1.begin();
1398 while ((G0ptr < G0.end()) && (Lptr < L[i]->end())) {
1399 *Lptr = (*G0ptr*(G0.begin()->conj()) + *G1ptr*(G1.begin()->conj()) )/d;
1400 Lptr++;
1401 G0ptr++;
1402 G1ptr++;
1403 }
1404 complex k = (*G1.begin())/(*G0.begin());
1405
1406 if (i != Nf-1) {
1407 signalVector G0new = G1;
1408 scaleVector(G0new,k.conj());
1409 addVector(G0new,G0);
1410
1411 signalVector G1new = G0;
1412 scaleVector(G1new,k*(-1.0));
1413 addVector(G1new,G1);
1414 delayVector(G1new,-1.0);
1415
1416 scaleVector(G0new,1.0/sqrtf(1.0+k.norm2()));
1417 scaleVector(G1new,1.0/sqrtf(1.0+k.norm2()));
1418 G0 = G0new;
1419 G1 = G1new;
1420 }
1421 }
1422
1423 *feedbackFilter = new signalVector(nu);
1424 L[Nf-1]->segmentCopyTo(**feedbackFilter,Nf,nu);
1425 scaleVector(**feedbackFilter,(complex) -1.0);
1426 conjugateVector(**feedbackFilter);
1427
1428 signalVector v(Nf);
1429 signalVector::iterator vStart = v.begin();
1430 signalVector::iterator vPtr;
1431 *(vStart+Nf-1) = (complex) 1.0;
1432 for(int k = Nf-2; k >= 0; k--) {
1433 Lptr = L[k]->begin()+k+1;
1434 vPtr = vStart + k+1;
1435 complex v_k = 0.0;
1436 for (int j = k+1; j < Nf; j++) {
1437 v_k -= (*vPtr)*(*Lptr);
1438 vPtr++; Lptr++;
1439 }
1440 *(vStart + k) = v_k;
1441 }
1442
1443 *feedForwardFilter = new signalVector(Nf);
1444 signalVector::iterator w = (*feedForwardFilter)->begin();
1445 for (int i = 0; i < Nf; i++) {
1446 delete L[i];
1447 complex w_i = 0.0;
1448 int endPt = ( nu < (Nf-1-i) ) ? nu : (Nf-1-i);
1449 vPtr = vStart+i;
1450 chanPtr = channelResponse.begin();
1451 for (int k = 0; k < endPt+1; k++) {
1452 w_i += (*vPtr)*(chanPtr->conj());
1453 vPtr++; chanPtr++;
1454 }
1455 *w = w_i/d;
1456 w++;
1457 }
1458
1459
1460 return true;
1461
1462}
1463
1464// Assumes symbol-rate sampling!!!!
1465SoftVector *equalizeBurst(signalVector &rxBurst,
1466 float TOA,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001467 int sps,
dburgessb3a0ca42011-10-12 07:44:40 +00001468 signalVector &w, // feedforward filter
1469 signalVector &b) // feedback filter
1470{
1471
1472 delayVector(rxBurst,-TOA);
1473
1474 signalVector* postForwardFull = convolve(&rxBurst,&w,NULL,FULL_SPAN);
1475
1476 signalVector* postForward = new signalVector(rxBurst.size());
1477 postForwardFull->segmentCopyTo(*postForward,w.size()-1,rxBurst.size());
1478 delete postForwardFull;
1479
1480 signalVector::iterator dPtr = postForward->begin();
1481 signalVector::iterator dBackPtr;
1482 signalVector::iterator rotPtr = GMSKRotation->begin();
1483 signalVector::iterator revRotPtr = GMSKReverseRotation->begin();
1484
1485 signalVector *DFEoutput = new signalVector(postForward->size());
1486 signalVector::iterator DFEItr = DFEoutput->begin();
1487
1488 // NOTE: can insert the midamble and/or use midamble to estimate BER
1489 for (; dPtr < postForward->end(); dPtr++) {
1490 dBackPtr = dPtr-1;
1491 signalVector::iterator bPtr = b.begin();
1492 while ( (bPtr < b.end()) && (dBackPtr >= postForward->begin()) ) {
1493 *dPtr = *dPtr + (*bPtr)*(*dBackPtr);
1494 bPtr++;
1495 dBackPtr--;
1496 }
1497 *dPtr = *dPtr * (*revRotPtr);
1498 *DFEItr = *dPtr;
1499 // make decision on symbol
1500 *dPtr = (dPtr->real() > 0.0) ? 1.0 : -1.0;
1501 //*DFEItr = *dPtr;
1502 *dPtr = *dPtr * (*rotPtr);
1503 DFEItr++;
1504 rotPtr++;
1505 revRotPtr++;
1506 }
1507
1508 vectorSlicer(DFEoutput);
1509
1510 SoftVector *burstBits = new SoftVector(postForward->size());
1511 SoftVector::iterator burstItr = burstBits->begin();
1512 DFEItr = DFEoutput->begin();
1513 for (; DFEItr < DFEoutput->end(); DFEItr++)
1514 *burstItr++ = DFEItr->real();
1515
1516 delete postForward;
1517
1518 delete DFEoutput;
1519
1520 return burstBits;
1521}