blob: cf72cae7ea25599103a3579c479a453b0dd9ee70 [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
219void initGMSKRotationTables(int samplesPerSymbol) {
220 GMSKRotation = new signalVector(157*samplesPerSymbol);
221 GMSKReverseRotation = new signalVector(157*samplesPerSymbol);
222 signalVector::iterator rotPtr = GMSKRotation->begin();
223 signalVector::iterator revPtr = GMSKReverseRotation->begin();
224 float phase = 0.0;
225 while (rotPtr != GMSKRotation->end()) {
226 *rotPtr++ = expjLookup(phase);
227 *revPtr++ = expjLookup(-phase);
228 phase += M_PI_F/2.0F/(float) samplesPerSymbol;
229 }
230}
231
232void sigProcLibSetup(int samplesPerSymbol) {
233 initTrigTables();
234 initGMSKRotationTables(samplesPerSymbol);
235}
236
237void GMSKRotate(signalVector &x) {
238 signalVector::iterator xPtr = x.begin();
239 signalVector::iterator rotPtr = GMSKRotation->begin();
240 if (x.isRealOnly()) {
241 while (xPtr < x.end()) {
242 *xPtr = *rotPtr++ * (xPtr->real());
243 xPtr++;
244 }
245 }
246 else {
247 while (xPtr < x.end()) {
248 *xPtr = *rotPtr++ * (*xPtr);
249 xPtr++;
250 }
251 }
252}
253
254void GMSKReverseRotate(signalVector &x) {
255 signalVector::iterator xPtr= x.begin();
256 signalVector::iterator rotPtr = GMSKReverseRotation->begin();
257 if (x.isRealOnly()) {
258 while (xPtr < x.end()) {
259 *xPtr = *rotPtr++ * (xPtr->real());
260 xPtr++;
261 }
262 }
263 else {
264 while (xPtr < x.end()) {
265 *xPtr = *rotPtr++ * (*xPtr);
266 xPtr++;
267 }
268 }
269}
270
271
272signalVector* convolve(const signalVector *a,
273 const signalVector *b,
274 signalVector *c,
275 ConvType spanType,
276 unsigned startIx,
277 unsigned len)
278{
279 if ((a==NULL) || (b==NULL)) return NULL;
280 int La = a->size();
281 int Lb = b->size();
282
283 int startIndex;
284 unsigned int outSize;
285 switch (spanType) {
286 case FULL_SPAN:
287 startIndex = 0;
288 outSize = La+Lb-1;
289 break;
290 case OVERLAP_ONLY:
291 startIndex = La;
292 outSize = abs(La-Lb)+1;
293 break;
294 case START_ONLY:
295 startIndex = 0;
296 outSize = La;
297 break;
298 case WITH_TAIL:
299 startIndex = Lb;
300 outSize = La;
301 break;
302 case NO_DELAY:
303 if (Lb % 2)
304 startIndex = Lb/2;
305 else
306 startIndex = Lb/2-1;
307 outSize = La;
308 break;
309 case CUSTOM:
310 startIndex = startIx;
311 outSize = len;
312 break;
313 default:
314 return NULL;
315 }
316
317
318 if (c==NULL)
319 c = new signalVector(outSize);
320 else if (c->size()!=outSize)
321 return NULL;
322
323 signalVector::const_iterator aStart = a->begin();
324 signalVector::const_iterator bStart = b->begin();
325 signalVector::const_iterator aEnd = a->end();
326 signalVector::const_iterator bEnd = b->end();
327 signalVector::iterator cPtr = c->begin();
328 int t = startIndex;
329 int stopIndex = startIndex + outSize;
330 switch (b->getSymmetry()) {
331 case NONE:
332 {
333 while (t < stopIndex) {
334 signalVector::const_iterator aP = aStart+t;
335 signalVector::const_iterator bP = bStart;
336 if (a->isRealOnly() && b->isRealOnly()) {
337 float sum = 0.0;
338 while (bP < bEnd) {
339 if (aP < aStart) break;
340 if (aP < aEnd) sum += (aP->real())*(bP->real());
341 aP--;
342 bP++;
343 }
344 *cPtr++ = sum;
345 }
346 else if (a->isRealOnly()) {
347 complex sum = 0.0;
348 while (bP < bEnd) {
349 if (aP < aStart) break;
350 if (aP < aEnd) sum += (*bP)*(aP->real());
351 aP--;
352 bP++;
353 }
354 *cPtr++ = sum;
355 }
356 else if (b->isRealOnly()) {
357 complex sum = 0.0;
358 while (bP < bEnd) {
359 if (aP < aStart) break;
360 if (aP < aEnd) sum += (*aP)*(bP->real());
361 aP--;
362 bP++;
363 }
364 *cPtr++ = sum;
365 }
366 else {
367 complex sum = 0.0;
368 while (bP < bEnd) {
369 if (aP < aStart) break;
370 if (aP < aEnd) sum += (*aP)*(*bP);
371 aP--;
372 bP++;
373 }
374 *cPtr++ = sum;
375 }
376 t++;
377 }
378 }
379 break;
380 case ABSSYM:
381 {
382 complex sum = 0.0;
383 bool isOdd = (bool) (Lb % 2);
384 if (isOdd)
385 bEnd = bStart + (Lb+1)/2;
386 else
387 bEnd = bStart + Lb/2;
388 while (t < stopIndex) {
389 signalVector::const_iterator aP = aStart+t;
390 signalVector::const_iterator aPsym = aP-Lb+1;
391 signalVector::const_iterator bP = bStart;
392 sum = 0.0;
393 if (!b->isRealOnly()) {
394 while (bP < bEnd) {
395 if (aP < aStart) break;
396 if (aP == aPsym)
397 sum+= (*aP)*(*bP);
398 else if ((aP < aEnd) && (aPsym >= aStart))
399 sum+= ((*aP)+(*aPsym))*(*bP);
400 else if (aP < aEnd)
401 sum += (*aP)*(*bP);
402 else if (aPsym >= aStart)
403 sum += (*aPsym)*(*bP);
404 aP--;
405 aPsym++;
406 bP++;
407 }
408 }
409 else {
410 while (bP < bEnd) {
411 if (aP < aStart) break;
412 if (aP == aPsym)
413 sum+= (*aP)*(bP->real());
414 else if ((aP < aEnd) && (aPsym >= aStart))
415 sum+= ((*aP)+(*aPsym))*(bP->real());
416 else if (aP < aEnd)
417 sum += (*aP)*(bP->real());
418 else if (aPsym >= aStart)
419 sum += (*aPsym)*(bP->real());
420 aP--;
421 aPsym++;
422 bP++;
423 }
424 }
425 *cPtr++ = sum;
426 t++;
427 }
428 }
429 break;
430 default:
431 return NULL;
432 break;
433 }
434
435
436 return c;
437}
438
439
440signalVector* generateGSMPulse(int symbolLength,
441 int samplesPerSymbol)
442{
443
444 int numSamples = samplesPerSymbol*symbolLength + 1;
445 signalVector *x = new signalVector(numSamples);
446 signalVector::iterator xP = x->begin();
447 int centerPoint = (numSamples-1)/2;
448 for (int i = 0; i < numSamples; i++) {
449 float arg = (float) (i-centerPoint)/(float) samplesPerSymbol;
450 *xP++ = 0.96*exp(-1.1380*arg*arg-0.527*arg*arg*arg*arg); // GSM pulse approx.
451 }
452
453 float avgAbsval = sqrtf(vectorNorm2(*x)/samplesPerSymbol);
454 xP = x->begin();
455 for (int i = 0; i < numSamples; i++)
456 *xP++ /= avgAbsval;
457 x->isRealOnly(true);
458 x->setSymmetry(ABSSYM);
459 return x;
460}
461
462signalVector* frequencyShift(signalVector *y,
463 signalVector *x,
464 float freq,
465 float startPhase,
466 float *finalPhase)
467{
468
469 if (!x) return NULL;
470
471 if (y==NULL) {
472 y = new signalVector(x->size());
473 y->isRealOnly(x->isRealOnly());
474 if (y==NULL) return NULL;
475 }
476
477 if (y->size() < x->size()) return NULL;
478
479 float phase = startPhase;
480 signalVector::iterator yP = y->begin();
481 signalVector::iterator xPEnd = x->end();
482 signalVector::iterator xP = x->begin();
483
484 if (x->isRealOnly()) {
485 while (xP < xPEnd) {
486 (*yP++) = expjLookup(phase)*( (xP++)->real() );
487 phase += freq;
488 }
489 }
490 else {
491 while (xP < xPEnd) {
492 (*yP++) = (*xP++)*expjLookup(phase);
493 phase += freq;
494 }
495 }
496
497
498 if (finalPhase) *finalPhase = phase;
499
500 return y;
501}
502
503signalVector* reverseConjugate(signalVector *b)
504{
505 signalVector *tmp = new signalVector(b->size());
506 tmp->isRealOnly(b->isRealOnly());
507 signalVector::iterator bP = b->begin();
508 signalVector::iterator bPEnd = b->end();
509 signalVector::iterator tmpP = tmp->end()-1;
510 if (!b->isRealOnly()) {
511 while (bP < bPEnd) {
512 *tmpP-- = bP->conj();
513 bP++;
514 }
515 }
516 else {
517 while (bP < bPEnd) {
518 *tmpP-- = bP->real();
519 bP++;
520 }
521 }
522
523 return tmp;
524}
525
526signalVector* correlate(signalVector *a,
527 signalVector *b,
528 signalVector *c,
529 ConvType spanType,
530 bool bReversedConjugated,
531 unsigned startIx,
532 unsigned len)
533{
534 signalVector *tmp = NULL;
535
536 if (!bReversedConjugated) {
537 tmp = reverseConjugate(b);
538 }
539 else {
540 tmp = b;
541 }
542
543 c = convolve(a,tmp,c,spanType,startIx,len);
544
545 if (!bReversedConjugated) delete tmp;
546
547 return c;
548}
549
550
551/* soft output slicer */
552bool vectorSlicer(signalVector *x)
553{
554
555 signalVector::iterator xP = x->begin();
556 signalVector::iterator xPEnd = x->end();
557 while (xP < xPEnd) {
558 *xP = (complex) (0.5*(xP->real()+1.0F));
559 if (xP->real() > 1.0) *xP = 1.0;
560 if (xP->real() < 0.0) *xP = 0.0;
561 xP++;
562 }
563 return true;
564}
565
566signalVector *modulateBurst(const BitVector &wBurst,
567 const signalVector &gsmPulse,
568 int guardPeriodLength,
569 int samplesPerSymbol)
570{
571
572 //static complex staticBurst[157];
573
574 int burstSize = samplesPerSymbol*(wBurst.size()+guardPeriodLength);
575 //signalVector modBurst((complex *) staticBurst,0,burstSize);
576 signalVector modBurst(burstSize);// = new signalVector(burstSize);
577 modBurst.isRealOnly(true);
578 //memset(staticBurst,0,sizeof(complex)*burstSize);
579 modBurst.fill(0.0);
580 signalVector::iterator modBurstItr = modBurst.begin();
581
582#if 0
583 // if wBurst is already differentially decoded
584 *modBurstItr = 2.0*(wBurst[0] & 0x01)-1.0;
585 signalVector::iterator prevVal = modBurstItr;
586 for (unsigned int i = 1; i < wBurst.size(); i++) {
587 modBurstItr += samplesPerSymbol;
588 if (wBurst[i] & 0x01)
589 *modBurstItr = *prevVal * complex(0.0,1.0);
590 else
591 *modBurstItr = *prevVal * complex(0.0,-1.0);
592 prevVal = modBurstItr;
593 }
594#else
595 // if wBurst are the raw bits
596 for (unsigned int i = 0; i < wBurst.size(); i++) {
597 *modBurstItr = 2.0*(wBurst[i] & 0x01)-1.0;
598 modBurstItr += samplesPerSymbol;
599 }
600
601 // shift up pi/2
602 // ignore starting phase, since spec allows for discontinuous phase
603 GMSKRotate(modBurst);
604#endif
605 modBurst.isRealOnly(false);
606
607 // filter w/ pulse shape
608 signalVector *shapedBurst = convolve(&modBurst,&gsmPulse,NULL,NO_DELAY);
609
610 //delete modBurst;
611
612 return shapedBurst;
613
614}
615
616float sinc(float x)
617{
618 if ((x >= 0.01F) || (x <= -0.01F)) return (sinLookup(x)/x);
619 return 1.0F;
620}
621
622void delayVector(signalVector &wBurst,
623 float delay)
624{
625
626 int intOffset = (int) floor(delay);
627 float fracOffset = delay - intOffset;
628
629 // do fractional shift first, only do it for reasonable offsets
630 if (fabs(fracOffset) > 1e-2) {
631 // create sinc function
632 signalVector sincVector(21);
633 sincVector.isRealOnly(true);
634 signalVector::iterator sincBurstItr = sincVector.begin();
635 for (int i = 0; i < 21; i++)
636 *sincBurstItr++ = (complex) sinc(M_PI_F*(i-10-fracOffset));
637
638 signalVector shiftedBurst(wBurst.size());
639 convolve(&wBurst,&sincVector,&shiftedBurst,NO_DELAY);
640 wBurst.clone(shiftedBurst);
641 }
642
643 if (intOffset < 0) {
644 intOffset = -intOffset;
645 signalVector::iterator wBurstItr = wBurst.begin();
646 signalVector::iterator shiftedItr = wBurst.begin()+intOffset;
647 while (shiftedItr < wBurst.end())
648 *wBurstItr++ = *shiftedItr++;
649 while (wBurstItr < wBurst.end())
650 *wBurstItr++ = 0.0;
651 }
652 else {
653 signalVector::iterator wBurstItr = wBurst.end()-1;
654 signalVector::iterator shiftedItr = wBurst.end()-1-intOffset;
655 while (shiftedItr >= wBurst.begin())
656 *wBurstItr-- = *shiftedItr--;
657 while (wBurstItr >= wBurst.begin())
658 *wBurstItr-- = 0.0;
659 }
660}
661
662signalVector *gaussianNoise(int length,
663 float variance,
664 complex mean)
665{
666
667 signalVector *noise = new signalVector(length);
668 signalVector::iterator nPtr = noise->begin();
669 float stddev = sqrtf(variance);
670 while (nPtr < noise->end()) {
671 float u1 = (float) rand()/ (float) RAND_MAX;
672 while (u1==0.0)
673 u1 = (float) rand()/ (float) RAND_MAX;
674 float u2 = (float) rand()/ (float) RAND_MAX;
675 float arg = 2.0*M_PI*u2;
676 *nPtr = mean + stddev*complex(cos(arg),sin(arg))*sqrtf(-2.0*log(u1));
677 nPtr++;
678 }
679
680 return noise;
681}
682
683complex interpolatePoint(const signalVector &inSig,
684 float ix)
685{
686
687 int start = (int) (floor(ix) - 10);
688 if (start < 0) start = 0;
689 int end = (int) (floor(ix) + 11);
690 if ((unsigned) end > inSig.size()-1) end = inSig.size()-1;
691
692 complex pVal = 0.0;
693 if (!inSig.isRealOnly()) {
694 for (int i = start; i < end; i++)
695 pVal += inSig[i] * sinc(M_PI_F*(i-ix));
696 }
697 else {
698 for (int i = start; i < end; i++)
699 pVal += inSig[i].real() * sinc(M_PI_F*(i-ix));
700 }
701
702 return pVal;
703}
704
705
706
707complex peakDetect(const signalVector &rxBurst,
708 float *peakIndex,
709 float *avgPwr)
710{
711
712
713 complex maxVal = 0.0;
714 float maxIndex = -1;
715 float sumPower = 0.0;
716
717 for (unsigned int i = 0; i < rxBurst.size(); i++) {
718 float samplePower = rxBurst[i].norm2();
719 if (samplePower > maxVal.real()) {
720 maxVal = samplePower;
721 maxIndex = i;
722 }
723 sumPower += samplePower;
724 }
725
726 // interpolate around the peak
727 // to save computation, we'll use early-late balancing
728 float earlyIndex = maxIndex-1;
729 float lateIndex = maxIndex+1;
730
731 float incr = 0.5;
732 while (incr > 1.0/1024.0) {
733 complex earlyP = interpolatePoint(rxBurst,earlyIndex);
734 complex lateP = interpolatePoint(rxBurst,lateIndex);
735 if (earlyP < lateP)
736 earlyIndex += incr;
737 else if (earlyP > lateP)
738 earlyIndex -= incr;
739 else break;
740 incr /= 2.0;
741 lateIndex = earlyIndex + 2.0;
742 }
743
744 maxIndex = earlyIndex + 1.0;
745 maxVal = interpolatePoint(rxBurst,maxIndex);
746
747 if (peakIndex!=NULL)
748 *peakIndex = maxIndex;
749
750 if (avgPwr!=NULL)
751 *avgPwr = (sumPower-maxVal.norm2()) / (rxBurst.size()-1);
752
753 return maxVal;
754
755}
756
757void scaleVector(signalVector &x,
758 complex scale)
759{
760 signalVector::iterator xP = x.begin();
761 signalVector::iterator xPEnd = x.end();
762 if (!x.isRealOnly()) {
763 while (xP < xPEnd) {
764 *xP = *xP * scale;
765 xP++;
766 }
767 }
768 else {
769 while (xP < xPEnd) {
770 *xP = xP->real() * scale;
771 xP++;
772 }
773 }
774}
775
776/** in-place conjugation */
777void conjugateVector(signalVector &x)
778{
779 if (x.isRealOnly()) return;
780 signalVector::iterator xP = x.begin();
781 signalVector::iterator xPEnd = x.end();
782 while (xP < xPEnd) {
783 *xP = xP->conj();
784 xP++;
785 }
786}
787
788
789// in-place addition!!
790bool addVector(signalVector &x,
791 signalVector &y)
792{
793 signalVector::iterator xP = x.begin();
794 signalVector::iterator yP = y.begin();
795 signalVector::iterator xPEnd = x.end();
796 signalVector::iterator yPEnd = y.end();
797 while ((xP < xPEnd) && (yP < yPEnd)) {
798 *xP = *xP + *yP;
799 xP++; yP++;
800 }
801 return true;
802}
803
804// in-place multiplication!!
805bool multVector(signalVector &x,
806 signalVector &y)
807{
808 signalVector::iterator xP = x.begin();
809 signalVector::iterator yP = y.begin();
810 signalVector::iterator xPEnd = x.end();
811 signalVector::iterator yPEnd = y.end();
812 while ((xP < xPEnd) && (yP < yPEnd)) {
813 *xP = (*xP) * (*yP);
814 xP++; yP++;
815 }
816 return true;
817}
818
819
820void offsetVector(signalVector &x,
821 complex offset)
822{
823 signalVector::iterator xP = x.begin();
824 signalVector::iterator xPEnd = x.end();
825 if (!x.isRealOnly()) {
826 while (xP < xPEnd) {
827 *xP += offset;
828 xP++;
829 }
830 }
831 else {
832 while (xP < xPEnd) {
833 *xP = xP->real() + offset;
834 xP++;
835 }
836 }
837}
838
839bool generateMidamble(signalVector &gsmPulse,
840 int samplesPerSymbol,
841 int TSC)
842{
843
844 if ((TSC < 0) || (TSC > 7))
845 return false;
846
847 if (gMidambles[TSC]) {
848 if (gMidambles[TSC]->sequence!=NULL) delete gMidambles[TSC]->sequence;
849 if (gMidambles[TSC]->sequenceReversedConjugated!=NULL) delete gMidambles[TSC]->sequenceReversedConjugated;
850 }
851
852 signalVector emptyPulse(1);
853 *(emptyPulse.begin()) = 1.0;
854
855 // only use middle 16 bits of each TSC
856 signalVector *middleMidamble = modulateBurst(gTrainingSequence[TSC].segment(5,16),
857 emptyPulse,
858 0,
859 samplesPerSymbol);
860 signalVector *midamble = modulateBurst(gTrainingSequence[TSC],
861 gsmPulse,
862 0,
863 samplesPerSymbol);
864
865 if (midamble == NULL) return false;
866 if (middleMidamble == NULL) return false;
867
868 // NOTE: Because ideal TSC 16-bit midamble is 66 symbols into burst,
869 // the ideal TSC has an + 180 degree phase shift,
870 // due to the pi/2 frequency shift, that
871 // needs to be accounted for.
872 // 26-midamble is 61 symbols into burst, has +90 degree phase shift.
873 scaleVector(*middleMidamble,complex(-1.0,0.0));
874 scaleVector(*midamble,complex(0.0,1.0));
875
876 signalVector *autocorr = correlate(midamble,middleMidamble,NULL,NO_DELAY);
877
878 if (autocorr == NULL) return false;
879
880 gMidambles[TSC] = new CorrelationSequence;
881 gMidambles[TSC]->sequence = middleMidamble;
882 gMidambles[TSC]->sequenceReversedConjugated = reverseConjugate(middleMidamble);
883 gMidambles[TSC]->gain = peakDetect(*autocorr,&gMidambles[TSC]->TOA,NULL);
884
885 LOG(DEBUG) << "midamble autocorr: " << *autocorr;
886
887 LOG(DEBUG) << "TOA: " << gMidambles[TSC]->TOA;
888
889 //gMidambles[TSC]->TOA -= 5*samplesPerSymbol;
890
891 delete autocorr;
892 delete midamble;
893
894 return true;
895}
896
897bool generateRACHSequence(signalVector &gsmPulse,
898 int samplesPerSymbol)
899{
900
901 if (gRACHSequence) {
902 if (gRACHSequence->sequence!=NULL) delete gRACHSequence->sequence;
903 if (gRACHSequence->sequenceReversedConjugated!=NULL) delete gRACHSequence->sequenceReversedConjugated;
904 }
905
906 signalVector *RACHSeq = modulateBurst(gRACHSynchSequence,
907 gsmPulse,
908 0,
909 samplesPerSymbol);
910
911 assert(RACHSeq);
912
913 signalVector *autocorr = correlate(RACHSeq,RACHSeq,NULL,NO_DELAY);
914
915 assert(autocorr);
916
917 gRACHSequence = new CorrelationSequence;
918 gRACHSequence->sequence = RACHSeq;
919 gRACHSequence->sequenceReversedConjugated = reverseConjugate(RACHSeq);
920 gRACHSequence->gain = peakDetect(*autocorr,&gRACHSequence->TOA,NULL);
921
922 delete autocorr;
923
924 return true;
925
926}
927
928
929bool detectRACHBurst(signalVector &rxBurst,
930 float detectThreshold,
931 int samplesPerSymbol,
932 complex *amplitude,
933 float* TOA)
934{
935
936 //static complex staticData[500];
937
938 //signalVector correlatedRACH(staticData,0,rxBurst.size());
939 signalVector correlatedRACH(rxBurst.size());
940 correlate(&rxBurst,gRACHSequence->sequenceReversedConjugated,&correlatedRACH,NO_DELAY,true);
941
942 float meanPower;
943 complex peakAmpl = peakDetect(correlatedRACH,TOA,&meanPower);
944
945 float valleyPower = 0.0;
946
947 // check for bogus results
948 if ((*TOA < 0.0) || (*TOA > correlatedRACH.size())) {
949 *amplitude = 0.0;
950 return false;
951 }
952 complex *peakPtr = correlatedRACH.begin() + (int) rint(*TOA);
953
954 LOG(DEBUG) << "RACH corr: " << correlatedRACH;
955
956 float numSamples = 0.0;
957 for (int i = 57*samplesPerSymbol; i <= 107*samplesPerSymbol;i++) {
958 if (peakPtr+i >= correlatedRACH.end())
959 break;
960 valleyPower += (peakPtr+i)->norm2();
961 numSamples++;
962 }
963
964 if (numSamples < 2) {
965 *amplitude = 0.0;
966 return false;
967 }
968
969 float RMS = sqrtf(valleyPower/(float) numSamples)+0.00001;
970 float peakToMean = peakAmpl.abs()/RMS;
971
972 LOG(DEBUG) << "RACH peakAmpl=" << peakAmpl << " RMS=" << RMS << " peakToMean=" << peakToMean;
973 *amplitude = peakAmpl/(gRACHSequence->gain);
974
975 *TOA = (*TOA) - gRACHSequence->TOA - 8*samplesPerSymbol;
976
977 LOG(DEBUG) << "RACH thresh: " << peakToMean;
978
979 return (peakToMean > detectThreshold);
980}
981
982bool energyDetect(signalVector &rxBurst,
983 unsigned windowLength,
984 float detectThreshold,
985 float *avgPwr)
986{
987
988 signalVector::const_iterator windowItr = rxBurst.begin(); //+rxBurst.size()/2 - 5*windowLength/2;
989 float energy = 0.0;
990 if (windowLength < 0) windowLength = 20;
991 if (windowLength > rxBurst.size()) windowLength = rxBurst.size();
992 for (unsigned i = 0; i < windowLength; i++) {
993 energy += windowItr->norm2();
994 windowItr+=4;
995 }
996 if (avgPwr) *avgPwr = energy/windowLength;
997 LOG(DEBUG) << "detected energy: " << energy/windowLength;
998 return (energy/windowLength > detectThreshold*detectThreshold);
999}
1000
1001
1002bool analyzeTrafficBurst(signalVector &rxBurst,
1003 unsigned TSC,
1004 float detectThreshold,
1005 int samplesPerSymbol,
1006 complex *amplitude,
1007 float *TOA,
1008 unsigned maxTOA,
1009 bool requestChannel,
1010 signalVector **channelResponse,
1011 float *channelResponseOffset)
1012{
1013
1014 assert(TSC<8);
1015 assert(amplitude);
1016 assert(TOA);
1017 assert(gMidambles[TSC]);
1018
1019 if (maxTOA < 3*samplesPerSymbol) maxTOA = 3*samplesPerSymbol;
1020 unsigned spanTOA = maxTOA;
1021 if (spanTOA < 5*samplesPerSymbol) spanTOA = 5*samplesPerSymbol;
1022
ttsoubec41032013-04-04 23:35:08 +00001023 unsigned startIx = 66*samplesPerSymbol-spanTOA;
1024 unsigned endIx = (66+16)*samplesPerSymbol+spanTOA;
dburgessb3a0ca42011-10-12 07:44:40 +00001025 unsigned windowLen = endIx - startIx;
1026 unsigned corrLen = 2*maxTOA+1;
1027
1028 unsigned expectedTOAPeak = (unsigned) round(gMidambles[TSC]->TOA + (gMidambles[TSC]->sequenceReversedConjugated->size()-1)/2);
1029
1030 signalVector burstSegment(rxBurst.begin(),startIx,windowLen);
1031
1032 //static complex staticData[200];
1033 //signalVector correlatedBurst(staticData,0,corrLen);
1034 signalVector correlatedBurst(corrLen);
1035 correlate(&burstSegment, gMidambles[TSC]->sequenceReversedConjugated,
1036 &correlatedBurst, CUSTOM,true,
1037 expectedTOAPeak-maxTOA,corrLen);
1038
1039 float meanPower;
1040 *amplitude = peakDetect(correlatedBurst,TOA,&meanPower);
1041 float valleyPower = 0.0; //amplitude->norm2();
1042 complex *peakPtr = correlatedBurst.begin() + (int) rint(*TOA);
1043
1044 // check for bogus results
1045 if ((*TOA < 0.0) || (*TOA > correlatedBurst.size())) {
1046 *amplitude = 0.0;
1047 return false;
1048 }
1049
1050 int numRms = 0;
1051 for (int i = 2*samplesPerSymbol; i <= 5*samplesPerSymbol;i++) {
1052 if (peakPtr - i >= correlatedBurst.begin()) {
1053 valleyPower += (peakPtr-i)->norm2();
1054 numRms++;
1055 }
1056 if (peakPtr + i < correlatedBurst.end()) {
1057 valleyPower += (peakPtr+i)->norm2();
1058 numRms++;
1059 }
1060 }
1061
1062 if (numRms < 2) {
1063 // check for bogus results
1064 *amplitude = 0.0;
1065 return false;
1066 }
1067
1068 float RMS = sqrtf(valleyPower/(float)numRms)+0.00001;
1069 float peakToMean = (amplitude->abs())/RMS;
1070
1071 // NOTE: Because ideal TSC is 66 symbols into burst,
1072 // the ideal TSC has an +/- 180 degree phase shift,
1073 // due to the pi/4 frequency shift, that
1074 // needs to be accounted for.
1075
1076 *amplitude = (*amplitude)/gMidambles[TSC]->gain;
1077 *TOA = (*TOA) - (maxTOA);
1078
1079 LOG(DEBUG) << "TCH peakAmpl=" << amplitude->abs() << " RMS=" << RMS << " peakToMean=" << peakToMean << " TOA=" << *TOA;
1080
1081 LOG(DEBUG) << "autocorr: " << correlatedBurst;
1082
1083 if (requestChannel && (peakToMean > detectThreshold)) {
1084 float TOAoffset = maxTOA; //gMidambles[TSC]->TOA+(66*samplesPerSymbol-startIx);
1085 delayVector(correlatedBurst,-(*TOA));
1086 // midamble only allows estimation of a 6-tap channel
1087 signalVector channelVector(6*samplesPerSymbol);
1088 float maxEnergy = -1.0;
1089 int maxI = -1;
1090 for (int i = 0; i < 7; i++) {
1091 if (TOAoffset+(i-5)*samplesPerSymbol + channelVector.size() > correlatedBurst.size()) continue;
1092 if (TOAoffset+(i-5)*samplesPerSymbol < 0) continue;
1093 correlatedBurst.segmentCopyTo(channelVector,(int) floor(TOAoffset+(i-5)*samplesPerSymbol),channelVector.size());
1094 float energy = vectorNorm2(channelVector);
1095 if (energy > 0.95*maxEnergy) {
1096 maxI = i;
1097 maxEnergy = energy;
1098 }
1099 }
1100
1101 *channelResponse = new signalVector(channelVector.size());
1102 correlatedBurst.segmentCopyTo(**channelResponse,(int) floor(TOAoffset+(maxI-5)*samplesPerSymbol),(*channelResponse)->size());
1103 scaleVector(**channelResponse,complex(1.0,0.0)/gMidambles[TSC]->gain);
1104 LOG(DEBUG) << "channelResponse: " << **channelResponse;
1105
1106 if (channelResponseOffset)
1107 *channelResponseOffset = 5*samplesPerSymbol-maxI;
1108
1109 }
1110
1111 return (peakToMean > detectThreshold);
1112
1113}
1114
1115signalVector *decimateVector(signalVector &wVector,
1116 int decimationFactor)
1117{
1118
1119 if (decimationFactor <= 1) return NULL;
1120
1121 signalVector *decVector = new signalVector(wVector.size()/decimationFactor);
1122 decVector->isRealOnly(wVector.isRealOnly());
1123
1124 signalVector::iterator vecItr = decVector->begin();
1125 for (unsigned int i = 0; i < wVector.size();i+=decimationFactor)
1126 *vecItr++ = wVector[i];
1127
1128 return decVector;
1129}
1130
1131
1132SoftVector *demodulateBurst(signalVector &rxBurst,
1133 const signalVector &gsmPulse,
1134 int samplesPerSymbol,
1135 complex channel,
1136 float TOA)
1137
1138{
1139 scaleVector(rxBurst,((complex) 1.0)/channel);
1140 delayVector(rxBurst,-TOA);
1141
1142 signalVector *shapedBurst = &rxBurst;
1143
1144 // shift up by a quarter of a frequency
1145 // ignore starting phase, since spec allows for discontinuous phase
1146 GMSKReverseRotate(*shapedBurst);
1147
1148 // run through slicer
1149 if (samplesPerSymbol > 1) {
1150 signalVector *decShapedBurst = decimateVector(*shapedBurst,samplesPerSymbol);
1151 shapedBurst = decShapedBurst;
1152 }
1153
1154 LOG(DEBUG) << "shapedBurst: " << *shapedBurst;
1155
1156 vectorSlicer(shapedBurst);
1157
1158 SoftVector *burstBits = new SoftVector(shapedBurst->size());
1159
1160 SoftVector::iterator burstItr = burstBits->begin();
1161 signalVector::iterator shapedItr = shapedBurst->begin();
1162 for (; shapedItr < shapedBurst->end(); shapedItr++)
1163 *burstItr++ = shapedItr->real();
1164
1165 if (samplesPerSymbol > 1) delete shapedBurst;
1166
1167 return burstBits;
1168
1169}
1170
1171
1172// 1.0 is sampling frequency
1173// must satisfy cutoffFreq > 1/filterLen
1174signalVector *createLPF(float cutoffFreq,
1175 int filterLen,
1176 float gainDC)
1177{
kurtis.heimerla198d452011-11-26 03:19:28 +00001178#if 0
dburgessb3a0ca42011-10-12 07:44:40 +00001179 signalVector *LPF = new signalVector(filterLen-1);
1180 LPF->isRealOnly(true);
1181 LPF->setSymmetry(ABSSYM);
1182 signalVector::iterator itr = LPF->begin();
1183 double sum = 0.0;
1184 for (int i = 1; i < filterLen; i++) {
1185 float ys = sinc(M_2PI_F*cutoffFreq*((float)i-(float)(filterLen)/2.0F));
1186 float yg = 4.0F * cutoffFreq;
1187 // Blackman -- less brickwall (sloping transition) but larger stopband attenuation
1188 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));
1189 // Hamming -- more brickwall with smaller stopband attenuation
1190 //float yw = 0.53836F - 0.46164F * cos(((float)i)*M_2PI_F/(float)(filterLen+1));
1191 *itr++ = (complex) ys*yg*yw;
1192 sum += ys*yg*yw;
1193 }
kurtis.heimerla198d452011-11-26 03:19:28 +00001194#else
1195 double sum = 0.0;
1196 signalVector *LPF;
1197 signalVector::iterator itr;
1198 if (filterLen == 651) { // receive LPF
1199 LPF = new signalVector(651);
1200 LPF->isRealOnly(true);
1201 itr = LPF->begin();
1202 for (int i = 0; i < filterLen; i++) {
1203 *itr++ = complex(rcvLPF_651[i],0.0);
1204 sum += rcvLPF_651[i];
1205 }
1206 }
1207 else {
1208 LPF = new signalVector(961);
1209 LPF->isRealOnly(true);
1210 itr = LPF->begin();
1211 for (int i = 0; i < filterLen; i++) {
1212 *itr++ = complex(sendLPF_961[i],0.0);
1213 sum += sendLPF_961[i];
1214 }
1215 }
1216#endif
1217
dburgessb3a0ca42011-10-12 07:44:40 +00001218 float normFactor = gainDC/sum; //sqrtf(gainDC/vectorNorm2(*LPF));
1219 // normalize power
1220 itr = LPF->begin();
kurtis.heimerla198d452011-11-26 03:19:28 +00001221 for (int i = 0; i < filterLen; i++) {
dburgessb3a0ca42011-10-12 07:44:40 +00001222 *itr = *itr*normFactor;
1223 itr++;
1224 }
1225 return LPF;
1226
1227}
1228
1229
1230
1231#define POLYPHASESPAN 10
1232
1233// assumes filter group delay is 0.5*(length of filter)
1234signalVector *polyphaseResampleVector(signalVector &wVector,
1235 int P, int Q,
1236 signalVector *LPF)
1237
1238{
1239
1240 bool deleteLPF = false;
1241
1242 if (LPF==NULL) {
1243 float cutoffFreq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P);
1244 LPF = createLPF(cutoffFreq/3.0,100*POLYPHASESPAN+1,Q);
1245 deleteLPF = true;
1246 }
1247
1248 signalVector *resampledVector = new signalVector((int) ceil(wVector.size()*(float) P / (float) Q));
1249 resampledVector->fill(0);
1250 resampledVector->isRealOnly(wVector.isRealOnly());
1251 signalVector::iterator newItr = resampledVector->begin();
1252
1253 //FIXME: need to update for real-only vectors
1254 int outputIx = (LPF->size()+1)/2/Q; //((P > Q) ? P : Q);
1255 while (newItr < resampledVector->end()) {
1256 int outputBranch = (outputIx*Q) % P;
1257 int inputOffset = (outputIx*Q - outputBranch)/P;
1258 signalVector::const_iterator inputItr = wVector.begin() + inputOffset;
1259 signalVector::const_iterator filtItr = LPF->begin() + outputBranch;
1260 while (inputItr >= wVector.end()) {
1261 inputItr--;
1262 filtItr+=P;
1263 }
1264 complex sum = 0.0;
1265 if ((LPF->getSymmetry()!=ABSSYM) || (P>1)) {
1266 if (!LPF->isRealOnly()) {
1267 while ( (inputItr >= wVector.begin()) && (filtItr < LPF->end()) ) {
1268 sum += (*inputItr)*(*filtItr);
1269 inputItr--;
1270 filtItr += P;
1271 }
1272 }
1273 else {
1274 while ( (inputItr >= wVector.begin()) && (filtItr < LPF->end()) ) {
1275 sum += (*inputItr)*(filtItr->real());
1276 inputItr--;
1277 filtItr += P;
1278 }
1279 }
1280 }
1281 else {
1282 signalVector::const_iterator revInputItr = inputItr- LPF->size() + 1;
1283 signalVector::const_iterator filtMidpoint = LPF->begin()+(LPF->size()-1)/2;
1284 if (!LPF->isRealOnly()) {
1285 while (filtItr <= filtMidpoint) {
1286 if (inputItr < revInputItr) break;
1287 if (inputItr == revInputItr)
1288 sum += (*inputItr)*(*filtItr);
1289 else if ( (inputItr < wVector.end()) && (revInputItr >= wVector.begin()) )
1290 sum += (*inputItr + *revInputItr)*(*filtItr);
1291 else if ( inputItr < wVector.end() )
1292 sum += (*inputItr)*(*filtItr);
1293 else if ( revInputItr >= wVector.begin() )
1294 sum += (*revInputItr)*(*filtItr);
1295 inputItr--;
1296 revInputItr++;
1297 filtItr++;
1298 }
1299 }
1300 else {
1301 while (filtItr <= filtMidpoint) {
1302 if (inputItr < revInputItr) break;
1303 if (inputItr == revInputItr)
1304 sum += (*inputItr)*(filtItr->real());
1305 else if ( (inputItr < wVector.end()) && (revInputItr >= wVector.begin()) )
1306 sum += (*inputItr + *revInputItr)*(filtItr->real());
1307 else if ( inputItr < wVector.end() )
1308 sum += (*inputItr)*(filtItr->real());
1309 else if ( revInputItr >= wVector.begin() )
1310 sum += (*revInputItr)*(filtItr->real());
1311 inputItr--;
1312 revInputItr++;
1313 filtItr++;
1314 }
1315 }
1316 }
1317 *newItr = sum;
1318 newItr++;
1319 outputIx++;
1320 }
1321
1322 if (deleteLPF) delete LPF;
1323
1324 return resampledVector;
1325}
1326
1327
1328signalVector *resampleVector(signalVector &wVector,
1329 float expFactor,
1330 complex endPoint)
1331
1332{
1333
1334 if (expFactor < 1.0) return NULL;
1335
1336 signalVector *retVec = new signalVector((int) ceil(wVector.size()*expFactor));
1337
1338 float t = 0.0;
1339
1340 signalVector::iterator retItr = retVec->begin();
1341 while (retItr < retVec->end()) {
1342 unsigned tLow = (unsigned int) floor(t);
1343 unsigned tHigh = tLow + 1;
1344 if (tLow > wVector.size()-1) break;
1345 if (tHigh > wVector.size()) break;
1346 complex lowPoint = wVector[tLow];
1347 complex highPoint = (tHigh == wVector.size()) ? endPoint : wVector[tHigh];
1348 complex a = (tHigh-t);
1349 complex b = (t-tLow);
1350 *retItr = (a*lowPoint + b*highPoint);
1351 t += 1.0/expFactor;
1352 }
1353
1354 return retVec;
1355
1356}
1357
1358
1359// Assumes symbol-spaced sampling!!!
1360// Based upon paper by Al-Dhahir and Cioffi
1361bool designDFE(signalVector &channelResponse,
1362 float SNRestimate,
1363 int Nf,
1364 signalVector **feedForwardFilter,
1365 signalVector **feedbackFilter)
1366{
1367
1368 signalVector G0(Nf);
1369 signalVector G1(Nf);
1370 signalVector::iterator G0ptr = G0.begin();
1371 signalVector::iterator G1ptr = G1.begin();
1372 signalVector::iterator chanPtr = channelResponse.begin();
1373
1374 int nu = channelResponse.size()-1;
1375
1376 *G0ptr = 1.0/sqrtf(SNRestimate);
1377 for(int j = 0; j <= nu; j++) {
1378 *G1ptr = chanPtr->conj();
1379 G1ptr++; chanPtr++;
1380 }
1381
1382 signalVector *L[Nf];
1383 signalVector::iterator Lptr;
1384 float d;
1385 for(int i = 0; i < Nf; i++) {
1386 d = G0.begin()->norm2() + G1.begin()->norm2();
1387 L[i] = new signalVector(Nf+nu);
1388 Lptr = L[i]->begin()+i;
1389 G0ptr = G0.begin(); G1ptr = G1.begin();
1390 while ((G0ptr < G0.end()) && (Lptr < L[i]->end())) {
1391 *Lptr = (*G0ptr*(G0.begin()->conj()) + *G1ptr*(G1.begin()->conj()) )/d;
1392 Lptr++;
1393 G0ptr++;
1394 G1ptr++;
1395 }
1396 complex k = (*G1.begin())/(*G0.begin());
1397
1398 if (i != Nf-1) {
1399 signalVector G0new = G1;
1400 scaleVector(G0new,k.conj());
1401 addVector(G0new,G0);
1402
1403 signalVector G1new = G0;
1404 scaleVector(G1new,k*(-1.0));
1405 addVector(G1new,G1);
1406 delayVector(G1new,-1.0);
1407
1408 scaleVector(G0new,1.0/sqrtf(1.0+k.norm2()));
1409 scaleVector(G1new,1.0/sqrtf(1.0+k.norm2()));
1410 G0 = G0new;
1411 G1 = G1new;
1412 }
1413 }
1414
1415 *feedbackFilter = new signalVector(nu);
1416 L[Nf-1]->segmentCopyTo(**feedbackFilter,Nf,nu);
1417 scaleVector(**feedbackFilter,(complex) -1.0);
1418 conjugateVector(**feedbackFilter);
1419
1420 signalVector v(Nf);
1421 signalVector::iterator vStart = v.begin();
1422 signalVector::iterator vPtr;
1423 *(vStart+Nf-1) = (complex) 1.0;
1424 for(int k = Nf-2; k >= 0; k--) {
1425 Lptr = L[k]->begin()+k+1;
1426 vPtr = vStart + k+1;
1427 complex v_k = 0.0;
1428 for (int j = k+1; j < Nf; j++) {
1429 v_k -= (*vPtr)*(*Lptr);
1430 vPtr++; Lptr++;
1431 }
1432 *(vStart + k) = v_k;
1433 }
1434
1435 *feedForwardFilter = new signalVector(Nf);
1436 signalVector::iterator w = (*feedForwardFilter)->begin();
1437 for (int i = 0; i < Nf; i++) {
1438 delete L[i];
1439 complex w_i = 0.0;
1440 int endPt = ( nu < (Nf-1-i) ) ? nu : (Nf-1-i);
1441 vPtr = vStart+i;
1442 chanPtr = channelResponse.begin();
1443 for (int k = 0; k < endPt+1; k++) {
1444 w_i += (*vPtr)*(chanPtr->conj());
1445 vPtr++; chanPtr++;
1446 }
1447 *w = w_i/d;
1448 w++;
1449 }
1450
1451
1452 return true;
1453
1454}
1455
1456// Assumes symbol-rate sampling!!!!
1457SoftVector *equalizeBurst(signalVector &rxBurst,
1458 float TOA,
1459 int samplesPerSymbol,
1460 signalVector &w, // feedforward filter
1461 signalVector &b) // feedback filter
1462{
1463
1464 delayVector(rxBurst,-TOA);
1465
1466 signalVector* postForwardFull = convolve(&rxBurst,&w,NULL,FULL_SPAN);
1467
1468 signalVector* postForward = new signalVector(rxBurst.size());
1469 postForwardFull->segmentCopyTo(*postForward,w.size()-1,rxBurst.size());
1470 delete postForwardFull;
1471
1472 signalVector::iterator dPtr = postForward->begin();
1473 signalVector::iterator dBackPtr;
1474 signalVector::iterator rotPtr = GMSKRotation->begin();
1475 signalVector::iterator revRotPtr = GMSKReverseRotation->begin();
1476
1477 signalVector *DFEoutput = new signalVector(postForward->size());
1478 signalVector::iterator DFEItr = DFEoutput->begin();
1479
1480 // NOTE: can insert the midamble and/or use midamble to estimate BER
1481 for (; dPtr < postForward->end(); dPtr++) {
1482 dBackPtr = dPtr-1;
1483 signalVector::iterator bPtr = b.begin();
1484 while ( (bPtr < b.end()) && (dBackPtr >= postForward->begin()) ) {
1485 *dPtr = *dPtr + (*bPtr)*(*dBackPtr);
1486 bPtr++;
1487 dBackPtr--;
1488 }
1489 *dPtr = *dPtr * (*revRotPtr);
1490 *DFEItr = *dPtr;
1491 // make decision on symbol
1492 *dPtr = (dPtr->real() > 0.0) ? 1.0 : -1.0;
1493 //*DFEItr = *dPtr;
1494 *dPtr = *dPtr * (*rotPtr);
1495 DFEItr++;
1496 rotPtr++;
1497 revRotPtr++;
1498 }
1499
1500 vectorSlicer(DFEoutput);
1501
1502 SoftVector *burstBits = new SoftVector(postForward->size());
1503 SoftVector::iterator burstItr = burstBits->begin();
1504 DFEItr = DFEoutput->begin();
1505 for (; DFEItr < DFEoutput->end(); DFEItr++)
1506 *burstItr++ = DFEItr->real();
1507
1508 delete postForward;
1509
1510 delete DFEoutput;
1511
1512 return burstBits;
1513}