propagate 'nextWriteTime' signal from L1 upwards
We drive it via SAPmux through OsmoLogicalChannel up into OsmoThreadMux
This commit is contained in:
parent
086a6a61cb
commit
3cabf472d9
|
@ -180,6 +180,7 @@ unsigned encodePower(int power)
|
||||||
|
|
||||||
L1Encoder::L1Encoder(unsigned wTN, const TDMAMapping& wMapping, L1FEC *wParent)
|
L1Encoder::L1Encoder(unsigned wTN, const TDMAMapping& wMapping, L1FEC *wParent)
|
||||||
:mDownstream(NULL),
|
:mDownstream(NULL),
|
||||||
|
mUpstream(NULL),
|
||||||
mMapping(wMapping),mTN(wTN),
|
mMapping(wMapping),mTN(wTN),
|
||||||
mTSC(gBTSL1.BCC()), // Note that TSC is hardcoded to the BCC.
|
mTSC(gBTSL1.BCC()), // Note that TSC is hardcoded to the BCC.
|
||||||
mParent(wParent),
|
mParent(wParent),
|
||||||
|
@ -203,8 +204,14 @@ void L1Encoder::rollForward()
|
||||||
mPrevWriteTime = mNextWriteTime;
|
mPrevWriteTime = mNextWriteTime;
|
||||||
mTotalBursts++;
|
mTotalBursts++;
|
||||||
mNextWriteTime.rollForward(mMapping.frameMapping(mTotalBursts),mMapping.repeatLength());
|
mNextWriteTime.rollForward(mMapping.frameMapping(mTotalBursts),mMapping.repeatLength());
|
||||||
|
signalNextWtime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void L1Encoder::signalNextWtime()
|
||||||
|
{
|
||||||
|
if (mUpstream)
|
||||||
|
mUpstream->signalNextWtime(mNextWriteTime);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned L1Encoder::ARFCN() const
|
unsigned L1Encoder::ARFCN() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,6 +85,7 @@ class L1Encoder {
|
||||||
ARFCNManager *mDownstream;
|
ARFCNManager *mDownstream;
|
||||||
TxBurst mBurst; ///< a preformatted burst template
|
TxBurst mBurst; ///< a preformatted burst template
|
||||||
TxBurst mFillerBurst; ///< the filler burst for this channel
|
TxBurst mFillerBurst; ///< the filler burst for this channel
|
||||||
|
SAPMux *mUpstream;
|
||||||
|
|
||||||
/**@name Config items that don't change. */
|
/**@name Config items that don't change. */
|
||||||
//@{
|
//@{
|
||||||
|
@ -130,6 +131,14 @@ class L1Encoder {
|
||||||
mDownstream=wDownstream;
|
mDownstream=wDownstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set the SAPMux pointer. */
|
||||||
|
virtual void upstream(SAPMux *wSapmux)
|
||||||
|
{
|
||||||
|
assert(mUpstream==NULL); // Don't call this twice.
|
||||||
|
mUpstream=wSapmux;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**@name Accessors. */
|
/**@name Accessors. */
|
||||||
//@{
|
//@{
|
||||||
const TDMAMapping& mapping() const { return mMapping; }
|
const TDMAMapping& mapping() const { return mMapping; }
|
||||||
|
@ -165,6 +174,8 @@ class L1Encoder {
|
||||||
/** Start the service loop thread, if there is one. */
|
/** Start the service loop thread, if there is one. */
|
||||||
virtual void start() { mRunning=true; }
|
virtual void start() { mRunning=true; }
|
||||||
|
|
||||||
|
void signalNextWtime();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** Roll write times forward to the next positions. */
|
/** Roll write times forward to the next positions. */
|
||||||
|
@ -359,7 +370,8 @@ class L1FEC {
|
||||||
|
|
||||||
/** Attach L1 to an upstream SAPI mux and L2. */
|
/** Attach L1 to an upstream SAPI mux and L2. */
|
||||||
void upstream(SAPMux* mux)
|
void upstream(SAPMux* mux)
|
||||||
{ if (mDecoder) mDecoder->upstream(mux); }
|
{ if (mDecoder) mDecoder->upstream(mux);
|
||||||
|
if (mEncoder) mEncoder->upstream(mux); }
|
||||||
|
|
||||||
/**@name Ganged actions. */
|
/**@name Ganged actions. */
|
||||||
//@{
|
//@{
|
||||||
|
|
|
@ -65,7 +65,8 @@ class SAPMux {
|
||||||
|
|
||||||
virtual void writeHighSide(const L2Frame& frame);
|
virtual void writeHighSide(const L2Frame& frame);
|
||||||
virtual void writeLowSide(const L2Frame& frame);
|
virtual void writeLowSide(const L2Frame& frame);
|
||||||
|
virtual void signalNextWtime(GSM::Time &time) {};
|
||||||
|
|
||||||
virtual void upstream( L2DL * wUpstream, unsigned wSAPI=0 )
|
virtual void upstream( L2DL * wUpstream, unsigned wSAPI=0 )
|
||||||
{ assert(mUpstream[wSAPI]==NULL); mUpstream[wSAPI]=wUpstream; }
|
{ assert(mUpstream[wSAPI]==NULL); mUpstream[wSAPI]=wUpstream; }
|
||||||
void downstream( L1FEC * wDownstream )
|
void downstream( L1FEC * wDownstream )
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
include $(top_srcdir)/Makefile.common
|
include $(top_srcdir)/Makefile.common
|
||||||
|
|
||||||
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
||||||
AM_CXXFLAGS = -O2 -g
|
AM_CXXFLAGS = -O0 -g
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libGSML1.la libGSM.la
|
noinst_LTLIBRARIES = libGSML1.la libGSM.la
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ libGSML1_la_SOURCES = \
|
||||||
GSMSAPMux.cpp \
|
GSMSAPMux.cpp \
|
||||||
OsmoSAPMux.cpp \
|
OsmoSAPMux.cpp \
|
||||||
OsmoLogicalChannel.cpp \
|
OsmoLogicalChannel.cpp \
|
||||||
|
OsmoThreadMuxer.cpp \
|
||||||
GSMTAPDump.cpp
|
GSMTAPDump.cpp
|
||||||
|
|
||||||
libGSM_la_SOURCES = \
|
libGSM_la_SOURCES = \
|
||||||
|
|
|
@ -98,6 +98,11 @@ ostream& GSM::operator<<(ostream& os, const OsmoLogicalChannel& lchan)
|
||||||
os << "(" << trx_nr << "," << ts_nr << "," << ss_nr << ")";
|
os << "(" << trx_nr << "," << ts_nr << "," << ss_nr << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OsmoLogicalChannel::signalNextWtime(GSM::Time &time)
|
||||||
|
{
|
||||||
|
if (mTM)
|
||||||
|
mTM->signalNextWtime(time);
|
||||||
|
}
|
||||||
|
|
||||||
void OsmoLogicalChannel::downstream(ARFCNManager* radio)
|
void OsmoLogicalChannel::downstream(ARFCNManager* radio)
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,9 +84,12 @@ protected:
|
||||||
unsigned int mTN;
|
unsigned int mTN;
|
||||||
OsmoTS *mTS[8];
|
OsmoTS *mTS[8];
|
||||||
public:
|
public:
|
||||||
OsmoTRX(TransceiverManager &TRXmgr, unsigned int trx_nr) {
|
OsmoTRX(TransceiverManager &TRXmgr, unsigned int trx_nr,
|
||||||
|
OsmoThreadMuxer *thread_mux)
|
||||||
|
{
|
||||||
mTRXmgr = &TRXmgr;
|
mTRXmgr = &TRXmgr;
|
||||||
mTN = trx_nr;
|
mTN = trx_nr;
|
||||||
|
mThreadMux = thread_mux;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransceiverManager *getTRXmgr() const { return mTRXmgr; }
|
TransceiverManager *getTRXmgr() const { return mTRXmgr; }
|
||||||
|
@ -151,6 +154,9 @@ public:
|
||||||
unsigned int SSnr() const { return mSS; }
|
unsigned int SSnr() const { return mSS; }
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
virtual void writeLowSide(const L2Frame& frame);
|
||||||
|
virtual void signalNextWtime(GSM::Time &time);
|
||||||
|
|
||||||
|
|
||||||
/**@name Pass-throughs. */
|
/**@name Pass-throughs. */
|
||||||
//@{
|
//@{
|
||||||
|
@ -167,14 +173,6 @@ public:
|
||||||
mSACCHL1->setPhy(*other.SACCH());
|
mSACCHL1->setPhy(*other.SACCH());
|
||||||
}
|
}
|
||||||
|
|
||||||
//@}
|
|
||||||
|
|
||||||
|
|
||||||
/**@name L3 interfaces */
|
|
||||||
//@{
|
|
||||||
//
|
|
||||||
virtual void writeLowSide(const L2Frame& frame);
|
|
||||||
|
|
||||||
//@} // passthrough
|
//@} // passthrough
|
||||||
|
|
||||||
/**@name Channel stats from the physical layer */
|
/**@name Channel stats from the physical layer */
|
||||||
|
|
|
@ -50,6 +50,12 @@ void OsmoSAPMux::writeLowSide(const L2Frame& frame)
|
||||||
mLchan->writeLowSide(frame);
|
mLchan->writeLowSide(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OsmoSAPMux::signalNextWtime(GSM::Time &time)
|
||||||
|
{
|
||||||
|
assert(mLchan);
|
||||||
|
mLchan->signalNextWtime(time);
|
||||||
|
}
|
||||||
|
|
||||||
void OsmoSAPMux::dispatch()
|
void OsmoSAPMux::dispatch()
|
||||||
{
|
{
|
||||||
L2Frame *frame;
|
L2Frame *frame;
|
||||||
|
|
|
@ -52,13 +52,15 @@ class OsmoSAPMux : public SAPMux {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
OsmoSAPMux() {
|
OsmoSAPMux()
|
||||||
|
:mLchan(NULL){
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~OsmoSAPMux() {}
|
virtual ~OsmoSAPMux() {}
|
||||||
|
|
||||||
virtual void writeHighSide(const L2Frame& frame);
|
virtual void writeHighSide(const L2Frame& frame);
|
||||||
virtual void writeLowSide(const L2Frame& frame);
|
virtual void writeLowSide(const L2Frame& frame);
|
||||||
|
virtual void signalNextWtime(GSM::Time &time);
|
||||||
|
|
||||||
void upstream(OsmoLogicalChannel *lchan) {
|
void upstream(OsmoLogicalChannel *lchan) {
|
||||||
assert(mLchan == NULL);
|
assert(mLchan == NULL);
|
||||||
|
|
|
@ -34,12 +34,17 @@ using namespace std;
|
||||||
using namespace GSM;
|
using namespace GSM;
|
||||||
|
|
||||||
|
|
||||||
OsmoThreadMuxer::writeLowSide(const L2Frame& frame,
|
void OsmoThreadMuxer::writeLowSide(const L2Frame& frame,
|
||||||
struct OsmoLogicalChannel *lchan)
|
struct OsmoLogicalChannel *lchan)
|
||||||
{
|
{
|
||||||
OBJLOG(DEEPDEBUG) << "OsmoThreadMuxer::writeLowSide" << lchan << " " << frame;
|
OBJLOG(INFO) << "OsmoThreadMuxer::writeLowSide" << lchan << " " << frame;
|
||||||
/* resolve SAPI, SS, TS, TRX numbers */
|
/* resolve SAPI, SS, TS, TRX numbers */
|
||||||
/* build primitive that we can put into the up-queue */
|
/* build primitive that we can put into the up-queue */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OsmoThreadMuxer::signalNextWtime(GSM::Time &time)
|
||||||
|
{
|
||||||
|
OBJLOG(DEBUG) << "NextWriteTime: " << time;
|
||||||
|
}
|
||||||
|
|
||||||
// vim: ts=4 sw=4
|
// vim: ts=4 sw=4
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
|
|
||||||
namespace GSM {
|
namespace GSM {
|
||||||
|
|
||||||
|
|
||||||
/* The idea of this monster is to provide an interface between the
|
/* The idea of this monster is to provide an interface between the
|
||||||
* heavily multi-threaded OpenBTS architecture and the single-threaded
|
* heavily multi-threaded OpenBTS architecture and the single-threaded
|
||||||
* osmo-bts architecture.
|
* osmo-bts architecture.
|
||||||
|
@ -54,7 +53,9 @@ protected:
|
||||||
unsigned int mNumTRX;
|
unsigned int mNumTRX;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OsmoThreadMuxer() {
|
OsmoThreadMuxer()
|
||||||
|
:mNumTRX(0)
|
||||||
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = socketpair(AF_UNIX, SOCK_DGRAM, 0, mSockFd);
|
rc = socketpair(AF_UNIX, SOCK_DGRAM, 0, mSockFd);
|
||||||
|
@ -64,17 +65,22 @@ public:
|
||||||
return mSockFd[1];
|
return mSockFd[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int addTRX(TransceiverManager &trx_mgr, unsigned int trx_nr) {
|
OsmoTRX &addTRX(TransceiverManager &trx_mgr, unsigned int trx_nr) {
|
||||||
/* for now we only support a single TRX */
|
/* for now we only support a single TRX */
|
||||||
assert(mNumTRX == 0);
|
assert(mNumTRX == 0);
|
||||||
OsmoTRX *otrx = new OsmoTRX(trx_mgr, trx_nr);
|
OsmoTRX *otrx = new OsmoTRX(trx_mgr, trx_nr, this);
|
||||||
mTRX[mNumTRX++] = otrx;
|
mTRX[mNumTRX++] = otrx;
|
||||||
|
return *otrx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive frame synchronously from L1Decoder->OsmoSAPMux and
|
/* receive frame synchronously from L1Decoder->OsmoSAPMux and
|
||||||
* euqneue it towards osmo-bts */
|
* euqneue it towards osmo-bts */
|
||||||
virtual void writeLowSide(const L2Frame& frame,
|
virtual void writeLowSide(const L2Frame& frame,
|
||||||
OsmoLogicalChannel *lchan);
|
OsmoLogicalChannel *lchan);
|
||||||
|
|
||||||
|
/* L1 informs us about the next TDMA time for which it needs
|
||||||
|
* data */
|
||||||
|
virtual void signalNextWtime(GSM::Time &time);
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // GSM
|
}; // GSM
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <GSMSAPMux.h>
|
#include <GSMSAPMux.h>
|
||||||
#include <GSML3RRMessages.h>
|
#include <GSML3RRMessages.h>
|
||||||
#include <OsmoLogicalChannel.h>
|
#include <OsmoLogicalChannel.h>
|
||||||
|
#include <OsmoThreadMuxer.h>
|
||||||
|
|
||||||
#include <Globals.h>
|
#include <Globals.h>
|
||||||
|
|
||||||
|
@ -549,7 +550,8 @@ int main(int argc, char *argv[])
|
||||||
// Set Receiver Gain
|
// Set Receiver Gain
|
||||||
radio->setRxGain(gConfig.getNum("GSM.RxGain"));
|
radio->setRxGain(gConfig.getNum("GSM.RxGain"));
|
||||||
|
|
||||||
OsmoTRX TRX0(gTRX, 0);
|
OsmoThreadMuxer ThreadMux;
|
||||||
|
OsmoTRX &TRX0 = ThreadMux.addTRX(gTRX, 0);
|
||||||
|
|
||||||
OsmoComb5TS TS0(TRX0, 0);
|
OsmoComb5TS TS0(TRX0, 0);
|
||||||
OsmoComb1TS TS1(TRX0, 1);
|
OsmoComb1TS TS1(TRX0, 1);
|
||||||
|
|
Reference in New Issue