aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M
diff options
context:
space:
mode:
authorThomas Tsou <tom@tsou.cc>2013-09-02 13:51:11 +0800
committerThomas Tsou <tom@tsou.cc>2013-09-05 04:55:30 -0400
commitc8ce878daf1ea2c2e05cc6ed70dad2069a69015f (patch)
tree60ca3dc2540993ba661e8f229da9934a9fccc6c7 /Transceiver52M
parente01e1b3fa825cf7d80d5f0bb35062cb6db7cdc49 (diff)
Transceiver52M: Make GSM pulse filter internal to implementation
There is no reason expose the pulse shaping filter outside of the signal processing calls. The main transceiver object makes no use of the filter and there's no reason to pass it around. Initialize the pulse shape with the signal processing library, and maintain an internal static member like many of the other library variables. Similarly destroy the object when the library is closed. Signed-off-by: Thomas Tsou <tom@tsou.cc>
Diffstat (limited to 'Transceiver52M')
-rw-r--r--Transceiver52M/DriveLoop.cpp49
-rw-r--r--Transceiver52M/DriveLoop.h3
-rw-r--r--Transceiver52M/Transceiver.cpp16
-rw-r--r--Transceiver52M/Transceiver.h2
-rw-r--r--Transceiver52M/multiTRX.cpp6
-rw-r--r--Transceiver52M/sigProcLib.cpp135
-rw-r--r--Transceiver52M/sigProcLib.h17
7 files changed, 113 insertions, 115 deletions
diff --git a/Transceiver52M/DriveLoop.cpp b/Transceiver52M/DriveLoop.cpp
index e50c5cd..b4541f6 100644
--- a/Transceiver52M/DriveLoop.cpp
+++ b/Transceiver52M/DriveLoop.cpp
@@ -46,18 +46,40 @@ DriveLoop::DriveLoop(int wBasePort, const char *TRXAddress,
mLastClockUpdateTime = mStartTime;
mRadioInterface->getClock()->set(mStartTime);
+ txFullScale = mRadioInterface->fullScaleInputValue();
- // generate pulse and setup up signal processing library
- gsmPulse = generateGSMPulse(2, mSPS);
- LOG(DEBUG) << "gsmPulse: " << *gsmPulse;
- sigProcLibSetup(mSPS);
+ mOn = false;
+}
- txFullScale = mRadioInterface->fullScaleInputValue();
+DriveLoop::~DriveLoop()
+{
+ if (mOn) {
+ mOn = false;
+
+ if (mRadioDriveLoopThread)
+ delete mRadioDriveLoopThread;
+ }
+
+ sigProcLibDestroy();
+}
+
+bool DriveLoop::init()
+{
+ if (!sigProcLibSetup(mSPS)) {
+ LOG(ALERT) << "Failed to initialize signal processing library";
+ return false;
+ }
// initialize filler tables with dummy bursts on C0, empty bursts otherwise
for (int i = 0; i < 8; i++) {
- signalVector* modBurst = modulateBurst(gDummyBurst, *gsmPulse,
+ signalVector* modBurst = modulateBurst(gDummyBurst,
8 + (i % 4 == 0), mSPS);
+ if (!modBurst) {
+ sigProcLibDestroy();
+ LOG(ALERT) << "Failed to initialize filler table";
+ return false;
+ }
+
scaleVector(*modBurst, txFullScale);
for (int j = 0; j < 102; j++) {
for (int n = 0; n < mChanM; n++) {
@@ -75,20 +97,7 @@ DriveLoop::DriveLoop(int wBasePort, const char *TRXAddress,
}
}
- mOn = false;
-}
-
-DriveLoop::~DriveLoop()
-{
- if (mOn) {
- mOn = false;
-
- if (mRadioDriveLoopThread)
- delete mRadioDriveLoopThread;
- }
-
- delete gsmPulse;
- sigProcLibDestroy();
+ return true;
}
void DriveLoop::start()
diff --git a/Transceiver52M/DriveLoop.h b/Transceiver52M/DriveLoop.h
index 0e7dc3c..0a1d6d5 100644
--- a/Transceiver52M/DriveLoop.h
+++ b/Transceiver52M/DriveLoop.h
@@ -79,8 +79,6 @@ private:
/** Pull and demodulate a burst from the receive FIFO */
SoftVector *pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset);
- signalVector *gsmPulse; ///< the GSM shaping pulse for modulation
-
int mSPS; ///< number of samples per GSM symbol
bool mOn; ///< flag to indicate that transceiver is powered on
@@ -113,6 +111,7 @@ public:
~DriveLoop();
/** start the Transceiver */
+ bool init();
void start();
VectorQueue *priorityQueue(int m) { return &mTransmitPriorityQueue[m]; }
diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp
index 055dd26..063f04a 100644
--- a/Transceiver52M/Transceiver.cpp
+++ b/Transceiver52M/Transceiver.cpp
@@ -62,10 +62,6 @@ Transceiver::Transceiver(int wBasePort, const char *TRXAddress,
mTransmitPriorityQueueServiceLoopThread = NULL;
mMaxExpectedDelay = 0;
- // generate pulse and setup up signal processing library
- gsmPulse = generateGSMPulse(2,mSPS);
- LOG(DEBUG) << "gsmPulse: " << *gsmPulse;
-
mTransmitPriorityQueue = mDriveLoop->priorityQueue(mChannel);
mReceiveFIFO = mRadioInterface->receiveFIFO(mChannel);
@@ -93,7 +89,6 @@ Transceiver::Transceiver(int wBasePort, const char *TRXAddress,
Transceiver::~Transceiver()
{
- delete gsmPulse;
mTransmitPriorityQueue->clear();
delete mFIFOServiceLoopThread;
@@ -107,9 +102,9 @@ void Transceiver::addRadioVector(BitVector &burst,
GSM::Time &wTime)
{
// modulate and stick into queue
- signalVector* modBurst = modulateBurst(burst,*gsmPulse,
- 8 + (wTime.TN() % 4 == 0),
- mSPS);
+ signalVector* modBurst = modulateBurst(burst,
+ 8 + (wTime.TN() % 4 == 0),
+ mSPS);
scaleVector(*modBurst,txFullScale * pow(10,-RSSI/10));
radioVector *newVec = new radioVector(*modBurst,wTime);
mTransmitPriorityQueue->write(newVec);
@@ -238,7 +233,6 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
if ((rxBurst) && (success)) {
if ((corrType == DriveLoop::RACH) || (!needDFE)) {
burst = demodulateBurst(*vectorBurst,
- *gsmPulse,
mSPS,
amplitude,TOA);
}
@@ -385,7 +379,7 @@ void Transceiver::driveControl()
mDriveLoop->start();
mDriveLoop->writeClockInterface();
- generateRACHSequence(*gsmPulse,mSPS);
+ generateRACHSequence(mSPS);
// Start radio interface threads.
mOn = true;
@@ -477,7 +471,7 @@ void Transceiver::driveControl()
sprintf(response,"RSP SETTSC 1 %d",TSC);
else {
mTSC = TSC;
- generateMidamble(*gsmPulse,mSPS,TSC);
+ generateMidamble(mSPS, TSC);
sprintf(response,"RSP SETTSC 0 %d",TSC);
}
}
diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h
index 847a3c6..46a721d 100644
--- a/Transceiver52M/Transceiver.h
+++ b/Transceiver52M/Transceiver.h
@@ -86,8 +86,6 @@ private:
void pullFIFO(void); ///< blocking call on receive FIFO
- signalVector *gsmPulse; ///< the GSM shaping pulse for modulation
-
int mSPS; ///< number of samples per GSM symbol
bool mOn; ///< flag to indicate that transceiver is powered on
diff --git a/Transceiver52M/multiTRX.cpp b/Transceiver52M/multiTRX.cpp
index e988eec..34d7a75 100644
--- a/Transceiver52M/multiTRX.cpp
+++ b/Transceiver52M/multiTRX.cpp
@@ -93,7 +93,11 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
- DriveLoop *drive = new DriveLoop(5700, "127.0.0.1", radio, numARFCN, 0);
+ DriveLoop *drive;
+ drive = new DriveLoop(5700, "127.0.0.1", radio, numARFCN, 0);
+ if (!drive->init()) {
+ LOG(ALERT) << "Failed to initialize drive loop";
+ }
Transceiver *trx[CHAN_MAX];
bool primary = true;
diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp
index b7f3511..ab605cf 100644
--- a/Transceiver52M/sigProcLib.cpp
+++ b/Transceiver52M/sigProcLib.cpp
@@ -58,8 +58,27 @@ typedef struct {
complex gain;
} CorrelationSequence;
+/*
+ * Gaussian and empty modulation pulses
+ */
+struct PulseSequence {
+ PulseSequence() : gaussian(NULL), empty(NULL)
+ {
+ }
+
+ ~PulseSequence()
+ {
+ delete gaussian;
+ delete empty;
+ }
+
+ signalVector *gaussian;
+ signalVector *empty;
+};
+
CorrelationSequence *gMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
CorrelationSequence *gRACHSequence = NULL;
+PulseSequence *GSMPulse = NULL;
void sigProcLibDestroy(void) {
if (GMSKRotation) {
@@ -234,6 +253,7 @@ void sigProcLibSetup(int sps)
{
initTrigTables();
initGMSKRotationTables(sps);
+ generateGSMPulse(sps, 2);
}
void GMSKRotate(signalVector &x) {
@@ -439,25 +459,36 @@ signalVector* convolve(const signalVector *a,
}
-signalVector* generateGSMPulse(int sps, int symbolLength)
+void generateGSMPulse(int sps, int symbolLength)
{
+ int len;
+ float arg, center;
- int numSamples = sps * symbolLength + 1;
- signalVector *x = new signalVector(numSamples);
- signalVector::iterator xP = x->begin();
- int centerPoint = (numSamples-1)/2;
- for (int i = 0; i < numSamples; i++) {
- float arg = (float) (i - centerPoint) / (float) sps;
- *xP++ = 0.96*exp(-1.1380*arg*arg-0.527*arg*arg*arg*arg); // GSM pulse approx.
+ delete GSMPulse;
+
+ /* Store a single tap filter used for correlation sequence generation */
+ GSMPulse = new PulseSequence();
+ GSMPulse->empty = new signalVector(1);
+ GSMPulse->empty->isRealOnly(true);
+ *(GSMPulse->empty->begin()) = 1.0f;
+
+ /* GSM pulse approximation */
+ GSMPulse->gaussian = new signalVector(len);
+ GSMPulse->gaussian->isRealOnly(true);
+ signalVector::iterator xP = GSMPulse->gaussian->begin();
+
+ center = (float) (len - 1.0) / 2.0;
+
+ for (int i = 0; i < len; i++) {
+ arg = ((float) i - center) / (float) sps;
+ *xP++ = 0.96 * exp(-1.1380 * arg * arg -
+ 0.527 * arg * arg * arg * arg);
}
- float avgAbsval = sqrtf(vectorNorm2(*x) / sps);
- xP = x->begin();
- for (int i = 0; i < numSamples; i++)
+ float avgAbsval = sqrtf(vectorNorm2(*GSMPulse->gaussian)/sps);
+ xP = GSMPulse->gaussian->begin();
+ for (int i = 0; i < len; i++)
*xP++ /= avgAbsval;
- x->isRealOnly(true);
- x->setSymmetry(ABSSYM);
- return x;
}
signalVector* frequencyShift(signalVector *y,
@@ -564,36 +595,22 @@ bool vectorSlicer(signalVector *x)
return true;
}
-signalVector *modulateBurst(const BitVector &wBurst,
- const signalVector &gsmPulse,
- int guardPeriodLength,
- int sps)
+signalVector *modulateBurst(const BitVector &wBurst, int guardPeriodLength,
+ int sps, bool emptyPulse)
{
+ int burstLen;
+ signalVector *pulse, modBurst;
+ signalVector::iterator modBurstItr;
+
+ if (emptyPulse)
+ pulse = GSMPulse->empty;
+ else
+ pulse = GSMPulse->gaussian;
+
+ burstLen = sps * (wBurst.size() + guardPeriodLength);
+ modBurst = signalVector(burstLen);
+ modBurstItr = modBurst.begin();
- //static complex staticBurst[157];
-
- int burstSize = sps * (wBurst.size() + guardPeriodLength);
- //signalVector modBurst((complex *) staticBurst,0,burstSize);
- signalVector modBurst(burstSize);// = new signalVector(burstSize);
- modBurst.isRealOnly(true);
- //memset(staticBurst,0,sizeof(complex)*burstSize);
- modBurst.fill(0.0);
- signalVector::iterator modBurstItr = modBurst.begin();
-
-#if 0
- // if wBurst is already differentially decoded
- *modBurstItr = 2.0*(wBurst[0] & 0x01)-1.0;
- signalVector::iterator prevVal = modBurstItr;
- for (unsigned int i = 1; i < wBurst.size(); i++) {
- modBurstItr += sps;
- if (wBurst[i] & 0x01)
- *modBurstItr = *prevVal * complex(0.0,1.0);
- else
- *modBurstItr = *prevVal * complex(0.0,-1.0);
- prevVal = modBurstItr;
- }
-#else
- // if wBurst are the raw bits
for (unsigned int i = 0; i < wBurst.size(); i++) {
*modBurstItr = 2.0*(wBurst[i] & 0x01)-1.0;
modBurstItr += sps;
@@ -602,16 +619,13 @@ signalVector *modulateBurst(const BitVector &wBurst,
// shift up pi/2
// ignore starting phase, since spec allows for discontinuous phase
GMSKRotate(modBurst);
-#endif
+
modBurst.isRealOnly(false);
// filter w/ pulse shape
- signalVector *shapedBurst = convolve(&modBurst,&gsmPulse,NULL,NO_DELAY);
+ signalVector *shapedBurst = convolve(&modBurst, pulse, NULL, NO_DELAY);
- //delete modBurst;
-
return shapedBurst;
-
}
float sinc(float x)
@@ -837,11 +851,8 @@ void offsetVector(signalVector &x,
}
}
-bool generateMidamble(signalVector &gsmPulse,
- int sps,
- int TSC)
+bool generateMidamble(int sps, int TSC)
{
-
if ((TSC < 0) || (TSC > 7))
return false;
@@ -850,18 +861,13 @@ bool generateMidamble(signalVector &gsmPulse,
if (gMidambles[TSC]->sequenceReversedConjugated!=NULL) delete gMidambles[TSC]->sequenceReversedConjugated;
}
- signalVector emptyPulse(1);
- *(emptyPulse.begin()) = 1.0;
-
// only use middle 16 bits of each TSC
signalVector *middleMidamble = modulateBurst(gTrainingSequence[TSC].segment(5,16),
- emptyPulse,
0,
- sps);
+ sps, true);
signalVector *midamble = modulateBurst(gTrainingSequence[TSC],
- gsmPulse,
0,
- sps);
+ sps, false);
if (midamble == NULL) return false;
if (middleMidamble == NULL) return false;
@@ -895,17 +901,14 @@ bool generateMidamble(signalVector &gsmPulse,
return true;
}
-bool generateRACHSequence(signalVector &gsmPulse,
- int sps)
+bool generateRACHSequence(int sps)
{
-
if (gRACHSequence) {
if (gRACHSequence->sequence!=NULL) delete gRACHSequence->sequence;
if (gRACHSequence->sequenceReversedConjugated!=NULL) delete gRACHSequence->sequenceReversedConjugated;
}
signalVector *RACHSeq = modulateBurst(gRACHSynchSequence,
- gsmPulse,
0,
sps);
@@ -1136,12 +1139,8 @@ signalVector *decimateVector(signalVector &wVector,
}
-SoftVector *demodulateBurst(signalVector &rxBurst,
- const signalVector &gsmPulse,
- int sps,
- complex channel,
- float TOA)
-
+SoftVector *demodulateBurst(signalVector &rxBurst, int sps,
+ complex channel, float TOA)
{
scaleVector(rxBurst,((complex) 1.0)/channel);
delayVector(rxBurst,-TOA);
diff --git a/Transceiver52M/sigProcLib.h b/Transceiver52M/sigProcLib.h
index e91644c..a9fabb0 100644
--- a/Transceiver52M/sigProcLib.h
+++ b/Transceiver52M/sigProcLib.h
@@ -125,7 +125,7 @@ signalVector* convolve(const signalVector *a,
@param symbolLength The size of the pulse.
@return The GSM pulse.
*/
-signalVector* generateGSMPulse(int sps, int symbolLength);
+void generateGSMPulse(int sps, int symbolLength);
/**
Frequency shift a vector.
@@ -162,9 +162,8 @@ bool vectorSlicer(signalVector *x);
/** GMSK modulate a GSM burst of bits */
signalVector *modulateBurst(const BitVector &wBurst,
- const signalVector &gsmPulse,
int guardPeriodLength,
- int sps);
+ int sps, bool emptyPulse = false);
/** Sinc function */
float sinc(float x);
@@ -229,15 +228,14 @@ void offsetVector(signalVector &x,
@param TSC The training sequence [0..7]
@return Success.
*/
-bool generateMidamble(signalVector &gsmPulse, int sps, int tsc);
+bool generateMidamble(int sps, int tsc);
/**
Generate a modulated RACH sequence, stored within the library.
@param gsmPulse The GSM pulse used for modulation.
@param sps The number of samples per GSM symbol.
@return Success.
*/
-bool generateRACHSequence(signalVector &gsmPulse,
- int sps);
+bool generateRACHSequence(int sps);
/**
Energy detector, checks to see if received burst energy is above a threshold.
@@ -310,11 +308,8 @@ signalVector *decimateVector(signalVector &wVector,
@param TOA The time-of-arrival of the received burst.
@return The demodulated bit sequence.
*/
-SoftVector *demodulateBurst(signalVector &rxBurst,
- const signalVector &gsmPulse,
- int sps,
- complex channel,
- float TOA);
+SoftVector *demodulateBurst(signalVector &rxBurst, int sps,
+ complex channel, float TOA);
/**
Creates a simple Kaiser-windowed low-pass FIR filter.