blob: ab605cf598ced7112755c85ba1df653f1d70447e [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
Thomas Tsou83e06892013-08-20 16:10:01 -040061/*
62 * Gaussian and empty modulation pulses
63 */
64struct PulseSequence {
65 PulseSequence() : gaussian(NULL), empty(NULL)
66 {
67 }
68
69 ~PulseSequence()
70 {
71 delete gaussian;
72 delete empty;
73 }
74
75 signalVector *gaussian;
76 signalVector *empty;
77};
78
dburgessb3a0ca42011-10-12 07:44:40 +000079CorrelationSequence *gMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
80CorrelationSequence *gRACHSequence = NULL;
Thomas Tsou83e06892013-08-20 16:10:01 -040081PulseSequence *GSMPulse = NULL;
dburgessb3a0ca42011-10-12 07:44:40 +000082
83void sigProcLibDestroy(void) {
84 if (GMSKRotation) {
85 delete GMSKRotation;
86 GMSKRotation = NULL;
87 }
88 if (GMSKReverseRotation) {
89 delete GMSKReverseRotation;
90 GMSKReverseRotation = NULL;
91 }
92 for (int i = 0; i < 8; i++) {
93 if (gMidambles[i]!=NULL) {
94 if (gMidambles[i]->sequence) delete gMidambles[i]->sequence;
95 if (gMidambles[i]->sequenceReversedConjugated) delete gMidambles[i]->sequenceReversedConjugated;
96 delete gMidambles[i];
97 gMidambles[i] = NULL;
98 }
99 }
100 if (gRACHSequence) {
101 if (gRACHSequence->sequence) delete gRACHSequence->sequence;
102 if (gRACHSequence->sequenceReversedConjugated) delete gRACHSequence->sequenceReversedConjugated;
103 delete gRACHSequence;
104 gRACHSequence = NULL;
105 }
106}
107
108
109
110// dB relative to 1.0.
111// if > 1.0, then return 0 dB
112float dB(float x) {
113
114 float arg = 1.0F;
115 float dB = 0.0F;
116
117 if (x >= 1.0F) return 0.0F;
118 if (x <= 0.0F) return -200.0F;
119
120 float prevArg = arg;
121 float prevdB = dB;
122 float stepSize = 16.0F;
123 float dBstepSize = 12.0F;
124 while (stepSize > 1.0F) {
125 do {
126 prevArg = arg;
127 prevdB = dB;
128 arg /= stepSize;
129 dB -= dBstepSize;
130 } while (arg > x);
131 arg = prevArg;
132 dB = prevdB;
133 stepSize *= 0.5F;
134 dBstepSize -= 3.0F;
135 }
136 return ((arg-x)*(dB-3.0F) + (x-arg*0.5F)*dB)/(arg - arg*0.5F);
137
138}
139
140// 10^(-dB/10), inverse of dB func.
141float dBinv(float x) {
142
143 float arg = 1.0F;
144 float dB = 0.0F;
145
146 if (x >= 0.0F) return 1.0F;
147 if (x <= -200.0F) return 0.0F;
148
149 float prevArg = arg;
150 float prevdB = dB;
151 float stepSize = 16.0F;
152 float dBstepSize = 12.0F;
153 while (stepSize > 1.0F) {
154 do {
155 prevArg = arg;
156 prevdB = dB;
157 arg /= stepSize;
158 dB -= dBstepSize;
159 } while (dB > x);
160 arg = prevArg;
161 dB = prevdB;
162 stepSize *= 0.5F;
163 dBstepSize -= 3.0F;
164 }
165
166 return ((dB-x)*(arg*0.5F)+(x-(dB-3.0F))*(arg))/3.0F;
167
168}
169
170float vectorNorm2(const signalVector &x)
171{
172 signalVector::const_iterator xPtr = x.begin();
173 float Energy = 0.0;
174 for (;xPtr != x.end();xPtr++) {
175 Energy += xPtr->norm2();
176 }
177 return Energy;
178}
179
180
181float vectorPower(const signalVector &x)
182{
183 return vectorNorm2(x)/x.size();
184}
185
186/** compute cosine via lookup table */
187float cosLookup(const float x)
188{
189 float arg = x*M_1_2PI_F;
190 while (arg > 1.0F) arg -= 1.0F;
191 while (arg < 0.0F) arg += 1.0F;
192
193 const float argT = arg*((float)TABLESIZE);
194 const int argI = (int)argT;
195 const float delta = argT-argI;
196 const float iDelta = 1.0F-delta;
197 return iDelta*cosTable[argI] + delta*cosTable[argI+1];
198}
199
200/** compute sine via lookup table */
201float sinLookup(const float x)
202{
203 float arg = x*M_1_2PI_F;
204 while (arg > 1.0F) arg -= 1.0F;
205 while (arg < 0.0F) arg += 1.0F;
206
207 const float argT = arg*((float)TABLESIZE);
208 const int argI = (int)argT;
209 const float delta = argT-argI;
210 const float iDelta = 1.0F-delta;
211 return iDelta*sinTable[argI] + delta*sinTable[argI+1];
212}
213
214
215/** compute e^(-jx) via lookup table. */
216complex expjLookup(float x)
217{
218 float arg = x*M_1_2PI_F;
219 while (arg > 1.0F) arg -= 1.0F;
220 while (arg < 0.0F) arg += 1.0F;
221
222 const float argT = arg*((float)TABLESIZE);
223 const int argI = (int)argT;
224 const float delta = argT-argI;
225 const float iDelta = 1.0F-delta;
226 return complex(iDelta*cosTable[argI] + delta*cosTable[argI+1],
227 iDelta*sinTable[argI] + delta*sinTable[argI+1]);
228}
229
230/** Library setup functions */
231void initTrigTables() {
232 for (int i = 0; i < TABLESIZE+1; i++) {
233 cosTable[i] = cos(2.0*M_PI*i/TABLESIZE);
234 sinTable[i] = sin(2.0*M_PI*i/TABLESIZE);
235 }
236}
237
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400238void initGMSKRotationTables(int sps)
239{
240 GMSKRotation = new signalVector(157 * sps);
241 GMSKReverseRotation = new signalVector(157 * sps);
dburgessb3a0ca42011-10-12 07:44:40 +0000242 signalVector::iterator rotPtr = GMSKRotation->begin();
243 signalVector::iterator revPtr = GMSKReverseRotation->begin();
244 float phase = 0.0;
245 while (rotPtr != GMSKRotation->end()) {
246 *rotPtr++ = expjLookup(phase);
247 *revPtr++ = expjLookup(-phase);
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400248 phase += M_PI_F / 2.0F / (float) sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000249 }
250}
251
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400252void sigProcLibSetup(int sps)
253{
dburgessb3a0ca42011-10-12 07:44:40 +0000254 initTrigTables();
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400255 initGMSKRotationTables(sps);
Thomas Tsou83e06892013-08-20 16:10:01 -0400256 generateGSMPulse(sps, 2);
dburgessb3a0ca42011-10-12 07:44:40 +0000257}
258
259void GMSKRotate(signalVector &x) {
260 signalVector::iterator xPtr = x.begin();
261 signalVector::iterator rotPtr = GMSKRotation->begin();
262 if (x.isRealOnly()) {
263 while (xPtr < x.end()) {
264 *xPtr = *rotPtr++ * (xPtr->real());
265 xPtr++;
266 }
267 }
268 else {
269 while (xPtr < x.end()) {
270 *xPtr = *rotPtr++ * (*xPtr);
271 xPtr++;
272 }
273 }
274}
275
276void GMSKReverseRotate(signalVector &x) {
277 signalVector::iterator xPtr= x.begin();
278 signalVector::iterator rotPtr = GMSKReverseRotation->begin();
279 if (x.isRealOnly()) {
280 while (xPtr < x.end()) {
281 *xPtr = *rotPtr++ * (xPtr->real());
282 xPtr++;
283 }
284 }
285 else {
286 while (xPtr < x.end()) {
287 *xPtr = *rotPtr++ * (*xPtr);
288 xPtr++;
289 }
290 }
291}
292
293
294signalVector* convolve(const signalVector *a,
295 const signalVector *b,
296 signalVector *c,
297 ConvType spanType,
298 unsigned startIx,
299 unsigned len)
300{
301 if ((a==NULL) || (b==NULL)) return NULL;
302 int La = a->size();
303 int Lb = b->size();
304
305 int startIndex;
306 unsigned int outSize;
307 switch (spanType) {
308 case FULL_SPAN:
309 startIndex = 0;
310 outSize = La+Lb-1;
311 break;
312 case OVERLAP_ONLY:
313 startIndex = La;
314 outSize = abs(La-Lb)+1;
315 break;
316 case START_ONLY:
317 startIndex = 0;
318 outSize = La;
319 break;
320 case WITH_TAIL:
321 startIndex = Lb;
322 outSize = La;
323 break;
324 case NO_DELAY:
325 if (Lb % 2)
326 startIndex = Lb/2;
327 else
328 startIndex = Lb/2-1;
329 outSize = La;
330 break;
331 case CUSTOM:
332 startIndex = startIx;
333 outSize = len;
334 break;
335 default:
336 return NULL;
337 }
338
339
340 if (c==NULL)
341 c = new signalVector(outSize);
342 else if (c->size()!=outSize)
343 return NULL;
344
345 signalVector::const_iterator aStart = a->begin();
346 signalVector::const_iterator bStart = b->begin();
347 signalVector::const_iterator aEnd = a->end();
348 signalVector::const_iterator bEnd = b->end();
349 signalVector::iterator cPtr = c->begin();
350 int t = startIndex;
351 int stopIndex = startIndex + outSize;
352 switch (b->getSymmetry()) {
353 case NONE:
354 {
355 while (t < stopIndex) {
356 signalVector::const_iterator aP = aStart+t;
357 signalVector::const_iterator bP = bStart;
358 if (a->isRealOnly() && b->isRealOnly()) {
359 float sum = 0.0;
360 while (bP < bEnd) {
361 if (aP < aStart) break;
362 if (aP < aEnd) sum += (aP->real())*(bP->real());
363 aP--;
364 bP++;
365 }
366 *cPtr++ = sum;
367 }
368 else if (a->isRealOnly()) {
369 complex sum = 0.0;
370 while (bP < bEnd) {
371 if (aP < aStart) break;
372 if (aP < aEnd) sum += (*bP)*(aP->real());
373 aP--;
374 bP++;
375 }
376 *cPtr++ = sum;
377 }
378 else if (b->isRealOnly()) {
379 complex sum = 0.0;
380 while (bP < bEnd) {
381 if (aP < aStart) break;
382 if (aP < aEnd) sum += (*aP)*(bP->real());
383 aP--;
384 bP++;
385 }
386 *cPtr++ = sum;
387 }
388 else {
389 complex sum = 0.0;
390 while (bP < bEnd) {
391 if (aP < aStart) break;
392 if (aP < aEnd) sum += (*aP)*(*bP);
393 aP--;
394 bP++;
395 }
396 *cPtr++ = sum;
397 }
398 t++;
399 }
400 }
401 break;
402 case ABSSYM:
403 {
404 complex sum = 0.0;
405 bool isOdd = (bool) (Lb % 2);
406 if (isOdd)
407 bEnd = bStart + (Lb+1)/2;
408 else
409 bEnd = bStart + Lb/2;
410 while (t < stopIndex) {
411 signalVector::const_iterator aP = aStart+t;
412 signalVector::const_iterator aPsym = aP-Lb+1;
413 signalVector::const_iterator bP = bStart;
414 sum = 0.0;
415 if (!b->isRealOnly()) {
416 while (bP < bEnd) {
417 if (aP < aStart) break;
418 if (aP == aPsym)
419 sum+= (*aP)*(*bP);
420 else if ((aP < aEnd) && (aPsym >= aStart))
421 sum+= ((*aP)+(*aPsym))*(*bP);
422 else if (aP < aEnd)
423 sum += (*aP)*(*bP);
424 else if (aPsym >= aStart)
425 sum += (*aPsym)*(*bP);
426 aP--;
427 aPsym++;
428 bP++;
429 }
430 }
431 else {
432 while (bP < bEnd) {
433 if (aP < aStart) break;
434 if (aP == aPsym)
435 sum+= (*aP)*(bP->real());
436 else if ((aP < aEnd) && (aPsym >= aStart))
437 sum+= ((*aP)+(*aPsym))*(bP->real());
438 else if (aP < aEnd)
439 sum += (*aP)*(bP->real());
440 else if (aPsym >= aStart)
441 sum += (*aPsym)*(bP->real());
442 aP--;
443 aPsym++;
444 bP++;
445 }
446 }
447 *cPtr++ = sum;
448 t++;
449 }
450 }
451 break;
452 default:
453 return NULL;
454 break;
455 }
456
457
458 return c;
459}
460
461
Thomas Tsou83e06892013-08-20 16:10:01 -0400462void generateGSMPulse(int sps, int symbolLength)
dburgessb3a0ca42011-10-12 07:44:40 +0000463{
Thomas Tsou83e06892013-08-20 16:10:01 -0400464 int len;
465 float arg, center;
dburgessb3a0ca42011-10-12 07:44:40 +0000466
Thomas Tsou83e06892013-08-20 16:10:01 -0400467 delete GSMPulse;
468
469 /* Store a single tap filter used for correlation sequence generation */
470 GSMPulse = new PulseSequence();
471 GSMPulse->empty = new signalVector(1);
472 GSMPulse->empty->isRealOnly(true);
473 *(GSMPulse->empty->begin()) = 1.0f;
474
475 /* GSM pulse approximation */
476 GSMPulse->gaussian = new signalVector(len);
477 GSMPulse->gaussian->isRealOnly(true);
478 signalVector::iterator xP = GSMPulse->gaussian->begin();
479
480 center = (float) (len - 1.0) / 2.0;
481
482 for (int i = 0; i < len; i++) {
483 arg = ((float) i - center) / (float) sps;
484 *xP++ = 0.96 * exp(-1.1380 * arg * arg -
485 0.527 * arg * arg * arg * arg);
dburgessb3a0ca42011-10-12 07:44:40 +0000486 }
487
Thomas Tsou83e06892013-08-20 16:10:01 -0400488 float avgAbsval = sqrtf(vectorNorm2(*GSMPulse->gaussian)/sps);
489 xP = GSMPulse->gaussian->begin();
490 for (int i = 0; i < len; i++)
dburgessb3a0ca42011-10-12 07:44:40 +0000491 *xP++ /= avgAbsval;
dburgessb3a0ca42011-10-12 07:44:40 +0000492}
493
494signalVector* frequencyShift(signalVector *y,
495 signalVector *x,
496 float freq,
497 float startPhase,
498 float *finalPhase)
499{
500
501 if (!x) return NULL;
502
503 if (y==NULL) {
504 y = new signalVector(x->size());
505 y->isRealOnly(x->isRealOnly());
506 if (y==NULL) return NULL;
507 }
508
509 if (y->size() < x->size()) return NULL;
510
511 float phase = startPhase;
512 signalVector::iterator yP = y->begin();
513 signalVector::iterator xPEnd = x->end();
514 signalVector::iterator xP = x->begin();
515
516 if (x->isRealOnly()) {
517 while (xP < xPEnd) {
518 (*yP++) = expjLookup(phase)*( (xP++)->real() );
519 phase += freq;
520 }
521 }
522 else {
523 while (xP < xPEnd) {
524 (*yP++) = (*xP++)*expjLookup(phase);
525 phase += freq;
526 }
527 }
528
529
530 if (finalPhase) *finalPhase = phase;
531
532 return y;
533}
534
535signalVector* reverseConjugate(signalVector *b)
536{
537 signalVector *tmp = new signalVector(b->size());
538 tmp->isRealOnly(b->isRealOnly());
539 signalVector::iterator bP = b->begin();
540 signalVector::iterator bPEnd = b->end();
541 signalVector::iterator tmpP = tmp->end()-1;
542 if (!b->isRealOnly()) {
543 while (bP < bPEnd) {
544 *tmpP-- = bP->conj();
545 bP++;
546 }
547 }
548 else {
549 while (bP < bPEnd) {
550 *tmpP-- = bP->real();
551 bP++;
552 }
553 }
554
555 return tmp;
556}
557
558signalVector* correlate(signalVector *a,
559 signalVector *b,
560 signalVector *c,
561 ConvType spanType,
562 bool bReversedConjugated,
563 unsigned startIx,
564 unsigned len)
565{
566 signalVector *tmp = NULL;
567
568 if (!bReversedConjugated) {
569 tmp = reverseConjugate(b);
570 }
571 else {
572 tmp = b;
573 }
574
575 c = convolve(a,tmp,c,spanType,startIx,len);
576
577 if (!bReversedConjugated) delete tmp;
578
579 return c;
580}
581
582
583/* soft output slicer */
584bool vectorSlicer(signalVector *x)
585{
586
587 signalVector::iterator xP = x->begin();
588 signalVector::iterator xPEnd = x->end();
589 while (xP < xPEnd) {
590 *xP = (complex) (0.5*(xP->real()+1.0F));
591 if (xP->real() > 1.0) *xP = 1.0;
592 if (xP->real() < 0.0) *xP = 0.0;
593 xP++;
594 }
595 return true;
596}
597
Thomas Tsou83e06892013-08-20 16:10:01 -0400598signalVector *modulateBurst(const BitVector &wBurst, int guardPeriodLength,
599 int sps, bool emptyPulse)
dburgessb3a0ca42011-10-12 07:44:40 +0000600{
Thomas Tsou83e06892013-08-20 16:10:01 -0400601 int burstLen;
602 signalVector *pulse, modBurst;
603 signalVector::iterator modBurstItr;
dburgessb3a0ca42011-10-12 07:44:40 +0000604
Thomas Tsou83e06892013-08-20 16:10:01 -0400605 if (emptyPulse)
606 pulse = GSMPulse->empty;
607 else
608 pulse = GSMPulse->gaussian;
dburgessb3a0ca42011-10-12 07:44:40 +0000609
Thomas Tsou83e06892013-08-20 16:10:01 -0400610 burstLen = sps * (wBurst.size() + guardPeriodLength);
611 modBurst = signalVector(burstLen);
612 modBurstItr = modBurst.begin();
dburgessb3a0ca42011-10-12 07:44:40 +0000613
dburgessb3a0ca42011-10-12 07:44:40 +0000614 for (unsigned int i = 0; i < wBurst.size(); i++) {
615 *modBurstItr = 2.0*(wBurst[i] & 0x01)-1.0;
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400616 modBurstItr += sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000617 }
618
619 // shift up pi/2
620 // ignore starting phase, since spec allows for discontinuous phase
621 GMSKRotate(modBurst);
Thomas Tsou83e06892013-08-20 16:10:01 -0400622
dburgessb3a0ca42011-10-12 07:44:40 +0000623 modBurst.isRealOnly(false);
624
625 // filter w/ pulse shape
Thomas Tsou83e06892013-08-20 16:10:01 -0400626 signalVector *shapedBurst = convolve(&modBurst, pulse, NULL, NO_DELAY);
dburgessb3a0ca42011-10-12 07:44:40 +0000627
dburgessb3a0ca42011-10-12 07:44:40 +0000628 return shapedBurst;
dburgessb3a0ca42011-10-12 07:44:40 +0000629}
630
631float sinc(float x)
632{
633 if ((x >= 0.01F) || (x <= -0.01F)) return (sinLookup(x)/x);
634 return 1.0F;
635}
636
637void delayVector(signalVector &wBurst,
638 float delay)
639{
640
641 int intOffset = (int) floor(delay);
642 float fracOffset = delay - intOffset;
643
644 // do fractional shift first, only do it for reasonable offsets
645 if (fabs(fracOffset) > 1e-2) {
646 // create sinc function
647 signalVector sincVector(21);
648 sincVector.isRealOnly(true);
649 signalVector::iterator sincBurstItr = sincVector.begin();
650 for (int i = 0; i < 21; i++)
651 *sincBurstItr++ = (complex) sinc(M_PI_F*(i-10-fracOffset));
652
653 signalVector shiftedBurst(wBurst.size());
654 convolve(&wBurst,&sincVector,&shiftedBurst,NO_DELAY);
655 wBurst.clone(shiftedBurst);
656 }
657
658 if (intOffset < 0) {
659 intOffset = -intOffset;
660 signalVector::iterator wBurstItr = wBurst.begin();
661 signalVector::iterator shiftedItr = wBurst.begin()+intOffset;
662 while (shiftedItr < wBurst.end())
663 *wBurstItr++ = *shiftedItr++;
664 while (wBurstItr < wBurst.end())
665 *wBurstItr++ = 0.0;
666 }
667 else {
668 signalVector::iterator wBurstItr = wBurst.end()-1;
669 signalVector::iterator shiftedItr = wBurst.end()-1-intOffset;
670 while (shiftedItr >= wBurst.begin())
671 *wBurstItr-- = *shiftedItr--;
672 while (wBurstItr >= wBurst.begin())
673 *wBurstItr-- = 0.0;
674 }
675}
676
677signalVector *gaussianNoise(int length,
678 float variance,
679 complex mean)
680{
681
682 signalVector *noise = new signalVector(length);
683 signalVector::iterator nPtr = noise->begin();
684 float stddev = sqrtf(variance);
685 while (nPtr < noise->end()) {
686 float u1 = (float) rand()/ (float) RAND_MAX;
687 while (u1==0.0)
688 u1 = (float) rand()/ (float) RAND_MAX;
689 float u2 = (float) rand()/ (float) RAND_MAX;
690 float arg = 2.0*M_PI*u2;
691 *nPtr = mean + stddev*complex(cos(arg),sin(arg))*sqrtf(-2.0*log(u1));
692 nPtr++;
693 }
694
695 return noise;
696}
697
698complex interpolatePoint(const signalVector &inSig,
699 float ix)
700{
701
702 int start = (int) (floor(ix) - 10);
703 if (start < 0) start = 0;
704 int end = (int) (floor(ix) + 11);
705 if ((unsigned) end > inSig.size()-1) end = inSig.size()-1;
706
707 complex pVal = 0.0;
708 if (!inSig.isRealOnly()) {
709 for (int i = start; i < end; i++)
710 pVal += inSig[i] * sinc(M_PI_F*(i-ix));
711 }
712 else {
713 for (int i = start; i < end; i++)
714 pVal += inSig[i].real() * sinc(M_PI_F*(i-ix));
715 }
716
717 return pVal;
718}
719
720
721
722complex peakDetect(const signalVector &rxBurst,
723 float *peakIndex,
724 float *avgPwr)
725{
726
727
728 complex maxVal = 0.0;
729 float maxIndex = -1;
730 float sumPower = 0.0;
731
732 for (unsigned int i = 0; i < rxBurst.size(); i++) {
733 float samplePower = rxBurst[i].norm2();
734 if (samplePower > maxVal.real()) {
735 maxVal = samplePower;
736 maxIndex = i;
737 }
738 sumPower += samplePower;
739 }
740
741 // interpolate around the peak
742 // to save computation, we'll use early-late balancing
743 float earlyIndex = maxIndex-1;
744 float lateIndex = maxIndex+1;
745
746 float incr = 0.5;
747 while (incr > 1.0/1024.0) {
748 complex earlyP = interpolatePoint(rxBurst,earlyIndex);
749 complex lateP = interpolatePoint(rxBurst,lateIndex);
750 if (earlyP < lateP)
751 earlyIndex += incr;
752 else if (earlyP > lateP)
753 earlyIndex -= incr;
754 else break;
755 incr /= 2.0;
756 lateIndex = earlyIndex + 2.0;
757 }
758
759 maxIndex = earlyIndex + 1.0;
760 maxVal = interpolatePoint(rxBurst,maxIndex);
761
762 if (peakIndex!=NULL)
763 *peakIndex = maxIndex;
764
765 if (avgPwr!=NULL)
766 *avgPwr = (sumPower-maxVal.norm2()) / (rxBurst.size()-1);
767
768 return maxVal;
769
770}
771
772void scaleVector(signalVector &x,
773 complex scale)
774{
775 signalVector::iterator xP = x.begin();
776 signalVector::iterator xPEnd = x.end();
777 if (!x.isRealOnly()) {
778 while (xP < xPEnd) {
779 *xP = *xP * scale;
780 xP++;
781 }
782 }
783 else {
784 while (xP < xPEnd) {
785 *xP = xP->real() * scale;
786 xP++;
787 }
788 }
789}
790
791/** in-place conjugation */
792void conjugateVector(signalVector &x)
793{
794 if (x.isRealOnly()) return;
795 signalVector::iterator xP = x.begin();
796 signalVector::iterator xPEnd = x.end();
797 while (xP < xPEnd) {
798 *xP = xP->conj();
799 xP++;
800 }
801}
802
803
804// in-place addition!!
805bool addVector(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// in-place multiplication!!
820bool multVector(signalVector &x,
821 signalVector &y)
822{
823 signalVector::iterator xP = x.begin();
824 signalVector::iterator yP = y.begin();
825 signalVector::iterator xPEnd = x.end();
826 signalVector::iterator yPEnd = y.end();
827 while ((xP < xPEnd) && (yP < yPEnd)) {
828 *xP = (*xP) * (*yP);
829 xP++; yP++;
830 }
831 return true;
832}
833
834
835void offsetVector(signalVector &x,
836 complex offset)
837{
838 signalVector::iterator xP = x.begin();
839 signalVector::iterator xPEnd = x.end();
840 if (!x.isRealOnly()) {
841 while (xP < xPEnd) {
842 *xP += offset;
843 xP++;
844 }
845 }
846 else {
847 while (xP < xPEnd) {
848 *xP = xP->real() + offset;
849 xP++;
850 }
851 }
852}
853
Thomas Tsou83e06892013-08-20 16:10:01 -0400854bool generateMidamble(int sps, int TSC)
dburgessb3a0ca42011-10-12 07:44:40 +0000855{
dburgessb3a0ca42011-10-12 07:44:40 +0000856 if ((TSC < 0) || (TSC > 7))
857 return false;
858
859 if (gMidambles[TSC]) {
860 if (gMidambles[TSC]->sequence!=NULL) delete gMidambles[TSC]->sequence;
861 if (gMidambles[TSC]->sequenceReversedConjugated!=NULL) delete gMidambles[TSC]->sequenceReversedConjugated;
862 }
863
dburgessb3a0ca42011-10-12 07:44:40 +0000864 // only use middle 16 bits of each TSC
865 signalVector *middleMidamble = modulateBurst(gTrainingSequence[TSC].segment(5,16),
dburgessb3a0ca42011-10-12 07:44:40 +0000866 0,
Thomas Tsou83e06892013-08-20 16:10:01 -0400867 sps, true);
dburgessb3a0ca42011-10-12 07:44:40 +0000868 signalVector *midamble = modulateBurst(gTrainingSequence[TSC],
dburgessb3a0ca42011-10-12 07:44:40 +0000869 0,
Thomas Tsou83e06892013-08-20 16:10:01 -0400870 sps, false);
dburgessb3a0ca42011-10-12 07:44:40 +0000871
872 if (midamble == NULL) return false;
873 if (middleMidamble == NULL) return false;
874
875 // NOTE: Because ideal TSC 16-bit midamble is 66 symbols into burst,
876 // the ideal TSC has an + 180 degree phase shift,
877 // due to the pi/2 frequency shift, that
878 // needs to be accounted for.
879 // 26-midamble is 61 symbols into burst, has +90 degree phase shift.
880 scaleVector(*middleMidamble,complex(-1.0,0.0));
881 scaleVector(*midamble,complex(0.0,1.0));
882
883 signalVector *autocorr = correlate(midamble,middleMidamble,NULL,NO_DELAY);
884
885 if (autocorr == NULL) return false;
886
887 gMidambles[TSC] = new CorrelationSequence;
888 gMidambles[TSC]->sequence = middleMidamble;
889 gMidambles[TSC]->sequenceReversedConjugated = reverseConjugate(middleMidamble);
890 gMidambles[TSC]->gain = peakDetect(*autocorr,&gMidambles[TSC]->TOA,NULL);
891
892 LOG(DEBUG) << "midamble autocorr: " << *autocorr;
893
894 LOG(DEBUG) << "TOA: " << gMidambles[TSC]->TOA;
895
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400896 //gMidambles[TSC]->TOA -= 5*sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000897
898 delete autocorr;
899 delete midamble;
900
901 return true;
902}
903
Thomas Tsou83e06892013-08-20 16:10:01 -0400904bool generateRACHSequence(int sps)
dburgessb3a0ca42011-10-12 07:44:40 +0000905{
dburgessb3a0ca42011-10-12 07:44:40 +0000906 if (gRACHSequence) {
907 if (gRACHSequence->sequence!=NULL) delete gRACHSequence->sequence;
908 if (gRACHSequence->sequenceReversedConjugated!=NULL) delete gRACHSequence->sequenceReversedConjugated;
909 }
910
911 signalVector *RACHSeq = modulateBurst(gRACHSynchSequence,
dburgessb3a0ca42011-10-12 07:44:40 +0000912 0,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400913 sps);
dburgessb3a0ca42011-10-12 07:44:40 +0000914
915 assert(RACHSeq);
916
917 signalVector *autocorr = correlate(RACHSeq,RACHSeq,NULL,NO_DELAY);
918
919 assert(autocorr);
920
921 gRACHSequence = new CorrelationSequence;
922 gRACHSequence->sequence = RACHSeq;
923 gRACHSequence->sequenceReversedConjugated = reverseConjugate(RACHSeq);
924 gRACHSequence->gain = peakDetect(*autocorr,&gRACHSequence->TOA,NULL);
925
926 delete autocorr;
927
928 return true;
929
930}
931
932
933bool detectRACHBurst(signalVector &rxBurst,
934 float detectThreshold,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400935 int sps,
dburgessb3a0ca42011-10-12 07:44:40 +0000936 complex *amplitude,
937 float* TOA)
938{
939
940 //static complex staticData[500];
941
942 //signalVector correlatedRACH(staticData,0,rxBurst.size());
943 signalVector correlatedRACH(rxBurst.size());
944 correlate(&rxBurst,gRACHSequence->sequenceReversedConjugated,&correlatedRACH,NO_DELAY,true);
945
946 float meanPower;
947 complex peakAmpl = peakDetect(correlatedRACH,TOA,&meanPower);
948
949 float valleyPower = 0.0;
950
951 // check for bogus results
952 if ((*TOA < 0.0) || (*TOA > correlatedRACH.size())) {
953 *amplitude = 0.0;
954 return false;
955 }
956 complex *peakPtr = correlatedRACH.begin() + (int) rint(*TOA);
957
958 LOG(DEBUG) << "RACH corr: " << correlatedRACH;
959
960 float numSamples = 0.0;
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400961 for (int i = 57 * sps; i <= 107 * sps; i++) {
dburgessb3a0ca42011-10-12 07:44:40 +0000962 if (peakPtr+i >= correlatedRACH.end())
963 break;
964 valleyPower += (peakPtr+i)->norm2();
965 numSamples++;
966 }
967
968 if (numSamples < 2) {
969 *amplitude = 0.0;
970 return false;
971 }
972
973 float RMS = sqrtf(valleyPower/(float) numSamples)+0.00001;
974 float peakToMean = peakAmpl.abs()/RMS;
975
976 LOG(DEBUG) << "RACH peakAmpl=" << peakAmpl << " RMS=" << RMS << " peakToMean=" << peakToMean;
977 *amplitude = peakAmpl/(gRACHSequence->gain);
978
Thomas Tsoud24cc2c2013-08-20 15:41:45 -0400979 *TOA = (*TOA) - gRACHSequence->TOA - 8 * sps;
dburgessb3a0ca42011-10-12 07:44:40 +0000980
981 LOG(DEBUG) << "RACH thresh: " << peakToMean;
982
983 return (peakToMean > detectThreshold);
984}
985
986bool energyDetect(signalVector &rxBurst,
987 unsigned windowLength,
988 float detectThreshold,
989 float *avgPwr)
990{
991
992 signalVector::const_iterator windowItr = rxBurst.begin(); //+rxBurst.size()/2 - 5*windowLength/2;
993 float energy = 0.0;
994 if (windowLength < 0) windowLength = 20;
995 if (windowLength > rxBurst.size()) windowLength = rxBurst.size();
996 for (unsigned i = 0; i < windowLength; i++) {
997 energy += windowItr->norm2();
998 windowItr+=4;
999 }
1000 if (avgPwr) *avgPwr = energy/windowLength;
1001 LOG(DEBUG) << "detected energy: " << energy/windowLength;
1002 return (energy/windowLength > detectThreshold*detectThreshold);
1003}
1004
1005
1006bool analyzeTrafficBurst(signalVector &rxBurst,
1007 unsigned TSC,
1008 float detectThreshold,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001009 int sps,
dburgessb3a0ca42011-10-12 07:44:40 +00001010 complex *amplitude,
1011 float *TOA,
1012 unsigned maxTOA,
1013 bool requestChannel,
1014 signalVector **channelResponse,
1015 float *channelResponseOffset)
1016{
1017
1018 assert(TSC<8);
1019 assert(amplitude);
1020 assert(TOA);
1021 assert(gMidambles[TSC]);
1022
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001023 if (maxTOA < 3*sps) maxTOA = 3*sps;
dburgessb3a0ca42011-10-12 07:44:40 +00001024 unsigned spanTOA = maxTOA;
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001025 if (spanTOA < 5*sps) spanTOA = 5*sps;
dburgessb3a0ca42011-10-12 07:44:40 +00001026
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001027 unsigned startIx = 66*sps-spanTOA;
1028 unsigned endIx = (66+16)*sps+spanTOA;
dburgessb3a0ca42011-10-12 07:44:40 +00001029 unsigned windowLen = endIx - startIx;
1030 unsigned corrLen = 2*maxTOA+1;
1031
1032 unsigned expectedTOAPeak = (unsigned) round(gMidambles[TSC]->TOA + (gMidambles[TSC]->sequenceReversedConjugated->size()-1)/2);
1033
1034 signalVector burstSegment(rxBurst.begin(),startIx,windowLen);
1035
1036 //static complex staticData[200];
1037 //signalVector correlatedBurst(staticData,0,corrLen);
1038 signalVector correlatedBurst(corrLen);
1039 correlate(&burstSegment, gMidambles[TSC]->sequenceReversedConjugated,
1040 &correlatedBurst, CUSTOM,true,
1041 expectedTOAPeak-maxTOA,corrLen);
1042
1043 float meanPower;
1044 *amplitude = peakDetect(correlatedBurst,TOA,&meanPower);
1045 float valleyPower = 0.0; //amplitude->norm2();
1046 complex *peakPtr = correlatedBurst.begin() + (int) rint(*TOA);
1047
1048 // check for bogus results
1049 if ((*TOA < 0.0) || (*TOA > correlatedBurst.size())) {
1050 *amplitude = 0.0;
1051 return false;
1052 }
1053
1054 int numRms = 0;
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001055 for (int i = 2*sps; i <= 5*sps;i++) {
dburgessb3a0ca42011-10-12 07:44:40 +00001056 if (peakPtr - i >= correlatedBurst.begin()) {
1057 valleyPower += (peakPtr-i)->norm2();
1058 numRms++;
1059 }
1060 if (peakPtr + i < correlatedBurst.end()) {
1061 valleyPower += (peakPtr+i)->norm2();
1062 numRms++;
1063 }
1064 }
1065
1066 if (numRms < 2) {
1067 // check for bogus results
1068 *amplitude = 0.0;
1069 return false;
1070 }
1071
1072 float RMS = sqrtf(valleyPower/(float)numRms)+0.00001;
1073 float peakToMean = (amplitude->abs())/RMS;
1074
1075 // NOTE: Because ideal TSC is 66 symbols into burst,
1076 // the ideal TSC has an +/- 180 degree phase shift,
1077 // due to the pi/4 frequency shift, that
1078 // needs to be accounted for.
1079
1080 *amplitude = (*amplitude)/gMidambles[TSC]->gain;
1081 *TOA = (*TOA) - (maxTOA);
1082
1083 LOG(DEBUG) << "TCH peakAmpl=" << amplitude->abs() << " RMS=" << RMS << " peakToMean=" << peakToMean << " TOA=" << *TOA;
1084
1085 LOG(DEBUG) << "autocorr: " << correlatedBurst;
1086
1087 if (requestChannel && (peakToMean > detectThreshold)) {
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001088 float TOAoffset = maxTOA;
dburgessb3a0ca42011-10-12 07:44:40 +00001089 delayVector(correlatedBurst,-(*TOA));
1090 // midamble only allows estimation of a 6-tap channel
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001091 signalVector chanVector(6 * sps);
dburgessb3a0ca42011-10-12 07:44:40 +00001092 float maxEnergy = -1.0;
1093 int maxI = -1;
1094 for (int i = 0; i < 7; i++) {
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001095 if (TOAoffset + (i-5) * sps + chanVector.size() > correlatedBurst.size())
1096 continue;
1097 if (TOAoffset + (i-5) * sps < 0)
1098 continue;
1099 correlatedBurst.segmentCopyTo(chanVector,
1100 (int) floor(TOAoffset + (i - 5) * sps),
1101 chanVector.size());
1102 float energy = vectorNorm2(chanVector);
dburgessb3a0ca42011-10-12 07:44:40 +00001103 if (energy > 0.95*maxEnergy) {
1104 maxI = i;
1105 maxEnergy = energy;
1106 }
1107 }
1108
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001109 *channelResponse = new signalVector(chanVector.size());
1110 correlatedBurst.segmentCopyTo(**channelResponse,
1111 (int) floor(TOAoffset + (maxI - 5) * sps),
1112 (*channelResponse)->size());
1113 scaleVector(**channelResponse, complex(1.0, 0.0) / gMidambles[TSC]->gain);
dburgessb3a0ca42011-10-12 07:44:40 +00001114 LOG(DEBUG) << "channelResponse: " << **channelResponse;
1115
1116 if (channelResponseOffset)
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001117 *channelResponseOffset = 5 * sps - maxI;
dburgessb3a0ca42011-10-12 07:44:40 +00001118
1119 }
1120
1121 return (peakToMean > detectThreshold);
1122
1123}
1124
1125signalVector *decimateVector(signalVector &wVector,
1126 int decimationFactor)
1127{
1128
1129 if (decimationFactor <= 1) return NULL;
1130
1131 signalVector *decVector = new signalVector(wVector.size()/decimationFactor);
1132 decVector->isRealOnly(wVector.isRealOnly());
1133
1134 signalVector::iterator vecItr = decVector->begin();
1135 for (unsigned int i = 0; i < wVector.size();i+=decimationFactor)
1136 *vecItr++ = wVector[i];
1137
1138 return decVector;
1139}
1140
1141
Thomas Tsou83e06892013-08-20 16:10:01 -04001142SoftVector *demodulateBurst(signalVector &rxBurst, int sps,
1143 complex channel, float TOA)
dburgessb3a0ca42011-10-12 07:44:40 +00001144{
1145 scaleVector(rxBurst,((complex) 1.0)/channel);
1146 delayVector(rxBurst,-TOA);
1147
1148 signalVector *shapedBurst = &rxBurst;
1149
1150 // shift up by a quarter of a frequency
1151 // ignore starting phase, since spec allows for discontinuous phase
1152 GMSKReverseRotate(*shapedBurst);
1153
1154 // run through slicer
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001155 if (sps > 1) {
1156 signalVector *decShapedBurst = decimateVector(*shapedBurst, sps);
dburgessb3a0ca42011-10-12 07:44:40 +00001157 shapedBurst = decShapedBurst;
1158 }
1159
1160 LOG(DEBUG) << "shapedBurst: " << *shapedBurst;
1161
1162 vectorSlicer(shapedBurst);
1163
1164 SoftVector *burstBits = new SoftVector(shapedBurst->size());
1165
1166 SoftVector::iterator burstItr = burstBits->begin();
1167 signalVector::iterator shapedItr = shapedBurst->begin();
1168 for (; shapedItr < shapedBurst->end(); shapedItr++)
1169 *burstItr++ = shapedItr->real();
1170
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001171 if (sps > 1)
1172 delete shapedBurst;
dburgessb3a0ca42011-10-12 07:44:40 +00001173
1174 return burstBits;
1175
1176}
1177
1178
1179// 1.0 is sampling frequency
1180// must satisfy cutoffFreq > 1/filterLen
1181signalVector *createLPF(float cutoffFreq,
1182 int filterLen,
1183 float gainDC)
1184{
kurtis.heimerla198d452011-11-26 03:19:28 +00001185#if 0
dburgessb3a0ca42011-10-12 07:44:40 +00001186 signalVector *LPF = new signalVector(filterLen-1);
1187 LPF->isRealOnly(true);
1188 LPF->setSymmetry(ABSSYM);
1189 signalVector::iterator itr = LPF->begin();
1190 double sum = 0.0;
1191 for (int i = 1; i < filterLen; i++) {
1192 float ys = sinc(M_2PI_F*cutoffFreq*((float)i-(float)(filterLen)/2.0F));
1193 float yg = 4.0F * cutoffFreq;
1194 // Blackman -- less brickwall (sloping transition) but larger stopband attenuation
1195 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));
1196 // Hamming -- more brickwall with smaller stopband attenuation
1197 //float yw = 0.53836F - 0.46164F * cos(((float)i)*M_2PI_F/(float)(filterLen+1));
1198 *itr++ = (complex) ys*yg*yw;
1199 sum += ys*yg*yw;
1200 }
kurtis.heimerla198d452011-11-26 03:19:28 +00001201#else
1202 double sum = 0.0;
1203 signalVector *LPF;
1204 signalVector::iterator itr;
1205 if (filterLen == 651) { // receive LPF
1206 LPF = new signalVector(651);
1207 LPF->isRealOnly(true);
1208 itr = LPF->begin();
1209 for (int i = 0; i < filterLen; i++) {
1210 *itr++ = complex(rcvLPF_651[i],0.0);
1211 sum += rcvLPF_651[i];
1212 }
1213 }
1214 else {
1215 LPF = new signalVector(961);
1216 LPF->isRealOnly(true);
1217 itr = LPF->begin();
1218 for (int i = 0; i < filterLen; i++) {
1219 *itr++ = complex(sendLPF_961[i],0.0);
1220 sum += sendLPF_961[i];
1221 }
1222 }
1223#endif
1224
dburgessb3a0ca42011-10-12 07:44:40 +00001225 float normFactor = gainDC/sum; //sqrtf(gainDC/vectorNorm2(*LPF));
1226 // normalize power
1227 itr = LPF->begin();
kurtis.heimerla198d452011-11-26 03:19:28 +00001228 for (int i = 0; i < filterLen; i++) {
dburgessb3a0ca42011-10-12 07:44:40 +00001229 *itr = *itr*normFactor;
1230 itr++;
1231 }
1232 return LPF;
1233
1234}
1235
1236
1237
1238#define POLYPHASESPAN 10
1239
1240// assumes filter group delay is 0.5*(length of filter)
1241signalVector *polyphaseResampleVector(signalVector &wVector,
1242 int P, int Q,
1243 signalVector *LPF)
1244
1245{
1246
1247 bool deleteLPF = false;
1248
1249 if (LPF==NULL) {
1250 float cutoffFreq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P);
1251 LPF = createLPF(cutoffFreq/3.0,100*POLYPHASESPAN+1,Q);
1252 deleteLPF = true;
1253 }
1254
1255 signalVector *resampledVector = new signalVector((int) ceil(wVector.size()*(float) P / (float) Q));
1256 resampledVector->fill(0);
1257 resampledVector->isRealOnly(wVector.isRealOnly());
1258 signalVector::iterator newItr = resampledVector->begin();
1259
1260 //FIXME: need to update for real-only vectors
1261 int outputIx = (LPF->size()+1)/2/Q; //((P > Q) ? P : Q);
1262 while (newItr < resampledVector->end()) {
1263 int outputBranch = (outputIx*Q) % P;
1264 int inputOffset = (outputIx*Q - outputBranch)/P;
1265 signalVector::const_iterator inputItr = wVector.begin() + inputOffset;
1266 signalVector::const_iterator filtItr = LPF->begin() + outputBranch;
1267 while (inputItr >= wVector.end()) {
1268 inputItr--;
1269 filtItr+=P;
1270 }
1271 complex sum = 0.0;
1272 if ((LPF->getSymmetry()!=ABSSYM) || (P>1)) {
1273 if (!LPF->isRealOnly()) {
1274 while ( (inputItr >= wVector.begin()) && (filtItr < LPF->end()) ) {
1275 sum += (*inputItr)*(*filtItr);
1276 inputItr--;
1277 filtItr += P;
1278 }
1279 }
1280 else {
1281 while ( (inputItr >= wVector.begin()) && (filtItr < LPF->end()) ) {
1282 sum += (*inputItr)*(filtItr->real());
1283 inputItr--;
1284 filtItr += P;
1285 }
1286 }
1287 }
1288 else {
1289 signalVector::const_iterator revInputItr = inputItr- LPF->size() + 1;
1290 signalVector::const_iterator filtMidpoint = LPF->begin()+(LPF->size()-1)/2;
1291 if (!LPF->isRealOnly()) {
1292 while (filtItr <= filtMidpoint) {
1293 if (inputItr < revInputItr) break;
1294 if (inputItr == revInputItr)
1295 sum += (*inputItr)*(*filtItr);
1296 else if ( (inputItr < wVector.end()) && (revInputItr >= wVector.begin()) )
1297 sum += (*inputItr + *revInputItr)*(*filtItr);
1298 else if ( inputItr < wVector.end() )
1299 sum += (*inputItr)*(*filtItr);
1300 else if ( revInputItr >= wVector.begin() )
1301 sum += (*revInputItr)*(*filtItr);
1302 inputItr--;
1303 revInputItr++;
1304 filtItr++;
1305 }
1306 }
1307 else {
1308 while (filtItr <= filtMidpoint) {
1309 if (inputItr < revInputItr) break;
1310 if (inputItr == revInputItr)
1311 sum += (*inputItr)*(filtItr->real());
1312 else if ( (inputItr < wVector.end()) && (revInputItr >= wVector.begin()) )
1313 sum += (*inputItr + *revInputItr)*(filtItr->real());
1314 else if ( inputItr < wVector.end() )
1315 sum += (*inputItr)*(filtItr->real());
1316 else if ( revInputItr >= wVector.begin() )
1317 sum += (*revInputItr)*(filtItr->real());
1318 inputItr--;
1319 revInputItr++;
1320 filtItr++;
1321 }
1322 }
1323 }
1324 *newItr = sum;
1325 newItr++;
1326 outputIx++;
1327 }
1328
1329 if (deleteLPF) delete LPF;
1330
1331 return resampledVector;
1332}
1333
1334
1335signalVector *resampleVector(signalVector &wVector,
1336 float expFactor,
1337 complex endPoint)
1338
1339{
1340
1341 if (expFactor < 1.0) return NULL;
1342
1343 signalVector *retVec = new signalVector((int) ceil(wVector.size()*expFactor));
1344
1345 float t = 0.0;
1346
1347 signalVector::iterator retItr = retVec->begin();
1348 while (retItr < retVec->end()) {
1349 unsigned tLow = (unsigned int) floor(t);
1350 unsigned tHigh = tLow + 1;
1351 if (tLow > wVector.size()-1) break;
1352 if (tHigh > wVector.size()) break;
1353 complex lowPoint = wVector[tLow];
1354 complex highPoint = (tHigh == wVector.size()) ? endPoint : wVector[tHigh];
1355 complex a = (tHigh-t);
1356 complex b = (t-tLow);
1357 *retItr = (a*lowPoint + b*highPoint);
1358 t += 1.0/expFactor;
1359 }
1360
1361 return retVec;
1362
1363}
1364
1365
1366// Assumes symbol-spaced sampling!!!
1367// Based upon paper by Al-Dhahir and Cioffi
1368bool designDFE(signalVector &channelResponse,
1369 float SNRestimate,
1370 int Nf,
1371 signalVector **feedForwardFilter,
1372 signalVector **feedbackFilter)
1373{
1374
1375 signalVector G0(Nf);
1376 signalVector G1(Nf);
1377 signalVector::iterator G0ptr = G0.begin();
1378 signalVector::iterator G1ptr = G1.begin();
1379 signalVector::iterator chanPtr = channelResponse.begin();
1380
1381 int nu = channelResponse.size()-1;
1382
1383 *G0ptr = 1.0/sqrtf(SNRestimate);
1384 for(int j = 0; j <= nu; j++) {
1385 *G1ptr = chanPtr->conj();
1386 G1ptr++; chanPtr++;
1387 }
1388
1389 signalVector *L[Nf];
1390 signalVector::iterator Lptr;
1391 float d;
1392 for(int i = 0; i < Nf; i++) {
1393 d = G0.begin()->norm2() + G1.begin()->norm2();
1394 L[i] = new signalVector(Nf+nu);
1395 Lptr = L[i]->begin()+i;
1396 G0ptr = G0.begin(); G1ptr = G1.begin();
1397 while ((G0ptr < G0.end()) && (Lptr < L[i]->end())) {
1398 *Lptr = (*G0ptr*(G0.begin()->conj()) + *G1ptr*(G1.begin()->conj()) )/d;
1399 Lptr++;
1400 G0ptr++;
1401 G1ptr++;
1402 }
1403 complex k = (*G1.begin())/(*G0.begin());
1404
1405 if (i != Nf-1) {
1406 signalVector G0new = G1;
1407 scaleVector(G0new,k.conj());
1408 addVector(G0new,G0);
1409
1410 signalVector G1new = G0;
1411 scaleVector(G1new,k*(-1.0));
1412 addVector(G1new,G1);
1413 delayVector(G1new,-1.0);
1414
1415 scaleVector(G0new,1.0/sqrtf(1.0+k.norm2()));
1416 scaleVector(G1new,1.0/sqrtf(1.0+k.norm2()));
1417 G0 = G0new;
1418 G1 = G1new;
1419 }
1420 }
1421
1422 *feedbackFilter = new signalVector(nu);
1423 L[Nf-1]->segmentCopyTo(**feedbackFilter,Nf,nu);
1424 scaleVector(**feedbackFilter,(complex) -1.0);
1425 conjugateVector(**feedbackFilter);
1426
1427 signalVector v(Nf);
1428 signalVector::iterator vStart = v.begin();
1429 signalVector::iterator vPtr;
1430 *(vStart+Nf-1) = (complex) 1.0;
1431 for(int k = Nf-2; k >= 0; k--) {
1432 Lptr = L[k]->begin()+k+1;
1433 vPtr = vStart + k+1;
1434 complex v_k = 0.0;
1435 for (int j = k+1; j < Nf; j++) {
1436 v_k -= (*vPtr)*(*Lptr);
1437 vPtr++; Lptr++;
1438 }
1439 *(vStart + k) = v_k;
1440 }
1441
1442 *feedForwardFilter = new signalVector(Nf);
1443 signalVector::iterator w = (*feedForwardFilter)->begin();
1444 for (int i = 0; i < Nf; i++) {
1445 delete L[i];
1446 complex w_i = 0.0;
1447 int endPt = ( nu < (Nf-1-i) ) ? nu : (Nf-1-i);
1448 vPtr = vStart+i;
1449 chanPtr = channelResponse.begin();
1450 for (int k = 0; k < endPt+1; k++) {
1451 w_i += (*vPtr)*(chanPtr->conj());
1452 vPtr++; chanPtr++;
1453 }
1454 *w = w_i/d;
1455 w++;
1456 }
1457
1458
1459 return true;
1460
1461}
1462
1463// Assumes symbol-rate sampling!!!!
1464SoftVector *equalizeBurst(signalVector &rxBurst,
1465 float TOA,
Thomas Tsoud24cc2c2013-08-20 15:41:45 -04001466 int sps,
dburgessb3a0ca42011-10-12 07:44:40 +00001467 signalVector &w, // feedforward filter
1468 signalVector &b) // feedback filter
1469{
1470
1471 delayVector(rxBurst,-TOA);
1472
1473 signalVector* postForwardFull = convolve(&rxBurst,&w,NULL,FULL_SPAN);
1474
1475 signalVector* postForward = new signalVector(rxBurst.size());
1476 postForwardFull->segmentCopyTo(*postForward,w.size()-1,rxBurst.size());
1477 delete postForwardFull;
1478
1479 signalVector::iterator dPtr = postForward->begin();
1480 signalVector::iterator dBackPtr;
1481 signalVector::iterator rotPtr = GMSKRotation->begin();
1482 signalVector::iterator revRotPtr = GMSKReverseRotation->begin();
1483
1484 signalVector *DFEoutput = new signalVector(postForward->size());
1485 signalVector::iterator DFEItr = DFEoutput->begin();
1486
1487 // NOTE: can insert the midamble and/or use midamble to estimate BER
1488 for (; dPtr < postForward->end(); dPtr++) {
1489 dBackPtr = dPtr-1;
1490 signalVector::iterator bPtr = b.begin();
1491 while ( (bPtr < b.end()) && (dBackPtr >= postForward->begin()) ) {
1492 *dPtr = *dPtr + (*bPtr)*(*dBackPtr);
1493 bPtr++;
1494 dBackPtr--;
1495 }
1496 *dPtr = *dPtr * (*revRotPtr);
1497 *DFEItr = *dPtr;
1498 // make decision on symbol
1499 *dPtr = (dPtr->real() > 0.0) ? 1.0 : -1.0;
1500 //*DFEItr = *dPtr;
1501 *dPtr = *dPtr * (*rotPtr);
1502 DFEItr++;
1503 rotPtr++;
1504 revRotPtr++;
1505 }
1506
1507 vectorSlicer(DFEoutput);
1508
1509 SoftVector *burstBits = new SoftVector(postForward->size());
1510 SoftVector::iterator burstItr = burstBits->begin();
1511 DFEItr = DFEoutput->begin();
1512 for (; DFEItr < DFEoutput->end(); DFEItr++)
1513 *burstItr++ = DFEItr->real();
1514
1515 delete postForward;
1516
1517 delete DFEoutput;
1518
1519 return burstBits;
1520}