TCHFACCHLogicalChannel *GSMConfig::getTCH() { mLock.lock(); TCHFACCHLogicalChannel *chan = getChan<TCHFACCHLogicalChannel>(mTCHPool); if (chan) chan->open(); mLock.unlock(); return chan; }
void GSMConfig::createCombinationI(TransceiverManager& TRX, unsigned CN, unsigned TN) { LOG_ASSERT((CN!=0)||(TN!=0)); LOG(NOTICE) << "Configuring combination I on C" << CN << "T" << TN; ARFCNManager *radio = TRX.ARFCN(CN); radio->setSlot(TN,1); // (pat) 1 => Transciever.h enum ChannelCombination = I TCHFACCHLogicalChannel* chan = new TCHFACCHLogicalChannel(CN,TN,gTCHF_T[TN]); chan->downstream(radio); Thread* thread = new Thread; thread->start((void*(*)(void*))Control::DCCHDispatcher,chan); chan->open(); gBTS.addTCH(chan); }
// (pat) By a very tortuous path, chan->open() calls L1Encoder::open() and L1Decoder::open(), // which sets mActive in both and resets the timers. TCHFACCHLogicalChannel *GSMConfig::getTCH( bool forGPRS, // If true, allocate the channel to gprs, else to RR use. bool onlyCN0) // If true, allocate only channels on the lowest ARFCN. { LOG(DEBUG); ScopedLock lock(mLock); //if (GPRS::GPRSDebug) { // const unsigned sz = mTCHPool.size(); // char buf[300]; int n = 0; // for (unsigned i=0; i<sz; i++) { // TCHFACCHLogicalChannel *chan = mTCHPool[i]; // n += sprintf(&buf[n],"ch=%d:%d,g=%d,r=%d ",chan->CN(),chan->TN(), // chan->inUseByGPRS(),chan->recyclable()); // } // LOG(WARNING)<<"getTCH list:"<<buf; //} TCHFACCHLogicalChannel *chan = getChan<TCHFACCHLogicalChannel>(mTCHPool,forGPRS); // (pat) We have to open it or set gprs mode before returning to avoid a race. if (chan) { // The channels are searched in order from low to high, so if the first channel // found is not on CN0, we have failed. //LOG(DEBUG)<<"getTCH returns"<<LOGVAR2("chan->CN",chan->CN()); if (onlyCN0 && chan->CN()) { return NULL; } if (forGPRS) { // (pat) Reserves channel for GPRS, but does not start delivering bursts yet. chan->debugGetL1()->setGPRS(true,NULL); return chan; } chan->open(); // (pat) LogicalChannel::open(); Opens mSACCH also. gReports.incr("OpenBTS.GSM.RR.ChannelAssignment"); } else { //LOG(DEBUG)<<"getTCH returns NULL"; } LOG(DEBUG); return chan; }
int main(int argc, char *argv[]) { srandom(time(NULL)); COUT("\n\n" << gOpenBTSWelcome << "\n"); COUT("\nStarting the system..."); gSetLogLevel(gConfig.getStr("LogLevel")); if (gConfig.defines("LogFileName")) { gSetLogFile(gConfig.getStr("LogFileName")); } // Start the transceiver binary, if the path is defined. // If the path is not defined, the transceiver must be started by some other process. const char *TRXPath = NULL; if (gConfig.defines("TRX.Path")) TRXPath=gConfig.getStr("TRX.Path"); pid_t transceiverPid = 0; if (TRXPath) { const char *TRXLogLevel = gConfig.getStr("TRX.LogLevel"); const char *TRXLogFileName = NULL; if (gConfig.defines("TRX.LogFileName")) TRXLogFileName=gConfig.getStr("TRX.LogFileName"); transceiverPid = vfork(); assert(transceiverPid>=0); if (transceiverPid==0) { execl(TRXPath,"transceiver",TRXLogLevel,TRXLogFileName,NULL); LOG(ERROR) << "cannot start transceiver"; _exit(0); } } // Start the SIP interface. gSIPInterface.start(); // Start the transceiver interface. gTRX.start(); // Set up the interface to the radio. // Get a handle to the C0 transceiver interface. ARFCNManager* radio = gTRX.ARFCN(0); // Tuning. // Make sure its off for tuning. radio->powerOff(); // Set TSC same as BSC everywhere. radio->setTSC(gBTS.BCC()); // Tune. radio->tune(gConfig.getNum("GSM.ARFCN")); // C-V on C0T0 radio->setSlot(0,5); // Turn on and power up. radio->powerOn(); radio->setPower(gConfig.getNum("GSM.PowerAttenDB")); // set up a combination V beacon set // SCH SCHL1FEC SCH; SCH.downstream(radio); SCH.open(); // FCCH FCCHL1FEC FCCH; FCCH.downstream(radio); FCCH.open(); // BCCH BCCHL1FEC BCCH; BCCH.downstream(radio); BCCH.open(); // RACH RACHL1FEC RACH(gRACHC5Mapping); RACH.downstream(radio); RACH.open(); // CCCHs CCCHLogicalChannel CCCH0(gCCCH_0Mapping); CCCH0.downstream(radio); CCCH0.open(); CCCHLogicalChannel CCCH1(gCCCH_1Mapping); CCCH1.downstream(radio); CCCH1.open(); CCCHLogicalChannel CCCH2(gCCCH_2Mapping); CCCH2.downstream(radio); CCCH2.open(); // use CCCHs as AGCHs gBTS.addAGCH(&CCCH0); gBTS.addAGCH(&CCCH1); gBTS.addAGCH(&CCCH2); // C-V C0T0 SDCCHs SDCCHLogicalChannel SDCCH[4] = { SDCCHLogicalChannel(0,gSDCCH_4_0), SDCCHLogicalChannel(0,gSDCCH_4_1), SDCCHLogicalChannel(0,gSDCCH_4_2), SDCCHLogicalChannel(0,gSDCCH_4_3) }; Thread SDCCHControlThread[4]; for (int i=0; i<4; i++) { SDCCH[i].downstream(radio); SDCCHControlThread[i].start((void*(*)(void*))Control::DCCHDispatcher,&SDCCH[i]); SDCCH[i].open(); gBTS.addSDCCH(&SDCCH[i]); } // Count configured slots. unsigned sCount = 1; // Create C-VII slots on C0Tn for (unsigned i=0; i<gConfig.getNum("GSM.NumC7s"); i++) { radio->setSlot(sCount,7); for (unsigned sub=0; sub<8; sub++) { SDCCHLogicalChannel* chan = new SDCCHLogicalChannel(sCount,gSDCCH8[sub]); chan->downstream(radio); Thread* thread = new Thread; thread->start((void*(*)(void*))Control::DCCHDispatcher,chan); chan->open(); gBTS.addSDCCH(chan); } sCount++; } // Create C-I slots on C0Tn for (unsigned i=0; i<gConfig.getNum("GSM.NumC1s"); i++) { radio->setSlot(sCount,1); TCHFACCHLogicalChannel* chan = new TCHFACCHLogicalChannel(sCount,gTCHF_T[sCount]); chan->downstream(radio); Thread* thread = new Thread; thread->start((void*(*)(void*))Control::DCCHDispatcher,chan); chan->open(); gBTS.addTCH(chan); sCount++; } assert(sCount<=8); /* Note: The number of different paging subchannels on the CCCH is: MAX(1,(3 - BS-AG-BLKS-RES)) * BS-PA-MFRMS if CCCH-CONF = "001" (9 - BS-AG-BLKS-RES) * BS-PA-MFRMS for other values of CCCH-CONF */ // Set up the pager. // Set up paging channels. gBTS.addPCH(&CCCH2); // Start the paging generator // Don't start the pager until some PCHs exist!! gBTS.pager().start(); LOG(INFO) << "system ready"; COUT("\n\nWelcome to OpenBTS. Type \"help\" to see available commands."); // FIXME: We want to catch control-d (emacs keybinding for exit()) while (1) { char inbuf[1024]; cout << "\nOpenBTS> "; cin.getline(inbuf,1024,'\n'); if (strcmp(inbuf,"exit")==0) break; gParser.process(inbuf,cout,cin); } if (transceiverPid) kill(transceiverPid,SIGKILL); }