Adding MultiARFCN support to core.

git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@3688 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
Kurtis Heimerl
2012-05-31 00:05:12 +00:00
parent 32c86513e3
commit 13ece1dbae
11 changed files with 156 additions and 78 deletions

View File

@@ -710,7 +710,7 @@ int rxgain(int argc, char** argv, ostream& os, istream& is)
if (argc==1) return SUCCESS;
if (argc!=2) return BAD_NUM_ARGS;
int newGain = gTRX.ARFCN()->setRxGain(atoi(argv[1]));
int newGain = gTRX.ARFCN(0)->setRxGain(atoi(argv[1]));
os << "new RX gain is " << newGain << " dB" << endl;
gConfig.set("GSM.Radio.RxGain",newGain);
@@ -722,7 +722,7 @@ int noise(int argc, char** argv, ostream& os, istream& is)
{
if (argc!=1) return BAD_NUM_ARGS;
int noise = gTRX.ARFCN()->getNoiseLevel();
int noise = gTRX.ARFCN(0)->getNoiseLevel();
os << "noise RSSI is -" << noise << " dB wrt full scale" << endl;
os << "MS RSSI target is " << gConfig.getNum("GSM.Radio.RSSITarget") << " dB wrt full scale" << endl;

View File

@@ -287,18 +287,18 @@ void GSMConfig::createCombination0(TransceiverManager& TRX, unsigned TN)
// This should not be applied to C0T0.
LOG_ASSERT(TN!=0);
LOG(NOTICE) << "Configuring dummy filling on C0T " << TN;
ARFCNManager *radio = TRX.ARFCN();
ARFCNManager *radio = TRX.ARFCN(0);
radio->setSlot(TN,0);
}
void GSMConfig::createCombinationI(TransceiverManager& TRX, unsigned TN)
void GSMConfig::createCombinationI(TransceiverManager& TRX, unsigned CN, unsigned TN)
{
LOG_ASSERT(TN!=0);
LOG(NOTICE) << "Configuring combination I on C0T" << TN;
ARFCNManager *radio = TRX.ARFCN();
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);
TCHFACCHLogicalChannel* chan = new TCHFACCHLogicalChannel(TN,gTCHF_T[TN]);
TCHFACCHLogicalChannel* chan = new TCHFACCHLogicalChannel(CN,TN,gTCHF_T[TN]);
chan->downstream(radio);
Thread* thread = new Thread;
thread->start((void*(*)(void*))Control::DCCHDispatcher,chan);
@@ -308,14 +308,14 @@ void GSMConfig::createCombinationI(TransceiverManager& TRX, unsigned TN)
}
void GSMConfig::createCombinationVII(TransceiverManager& TRX, unsigned TN)
void GSMConfig::createCombinationVII(TransceiverManager& TRX, unsigned CN, unsigned TN)
{
LOG_ASSERT(TN!=0);
LOG(NOTICE) << "Configuring combination VII on C0T" << TN;
ARFCNManager *radio = TRX.ARFCN();
LOG_ASSERT((CN!=0)||(TN!=0));
LOG(NOTICE) << "Configuring combination VII on C" << CN << "T" << TN;
ARFCNManager *radio = TRX.ARFCN(CN);
radio->setSlot(TN,7);
for (int i=0; i<8; i++) {
SDCCHLogicalChannel* chan = new SDCCHLogicalChannel(TN,gSDCCH8[i]);
SDCCHLogicalChannel* chan = new SDCCHLogicalChannel(CN,TN,gSDCCH8[i]);
chan->downstream(radio);
Thread* thread = new Thread;
thread->start((void*(*)(void*))Control::DCCHDispatcher,chan);

View File

@@ -268,9 +268,9 @@ class GSMConfig {
/** Combination 0 is a idle slot, as opposed to a non-transmitting one. */
void createCombination0(TransceiverManager &TRX, unsigned TN);
/** Combination I is full rate traffic. */
void createCombinationI(TransceiverManager &TRX, unsigned TN);
void createCombinationI(TransceiverManager &TRX, unsigned CN, unsigned TN);
/** Combination VII is 8 SDCCHs. */
void createCombinationVII(TransceiverManager &TRX, unsigned TN);
void createCombinationVII(TransceiverManager &TRX, unsigned CN, unsigned TN);
//@}
/** Return number of seconds since starting. */

View File

@@ -181,9 +181,9 @@ unsigned encodePower(int power)
*/
L1Encoder::L1Encoder(unsigned wTN, const TDMAMapping& wMapping, L1FEC *wParent)
L1Encoder::L1Encoder(unsigned wCN, unsigned wTN, const TDMAMapping& wMapping, L1FEC *wParent)
:mDownstream(NULL),
mTN(wTN),
mCN(wCN),mTN(wTN),
mMapping(wMapping),
mTSC(gBTS.BCC()), // Note that TSC is hardcoded to the BCC.
mParent(wParent),
@@ -192,6 +192,7 @@ L1Encoder::L1Encoder(unsigned wTN, const TDMAMapping& wMapping, L1FEC *wParent)
mNextWriteTime(gBTS.time().FN(),wTN),
mRunning(false),mActive(false)
{
assert(mCN<gConfig.getNum("GSM.Radio.ARFCNs"));
assert(mMapping.allowedSlot(mTN));
assert(mMapping.downlink());
mNextWriteTime.rollForward(mMapping.frameMapping(0),mMapping.repeatLength());
@@ -200,7 +201,7 @@ L1Encoder::L1Encoder(unsigned wTN, const TDMAMapping& wMapping, L1FEC *wParent)
// Build the descriptive string.
ostringstream ss;
ss << wMapping.typeAndOffset();
sprintf(mDescriptiveString,"C0T%d %s", wTN, ss.str().c_str());
sprintf(mDescriptiveString,"C%dT%d %s", wCN, wTN, ss.str().c_str());
}
@@ -297,6 +298,7 @@ void L1Encoder::sendIdleFill()
// For C0, that's the dummy burst.
// For Cn, don't do anything.
resync();
if (mCN!=0) return;
for (unsigned i=0; i<mMapping.numFrames(); i++) {
mFillerBurst.time(mNextWriteTime);
mDownstream->writeHighSide(mFillerBurst);
@@ -522,10 +524,11 @@ void RACHL1Decoder::writeLowSide(const RxBurst& burst)
XCCHL1Decoder::XCCHL1Decoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
L1FEC *wParent)
:L1Decoder(wTN,wMapping,wParent),
:L1Decoder(wCN,wTN,wMapping,wParent),
mBlockCoder(0x10004820009ULL, 40, 224),
mC(456), mU(228),
mP(mU.segment(184,40)),mDP(mU.head(224)),mD(mU.head(184))
@@ -730,10 +733,11 @@ void SACCHL1Decoder::handleGoodFrame()
XCCHL1Encoder::XCCHL1Encoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
L1FEC* wParent)
:L1Encoder(wTN,wMapping,wParent),
:L1Encoder(wCN,wTN,wMapping,wParent),
mBlockCoder(0x10004820009ULL, 40, 224),
mC(456), mU(228),
mD(mU.head(184)),mP(mU.segment(184,40))
@@ -918,7 +922,7 @@ void GeneratorL1Encoder::serviceLoop()
SCHL1Encoder::SCHL1Encoder(L1FEC* wParent)
:GeneratorL1Encoder(0,gSCHMapping,wParent),
:GeneratorL1Encoder(0,0,gSCHMapping,wParent),
mBlockCoder(0x0575,10,25),
mU(25+10+4), mE(78),
mD(mU.head(25)),mP(mU.segment(25,10)),
@@ -965,7 +969,7 @@ void SCHL1Encoder::generate()
FCCHL1Encoder::FCCHL1Encoder(L1FEC *wParent)
:GeneratorL1Encoder(0,gFCCHMapping,wParent)
:GeneratorL1Encoder(0,0,gFCCHMapping,wParent)
{
mBurst.zero();
mFillerBurst.zero();
@@ -1036,10 +1040,11 @@ void BCCHL1Encoder::generate()
TCHFACCHL1Decoder::TCHFACCHL1Decoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
L1FEC *wParent)
:XCCHL1Decoder(wTN, wMapping, wParent),
:XCCHL1Decoder(wCN,wTN, wMapping, wParent),
mTCHU(189),mTCHD(260),
mClass1_c(mC.head(378)),mClass1A_d(mTCHD.head(50)),mClass2_c(mC.segment(378,78)),
mTCHParity(0x0b,3,50)
@@ -1241,10 +1246,11 @@ void GSM::TCHFACCHL1EncoderRoutine( TCHFACCHL1Encoder * encoder )
TCHFACCHL1Encoder::TCHFACCHL1Encoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
L1FEC *wParent)
:XCCHL1Encoder(wTN, wMapping, wParent),
:XCCHL1Encoder(wCN, wTN, wMapping, wParent),
mPreviousFACCH(false),mOffset(0),
mTCHU(189),mTCHD(260),
mClass1_c(mC.head(378)),mClass1A_d(mTCHD.head(50)),mClass2_d(mTCHD.segment(182,78)),
@@ -1525,8 +1531,8 @@ void SACCHL1Encoder::setPhy(const SACCHL1Encoder& other)
SACCHL1Encoder::SACCHL1Encoder(unsigned wTN, const TDMAMapping& wMapping, SACCHL1FEC *wParent)
:XCCHL1Encoder(wTN,wMapping,(L1FEC*)wParent),
SACCHL1Encoder::SACCHL1Encoder(unsigned wCN, unsigned wTN, const TDMAMapping& wMapping, SACCHL1FEC *wParent)
:XCCHL1Encoder(wCN,wTN,wMapping,(L1FEC*)wParent),
mSACCHParent(wParent),
mOrderedMSPower(33),mOrderedMSTiming(0)
{ }

View File

@@ -92,6 +92,7 @@ class L1Encoder {
/**@name Config items that don't change. */
//@{
const TDMAMapping& mMapping; ///< multiplexing description
unsigned mCN; ///< carrier index
unsigned mTN; ///< timeslot number to use
unsigned mTSC; ///< training sequence for this channel
L1FEC *mParent; ///< a containing L1FEC, if any
@@ -119,11 +120,12 @@ class L1Encoder {
/**
The basic encoder constructor.
@param wCN carrier index.
@param wTN TDMA timeslot number.
@param wMapping TDMA mapping onto the timeslot -- MUST PERSIST.
@param wParent The containing L1FEC, for sibling access -- may be NULL.
*/
L1Encoder(unsigned wTN, const TDMAMapping& wMapping, L1FEC *wParent);
L1Encoder(unsigned wCN, unsigned wTN, const TDMAMapping& wMapping, L1FEC *wParent);
virtual ~L1Encoder() {}
@@ -139,6 +141,7 @@ class L1Encoder {
const TDMAMapping& mapping() const { return mMapping; }
/**@name Components of the channel description. */
//@{
unsigned CN() const { return mCN; }
unsigned TN() const { return mTN; }
unsigned TSC() const { return mTSC; }
unsigned ARFCN() const;
@@ -231,6 +234,7 @@ class L1Decoder {
/**@name Parameters fixed by the constructor, not requiring mutex protection. */
//@{
unsigned mCN; ///< carrier index
unsigned mTN; ///< timeslot number
const TDMAMapping& mMapping; ///< demux parameters
L1FEC* mParent; ///< a containing L1 processor, if any
@@ -247,13 +251,13 @@ class L1Decoder {
@param wMapping Demux parameters, MUST BE PERSISTENT.
@param wParent The containing L1FEC, for sibling access.
*/
L1Decoder(unsigned wTN, const TDMAMapping& wMapping, L1FEC* wParent)
L1Decoder(unsigned wCN, unsigned wTN, const TDMAMapping& wMapping, L1FEC* wParent)
:mUpstream(NULL),
mT3101(T3101ms),mT3109(T3109ms),mT3111(T3111ms),
mActive(false),
mRunning(false),
mFER(0.0F),
mTN(wTN),
mCN(wCN),mTN(wTN),
mMapping(wMapping),mParent(wParent)
{
// Start T3101 so that the channel will
@@ -383,6 +387,9 @@ class L1FEC {
unsigned TN() const
{ assert(mEncoder); return mEncoder->TN(); }
unsigned CN() const
{ assert(mEncoder); return mEncoder->CN(); }
unsigned TSC() const
{ assert(mEncoder); return mEncoder->TSC(); }
@@ -458,7 +465,7 @@ class RACHL1Decoder : public L1Decoder {
RACHL1Decoder(const TDMAMapping &wMapping,
L1FEC *wParent)
:L1Decoder(0,wMapping,wParent),
:L1Decoder(0,0,wMapping,wParent),
mParity(0x06f,6,8),mU(18),mD(mU.head(8))
{ }
@@ -500,7 +507,7 @@ class XCCHL1Decoder : public L1Decoder {
public:
XCCHL1Decoder(unsigned wTN, const TDMAMapping& wMapping,
XCCHL1Decoder(unsigned wCN, unsigned wTN, const TDMAMapping& wMapping,
L1FEC *wParent);
protected:
@@ -548,10 +555,11 @@ class SDCCHL1Decoder : public XCCHL1Decoder {
public:
SDCCHL1Decoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
L1FEC *wParent)
:XCCHL1Decoder(wTN,wMapping,wParent)
:XCCHL1Decoder(wCN,wTN,wMapping,wParent)
{ }
ChannelType channelType() const { return SDCCHType; }
@@ -579,10 +587,11 @@ class SACCHL1Decoder : public XCCHL1Decoder {
public:
SACCHL1Decoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
SACCHL1FEC *wParent)
:XCCHL1Decoder(wTN,wMapping,(L1FEC*)wParent),
:XCCHL1Decoder(wCN,wTN,wMapping,(L1FEC*)wParent),
mSACCHParent(wParent),
mRSSICounter(0)
{
@@ -653,6 +662,7 @@ class XCCHL1Encoder : public L1Encoder {
public:
XCCHL1Encoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
L1FEC* wParent);
@@ -720,7 +730,7 @@ private:
public:
TCHFACCHL1Encoder(unsigned wTN,
TCHFACCHL1Encoder(unsigned wCN, unsigned wTN,
const TDMAMapping& wMapping,
L1FEC* wParent);
@@ -780,7 +790,7 @@ class TCHFACCHL1Decoder : public XCCHL1Decoder {
public:
TCHFACCHL1Decoder(unsigned wTN,
TCHFACCHL1Decoder(unsigned wCN, unsigned wTN,
const TDMAMapping& wMapping,
L1FEC *wParent);
@@ -836,10 +846,11 @@ class GeneratorL1Encoder : public L1Encoder {
public:
GeneratorL1Encoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
L1FEC* wParent)
:L1Encoder(wTN,wMapping,wParent)
:L1Encoder(wCN,wTN,wMapping,wParent)
{ }
void start();
@@ -924,10 +935,11 @@ class NDCCHL1Encoder : public XCCHL1Encoder {
NDCCHL1Encoder(
unsigned wCN,
unsigned wTN,
const TDMAMapping& wMapping,
L1FEC *wParent)
:XCCHL1Encoder(wTN, wMapping, wParent)
:XCCHL1Encoder(wCN, wTN, wMapping, wParent)
{ }
void start();
@@ -954,7 +966,7 @@ class BCCHL1Encoder : public NDCCHL1Encoder {
public:
BCCHL1Encoder(L1FEC *wParent)
:NDCCHL1Encoder(0,gBCCHMapping,wParent)
:NDCCHL1Encoder(0,0,gBCCHMapping,wParent)
{}
private:
@@ -983,7 +995,7 @@ class SACCHL1Encoder : public XCCHL1Encoder {
public:
SACCHL1Encoder(unsigned wTN, const TDMAMapping& wMapping, SACCHL1FEC *wParent);
SACCHL1Encoder(unsigned wCN, unsigned wTN, const TDMAMapping& wMapping, SACCHL1FEC *wParent);
void orderedMSPower(int power) { mOrderedMSPower = power; }
void orderedMSTiming(int timing) { mOrderedMSTiming = timing; }
@@ -1021,12 +1033,29 @@ class CCCHL1Encoder : public XCCHL1Encoder {
CCCHL1Encoder(const TDMAMapping& wMapping,
L1FEC* wParent)
:XCCHL1Encoder(0,wMapping,wParent)
:XCCHL1Encoder(0,0,wMapping,wParent)
{}
};
/** Cell Broadcast Channel (CBCH). */
class CBCHL1Encoder : public XCCHL1Encoder {
public:
CBCHL1Encoder(const TDMAMapping& wMapping,
L1FEC* wParent)
:XCCHL1Encoder(0,0,wMapping,wParent)
{}
/** Override sendFrame to meet sync requirements of GSM 05.02 6.5.4. */
virtual void sendFrame(const L2Frame&);
};
@@ -1035,12 +1064,13 @@ class SDCCHL1FEC : public L1FEC {
public:
SDCCHL1FEC(
unsigned wCN,
unsigned wTN,
const MappingPair& wMapping)
:L1FEC()
{
mEncoder = new SDCCHL1Encoder(wTN,wMapping.downlink(),this);
mDecoder = new SDCCHL1Decoder(wTN,wMapping.uplink(),this);
mEncoder = new SDCCHL1Encoder(wCN,wTN,wMapping.downlink(),this);
mDecoder = new SDCCHL1Decoder(wCN,wTN,wMapping.uplink(),this);
}
};
@@ -1049,6 +1079,21 @@ class SDCCHL1FEC : public L1FEC {
class CBCHL1FEC : public L1FEC {
public:
CBCHL1FEC(const MappingPair& wMapping)
:L1FEC()
{
mEncoder = new CBCHL1Encoder(wMapping.downlink(),this);
}
};
@@ -1065,13 +1110,14 @@ public:
TCHFACCHL1FEC(
unsigned wCN,
unsigned wTN,
const MappingPair& wMapping)
:L1FEC()
{
mTCHEncoder = new TCHFACCHL1Encoder(wTN, wMapping.downlink(), this );
mTCHEncoder = new TCHFACCHL1Encoder(wCN, wTN, wMapping.downlink(), this );
mEncoder = mTCHEncoder;
mTCHDecoder = new TCHFACCHL1Decoder(wTN, wMapping.uplink(), this );
mTCHDecoder = new TCHFACCHL1Decoder(wCN, wTN, wMapping.uplink(), this );
mDecoder = mTCHDecoder;
}
@@ -1107,13 +1153,14 @@ class SACCHL1FEC : public L1FEC {
public:
SACCHL1FEC(
unsigned wCN,
unsigned wTN,
const MappingPair& wMapping)
:L1FEC()
{
mSACCHEncoder = new SACCHL1Encoder(wTN,wMapping.downlink(),this);
mSACCHEncoder = new SACCHL1Encoder(wCN,wTN,wMapping.downlink(),this);
mEncoder = mSACCHEncoder;
mSACCHDecoder = new SACCHL1Decoder(wTN,wMapping.uplink(),this);
mSACCHDecoder = new SACCHL1Decoder(wCN,wTN,wMapping.uplink(),this);
mDecoder = mSACCHDecoder;
}
@@ -1142,11 +1189,11 @@ class LoopbackL1FEC : public L1FEC {
public:
LoopbackL1FEC(unsigned wTN)
LoopbackL1FEC(unsigned wCN, unsigned wTN)
:L1FEC()
{
mEncoder = new XCCHL1Encoder(wTN,gLoopbackTestFullMapping,this);
mDecoder = new SDCCHL1Decoder(wTN,gLoopbackTestFullMapping,this);
mEncoder = new XCCHL1Encoder(wCN,wTN,gLoopbackTestFullMapping,this);
mDecoder = new SDCCHL1Decoder(wCN,wTN,gLoopbackTestFullMapping,this);
}
};

View File

@@ -163,10 +163,11 @@ L3ChannelDescription LogicalChannel::channelDescription() const
SDCCHLogicalChannel::SDCCHLogicalChannel(
unsigned wCN,
unsigned wTN,
const CompleteMapping& wMapping)
{
mL1 = new SDCCHL1FEC(wTN,wMapping.LCH());
mL1 = new SDCCHL1FEC(wCN,wTN,wMapping.LCH());
// SAP0 is RR/MM/CC, SAP3 is SMS
// SAP1 and SAP2 are not used.
L2LAPDm *SAP0L2 = new SDCCHL2(1,0);
@@ -175,7 +176,7 @@ SDCCHLogicalChannel::SDCCHLogicalChannel(
SAP3L2->master(SAP0L2);
mL2[0] = SAP0L2;
mL2[3] = SAP3L2;
mSACCH = new SACCHLogicalChannel(wTN,wMapping.SACCH());
mSACCH = new SACCHLogicalChannel(wCN,wTN,wMapping.SACCH());
connect();
}
@@ -184,11 +185,12 @@ SDCCHLogicalChannel::SDCCHLogicalChannel(
SACCHLogicalChannel::SACCHLogicalChannel(
unsigned wCN,
unsigned wTN,
const MappingPair& wMapping)
: mRunning(false)
{
mSACCHL1 = new SACCHL1FEC(wTN,wMapping);
mSACCHL1 = new SACCHL1FEC(wCN,wTN,wMapping);
mL1 = mSACCHL1;
// SAP0 is RR, SAP3 is SMS
// SAP1 and SAP2 are not used.
@@ -349,16 +351,17 @@ int LogicalChannel::actualMSTiming() const
TCHFACCHLogicalChannel::TCHFACCHLogicalChannel(
unsigned wCN,
unsigned wTN,
const CompleteMapping& wMapping)
{
mTCHL1 = new TCHFACCHL1FEC(wTN,wMapping.LCH());
mTCHL1 = new TCHFACCHL1FEC(wCN,wTN,wMapping.LCH());
mL1 = mTCHL1;
// SAP0 is RR/MM/CC, SAP3 is SMS
// SAP1 and SAP2 are not used.
mL2[0] = new FACCHL2(1,0);
mL2[3] = new FACCHL2(1,3);
mSACCH = new SACCHLogicalChannel(wTN,wMapping.SACCH());
mSACCH = new SACCHLogicalChannel(wCN,wTN,wMapping.SACCH());
connect();
}

View File

@@ -220,7 +220,7 @@ public:
/**@name Channel stats from the physical layer */
//@{
/** Carrier index. */
unsigned CN() const { return 0; }
unsigned CN() const { assert(mL1); return mL1->CN(); }
/** Slot number. */
unsigned TN() const { assert(mL1); return mL1->TN(); }
/** Receive FER. */
@@ -296,6 +296,7 @@ class SDCCHLogicalChannel : public LogicalChannel {
public:
SDCCHLogicalChannel(
unsigned wCN,
unsigned wTN,
const CompleteMapping& wMapping);
@@ -360,6 +361,7 @@ class SACCHLogicalChannel : public LogicalChannel {
public:
SACCHLogicalChannel(
unsigned wCN,
unsigned wTN,
const MappingPair& wMapping);
@@ -466,6 +468,7 @@ class TCHFACCHLogicalChannel : public LogicalChannel {
public:
TCHFACCHLogicalChannel(
unsigned wCN,
unsigned wTN,
const CompleteMapping& wMapping);
@@ -531,6 +534,7 @@ class SDCCHLogicalChannel_LB : public SDCCHLogicalChannel
{
public :
SDCCHLogicalChannel_LB(
unsigned wCN,
unsigned wTN,
const CompleteMapping& wMapping);
};
@@ -541,6 +545,7 @@ class TCHFACCHLogicalChannel_UPLINK : public TCHFACCHLogicalChannel
public:
/** Custom constructor, L2 is Uplink instead of downlink. */
TCHFACCHLogicalChannel_UPLINK(
unsigned wCN,
unsigned wTN,
const CompleteMapping& wMapping);

View File

@@ -124,7 +124,7 @@ void* GSM::PowerManagerServiceLoopAdapter(PowerManager *pm)
void PowerManager::start()
{
mRadio = gTRX.ARFCN();
mRadio = gTRX.ARFCN(0);
mRadio->setPower(mAtten);
mThread.start((void*(*)(void*))PowerManagerServiceLoopAdapter,this);
}

View File

@@ -45,12 +45,16 @@ using namespace GSM;
using namespace std;
TransceiverManager::TransceiverManager(const char* wTRXAddress, int wBasePort)
TransceiverManager::TransceiverManager(int numARFCNs,
const char* wTRXAddress, int wBasePort)
:mHaveClock(false),
mClockSocket(wBasePort+100)
{
// set up the ARFCN manager
mARFCN = new ::ARFCNManager(wTRXAddress,wBasePort+1,*this);
// set up the ARFCN managers
for (int i=0; i<numARFCNs; i++) {
int thisBasePort = wBasePort + 1 + 2*i;
mARFCNs.push_back(new ::ARFCNManager(wTRXAddress,thisBasePort,*this));
}
}
@@ -58,7 +62,9 @@ TransceiverManager::TransceiverManager(const char* wTRXAddress, int wBasePort)
void TransceiverManager::start()
{
mClockThread.start((void*(*)(void*))ClockLoopAdapter,this);
mARFCN->start();
for (unsigned i=0; i<mARFCNs.size(); i++) {
mARFCNs[i]->start();
}
}

View File

@@ -58,8 +58,8 @@ class TransceiverManager {
private:
/// the ARFCN mananger under this TRX
ARFCNManager* mARFCN;
/// the ARFCN manangers under this TRX
std::vector<ARFCNManager*> mARFCNs;
/// set true when the first CLOCK packet is received
volatile bool mHaveClock;
@@ -73,16 +73,23 @@ class TransceiverManager {
/**
Construct a TransceiverManager.
@param numARFCNs Number of ARFCNs supported by the transceiver.
@param wTRXAddress IP address of the transceiver.
@param wBasePort The base port for the interface, as defined in README.TRX.
*/
TransceiverManager(const char* wTRXAddress, int wBasePort);
TransceiverManager(int numARFCNs,
const char* wTRXAddress, int wBasePort);
/**@name Accessors. */
//@{
ARFCNManager* ARFCN() { return mARFCN; }
ARFCNManager* ARFCN(unsigned i) { assert(i<mARFCNs.size()); return mARFCNs.at(i); }
//@}
unsigned numARFCNs() const { return mARFCNs.size(); }
/** Block until the clock is set over the UDP link. */
//void waitForClockInit() const;
/** Start the clock management thread and all ARFCN managers. */
void start();

View File

@@ -91,7 +91,7 @@ SIP::SIPInterface gSIPInterface;
GSMConfig gBTS;
// Our interface to the software-defined radio.
TransceiverManager gTRX(gConfig.getStr("TRX.IP").c_str(), gConfig.getNum("TRX.Port"));
TransceiverManager gTRX(gConfig.getNum("GSM.Radio.ARFCNs"), gConfig.getStr("TRX.IP").c_str(), gConfig.getNum("TRX.Port"));
// Subscriber registry
SubscriberRegistry gSubscriberRegistry;
@@ -116,7 +116,7 @@ void startTransceiver()
// Start the transceiver binary, if the path is defined.
// If the path is not defined, the transceiver must be started by some other process.
char TRXnumARFCN[4];
sprintf(TRXnumARFCN,"%1d",1);
sprintf(TRXnumARFCN,"%1d",gConfig.getNum("GSM.Radio.ARFCNs"));
LOG(NOTICE) << "starting transceiver " << transceiverPath << " " << TRXnumARFCN;
gTransceiverPid = vfork();
LOG_ASSERT(gTransceiverPid>=0);
@@ -175,17 +175,21 @@ int main(int argc, char *argv[])
// Set up the interface to the radio.
// Get a handle to the C0 transceiver interface.
ARFCNManager* C0radio = gTRX.ARFCN();
ARFCNManager* C0radio = gTRX.ARFCN(0);
// Tuning.
// Make sure its off for tuning.
C0radio->powerOff();
// Get the ARFCN list.
unsigned C0 = gConfig.getNum("GSM.Radio.C0");
// Tune the radio.
LOG(INFO) << "tuning TRX to ARFCN " << C0;
ARFCNManager* radio = gTRX.ARFCN();
radio->tune(C0);
unsigned numARFCNs = gConfig.getNum("GSM.Radio.ARFCNs");
for (unsigned i=0; i<numARFCNs; i++) {
// Tune the radios.
unsigned ARFCN = C0 + i*2;
LOG(INFO) << "tuning TRX " << i << " to ARFCN " << ARFCN;
ARFCNManager* radio = gTRX.ARFCN(i);
radio->tune(ARFCN);
}
// Set TSC same as BCC everywhere.
C0radio->setTSC(gBTS.BCC());
@@ -239,10 +243,10 @@ int main(int argc, char *argv[])
// C-V C0T0 SDCCHs
SDCCHLogicalChannel C0T0SDCCH[4] = {
SDCCHLogicalChannel(0,gSDCCH_4_0),
SDCCHLogicalChannel(0,gSDCCH_4_1),
SDCCHLogicalChannel(0,gSDCCH_4_2),
SDCCHLogicalChannel(0,gSDCCH_4_3),
SDCCHLogicalChannel(0,0,gSDCCH_4_0),
SDCCHLogicalChannel(0,0,gSDCCH_4_1),
SDCCHLogicalChannel(0,0,gSDCCH_4_2),
SDCCHLogicalChannel(0,0,gSDCCH_4_3),
};
Thread C0T0SDCCHControlThread[4];
for (int i=0; i<4; i++) {
@@ -263,21 +267,21 @@ int main(int argc, char *argv[])
if (gConfig.defines("GSM.Channels.C1sFirst")) {
// Create C-I slots.
for (int i=0; i<gConfig.getNum("GSM.Channels.NumC1s"); i++) {
gBTS.createCombinationI(gTRX,sCount);
gBTS.createCombinationI(gTRX,sCount/8,sCount%8);
sCount++;
}
}
// Create C-VII slots.
for (int i=0; i<gConfig.getNum("GSM.Channels.NumC7s"); i++) {
gBTS.createCombinationVII(gTRX,sCount);
gBTS.createCombinationVII(gTRX,sCount/8,sCount%8);
sCount++;
}
if (!gConfig.defines("GSM.Channels.C1sFirst")) {
// Create C-I slots.
for (int i=0; i<gConfig.getNum("GSM.Channels.NumC1s"); i++) {
gBTS.createCombinationI(gTRX,sCount);
gBTS.createCombinationI(gTRX,sCount/8,sCount%8);
sCount++;
}
}