// pats TODO: Send the transceiver an idle frame rather than doing it here. // There is one of these for each timeslot, ie, for ccch_group. void CCCHLogicalChannel::ccchServiceLoop() { // build the idle frame static const L3PagingRequestType1 filler; static const L3Frame idleFrame(filler,L3_UNIT_DATA); bool isCCCHCombined = gControlChannelDescription->isCCCHCombined(); // TODO: Send idle frame to transceiver. // Calculate maximum number of frames of delay. // See GSM 04.08 3.3.1.1.2 for the logic here. static const unsigned txInteger = gConfig.getNum("GSM.RACH.TxInteger"); assert(txInteger <= 15); // RACH slot definition: we see in GSM 5.02 clause 7 table 3 of 9 that a RACH can appear on timeslots 0,2,4, or 6, and in table 5 of 9 we // see that for a non-combined CCCH-CONF any of the 51 frames can be used, and for combined CCCH-CONF the available (51*4=204 slots/51-multiframe) // frames are: B4, B5, B14, B15 ... B36, B45, B46 (27*4=108 slots/51-multiframe.) // GSM 4.08 11.1.1, And I quote: "The minimum value of this timer is equal to the time taken by T+2S slots of the mobile station's // RACH. S and T are defined in sub-clause 3.3.1.2. The maximum value of this timer is 5 seconds." static const int stval = GSM::RACHSpreadSlots[txInteger] + 2*(isCCCHCombined ? GSM::RACHWaitSParamCombined[txInteger] : GSM::RACHWaitSParam[txInteger]); // Subtract some frames from the maxAge to make sure we still have time left to send it; the amount should be 4 frames // plus some time for the MS to receive and decode it plus the slack induced by the OpenBTS tranceiver interface, which we do not know. sMaxAge = min(stval, (int)(5 * 51 * 4.2)) - 6; for (int i = 0; i < 51; i++) { mRevPCH[i] = -1; // -1 means not used for paging. } mRevPCH[16] = 0; int cnt = 0; while (! gBTS.btsShutdown()) { if (! ccchServiceQueue()) { // Nothing to send on CCCH frame, so just send an idle frame. //LOG(DEBUG)<<"sending page as idleframe"; l2sendf(idleFrame); } } if (cnt); // shut up gcc. }
void CBCHLogicalChannel::l2sendm(const L3SMSCBMessage& msg) { L3Frame frame(L3_UNIT_DATA,88*8); msg.write(frame); l2sendf(frame); }
// Serialize and send an L3Message with a given primitive. // The msg is not deleted; its value is used before return. void L2LogicalChannelBase::l2sendm(const L3Message& msg, GSM::Primitive prim, SAPI_t SAPI) { //OBJLOG(INFO) << "L3" <<LOGVAR(SAPI) << " sending " << msg; WATCHINFO("l2sendm "<<this <<LOGVAR(SAPI) << " sending " << msg); l2sendf(L3Frame(msg,prim,SAPI)); }