Example #1
0
void rateMatchFunc(BitVector &in,BitVector &out, int eini)
{
	int nin = in.size();
	int nout = out.size();
	if (nout == nin) {
		in.copyTo(out);
		return;
	}
	int eplus = 2 * nin;				// eplus = a * Ni,j
	int eminus = 2 * (nout - nin);	// eminus = a * abs(deltaNi,j)
	if (eminus < 0) { eminus = - eminus; }
	float e = eini;
	int m; // index of current bit, except zero-based as opposed to spec that is 1 based.
	char *inp = in.begin();		// cheating just a bit for efficiency.
	char *outp = out.begin();
	char *outend = out.end();
	if (nout < nin) {
		// Puncture bits as necessary.
		// Note from spec: loop termination Xi == Xij == number of bits before rate matching == nin.
		for (m=0; m < nin && outp < outend; m++) {
			e = e - eminus;
			if (e <= 0) {
				e = e + eplus;
				continue;		// skip the bit.
			}
			*outp++ = inp[m];
		}
	} else {
		// Repeat bits as necessary.
		for (m=0; m < nin && outp < outend; m++) {
			e = e - eminus;
			while (e <= 0) {
				if (outp >= outend) goto failed;
				*outp++ = inp[m];	// repeat the bit.
				e = e + eplus;
			}
			*outp++ = inp[m];
		}
	}
	if (m != nin || outp != outend) {
		failed:
		LOG(ERR) << "rate matching mis-calculation, results:"
			<<LOGVAR(nin)<<LOGVAR(m)<<LOGVAR(nout)<<LOGVAR2(outp,outp-out.begin())
			<<LOGVAR(e)<<LOGVAR(eplus)<<LOGVAR(eminus)<<LOGVAR(eini);
	}
}
Example #2
0
void TCHFACCHL1Encoder::dispatch()
{

	// No downstream?  That's a problem.
	assert(mDownstream);

	// Get right with the system clock.
	resync();

	// If the channel is not active, wait for a multiframe and return.
	// Most channels do not need this, becuase they are entirely data-driven
	// from above.  TCH/FACCH, however, must feed the interleaver on time.
	if (!active()) {
		mNextWriteTime += 26;
		gBTS.clock().wait(mNextWriteTime);
		return;
	}

	// Let previous data get transmitted.
	resync();
	waitToSend();

	// flag to control stealing bits
	bool currentFACCH = false;

	// Speech latency control.
	// Since Asterisk is local, latency should be small.
	OBJLOG(DEBUG) <<"TCHFACCHL1Encoder speechQ.size=" << mSpeechQ.size();
	int maxQ = gConfig.getNum("GSM.MaxSpeechLatency");
	while (mSpeechQ.size() > maxQ) delete mSpeechQ.read();

	// Send, by priority: (1) FACCH, (2) TCH, (3) filler.
	if (L2Frame *fFrame = mL2Q.readNoBlock()) {
		OBJLOG(DEEPDEBUG) <<"TCHFACCHL1Encoder FACCH " << *fFrame;
		currentFACCH = true;
		// Copy the L2 frame into u[] for processing.
		// GSM 05.03 4.1.1.
		fFrame->LSB8MSB();
		fFrame->copyTo(mU);
		// Encode u[] to c[], GSM 05.03 4.1.2 and 4.1.3.
		encode();
		delete fFrame;
		OBJLOG(DEEPDEBUG) <<"TCHFACCHL1Encoder FACCH c[]=" << mC;
		// Flush the vocoder FIFO to limit latency.
		while (mSpeechQ.size()>0) delete mSpeechQ.read();
	} else if (VocoderFrame *tFrame = mSpeechQ.readNoBlock()) {
		OBJLOG(DEEPDEBUG) <<"TCHFACCHL1Encoder TCH " << *tFrame;
		// Encode the speech frame into c[] as per GSM 05.03 3.1.2.
		encodeTCH(*tFrame);
		delete tFrame;
		OBJLOG(DEEPDEBUG) <<"TCHFACCHL1Encoder TCH c[]=" << mC;
	} else {
		// We have no ready data but must send SOMETHING.
		// This filler pattern was captured from a Nokia 3310, BTW.
		static const BitVector fillerC("110100001000111100000000111001111101011100111101001111000000000000110111101111111110100110101010101010101010101010101010101010101010010000110000000000000000000000000000000000000000001101001111000000000000000000000000000000000000000000000000111010011010101010101010101010101010101010101010101001000011000000000000000000110100111100000000111001111101101000001100001101001111000000000000000000011001100000000000000000000000000000000000000000000000000000000001");
		fillerC.copyTo(mC);
		OBJLOG(DEEPDEBUG) <<"TCHFACCHL1Encoder filler FACCH=" << currentFACCH << " c[]=" << mC;
	}

	// Interleave c[] to i[].
	LOG(INFO)<<"TCH START INTERLEAVE";
	interleave(mOffset);
	LOG(INFO)<<"TCH START ENCRYPT";
	encrypt();
	LOG(INFO)<<"TCH START ENCRYPTed";
	// "mapping on a burst"
	// Map c[] into outgoing normal bursts, marking stealing flags as needed.
	// GMS 05.03 3.1.4.
//////////////////////////////////////////////////////////////////////////////////////////////////
/*for (int B=0; B<4; B++) {
		// set TDMA position
		mBurst.time(mNextWriteTime);
		// copy in the bits
		mI[B+mOffset].segment(0,57).copyToSegment(mBurst,3);
		mI[B+mOffset].segment(57,57).copyToSegment(mBurst,88);
		// stealing bits
		mBurst.Hu(currentFACCH);
		mBurst.Hl(mPreviousFACCH);
		// send
		OBJLOG(DEEPDEBUG) <<"TCHFACCHEncoder sending burst=" << mBurst;
		mDownstream->writeHighSide(mBurst);
		rollForward();
	}	
*/

	for (int B=0; B<8; B++) {
		// set TDMA position
		mBurst.time(mNextWriteTime);
		// copy in the bits
		
		mE[B].segment(0,57).copyToSegment(mBurst,3);
		mE[B].segment(57,57).copyToSegment(mBurst,88);
		LOG(INFO) <<"TCHFACCHL1Decoder  COPYTOSEGMENT";
		// stealing bits
		mBurst.Hu(currentFACCH);
		mBurst.Hl(mPreviousFACCH);
		// send
		OBJLOG(DEEPDEBUG) <<"TCHFACCHEncoder sending burst=" << mBurst;
		mDownstream->writeHighSide(mBurst);
		rollForward();
	}

	// Updaet the offset for the next transmission.
	if (mOffset==0) mOffset=4;
	else mOffset=0;

	// Save the stealing flag.
	mPreviousFACCH = currentFACCH;
}