Esempio n. 1
0
bool RadioInterface::driveReceiveRadio()
{
  radioVector *burst = NULL;

  if (!mOn)
    return false;

  pullBuffer();

  GSM::Time rcvClock = mClock.get();
  rcvClock.decTN(receiveOffset);
  unsigned tN = rcvClock.TN();
  int recvSz = recvBuffer[0]->getAvailSamples();
  const int symbolsPerSlot = gSlotLen + 8;
  int burstSize;

  if (mSPSRx == 4)
    burstSize = 625;
  else
    burstSize = symbolsPerSlot + (tN % 4 == 0);

  /* 
   * Pre-allocate head room for the largest correlation size
   * so we can later avoid a re-allocation and copy
   * */
  size_t head = GSM::gRACHSynchSequence.size();

  /*
   * Form receive bursts and pass up to transceiver. Use repeating
   * pattern of 157-156-156-156 symbols per timeslot
   */
  while (recvSz > burstSize) {
    for (size_t i = 0; i < mChans; i++) {
      burst = new radioVector(rcvClock, burstSize, head, mMIMO);

      for (size_t n = 0; n < mMIMO; n++)
        unRadioifyVector(burst->getVector(n), i);

      if (mReceiveFIFO[i].size() < 32)
        mReceiveFIFO[i].write(burst);
      else
        delete burst;
    }

    mClock.incTN();
    rcvClock.incTN();
    recvSz -= burstSize;

    tN = rcvClock.TN();

    if (mSPSRx != 4)
      burstSize = (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx;
  }

  return true;
}
Esempio n. 2
0
double Clock::systime(const GSM::Time& when) const
{
	ScopedLock lock(mLock);
	const double slotMicroseconds = (48.0 / 13e6) * 156.25;
	const double frameMicroseconds = slotMicroseconds * 8.0;
	int32_t elapsedFrames = when.FN() - mBaseFN;
	if (elapsedFrames<0) elapsedFrames += gHyperframe;
	double elapsedUSec = elapsedFrames * frameMicroseconds + when.TN() * slotMicroseconds;
	double baseSeconds = mBaseTime.sec() + mBaseTime.usec()*1e-6;
	double st = baseSeconds + 1e-6*elapsedUSec;
	return st;
}
Esempio n. 3
0
// (pat) BUG TODO: TO WHOM IT MAY CONCERN:
// I am not sure this routine works properly.  If there is no CCCH message (an L3Frame)
// in the queue immediately after the previous frame is sent, an idle frame is inserted.
// If a subsequent valid CCCH message (paging response or MS initiated RR call or packet
// uplink request) arrives it will be blocked until the idle frame is sent.
// Probably doesnt matter for RR establishment, but for packets, the extra 1/4 sec
// delay (length of a 51-multiframe) is going to hurt.
// Note that a GPRS Immediate Assignment message must know when this CCCH gets sent.
// Right now, it has to guess.
// pats TODO: Send the transceiver an idle frame rather than doing it here.
// This should be architecturally changed to a pull-system instead of push.
// Among other things, that would let us prioritize the responses
// (eg, emergency calls go first) and let the packet Immediate Assignment message be
// created right before being sent, when we are certain when the
// Immediate Assignment is being sent.
void CCCHLogicalChannel::serviceLoop()
{
	// build the idle frame
	static const L3PagingRequestType1 filler;
	static const L3Frame idleFrame(filler,UNIT_DATA);
#if ENABLE_PAGING_CHANNELS
	L3ControlChannelDescription mCC;
	unsigned bs_pa_mfrms = mCC.getBS_PA_MFRMS();
#endif
	// prime the first idle frame
	LogicalChannel::send(idleFrame);
	// run the loop
	while (true) {
		L3Frame* frame = NULL;
#if ENABLE_PAGING_CHANNELS
		// Check for paging message for this specific paging slot first,
		// and if none, send any message in the mQ.
		// The multiframe paging logic is from GSM 05.02 6.5.3.
		// See documentation at crackPagingFromImsi() which is used to
		// get the messages into the proper mPagingQ.
		GSM::Time next = getNextWriteTime();
		unsigned multiframe_index = (next.FN() / 51) % bs_pa_mfrms;
		frame = mPagingQ[multiframe_index].read();
#endif
		if (frame == NULL) {
			frame = mQ.read();	// (pat) This is a blocking read; mQ is an InterThreadQueue
		}
		if (frame) {
			// (pat) This tortuously calls XCCCHL1Encoder::transmit (see my documentation
			// at LogicalChannel::send), which blocks until L1Encoder::mPrevWriteTime.
			// Note: The q size is 0 while we are blocked here, so if we are trying
			// to determine the next write time by adding the qsize, we are way off.
			// Thats why there is an mWaitingToSend flag.
			mWaitingToSend = true;	// Waiting to send this block at mNextWriteTime.
			LogicalChannel::send(*frame);
			mWaitingToSend = false;
			OBJLOG(DEBUG) << "CCCHLogicalChannel::serviceLoop sending " << *frame
				<< " load: " << load() << " time: " << getNextWriteTime();
			delete frame;
		}
		if (mQ.size()==0) {
			// (pat) The radio continues to send the last frame forever,
			// so we only send one idle frame here.
			// Unfortunately, this slows the response.
			// TODO: Send a static idle frame to the Transciever and rewrite this.
			mWaitingToSend = true;	// Waiting to send an idle frame at mNextWriteTime.
			LogicalChannel::send(idleFrame);
			mWaitingToSend = false;
			OBJLOG(DEBUG) << "CCCHLogicalChannel::serviceLoop sending idle frame";
		}
	}
}
Esempio n. 4
0
bool CCCHLogicalChannel::sendGprsCcchMessage(NewPagingEntry *gprsMsg, GSM::Time &frameTime)
{
    if (! gprsPageCcchSetTime(gprsMsg->mGprsClient,gprsMsg->mImmAssign,frameTime.FN())) {
        return false;
    }
    L2LogicalChannelBase::l2sendm(*(gprsMsg->mImmAssign),L3_UNIT_DATA);
    return true;
}
// (pat) This routine is going to be entirely replaced with one that works better for gprs.
// In the meantime, just return a number that is large enough to cover
// the worst case, which assumes that the messages in mQ also
// must go out on the paging timeslot.
Time GSM::CCCHLogicalChannel::getNextPchSendTime(unsigned multiframe_index)
{
	L3ControlChannelDescription mCC;
	// Paging is distributed over this many multi-frames.
	unsigned bs_pa_mfrms = mCC.getBS_PA_MFRMS();

	GSM::Time next = getNextWriteTime();
	unsigned next_multiframe_index = (next.FN() / 51) % bs_pa_mfrms;
	assert(bs_pa_mfrms > 1);
	assert(multiframe_index < bs_pa_mfrms);
	assert(next_multiframe_index < bs_pa_mfrms);
	int achload = mQ.size();
	if (mWaitingToSend) { achload++; }

	// Total wait time is time needed to empty queue, plus the time until the first
	// paging opportunity, plus 2 times the number of guys waiting in the paging queue,
	// but it is all nonsense because if a new agch comes in,
	// it will displace the paging message because the q is sent first.
	// This just needs to be totally redone, and the best way is not to figure out
	// when the message will be sent at all, but rather use a call-back to gprs
	// just before the message is finally sent.
	int multiframesToWait = 0;
	if (achload) {
		multiframesToWait = bs_pa_mfrms - 1;	// Assume worst case.
	} else {
		// If there is nothing else waiting, we can estimate better:
		while (next_multiframe_index != multiframe_index) {
			multiframe_index = (multiframe_index+1) % bs_pa_mfrms;
			multiframesToWait++;
		}
	}
	int total = achload + multiframesToWait + bs_pa_mfrms * mPagingQ[multiframe_index].size();

	int fnresult = (next.FN() + total * 51) % gHyperframe;
	GSM::Time result(fnresult);
	LOG(DEBUG) << "CCCHLogicalChannel::getNextSend="<< next.FN()
		<<" load="<<achload<<LOGVAR(mWaitingToSend) <<" now="<<gBTS.time().FN()<<LOGVAR(fnresult);
	return result;
}
Time GSM::CCCHLogicalChannel::getNextMsgSendTime() {
	// Get the current frame.
	// DAB GPRS - This should call L1->resync() first, otherwise, in an idle system,
	// DAB GPRS - you can get times well into the past..
	// (pat) Above is done in the underlying getNextWriteTime()
	// Pats note: This may return the current frame number if it is ready to send now.
	// 3-18-2012: FIXME: This result is not monotonically increasing!!
	// That is screwing up GPRS sendAssignment.
	GSM::Time next = getNextWriteTime();
	int achload = load();
	if (mWaitingToSend) { achload++; }
	//old: GSM::Time result = next + (achload+3) * 51;	// add one to be safe.

	// (pat) TODO: We are adding a whole 51-multframe for each additional
	// CCCH message, which may not be correct.
	// Note: We dont need to carefully make sure the frame
	// numbers are valid (eg, by rollForward), because this code is used by GPRS
	// which is going to convert it to an RLC block time anyway.
	int fnresult = (next.FN() + achload * 51) % gHyperframe;
	GSM::Time result(fnresult);
	LOG(DEBUG) << "CCCHLogicalChannel::getNextSend="<< next.FN()
		<<" load="<<achload<<LOGVAR(mWaitingToSend) <<" now="<<gBTS.time().FN()<<LOGVAR(fnresult);
	return result;
}
Esempio n. 7
0
void RadioInterface::driveReceiveRadio() {

  if (!mOn) return;

  if (mReceiveFIFO.size() > 8) return;

  pullBuffer();

  GSM::Time rcvClock = mClock.get();
  rcvClock.decTN(receiveOffset);
  unsigned tN = rcvClock.TN();
  int rcvSz = rcvCursor/2;
  int readSz = 0;
  const int symbolsPerSlot = gSlotLen + 8;

  // while there's enough data in receive buffer, form received 
  //    GSM bursts and pass up to Transceiver
  // Using the 157-156-156-156 symbols per timeslot format.
  while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
    signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
    unRadioifyVector(rcvBuffer+readSz*2,rxVector);

    GSM::Time tmpTime = rcvClock;
    if (rcvClock.FN() >= 0) {
      //LOG(DEBUG) << "FN: " << rcvClock.FN();
      int dummyARFCN = 0;
      radioVector *rxBurst = NULL;
      if (!loadTest)
        rxBurst = new radioVector(rxVector,tmpTime,dummyARFCN);
      else {
	if (tN % 4 == 0)
	  rxBurst = new radioVector(*finalVec9,tmpTime,dummyARFCN);
        else
          rxBurst = new radioVector(*finalVec,tmpTime,dummyARFCN); 
      }
      mReceiveFIFO.put(rxBurst); 
    }
    mClock.incTN(); 
    rcvClock.incTN();
    //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
    //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
    readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
    rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;


    tN = rcvClock.TN();
  }

  if (readSz > 0) { 
    memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor/2-readSz));
    rcvCursor = rcvCursor-2*readSz;
  }
} 
Esempio n. 8
0
void RadioInterface::driveReceiveRadio() {
  pullBuffer();

  if (!rcvBuffer) {
    return;}

  GSM::Time rcvClock = mClock.get();
  rcvClock.decTN(receiveOffset);
  unsigned tN = rcvClock.TN();
  int rcvSz = rcvBuffer->size();
  int readSz = 0;
  const int symbolsPerSlot = gSlotLen + 8;

  // while there's enough data in receive buffer, form received 
  //    GSM bursts and pass up to Transceiver
  // Using the 157-156-156-156 symbols per timeslot format.
  while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
    signalVector rxVector(rcvBuffer->begin(),
			  readSz,
			  (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
    GSM::Time tmpTime = rcvClock;
    if (rcvClock.FN() >= 0) {
      LOG(DEEPDEBUG) << "FN: " << rcvClock.FN();
      radioVector* rxBurst = new radioVector(rxVector,tmpTime);
      mReceiveFIFO.write(rxBurst);
    }
    mClock.incTN(); 
    rcvClock.incTN();
    if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);

    LOG(DEEPDEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
    readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
    rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;

    tN = rcvClock.TN();
  }
  
  signalVector *tmp = new signalVector(rcvBuffer->size()-readSz);
  rcvBuffer->segmentCopyTo(*tmp,readSz,tmp->size());
  delete rcvBuffer;
  rcvBuffer = tmp;

} 
Esempio n. 9
0
bool RadioInterface::driveReceiveRadio()
{
  radioVector *burst = NULL;

  if (!mOn)
    return false;

  pullBuffer();

  GSM::Time rcvClock = mClock.get();
  rcvClock.decTN(receiveOffset);
  unsigned tN = rcvClock.TN();
  int recvSz = recvCursor;
  int readSz = 0;
  const int symbolsPerSlot = gSlotLen + 8;
  int burstSize = (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx;

  /* 
   * Pre-allocate head room for the largest correlation size
   * so we can later avoid a re-allocation and copy
   * */
  size_t head = GSM::gRACHSynchSequence.size();

  /*
   * Form receive bursts and pass up to transceiver. Use repeating
   * pattern of 157-156-156-156 symbols per timeslot
   */
  while (recvSz > burstSize) {
    for (size_t i = 0; i < mChans; i++) {
      burst = new radioVector(rcvClock, burstSize, head, mMIMO);

      for (size_t n = 0; n < mMIMO; n++) {
        unRadioifyVector((float *)
                         (recvBuffer[mMIMO * i + n]->begin() + readSz),
                         *burst->getVector(n));
      }

      if (mReceiveFIFO[i].size() < 32)
        mReceiveFIFO[i].write(burst);
      else
        delete burst;
    }

    mClock.incTN();
    rcvClock.incTN();
    readSz += burstSize;
    recvSz -= burstSize;

    tN = rcvClock.TN();

    burstSize = (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx;
  }

  if (readSz > 0) {
    for (size_t i = 0; i < recvBuffer.size(); i++) {
      memmove(recvBuffer[i]->begin(),
              recvBuffer[i]->begin() + readSz,
              (recvCursor - readSz) * 2 * sizeof(float));
    }

    recvCursor -= readSz;
  }

  return true;
}