Compare commits

..

3 Commits

Author SHA1 Message Date
Alexander Chemeris
0832c0c34b Transceiver52M: HACK: Exit transceiver on POWEROFF command.
This hack allows OsmoBTS to correctly restart itself with different parameters.
We assume that transceiver is run as a service and will be restarted on exit.
2013-07-16 07:36:17 +04:00
Alexander Chemeris
9cddd4aa5d Transceiver52M: Start and stop all threads on POWERON/POWEROFF.
This change reveals some issue with the UHD start/stop code. Specifically,
we get a failed assert in RadioInterface::pullBuffer() (num_rd == OUTCHUNK
with num_rd=0) with the POWERON/POWEROFF/POWERON sequence.
2013-07-16 07:36:17 +04:00
Alexander Chemeris
f1c5b4f765 Transceiver52M: Introduce usage counting for DriveLoop and RadioInterface.
The reason is to allow them to be started from any TRX. I.e. they are started
when the first TRX starts and stopped when the last TRX stops.
2013-07-16 07:36:17 +04:00
6 changed files with 82 additions and 17 deletions

View File

@@ -18,11 +18,18 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#hack to get around symlink svn:externals in git -kurtis
top_srcdir = $(abs_top_srcdir)
top_builddir = $(abs_top_builddir)
COMMON_INCLUDEDIR = $(top_srcdir)/CommonLibs
GSM_INCLUDEDIR = $(top_srcdir)/GSM
SQLITE_INCLUDEDIR = $(top_srcdir)/sqlite3
SVNDEV = -D'SVN_REV="$(shell svnversion -n $(top_builddir))"'
STD_DEFINES_AND_INCLUDES = \
$(SVNDEV) \
-I$(COMMON_INCLUDEDIR) \
-I$(GSM_INCLUDEDIR) \
-I$(SQLITE_INCLUDEDIR)

View File

@@ -33,6 +33,7 @@ DriveLoop::DriveLoop(int wBasePort, const char *TRXAddress,
int wChanM, int wC0, int wSamplesPerSymbol,
GSM::Time wTransmitLatency)
: Thread("DriveLoop")
, mUseCount(0)
, mClockSocket(wBasePort, TRXAddress, wBasePort + 100)
, mC0(wC0)
{
@@ -85,6 +86,32 @@ DriveLoop::~DriveLoop()
sigProcLibDestroy();
}
bool DriveLoop::start()
{
// Use count must not be negative
assert(mUseCount>=0);
mUseCount++;
if (mUseCount>1)
return false;
startThread();
return true;
}
bool DriveLoop::stop()
{
// Use count must not be negative or zero
assert(mUseCount>0);
mUseCount--;
if (mUseCount>0)
return false;
stopThread();
return true;
}
void DriveLoop::pushRadioVector(GSM::Time &nowTime)
{
int i;

View File

@@ -45,10 +45,12 @@
//#define TRANSMIT_LOGGING 1
/** The Transceiver class, responsible for physical layer of basestation */
class DriveLoop : public Thread {
class DriveLoop : private Thread {
private:
int mUseCount; ///< Use counter
GSM::Time mTransmitLatency; ///< latency between basestation clock and transmit deadline clock
GSM::Time mLatencyUpdateTime; ///< last time latency was updated
GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core
@@ -110,6 +112,11 @@ public:
/** Destructor */
~DriveLoop();
/** Increase usage counter and start the thread if not started yet */
bool start();
/** Decrease usage counter and stop the thread if no users left */
bool stop();
VectorQueue *priorityQueue(int m) { return &mTransmitPriorityQueue[m]; }
/** Codes for burst types of received bursts*/

View File

@@ -37,6 +37,8 @@
#include "config.h"
#endif
extern volatile bool gbShutdown;
using namespace GSM;
#define USB_LATENCY_INTRVL 10,0
@@ -85,7 +87,7 @@ Transceiver::Transceiver(int wBasePort, const char *TRXAddress,
mRxFreq = 0.0;
mFreqOffset = 0.0;
mPower = -10;
mPower = -20;
mEnergyThreshold = INIT_ENERGY_THRSHD;
prevFalseDetectionTime = mDriveLoop->getStartTime();
}
@@ -306,12 +308,6 @@ void Transceiver::start()
{
mRunning = true;
mControlServiceLoop.startThread((void*) this);
if (!mPrimary) {
mOn = true;
mFIFOServiceLoop.startThread((void*) this);
mTransmitPriorityQueueServiceLoop.startThread((void*) this);
}
}
void Transceiver::shutdown()
@@ -371,6 +367,19 @@ void Transceiver::driveControl()
if (strcmp(command,"POWEROFF")==0) {
// turn off transmitter/demod
sprintf(response,"RSP POWEROFF 0");
if (mOn) {
// Stop radio interface threads.
mOn = false;
mFIFOServiceLoop.shutdown();
mTransmitPriorityQueueServiceLoop.shutdown();
mRadioInterface->stop();
mDriveLoop->stop();
if (mPrimary) {
gbShutdown = true;
}
}
}
else if (strcmp(command,"POWERON")==0) {
// turn on transmitter/demod
@@ -378,14 +387,15 @@ void Transceiver::driveControl()
sprintf(response,"RSP POWERON 1");
else {
sprintf(response,"RSP POWERON 0");
if (mPrimary && !mOn) {
if (!mOn) {
// Prepare for thread start
mPower = -20;
mRadioInterface->start();
mDriveLoop->startThread();
mDriveLoop->start();
mDriveLoop->writeClockInterface();
generateRACHSequence(*gsmPulse,mSamplesPerSymbol);
if (mPrimary) {
generateRACHSequence(*gsmPulse,mSamplesPerSymbol);
}
// Start radio interface threads.
mOn = true;

View File

@@ -55,6 +55,7 @@ RadioInterface::RadioInterface(RadioDevice *wRadio,
int wReceiveOffset,
GSM::Time wStartTime)
: mChanM(wChanM), underrun(false), sendCursor(0), rcvCursor(0), mOn(false),
mUseCount(0),
mRadio(wRadio), receiveOffset(wReceiveOffset), samplesPerSymbol(wSPS),
powerScaling(1.0), loadTest(false)
{
@@ -147,9 +148,13 @@ bool RadioInterface::tuneRx(double freq, int chan)
bool RadioInterface::start()
{
int i;
// Use count must not be negative
assert(mUseCount>=0);
// Being on while mUseCount is 0 is a wrong condition
assert(!(mOn && mUseCount==0));
if (mOn)
mUseCount++;
if (mOn || mUseCount>1)
return false;
mOn = true;
@@ -160,7 +165,7 @@ bool RadioInterface::start()
#endif
writeTimestamp = mRadio->initialWriteTimestamp();
readTimestamp = mRadio->initialReadTimestamp();
for (i = 0; i < mChanM; i++) {
for (int i = 0; i < mChanM; i++) {
sendBuffer[i] = new float[8*2*INCHUNK];
rcvBuffer[i] = new float[8*2*OUTCHUNK];
}
@@ -178,11 +183,18 @@ bool RadioInterface::start()
bool RadioInterface::stop()
{
if (!mOn)
// Use count must not be negative or zero
assert(mUseCount>0);
// Must be on while stopping
assert(mOn);
mUseCount--;
if (mUseCount>0)
return false;
mOn = false;
mRadio->stop();
return true;
}
#ifdef USRP1

View File

@@ -59,6 +59,7 @@ protected:
int receiveOffset; ///< offset b/w transmit and receive GSM timestamps, in timeslots
bool mOn; ///< indicates radio is on
int mUseCount; ///< Use counter
double powerScaling;
@@ -90,8 +91,9 @@ private:
public:
/** start the interface */
/** Increase usage counter and start the interface if not started yet */
bool start();
/** Decrease usage counter and stop the interface if no users left */
bool stop();
bool started() { return mOn; };