aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/Transceiver.cpp
diff options
context:
space:
mode:
authorThomas Tsou <tom@tsou.cc>2013-10-29 18:34:16 -0400
committerThomas Tsou <tom@tsou.cc>2013-11-15 14:45:20 -0500
commit204a9f135ac2408dd62b55462ebe4b2d10be4f56 (patch)
tree80de459f10c23a103bf80172ba762f2577da0859 /Transceiver52M/Transceiver.cpp
parent0169b310de2789cbe2ec9a447caae494fbea13d0 (diff)
Transceiver52M: Add multi channel transceiver support
This patch primarily addresses devices with multiple RF front end support. Currently device support is limited to UmTRX. Vectorize transceiver variables to allow multiple asynchronous threads on the upper layer with single downlink and uplink threads driving the UHD I/O interface synchronously. Signed-off-by: Thomas Tsou <tom@tsou.cc>
Diffstat (limited to 'Transceiver52M/Transceiver.cpp')
-rw-r--r--Transceiver52M/Transceiver.cpp403
1 files changed, 238 insertions, 165 deletions
diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp
index fd6a008..2d4a3cb 100644
--- a/Transceiver52M/Transceiver.cpp
+++ b/Transceiver52M/Transceiver.cpp
@@ -76,142 +76,172 @@ void TransceiverState::init(size_t slot, signalVector *burst)
Transceiver::Transceiver(int wBasePort,
const char *TRXAddress,
- int wSPS,
+ size_t wSPS, size_t wChans,
GSM::Time wTransmitLatency,
RadioInterface *wRadioInterface)
: mBasePort(wBasePort), mAddr(TRXAddress),
- mDataSocket(NULL), mCtrlSocket(NULL), mClockSocket(NULL),
- mSPSTx(wSPS), mSPSRx(1), mNoises(NOISE_CNT)
+ mTransmitLatency(wTransmitLatency), mClockSocket(NULL), mRadioInterface(wRadioInterface),
+ mNoiseLev(0.0), mNoises(NOISE_CNT), mSPSTx(wSPS), mSPSRx(1), mChans(wChans),
+ mOn(false), mTxFreq(0.0), mRxFreq(0.0), mPower(-10), mMaxExpectedDelay(0)
{
GSM::Time startTime(random() % gHyperframe,0);
- mRxServiceLoopThread = new Thread(32768);
- mTxServiceLoopThread = new Thread(32768);
- mControlServiceLoopThread = new Thread(32768); ///< thread to process control messages from GSM core
- mTransmitPriorityQueueServiceLoopThread = new Thread(32768);///< thread to process transmit bursts from GSM core
+ mRxLowerLoopThread = new Thread(32768);
+ mTxLowerLoopThread = new Thread(32768);
- mRadioInterface = wRadioInterface;
- mTransmitLatency = wTransmitLatency;
mTransmitDeadlineClock = startTime;
mLastClockUpdateTime = startTime;
mLatencyUpdateTime = startTime;
mRadioInterface->getClock()->set(startTime);
- mMaxExpectedDelay = 0;
txFullScale = mRadioInterface->fullScaleInputValue();
rxFullScale = mRadioInterface->fullScaleOutputValue();
-
- mOn = false;
- mTxFreq = 0.0;
- mRxFreq = 0.0;
- mPower = -10;
- mNoiseLev = 0.0;
}
Transceiver::~Transceiver()
{
sigProcLibDestroy();
- mTransmitPriorityQueue.clear();
delete mClockSocket;
- delete mCtrlSocket;
- delete mDataSocket;
+
+ for (size_t i = 0; i < mChans; i++) {
+ mTxPriorityQueues[i].clear();
+ delete mCtrlSockets[i];
+ delete mDataSockets[i];
+ }
}
bool Transceiver::init()
{
signalVector *burst;
+ if (!mChans) {
+ LOG(ALERT) << "No channels assigned";
+ return false;
+ }
+
if (!sigProcLibSetup(mSPSTx)) {
LOG(ALERT) << "Failed to initialize signal processing library";
return false;
}
+ mDataSockets.resize(mChans);
+ mCtrlSockets.resize(mChans);
+
+ mControlServiceLoopThreads.resize(mChans);
+ mTxPriorityQueueServiceLoopThreads.resize(mChans);
+ mRxServiceLoopThreads.resize(mChans);
+
+ mTxPriorityQueues.resize(mChans);
+ mReceiveFIFO.resize(mChans);
+ mStates.resize(mChans);
+
mClockSocket = new UDPSocket(mBasePort, mAddr.c_str(), mBasePort + 100);
- mCtrlSocket = new UDPSocket(mBasePort + 1, mAddr.c_str(), mBasePort + 101);
- mDataSocket = new UDPSocket(mBasePort + 2, mAddr.c_str(), mBasePort + 102);
- for (size_t n = 0; n < 8; n++) {
- burst = modulateBurst(gDummyBurst, 8 + (n % 4 == 0), mSPSTx);
- scaleVector(*burst, txFullScale);
- mState.init(n, burst);
- mState.chanEstimateTime[n] = mTransmitDeadlineClock;
+ for (size_t i = 0; i < mChans; i++) {
+ mDataSockets[i] = new UDPSocket(mBasePort + 2 * i + 2, mAddr.c_str(),
+ mBasePort + 2 * i + 102);
+ mCtrlSockets[i] = new UDPSocket(mBasePort + 2 * i + 1, mAddr.c_str(),
+ mBasePort + 2 * i + 101);
+ }
+
+ for (size_t i = 0; i < mChans; i++) {
+ mControlServiceLoopThreads[i] = new Thread(32768);
+ mTxPriorityQueueServiceLoopThreads[i] = new Thread(32768);
+ mRxServiceLoopThreads[i] = new Thread(32768);
- delete burst;
+ for (size_t n = 0; n < 8; n++) {
+ burst = modulateBurst(gDummyBurst, 8 + (n % 4 == 0), mSPSTx);
+ scaleVector(*burst, txFullScale);
+ mStates[i].init(n, burst);
+ delete burst;
+ }
}
return true;
}
-void Transceiver::addRadioVector(BitVector &burst,
- int RSSI,
- GSM::Time &wTime)
+void Transceiver::addRadioVector(size_t chan, BitVector &burst,
+ int RSSI, GSM::Time &wTime)
{
+ if (chan >= mTxPriorityQueues.size()) {
+ LOG(ALERT) << "Invalid channel " << chan;
+ return;
+ }
+
// modulate and stick into queue
signalVector* modBurst = modulateBurst(burst,
8 + (wTime.TN() % 4 == 0),
mSPSTx);
scaleVector(*modBurst,txFullScale * pow(10,-RSSI/10));
radioVector *newVec = new radioVector(*modBurst,wTime);
- mTransmitPriorityQueue.write(newVec);
+ mTxPriorityQueues[chan].write(newVec);
delete modBurst;
}
void Transceiver::pushRadioVector(GSM::Time &nowTime)
{
+ int TN, modFN;
+ radioVector *burst;
+ TransceiverState *state;
+ std::vector<signalVector *> bursts(mChans);
+ std::vector<bool> zeros(mChans);
- // dump stale bursts, if any
- while (radioVector* staleBurst = mTransmitPriorityQueue.getStaleBurst(nowTime)) {
- // Even if the burst is stale, put it in the fillter table.
- // (It might be an idle pattern.)
- LOG(NOTICE) << "dumping STALE burst in TRX->USRP interface";
- const GSM::Time& nextTime = staleBurst->getTime();
- int TN = nextTime.TN();
- int modFN = nextTime.FN() % mState.fillerModulus[TN];
- delete mState.fillerTable[modFN][TN];
- mState.fillerTable[modFN][TN] = staleBurst;
- }
-
- int TN = nowTime.TN();
- int modFN = nowTime.FN() % mState.fillerModulus[nowTime.TN()];
-
- // if queue contains data at the desired timestamp, stick it into FIFO
- if (radioVector *next = (radioVector*) mTransmitPriorityQueue.getCurrentBurst(nowTime)) {
- LOG(DEBUG) << "transmitFIFO: wrote burst " << next << " at time: " << nowTime;
- delete mState.fillerTable[modFN][TN];
- mState.fillerTable[modFN][TN] = new signalVector(*(next));
- mRadioInterface->driveTransmitRadio(*(next), mState.chanType[TN] == NONE);
- delete next;
- return;
+ for (size_t i = 0; i < mChans; i ++) {
+ state = &mStates[i];
+
+ while ((burst = mTxPriorityQueues[i].getStaleBurst(nowTime))) {
+ LOG(NOTICE) << "dumping STALE burst in TRX->USRP interface";
+
+ TN = burst->getTime().TN();
+ modFN = burst->getTime().FN() % state->fillerModulus[TN];
+
+ delete state->fillerTable[modFN][TN];
+ state->fillerTable[modFN][TN] = burst;
+ }
+
+ TN = nowTime.TN();
+ modFN = nowTime.FN() % state->fillerModulus[TN];
+
+ bursts[i] = state->fillerTable[modFN][TN];
+ zeros[i] = state->chanType[TN] == NONE;
+
+ if ((burst = mTxPriorityQueues[i].getCurrentBurst(nowTime))) {
+ delete state->fillerTable[modFN][TN];
+ state->fillerTable[modFN][TN] = burst;
+ bursts[i] = burst;
+ }
}
- // otherwise, pull filler data, and push to radio FIFO
- mRadioInterface->driveTransmitRadio(*(mState.fillerTable[modFN][TN]),
- mState.chanType[TN]==NONE);
+ mRadioInterface->driveTransmitRadio(bursts, zeros);
+
+ return;
}
-void Transceiver::setModulus(int timeslot)
+void Transceiver::setModulus(size_t timeslot, size_t chan)
{
- switch (mState.chanType[timeslot]) {
+ TransceiverState *state = &mStates[chan];
+
+ switch (state->chanType[timeslot]) {
case NONE:
case I:
case II:
case III:
case FILL:
- mState.fillerModulus[timeslot] = 26;
+ state->fillerModulus[timeslot] = 26;
break;
case IV:
case VI:
case V:
- mState.fillerModulus[timeslot] = 51;
+ state->fillerModulus[timeslot] = 51;
break;
//case V:
case VII:
- mState.fillerModulus[timeslot] = 102;
+ state->fillerModulus[timeslot] = 102;
break;
case XIII:
- mState.fillerModulus[timeslot] = 52;
+ state->fillerModulus[timeslot] = 52;
break;
default:
break;
@@ -219,13 +249,14 @@ void Transceiver::setModulus(int timeslot)
}
-Transceiver::CorrType Transceiver::expectedCorrType(GSM::Time currTime)
+Transceiver::CorrType Transceiver::expectedCorrType(GSM::Time currTime,
+ size_t chan)
{
-
+ TransceiverState *state = &mStates[chan];
unsigned burstTN = currTime.TN();
unsigned burstFN = currTime.FN();
- switch (mState.chanType[burstTN]) {
+ switch (state->chanType[burstTN]) {
case NONE:
return OFF;
break;
@@ -287,25 +318,24 @@ Transceiver::CorrType Transceiver::expectedCorrType(GSM::Time currTime)
return OFF;
break;
}
-
}
-SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
- int &RSSI,
- int &timingOffset)
+SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, int &RSSI,
+ int &timingOffset, size_t chan)
{
- bool needDFE = false, success = false, estimateChannel = false;
+ bool needDFE = false;
+ bool success = false;
complex amp = 0.0;
float TOA = 0.0, avg = 0.0;
- signalVector *chanResponse;
+ TransceiverState *state = &mStates[chan];
- radioVector *rxBurst = (radioVector *) mReceiveFIFO->get();
+ radioVector *rxBurst = (radioVector *) mReceiveFIFO[chan]->read();
if (!rxBurst) return NULL;
int timeslot = rxBurst->getTime().TN();
- CorrType corrType = expectedCorrType(rxBurst->getTime());
+ CorrType corrType = expectedCorrType(rxBurst->getTime(), chan);
if ((corrType==OFF) || (corrType==IDLE)) {
delete rxBurst;
@@ -323,55 +353,58 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
// run the proper correlator
if (corrType==TSC) {
LOG(DEBUG) << "looking for TSC at time: " << rxBurst->getTime();
- double framesElapsed = rxBurst->getTime() - mState.chanEstimateTime[timeslot];
- if ((framesElapsed > 50) || (!mState.chanResponse[timeslot])) {
- delete mState.chanResponse[timeslot];
- delete mState.DFEForward[timeslot];
- delete mState.DFEFeedback[timeslot];
-
- mState.chanResponse[timeslot] = NULL;
- mState.DFEForward[timeslot] = NULL;
- mState.DFEFeedback[timeslot] = NULL;
-
- if (needDFE)
- estimateChannel = true;
+ signalVector *channelResp;
+ double framesElapsed = rxBurst->getTime() - state->chanEstimateTime[timeslot];
+ bool estimateChannel = false;
+ if ((framesElapsed > 50) || (state->chanResponse[timeslot]==NULL)) {
+ if (state->chanResponse[timeslot])
+ delete state->chanResponse[timeslot];
+ if (state->DFEForward[timeslot])
+ delete state->DFEForward[timeslot];
+ if (state->DFEFeedback[timeslot])
+ delete state->DFEFeedback[timeslot];
+
+ state->chanResponse[timeslot] = NULL;
+ state->DFEForward[timeslot] = NULL;
+ state->DFEFeedback[timeslot] = NULL;
+ estimateChannel = true;
}
-
+ if (!needDFE) estimateChannel = false;
float chanOffset;
success = analyzeTrafficBurst(*vectorBurst,
- mTSC,
- 5.0,
- mSPSRx,
- &amp,
- &TOA,
- mMaxExpectedDelay,
- estimateChannel,
- &chanResponse,
- &chanOffset);
+ mTSC,
+ 5.0,
+ mSPSRx,
+ &amp,
+ &TOA,
+ mMaxExpectedDelay,
+ estimateChannel,
+ &channelResp,
+ &chanOffset);
if (success) {
- mState.SNRestimate[timeslot] = amp.norm2() / (mNoiseLev * mNoiseLev+1.0);
- if (estimateChannel) {
- mState.chanResponse[timeslot] = chanResponse;
- mState.chanRespOffset[timeslot] = chanOffset;
- mState.chanRespAmplitude[timeslot] = amp;
- scaleVector(*chanResponse, complex(1.0,0.0) / amp);
-
- designDFE(*chanResponse, mState.SNRestimate[timeslot], 7,
- &mState.DFEForward[timeslot],
- &mState.DFEFeedback[timeslot]);
+ state->SNRestimate[timeslot] = amp.norm2() / (mNoiseLev * mNoiseLev + 1.0);
- mState.chanEstimateTime[timeslot] = rxBurst->getTime();
+ if (estimateChannel) {
+ state->chanResponse[timeslot] = channelResp;
+ state->chanRespOffset[timeslot] = chanOffset;
+ state->chanRespAmplitude[timeslot] = amp;
+ scaleVector(*channelResp, complex(1.0, 0.0) / amp);
+ designDFE(*channelResp, state->SNRestimate[timeslot],
+ 7, &state->DFEForward[timeslot],
+ &state->DFEFeedback[timeslot]);
+
+ state->chanEstimateTime[timeslot] = rxBurst->getTime();
}
}
else {
- mState.chanResponse[timeslot] = NULL;
+ state->chanResponse[timeslot] = NULL;
mNoises.insert(avg);
}
}
else {
// RACH burst
- if (success = detectRACHBurst(*vectorBurst, 6.0, mSPSRx, &amp, &TOA))
- mState.chanResponse[timeslot] = NULL;
+ if ((success = detectRACHBurst(*vectorBurst, 6.0, mSPSRx, &amp, &TOA)))
+ state->chanResponse[timeslot] = NULL;
else
mNoises.insert(avg);
}
@@ -382,12 +415,12 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
if ((corrType==RACH) || (!needDFE)) {
burst = demodulateBurst(*vectorBurst, mSPSRx, amp, TOA);
} else {
- scaleVector(*vectorBurst,complex(1.0,0.0) / amp);
+ scaleVector(*vectorBurst, complex(1.0, 0.0) / amp);
burst = equalizeBurst(*vectorBurst,
- TOA - mState.chanRespOffset[timeslot],
- mSPSRx,
- *mState.DFEForward[timeslot],
- *mState.DFEFeedback[timeslot]);
+ TOA - state->chanRespOffset[timeslot],
+ mSPSRx,
+ *state->DFEForward[timeslot],
+ *state->DFEFeedback[timeslot]);
}
wTime = rxBurst->getTime();
RSSI = (int) floor(20.0*log10(rxFullScale/avg));
@@ -395,8 +428,6 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
timingOffset = (int) round(TOA * 256.0 / mSPSRx);
}
- //if (burst) LOG(DEBUG) << "burst: " << *burst << '\n';
-
delete rxBurst;
return burst;
@@ -404,20 +435,24 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
void Transceiver::start()
{
- mControlServiceLoopThread->start((void * (*)(void*))ControlServiceLoopAdapter,(void*) this);
+ TransceiverChannel *chan;
+
+ for (size_t i = 0; i < mControlServiceLoopThreads.size(); i++) {
+ chan = new TransceiverChannel(this, i);
+ mControlServiceLoopThreads[i]->start((void * (*)(void*))
+ ControlServiceLoopAdapter, (void*) chan);
+ }
}
void Transceiver::reset()
{
- mTransmitPriorityQueue.clear();
- //mTransmitFIFO->clear();
- //mReceiveFIFO->clear();
+ for (size_t i = 0; i < mTxPriorityQueues.size(); i++)
+ mTxPriorityQueues[i].clear();
}
-void Transceiver::driveControl()
+void Transceiver::driveControl(size_t chan)
{
-
int MAX_PACKET_LENGTH = 100;
// check control socket
@@ -425,7 +460,7 @@ void Transceiver::driveControl()
int msgLen = -1;
buffer[0] = '\0';
- msgLen = mCtrlSocket->read(buffer);
+ msgLen = mCtrlSockets[chan]->read(buffer);
if (msgLen < 1) {
return;
@@ -436,8 +471,9 @@ void Transceiver::driveControl()
char response[MAX_PACKET_LENGTH];
sscanf(buffer,"%3s %s",cmdcheck,command);
-
- writeClockInterface();
+
+ if (!chan)
+ writeClockInterface();
if (strcmp(cmdcheck,"CMD")!=0) {
LOG(WARNING) << "bogus message on control interface";
@@ -455,17 +491,28 @@ void Transceiver::driveControl()
sprintf(response,"RSP POWERON 1");
else {
sprintf(response,"RSP POWERON 0");
- if (!mOn) {
+ if (!chan && !mOn) {
// Prepare for thread start
mPower = -20;
mRadioInterface->start();
// Start radio interface threads.
- mTxServiceLoopThread->start((void * (*)(void*))TxServiceLoopAdapter,(void*) this);
- mRxServiceLoopThread->start((void * (*)(void*))RxServiceLoopAdapter,(void*) this);
- mTransmitPriorityQueueServiceLoopThread->start((void * (*)(void*))TransmitPriorityQueueServiceLoopAdapter,(void*) this);
- writeClockInterface();
+ mTxLowerLoopThread->start((void * (*)(void*))
+ TxLowerLoopAdapter,(void*) this);
+ mRxLowerLoopThread->start((void * (*)(void*))
+ RxLowerLoopAdapter,(void*) this);
+
+ for (size_t i = 0; i < mChans; i++) {
+ TransceiverChannel *chan = new TransceiverChannel(this, i);
+ mRxServiceLoopThreads[i]->start((void * (*)(void*))
+ RxUpperLoopAdapter, (void*) chan);
+
+ chan = new TransceiverChannel(this, i);
+ mTxPriorityQueueServiceLoopThreads[i]->start((void * (*)(void*))
+ TxUpperLoopAdapter, (void*) chan);
+ }
+ writeClockInterface();
mOn = true;
}
}
@@ -481,7 +528,7 @@ void Transceiver::driveControl()
//set expected maximum time-of-arrival
int newGain;
sscanf(buffer,"%3s %s %d",cmdcheck,command,&newGain);
- newGain = mRadioInterface->setRxGain(newGain);
+ newGain = mRadioInterface->setRxGain(newGain, chan);
sprintf(response,"RSP SETRXGAIN 0 %d",newGain);
}
else if (strcmp(command,"NOISELEV")==0) {
@@ -501,7 +548,7 @@ void Transceiver::driveControl()
sprintf(response,"RSP SETPOWER 1 %d",dbPwr);
else {
mPower = dbPwr;
- mRadioInterface->setPowerAttenuation(dbPwr);
+ mRadioInterface->setPowerAttenuation(dbPwr, chan);
sprintf(response,"RSP SETPOWER 0 %d",dbPwr);
}
}
@@ -522,7 +569,7 @@ void Transceiver::driveControl()
int freqKhz;
sscanf(buffer,"%3s %s %d",cmdcheck,command,&freqKhz);
mRxFreq = freqKhz*1.0e3+FREQOFFSET;
- if (!mRadioInterface->tuneRx(mRxFreq)) {
+ if (!mRadioInterface->tuneRx(mRxFreq, chan)) {
LOG(ALERT) << "RX failed to tune";
sprintf(response,"RSP RXTUNE 1 %d",freqKhz);
}
@@ -535,7 +582,7 @@ void Transceiver::driveControl()
sscanf(buffer,"%3s %s %d",cmdcheck,command,&freqKhz);
//freqKhz = 890e3;
mTxFreq = freqKhz*1.0e3+FREQOFFSET;
- if (!mRadioInterface->tuneTx(mTxFreq)) {
+ if (!mRadioInterface->tuneTx(mTxFreq, chan)) {
LOG(ALERT) << "TX failed to tune";
sprintf(response,"RSP TXTUNE 1 %d",freqKhz);
}
@@ -564,8 +611,8 @@ void Transceiver::driveControl()
sprintf(response,"RSP SETSLOT 1 %d %d",timeslot,corrCode);
return;
}
- mState.chanType[timeslot] = corrCode;
- setModulus(timeslot);
+ mStates[chan].chanType[timeslot] = (ChannelCombination) corrCode;
+ setModulus(timeslot, chan);
sprintf(response,"RSP SETSLOT 0 %d %d",timeslot,corrCode);
}
@@ -573,16 +620,15 @@ void Transceiver::driveControl()
LOG(WARNING) << "bogus command " << command << " on control interface.";
}
- mCtrlSocket->write(response, strlen(response) + 1);
+ mCtrlSockets[chan]->write(response, strlen(response) + 1);
}
-bool Transceiver::driveTransmitPriorityQueue()
+bool Transceiver::driveTxPriorityQueue(size_t chan)
{
-
char buffer[gSlotLen+50];
// check data socket
- size_t msgLen = mDataSocket->read(buffer);
+ size_t msgLen = mDataSockets[chan]->read(buffer);
if (msgLen!=gSlotLen+1+4+1) {
LOG(ERR) << "badly formatted packet on GSM->TRX interface";
@@ -613,9 +659,11 @@ bool Transceiver::driveTransmitPriorityQueue()
// periodically update GSM core clock
LOG(DEBUG) << "mTransmitDeadlineClock " << mTransmitDeadlineClock
<< " mLastClockUpdateTime " << mLastClockUpdateTime;
- if (mTransmitDeadlineClock > mLastClockUpdateTime + GSM::Time(216,0))
- writeClockInterface();
+ if (!chan) {
+ if (mTransmitDeadlineClock > mLastClockUpdateTime + GSM::Time(216,0))
+ writeClockInterface();
+ }
LOG(DEBUG) << "rcvd. burst at: " << GSM::Time(frameNum,timeSlot);
@@ -627,27 +675,28 @@ bool Transceiver::driveTransmitPriorityQueue()
*itr++ = *bufferItr++;
GSM::Time currTime = GSM::Time(frameNum,timeSlot);
-
- addRadioVector(newBurst,RSSI,currTime);
-
- LOG(DEBUG) "added burst - time: " << currTime << ", RSSI: " << RSSI; // << ", data: " << newBurst;
+
+ addRadioVector(chan, newBurst, RSSI, currTime);
return true;
}
-
-void Transceiver::driveReceiveFIFO()
+
+void Transceiver::driveReceiveRadio()
{
+ if (!mRadioInterface->driveReceiveRadio())
+ usleep(100000);
+}
+void Transceiver::driveReceiveFIFO(size_t chan)
+{
SoftVector *rxBurst = NULL;
int RSSI;
int TOA; // in 1/256 of a symbol
GSM::Time burstTime;
- mRadioInterface->driveReceiveRadio();
-
- rxBurst = pullRadioVector(burstTime,RSSI,TOA);
+ rxBurst = pullRadioVector(burstTime, RSSI, TOA, chan);
if (rxBurst) {
@@ -672,11 +721,11 @@ void Transceiver::driveReceiveFIFO()
burstString[gSlotLen+9] = '\0';
delete rxBurst;
- mDataSocket->write(burstString, gSlotLen + 10);
+ mDataSockets[chan]->write(burstString,gSlotLen+10);
}
}
-void Transceiver::driveTransmitFIFO()
+void Transceiver::driveTxFIFO()
{
/**
@@ -744,46 +793,70 @@ void Transceiver::writeClockInterface()
}
-void *RxServiceLoopAdapter(Transceiver *transceiver)
+void *RxUpperLoopAdapter(TransceiverChannel *chan)
+{
+ Transceiver *trx = chan->trx;
+ size_t num = chan->num;
+
+ delete chan;
+
+ while (1) {
+ trx->driveReceiveFIFO(num);
+ pthread_testcancel();
+ }
+ return NULL;
+}
+
+void *RxLowerLoopAdapter(Transceiver *transceiver)
{
transceiver->setPriority();
while (1) {
- transceiver->driveReceiveFIFO();
+ transceiver->driveReceiveRadio();
pthread_testcancel();
}
return NULL;
}
-void *TxServiceLoopAdapter(Transceiver *transceiver)
+void *TxLowerLoopAdapter(Transceiver *transceiver)
{
while (1) {
- transceiver->driveTransmitFIFO();
+ transceiver->driveTxFIFO();
pthread_testcancel();
}
return NULL;
}
-void *ControlServiceLoopAdapter(Transceiver *transceiver)
+void *ControlServiceLoopAdapter(TransceiverChannel *chan)
{
+ Transceiver *trx = chan->trx;
+ size_t num = chan->num;
+
+ delete chan;
+
while (1) {
- transceiver->driveControl();
+ trx->driveControl(num);
pthread_testcancel();
}
return NULL;
}
-void *TransmitPriorityQueueServiceLoopAdapter(Transceiver *transceiver)
+void *TxUpperLoopAdapter(TransceiverChannel *chan)
{
+ Transceiver *trx = chan->trx;
+ size_t num = chan->num;
+
+ delete chan;
+
while (1) {
bool stale = false;
// Flush the UDP packets until a successful transfer.
- while (!transceiver->driveTransmitPriorityQueue()) {
- stale = true;
+ while (!trx->driveTxPriorityQueue(num)) {
+ stale = true;
}
- if (stale) {
+ if (!num && stale) {
// If a packet was stale, remind the GSM stack of the clock.
- transceiver->writeClockInterface();
+ trx->writeClockInterface();
}
pthread_testcancel();
}