// Assumes symbol-rate sampling!!!! SoftVector *equalizeBurst(signalVector &rxBurst, float TOA, int samplesPerSymbol, signalVector &w, // feedforward filter signalVector &b) // feedback filter { delayVector(rxBurst,-TOA); signalVector* postForwardFull = convolve(&rxBurst,&w,NULL,FULL_SPAN); signalVector* postForward = new signalVector(rxBurst.size()); postForwardFull->segmentCopyTo(*postForward,w.size()-1,rxBurst.size()); delete postForwardFull; signalVector::iterator dPtr = postForward->begin(); signalVector::iterator dBackPtr; signalVector::iterator rotPtr = GMSKRotation->begin(); signalVector::iterator revRotPtr = GMSKReverseRotation->begin(); signalVector *DFEoutput = new signalVector(postForward->size()); signalVector::iterator DFEItr = DFEoutput->begin(); // NOTE: can insert the midamble and/or use midamble to estimate BER for (; dPtr < postForward->end(); dPtr++) { dBackPtr = dPtr-1; signalVector::iterator bPtr = b.begin(); while ( (bPtr < b.end()) && (dBackPtr >= postForward->begin()) ) { *dPtr = *dPtr + (*bPtr)*(*dBackPtr); bPtr++; dBackPtr--; } *dPtr = *dPtr * (*revRotPtr); *DFEItr = *dPtr; // make decision on symbol *dPtr = (dPtr->real() > 0.0) ? 1.0 : -1.0; //*DFEItr = *dPtr; *dPtr = *dPtr * (*rotPtr); DFEItr++; rotPtr++; revRotPtr++; } vectorSlicer(DFEoutput); SoftVector *burstBits = new SoftVector(postForward->size()); SoftVector::iterator burstItr = burstBits->begin(); DFEItr = DFEoutput->begin(); for (; DFEItr < DFEoutput->end(); DFEItr++) *burstItr++ = DFEItr->real(); delete postForward; delete DFEoutput; return burstBits; }
SoftVector *demodulateBurst(signalVector &rxBurst, const signalVector &gsmPulse, int samplesPerSymbol, complex channel, float TOA) { scaleVector(rxBurst,((complex) 1.0)/channel); delayVector(rxBurst,-TOA); signalVector *shapedBurst = &rxBurst; // shift up by a quarter of a frequency // ignore starting phase, since spec allows for discontinuous phase GMSKReverseRotate(*shapedBurst); // run through slicer if (samplesPerSymbol > 1) { signalVector *decShapedBurst = decimateVector(*shapedBurst,samplesPerSymbol); shapedBurst = decShapedBurst; } LOG(DEEPDEBUG) << "shapedBurst: " << *shapedBurst; vectorSlicer(shapedBurst); SoftVector *burstBits = new SoftVector(shapedBurst->size()); SoftVector::iterator burstItr = burstBits->begin(); signalVector::iterator shapedItr = shapedBurst->begin(); for (; shapedItr < shapedBurst->end(); shapedItr++) *burstItr++ = shapedItr->real(); if (samplesPerSymbol > 1) delete shapedBurst; return burstBits; }
void ViterbiTCH_AFS7_4::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS7_4 &decoder = *this; const size_t sz = in.size() - 12; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i<sz; i++) { accum = (accum<<1) | bits.bit(i); history[i] = accum; } // Repeat last bit at the end. for (size_t i=sz; i<ctsz; i++) { accum = (accum<<1) | (accum & 0x01); history[i] = accum; } } // Precompute metric tables. float matchCostTable[ctsz]; float mismatchCostTable[ctsz]; { const float *dp = in.begin(); for (size_t i=0; i<sz; i++) { // pVal is the probability that a bit is correct. // ipVal is the probability that a bit is incorrect. float pVal = dp[i]; if (pVal>0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i<ctsz; i++) { matchCostTable[i] = 0.5F; mismatchCostTable[i] = 0.5F; } } { decoder.initializeStates(); // Each sample of history[] carries its history. // So we only have to process every iRate-th sample. const unsigned step = decoder.iRate(); // input pointer const uint32_t *ip = history + step - 1; // output pointers char *op = target.begin(); const char *const opt = target.end(); // table pointers const float* match = matchCostTable; const float* mismatch = mismatchCostTable; size_t oCount = 0; while (op<opt) { // Viterbi algorithm assert(match-matchCostTable<(int)(sizeof(matchCostTable)/sizeof(matchCostTable[0])-1)); assert(mismatch-mismatchCostTable<(int)(sizeof(mismatchCostTable)/sizeof(mismatchCostTable[0])-1)); const ViterbiTCH_AFS7_4::vCand &minCost = decoder.step(*ip, match, mismatch); ip += step; match += step; mismatch += step; // output if (oCount>=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } }