diff options
Diffstat (limited to 'Transceiver52M/sigProcLib.cpp')
-rw-r--r-- | Transceiver52M/sigProcLib.cpp | 644 |
1 files changed, 295 insertions, 349 deletions
diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp index 2ccc714..8237aa5 100644 --- a/Transceiver52M/sigProcLib.cpp +++ b/Transceiver52M/sigProcLib.cpp @@ -29,6 +29,10 @@ using namespace GSM; +extern "C" { +#include "convolve.h" +} + #define TABLESIZE 1024 /** Lookup tables for trigonometric approximation */ @@ -45,28 +49,35 @@ signalVector *GMSKRotation = NULL; signalVector *GMSKReverseRotation = NULL; /* - * RACH and midamble correlation waveforms + * RACH and midamble correlation waveforms. Store the buffer separately + * because we need to allocate it explicitly outside of the signal vector + * constructor. This is because C++ (prior to C++11) is unable to natively + * perform 16-byte memory alignment required by many SSE instructions. */ struct CorrelationSequence { - CorrelationSequence() : sequence(NULL) + CorrelationSequence() : sequence(NULL), buffer(NULL) { } ~CorrelationSequence() { delete sequence; + free(buffer); } signalVector *sequence; + void *buffer; float TOA; complex gain; }; /* - * Gaussian and empty modulation pulses + * Gaussian and empty modulation pulses. Like the correlation sequences, + * store the runtime (Gaussian) buffer separately because of needed alignment + * for SSE instructions. */ struct PulseSequence { - PulseSequence() : gaussian(NULL), empty(NULL) + PulseSequence() : gaussian(NULL), empty(NULL), buffer(NULL) { } @@ -74,10 +85,12 @@ struct PulseSequence { { delete gaussian; delete empty; + free(buffer); } signalVector *gaussian; signalVector *empty; + void *buffer; }; CorrelationSequence *gMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; @@ -246,7 +259,7 @@ void initGMSKRotationTables(int sps) bool sigProcLibSetup(int sps) { - if ((sps != 0) && (sps != 2) && (sps != 4)) + if ((sps != 1) && (sps != 2) && (sps != 4)) return false; initTrigTables(); @@ -295,174 +308,106 @@ void GMSKReverseRotate(signalVector &x) { } } - -signalVector* convolve(const signalVector *a, - const signalVector *b, - signalVector *c, - ConvType spanType, - unsigned startIx, - unsigned len) +signalVector *convolve(const signalVector *x, + const signalVector *h, + signalVector *y, + ConvType spanType, int start, + unsigned len, unsigned step, int offset) { - if ((a==NULL) || (b==NULL)) return NULL; - int La = a->size(); - int Lb = b->size(); - - int startIndex; - unsigned int outSize; - switch (spanType) { - case FULL_SPAN: - startIndex = 0; - outSize = La+Lb-1; - break; - case OVERLAP_ONLY: - startIndex = La; - outSize = abs(La-Lb)+1; - break; - case START_ONLY: - startIndex = 0; - outSize = La; - break; - case WITH_TAIL: - startIndex = Lb; - outSize = La; - break; - case NO_DELAY: - if (Lb % 2) - startIndex = Lb/2; - else - startIndex = Lb/2-1; - outSize = La; - break; - case CUSTOM: - startIndex = startIx; - outSize = len; - break; - default: - return NULL; - } + int rc, head = 0, tail = 0; + bool alloc = false, append = false; + const signalVector *_x = NULL; - - if (c==NULL) - c = new signalVector(outSize); - else if (c->size()!=outSize) + if (!x || !h) return NULL; - signalVector::const_iterator aStart = a->begin(); - signalVector::const_iterator bStart = b->begin(); - signalVector::const_iterator aEnd = a->end(); - signalVector::const_iterator bEnd = b->end(); - signalVector::iterator cPtr = c->begin(); - int t = startIndex; - int stopIndex = startIndex + outSize; - switch (b->getSymmetry()) { - case NONE: - { - while (t < stopIndex) { - signalVector::const_iterator aP = aStart+t; - signalVector::const_iterator bP = bStart; - if (a->isRealOnly() && b->isRealOnly()) { - float sum = 0.0; - while (bP < bEnd) { - if (aP < aStart) break; - if (aP < aEnd) sum += (aP->real())*(bP->real()); - aP--; - bP++; - } - *cPtr++ = sum; - } - else if (a->isRealOnly()) { - complex sum = 0.0; - while (bP < bEnd) { - if (aP < aStart) break; - if (aP < aEnd) sum += (*bP)*(aP->real()); - aP--; - bP++; - } - *cPtr++ = sum; - } - else if (b->isRealOnly()) { - complex sum = 0.0; - while (bP < bEnd) { - if (aP < aStart) break; - if (aP < aEnd) sum += (*aP)*(bP->real()); - aP--; - bP++; - } - *cPtr++ = sum; - } - else { - complex sum = 0.0; - while (bP < bEnd) { - if (aP < aStart) break; - if (aP < aEnd) sum += (*aP)*(*bP); - aP--; - bP++; - } - *cPtr++ = sum; - } - t++; - } - } + switch (spanType) { + case START_ONLY: + start = 0; + head = h->size(); + len = x->size(); + append = true; break; - case ABSSYM: - { - complex sum = 0.0; - bool isOdd = (bool) (Lb % 2); - if (isOdd) - bEnd = bStart + (Lb+1)/2; - else - bEnd = bStart + Lb/2; - while (t < stopIndex) { - signalVector::const_iterator aP = aStart+t; - signalVector::const_iterator aPsym = aP-Lb+1; - signalVector::const_iterator bP = bStart; - sum = 0.0; - if (!b->isRealOnly()) { - while (bP < bEnd) { - if (aP < aStart) break; - if (aP == aPsym) - sum+= (*aP)*(*bP); - else if ((aP < aEnd) && (aPsym >= aStart)) - sum+= ((*aP)+(*aPsym))*(*bP); - else if (aP < aEnd) - sum += (*aP)*(*bP); - else if (aPsym >= aStart) - sum += (*aPsym)*(*bP); - aP--; - aPsym++; - bP++; - } - } - else { - while (bP < bEnd) { - if (aP < aStart) break; - if (aP == aPsym) - sum+= (*aP)*(bP->real()); - else if ((aP < aEnd) && (aPsym >= aStart)) - sum+= ((*aP)+(*aPsym))*(bP->real()); - else if (aP < aEnd) - sum += (*aP)*(bP->real()); - else if (aPsym >= aStart) - sum += (*aPsym)*(bP->real()); - aP--; - aPsym++; - bP++; - } - } - *cPtr++ = sum; - t++; - } + case NO_DELAY: + start = h->size() / 2; + head = start; + tail = start; + len = x->size(); + append = true; + break; + case CUSTOM: + if (start < h->size() - 1) { + head = h->size() - start; + append = true; + } + if (start + len > x->size()) { + tail = start + len - x->size(); + append = true; } break; default: return NULL; - break; } - - - return c; -} + /* + * Error if the output vector is too small. Create the output vector + * if the pointer is NULL. + */ + if (y && (len > y->size())) + return NULL; + if (!y) { + y = new signalVector(len); + alloc = true; + } + + /* Prepend or post-pend the input vector if the parameters require it */ + if (append) + _x = new signalVector(*x, head, tail); + else + _x = x; + + /* + * Four convovle types: + * 1. Complex-Real (aligned) + * 2. Complex-Complex (aligned) + * 3. Complex-Real (!aligned) + * 4. Complex-Complex (!aligned) + */ + if (h->isRealOnly() && h->isAligned()) { + rc = convolve_real((float *) _x->begin(), _x->size(), + (float *) h->begin(), h->size(), + (float *) y->begin(), y->size(), + start, len, step, offset); + } else if (!h->isRealOnly() && h->isAligned()) { + rc = convolve_complex((float *) _x->begin(), _x->size(), + (float *) h->begin(), h->size(), + (float *) y->begin(), y->size(), + start, len, step, offset); + } else if (h->isRealOnly() && !h->isAligned()) { + rc = base_convolve_real((float *) _x->begin(), _x->size(), + (float *) h->begin(), h->size(), + (float *) y->begin(), y->size(), + start, len, step, offset); + } else if (!h->isRealOnly() && !h->isAligned()) { + rc = base_convolve_complex((float *) _x->begin(), _x->size(), + (float *) h->begin(), h->size(), + (float *) y->begin(), y->size(), + start, len, step, offset); + } else { + rc = -1; + } + + if (append) + delete _x; + + if (rc < 0) { + if (alloc) + delete y; + return NULL; + } + + return y; +} void generateGSMPulse(int sps, int symbolLength) { @@ -477,9 +422,17 @@ void generateGSMPulse(int sps, int symbolLength) GSMPulse->empty->isRealOnly(true); *(GSMPulse->empty->begin()) = 1.0f; + len = sps * symbolLength; + if (len < 4) + len = 4; + /* GSM pulse approximation */ - GSMPulse->gaussian = new signalVector(len); + GSMPulse->buffer = convolve_h_alloc(len); + GSMPulse->gaussian = new signalVector((complex *) + GSMPulse->buffer, 0, len); + GSMPulse->gaussian->setAligned(true); GSMPulse->gaussian->isRealOnly(true); + signalVector::iterator xP = GSMPulse->gaussian->begin(); center = (float) (len - 1.0) / 2.0; @@ -560,31 +513,6 @@ signalVector* reverseConjugate(signalVector *b) return tmp; } -signalVector* correlate(signalVector *a, - signalVector *b, - signalVector *c, - ConvType spanType, - bool bReversedConjugated, - unsigned startIx, - unsigned len) -{ - signalVector *tmp = NULL; - - if (!bReversedConjugated) { - tmp = reverseConjugate(b); - } - else { - tmp = b; - } - - c = convolve(a,tmp,c,spanType,startIx,len); - - if (!bReversedConjugated) delete tmp; - - return c; -} - - /* soft output slicer */ bool vectorSlicer(signalVector *x) { @@ -599,12 +527,13 @@ bool vectorSlicer(signalVector *x) } return true; } - + +/* Assume input bits are not differentially encoded */ signalVector *modulateBurst(const BitVector &wBurst, int guardPeriodLength, int sps, bool emptyPulse) { int burstLen; - signalVector *pulse, modBurst; + signalVector *pulse, *shapedBurst, modBurst; signalVector::iterator modBurstItr; if (emptyPulse) @@ -628,7 +557,9 @@ signalVector *modulateBurst(const BitVector &wBurst, int guardPeriodLength, modBurst.isRealOnly(false); // filter w/ pulse shape - signalVector *shapedBurst = convolve(&modBurst, pulse, NULL, NO_DELAY); + shapedBurst = convolve(&modBurst, pulse, NULL, START_ONLY); + if (!shapedBurst) + return NULL; return shapedBurst; } @@ -639,24 +570,24 @@ float sinc(float x) return 1.0F; } -void delayVector(signalVector &wBurst, - float delay) +bool delayVector(signalVector &wBurst, float delay) { int intOffset = (int) floor(delay); float fracOffset = delay - intOffset; - + // do fractional shift first, only do it for reasonable offsets if (fabs(fracOffset) > 1e-2) { // create sinc function signalVector sincVector(21); sincVector.isRealOnly(true); - signalVector::iterator sincBurstItr = sincVector.begin(); + signalVector::iterator sincBurstItr = sincVector.end(); for (int i = 0; i < 21; i++) - *sincBurstItr++ = (complex) sinc(M_PI_F*(i-10-fracOffset)); + *--sincBurstItr = (complex) sinc(M_PI_F*(i-10-fracOffset)); signalVector shiftedBurst(wBurst.size()); - convolve(&wBurst,&sincVector,&shiftedBurst,NO_DELAY); + if (!convolve(&wBurst, &sincVector, &shiftedBurst, NO_DELAY)) + return false; wBurst.clone(shiftedBurst); } @@ -861,25 +792,25 @@ bool generateMidamble(int sps, int tsc) bool status = true; complex *data = NULL; signalVector *autocorr = NULL, *midamble = NULL; - signalVector *midMidamble = NULL; + signalVector *midMidamble = NULL, *_midMidamble = NULL; - if ((tsc < 0) || (tsc > 7)) + if ((tsc < 0) || (tsc > 7)) return false; delete gMidambles[tsc]; - + /* Use middle 16 bits of each TSC. Correlation sequence is not pulse shaped */ midMidamble = modulateBurst(gTrainingSequence[tsc].segment(5,16), 0, sps, true); if (!midMidamble) return false; - /* Simulated receive sequence is pulse shaped */ + /* Simulated receive sequence is pulse shaped */ midamble = modulateBurst(gTrainingSequence[tsc], 0, sps, false); if (!midamble) { status = false; goto release; } - + // NOTE: Because ideal TSC 16-bit midamble is 66 symbols into burst, // the ideal TSC has an + 180 degree phase shift, // due to the pi/2 frequency shift, that @@ -890,22 +821,32 @@ bool generateMidamble(int sps, int tsc) conjugateVector(*midMidamble); - autocorr = correlate(midamble, midMidamble, NULL, NO_DELAY); + /* For SSE alignment, reallocate the midamble sequence on 16-byte boundary */ + data = (complex *) convolve_h_alloc(midMidamble->size()); + _midMidamble = new signalVector(data, 0, midMidamble->size()); + _midMidamble->setAligned(true); + memcpy(_midMidamble->begin(), midMidamble->begin(), + midMidamble->size() * sizeof(complex)); + + autocorr = convolve(midamble, _midMidamble, NULL, NO_DELAY); if (!autocorr) { status = false; goto release; } gMidambles[tsc] = new CorrelationSequence; - gMidambles[tsc]->sequence = midMidamble; - gMidambles[tsc]->gain = peakDetect(*autocorr,&gMidambles[tsc]->TOA,NULL); + gMidambles[tsc]->buffer = data; + gMidambles[tsc]->sequence = _midMidamble; + gMidambles[tsc]->gain = peakDetect(*autocorr,&gMidambles[tsc]->TOA, NULL); release: delete autocorr; delete midamble; + delete midMidamble; if (!status) { - delete midMidamble; + delete _midMidamble; + free(data); gMidambles[tsc] = NULL; } @@ -917,7 +858,7 @@ bool generateRACHSequence(int sps) bool status = true; complex *data = NULL; signalVector *autocorr = NULL; - signalVector *seq0 = NULL, *seq1 = NULL; + signalVector *seq0 = NULL, *seq1 = NULL, *_seq1 = NULL; delete gRACHSequence; @@ -933,74 +874,100 @@ bool generateRACHSequence(int sps) conjugateVector(*seq1); - autocorr = new signalVector(seq0->size()); - if (!convolve(seq0, seq1, autocorr, NO_DELAY)) { + /* For SSE alignment, reallocate the midamble sequence on 16-byte boundary */ + data = (complex *) convolve_h_alloc(seq1->size()); + _seq1 = new signalVector(data, 0, seq1->size()); + _seq1->setAligned(true); + memcpy(_seq1->begin(), seq1->begin(), seq1->size() * sizeof(complex)); + + autocorr = convolve(seq0, _seq1, autocorr, NO_DELAY); + if (!autocorr) { status = false; goto release; } gRACHSequence = new CorrelationSequence; - gRACHSequence->sequence = seq1; - gRACHSequence->gain = peakDetect(*autocorr,&gRACHSequence->TOA,NULL); + gRACHSequence->sequence = _seq1; + gRACHSequence->buffer = data; + gRACHSequence->gain = peakDetect(*autocorr,&gRACHSequence->TOA, NULL); release: delete autocorr; delete seq0; + delete seq1; if (!status) { - delete seq1; + delete _seq1; + free(data); gRACHSequence = NULL; } return status; } - -bool detectRACHBurst(signalVector &rxBurst, - float detectThreshold, - int sps, - complex *amplitude, - float* TOA) -{ - //static complex staticData[500]; - - //signalVector correlatedRACH(staticData,0,rxBurst.size()); - signalVector correlatedRACH(rxBurst.size()); - correlate(&rxBurst,gRACHSequence->sequence,&correlatedRACH,NO_DELAY,true); +int detectRACHBurst(signalVector &rxBurst, + float thresh, + int sps, + complex *amp, + float *toa) +{ + int start, len, num = 0; + float _toa, rms, par, avg = 0.0f; + complex _amp, *peak; + signalVector corr, *sync = gRACHSequence->sequence; - float meanPower; - complex peakAmpl = peakDetect(correlatedRACH,TOA,&meanPower); + if ((sps != 1) && (sps != 2) && (sps != 4)) + return -1; - float valleyPower = 0.0; + start = 40 * sps; + len = 24 * sps; + corr = signalVector(len); - // check for bogus results - if ((*TOA < 0.0) || (*TOA > correlatedRACH.size())) { - *amplitude = 0.0; - return false; + if (!convolve(&rxBurst, sync, &corr, + CUSTOM, start, len, sps, 0)) { + return -1; } - complex *peakPtr = correlatedRACH.begin() + (int) rint(*TOA); - float numSamples = 0.0; - for (int i = 57 * sps; i <= 107 * sps; i++) { - if (peakPtr+i >= correlatedRACH.end()) - break; - valleyPower += (peakPtr+i)->norm2(); - numSamples++; - } + _amp = peakDetect(corr, &_toa, NULL); + if ((_toa < 3) || (_toa > len - 3)) + goto notfound; - if (numSamples < 2) { - *amplitude = 0.0; - return false; + peak = corr.begin() + (int) rint(_toa); + + for (int i = 2 * sps; i <= 5 * sps; i++) { + if (peak - i >= corr.begin()) { + avg += (peak - i)->norm2(); + num++; + } + if (peak + i < corr.end()) { + avg += (peak + i)->norm2(); + num++; + } } - float RMS = sqrtf(valleyPower/(float) numSamples)+0.00001; - float peakToMean = peakAmpl.abs()/RMS; + if (num < 2) + goto notfound; + + rms = sqrtf(avg / (float) num) + 0.00001; + par = _amp.abs() / rms; + if (par < thresh) + goto notfound; + + /* Subtract forward tail bits from delay */ + if (toa) + *toa = _toa - 8 * sps; + if (amp) + *amp = _amp / gRACHSequence->gain; - *amplitude = peakAmpl/(gRACHSequence->gain); + return 1; - *TOA = (*TOA) - gRACHSequence->TOA - 8 * sps; +notfound: + if (amp) + *amp = 0.0f; + if (toa) + *toa = 0.0f; - return (peakToMean > detectThreshold); + return 0; } bool energyDetect(signalVector &rxBurst, @@ -1020,120 +987,95 @@ bool energyDetect(signalVector &rxBurst, if (avgPwr) *avgPwr = energy/windowLength; return (energy/windowLength > detectThreshold*detectThreshold); } - -bool analyzeTrafficBurst(signalVector &rxBurst, - unsigned TSC, - float detectThreshold, - int sps, - complex *amplitude, - float *TOA, - unsigned maxTOA, - bool requestChannel, - signalVector **channelResponse, - float *channelResponseOffset) +int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh, + int sps, complex *amp, float *toa, unsigned max_toa, + bool chan_req, signalVector **chan, float *chan_offset) { + int start, target, len, num = 0; + complex _amp, *peak; + float _toa, rms, par, avg = 0.0f; + signalVector corr, *sync, *_chan; - assert(TSC<8); - assert(amplitude); - assert(TOA); - assert(gMidambles[TSC]); - - if (maxTOA < 3*sps) maxTOA = 3*sps; - unsigned spanTOA = maxTOA; - if (spanTOA < 5*sps) spanTOA = 5*sps; + if ((tsc < 0) || (tsc > 7) || ((sps != 1) && (sps != 2) && (sps != 4))) + return -1; - unsigned startIx = 66*sps-spanTOA; - unsigned endIx = (66+16)*sps+spanTOA; - unsigned windowLen = endIx - startIx; - unsigned corrLen = 2*maxTOA+1; + target = 3 + 58 + 5 + 16; + start = (target - 8) * sps; + len = (8 + 8 + max_toa) * sps; - unsigned expectedTOAPeak = (unsigned) round(gMidambles[TSC]->TOA + (gMidambles[TSC]->sequence->size()-1)/2); + sync = gMidambles[tsc]->sequence; + sync = gMidambles[tsc]->sequence; + corr = signalVector(len); - signalVector burstSegment(rxBurst.begin(),startIx,windowLen); - - //static complex staticData[200]; - //signalVector correlatedBurst(staticData,0,corrLen); - signalVector correlatedBurst(corrLen); - correlate(&burstSegment, gMidambles[TSC]->sequence, - &correlatedBurst, CUSTOM,true, - expectedTOAPeak-maxTOA,corrLen); + if (!convolve(&rxBurst, sync, &corr, + CUSTOM, start, len, sps, 0)) { + return -1; + } - float meanPower; - *amplitude = peakDetect(correlatedBurst,TOA,&meanPower); - float valleyPower = 0.0; //amplitude->norm2(); - complex *peakPtr = correlatedBurst.begin() + (int) rint(*TOA); + _amp = peakDetect(corr, &_toa, NULL); + peak = corr.begin() + (int) rint(_toa); - // check for bogus results - if ((*TOA < 0.0) || (*TOA > correlatedBurst.size())) { - *amplitude = 0.0; - return false; - } + /* Check for bogus results */ + if ((_toa < 0.0) || (_toa > corr.size())) + goto notfound; - int numRms = 0; - for (int i = 2*sps; i <= 5*sps;i++) { - if (peakPtr - i >= correlatedBurst.begin()) { - valleyPower += (peakPtr-i)->norm2(); - numRms++; + for (int i = 2 * sps; i <= 5 * sps; i++) { + if (peak - i >= corr.begin()) { + avg += (peak - i)->norm2(); + num++; } - if (peakPtr + i < correlatedBurst.end()) { - valleyPower += (peakPtr+i)->norm2(); - numRms++; + if (peak + i < corr.end()) { + avg += (peak + i)->norm2(); + num++; } } - if (numRms < 2) { - // check for bogus results - *amplitude = 0.0; - return false; - } + if (num < 2) + goto notfound; - float RMS = sqrtf(valleyPower/(float)numRms)+0.00001; - float peakToMean = (amplitude->abs())/RMS; + rms = sqrtf(avg / (float) num) + 0.00001; + par = (_amp.abs()) / rms; + if (par < thresh) + goto notfound; - // NOTE: Because ideal TSC is 66 symbols into burst, - // the ideal TSC has an +/- 180 degree phase shift, - // due to the pi/4 frequency shift, that - // needs to be accounted for. - - *amplitude = (*amplitude)/gMidambles[TSC]->gain; - *TOA = (*TOA) - (maxTOA); - - if (requestChannel && (peakToMean > detectThreshold)) { - float TOAoffset = maxTOA; - delayVector(correlatedBurst,-(*TOA)); - // midamble only allows estimation of a 6-tap channel - signalVector chanVector(6 * sps); - float maxEnergy = -1.0; - int maxI = -1; - for (int i = 0; i < 7; i++) { - if (TOAoffset + (i-5) * sps + chanVector.size() > correlatedBurst.size()) - continue; - if (TOAoffset + (i-5) * sps < 0) - continue; - correlatedBurst.segmentCopyTo(chanVector, - (int) floor(TOAoffset + (i - 5) * sps), - chanVector.size()); - float energy = vectorNorm2(chanVector); - if (energy > 0.95*maxEnergy) { - maxI = i; - maxEnergy = energy; - } - } - - *channelResponse = new signalVector(chanVector.size()); - correlatedBurst.segmentCopyTo(**channelResponse, - (int) floor(TOAoffset + (maxI - 5) * sps), - (*channelResponse)->size()); - scaleVector(**channelResponse, complex(1.0, 0.0) / gMidambles[TSC]->gain); - - if (channelResponseOffset) - *channelResponseOffset = 5 * sps - maxI; - + /* + * NOTE: Because ideal TSC is 66 symbols into burst, + * the ideal TSC has an +/- 180 degree phase shift, + * due to the pi/4 frequency shift, that + * needs to be accounted for. + */ + if (amp) + *amp = _amp / gMidambles[tsc]->gain; + + /* Delay one half of peak-centred correlation length */ + _toa -= sps * 8; + + if (toa) + *toa = _toa; + + if (chan_req) { + _chan = new signalVector(6 * sps); + + delayVector(corr, -_toa); + corr.segmentCopyTo(*_chan, target - 3, _chan->size()); + scaleVector(*_chan, complex(1.0, 0.0) / gMidambles[tsc]->gain); + + *chan = _chan; + + if (chan_offset) + *chan_offset = 3.0 * sps;; } - return (peakToMean > detectThreshold); - + return 1; + +notfound: + if (amp) + *amp = 0.0f; + if (toa) + *toa = 0.0f; + + return 0; } signalVector *decimateVector(signalVector &wVector, @@ -1452,7 +1394,7 @@ bool designDFE(signalVector &channelResponse, } *feedForwardFilter = new signalVector(Nf); - signalVector::iterator w = (*feedForwardFilter)->begin(); + signalVector::iterator w = (*feedForwardFilter)->end(); for (int i = 0; i < Nf; i++) { delete L[i]; complex w_i = 0.0; @@ -1463,8 +1405,7 @@ bool designDFE(signalVector &channelResponse, w_i += (*vPtr)*(chanPtr->conj()); vPtr++; chanPtr++; } - *w = w_i/d; - w++; + *--w = w_i/d; } @@ -1479,10 +1420,15 @@ SoftVector *equalizeBurst(signalVector &rxBurst, signalVector &w, // feedforward filter signalVector &b) // feedback filter { + signalVector *postForwardFull; - delayVector(rxBurst,-TOA); + if (!delayVector(rxBurst, -TOA)) + return NULL; - signalVector* postForwardFull = convolve(&rxBurst,&w,NULL,FULL_SPAN); + postForwardFull = convolve(&rxBurst, &w, NULL, + CUSTOM, 0, rxBurst.size() + w.size() - 1); + if (!postForwardFull) + return NULL; signalVector* postForward = new signalVector(rxBurst.size()); postForwardFull->segmentCopyTo(*postForward,w.size()-1,rxBurst.size()); |