// 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; }
// 1 is perfect and 0 means all the bits were 0.5 static float getEnergy(const SoftVector &vec,float &low) { int len = vec.size(); avg = 0; low = 1; for (int i = 0; i < len; i++) { float bit = vec[i]; float energy = 2*((bit < 0.5) ? (0.5-bit) : (bit-0.5)); if (energy < low) low = energy; avg += energy/len; } }
void RACHL1Decoder::writeLowSide(const RxBurst& burst) { // The L1 FEC for the RACH is defined in GSM 05.03 4.6. // Decode the burst. const SoftVector e(burst.segment(49,36)); e.decode(mVCoder,mU); // To check validity, we have 4 tail bits and 6 parity bits. // False alarm rate for random inputs is 1/1024. // Check the tail bits -- should all the zero. if (mU.peekField(14,4)) { countBadFrame(); return; } // Check the parity. // The parity word is XOR'd with the BSIC. (GSM 05.03 4.6.) unsigned sentParity = ~mU.peekField(8,6); unsigned checkParity = mD.parity(mParity); unsigned encodedBSIC = (sentParity ^ checkParity) & 0x03f; if (encodedBSIC != gBTS.BSIC()) { countBadFrame(); return; } // We got a valid RACH burst. // The "payload" is an 8-bit field, "RA", defined in GSM 04.08 9.1.8. // The channel assignment procedure is in GSM 04.08 3.3.1.1.3. // It requires knowledge of the RA value and the burst receive time. // The RACH L2 is so thin that we don't even need code for it. // Just pass the required information directly to the control layer. countGoodFrame(); mD.LSB8MSB(); unsigned RA = mD.peekField(0,8); OBJLOG(INFO) <<"RACHL1Decoder received RA=" << RA << " at time " << burst.time() << " with RSSI=" << burst.RSSI() << " timingError=" << burst.timingError(); Control::AccessGrantResponder(RA,burst.time(),burst.RSSI(),burst.timingError()); }
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; }
// Do the reverse encoding on usf, and return the reversed usf, // ie, the returned usf is byte-swapped. static int decodeUSF(SoftVector &mC) { // TODO: Make this more robust. // Update: No dont bother, should always be zero anyway. return (mC.bit(0)<<2) | (mC.bit(6)<<1) | mC.bit(4); }
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++; } } }