From 9d5d9217996fa961b7e391097eaede3f01378709 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Mon, 29 Jun 2015 20:16:47 -0400 Subject: Transceiver: First attempt to calculate received bursts phase error. --- CommonLibs/BitVector.cpp | 4 +- Transceiver52M/Transceiver.cpp | 147 +++++++++++++++++++++++++++++++++++------ Transceiver52M/Transceiver.h | 16 ++++- Transceiver52M/sigProcLib.cpp | 31 +++++---- Transceiver52M/sigProcLib.h | 17 +++-- 5 files changed, 174 insertions(+), 41 deletions(-) diff --git a/CommonLibs/BitVector.cpp b/CommonLibs/BitVector.cpp index 7487834..ccd3113 100644 --- a/CommonLibs/BitVector.cpp +++ b/CommonLibs/BitVector.cpp @@ -30,6 +30,7 @@ #include #include #include +#include using namespace std; @@ -533,7 +534,8 @@ float SoftVector::getEnergy(float *plow) const float avg = 0; float low = 1; for (int i = 0; i < len; i++) { float bit = vec[i]; - float energy = 2*((bit < 0.5) ? (0.5-bit) : (bit-0.5)); + float energy = 2*bit-1.0; + energy *= energy; if (energy < low) low = energy; avg += energy/len; } diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp index a4eda4b..d7b2da3 100644 --- a/Transceiver52M/Transceiver.cpp +++ b/Transceiver52M/Transceiver.cpp @@ -621,14 +621,28 @@ int Transceiver::detectTSC(TransceiverState *state, signalVector &burst, return 1; } +void writeToFile(signalVector *burst, const GSM::Time &time, size_t chan, const std::string postfix="") +{ + std::ostringstream fname; + fname << chan << "_" << time.FN() << "_" << time.TN() << postfix << ".fc"; + std::ofstream outfile(fname.str().c_str(), std::ofstream::binary); + outfile.write((char*)burst->begin(), burst->size() * 2 * sizeof(float)); + outfile.close(); +} + /* * Demodulate GMSK burst using equalization if requested. Otherwise * demodulate by direct rotation and soft slicing. */ SoftVector *Transceiver::demodulate(TransceiverState *state, signalVector &burst, complex amp, - float toa, size_t tn, bool equalize) + float toa, size_t tn, bool equalize, + GSM::Time &wTime, size_t chan) { + signalVector *aligned, *bit_aligned=NULL; + SoftVector *bits; + bool estimateQuality = true; + if (equalize) { scaleVector(burst, complex(1.0, 0.0) / amp); return equalizeBurst(burst, @@ -638,17 +652,28 @@ SoftVector *Transceiver::demodulate(TransceiverState *state, *state->DFEFeedback[tn]); } - return demodulateBurst(burst, mSPSRx, amp, toa); -} + aligned = alignBurst(burst, amp, toa); -void writeToFile(radioVector *radio_burst, size_t chan) -{ - GSM::Time time = radio_burst->getTime(); - std::ostringstream fname; - fname << chan << "_" << time.FN() << "_" << time.TN() << ".fc"; - std::ofstream outfile (fname.str().c_str(), std::ofstream::binary); - outfile.write((char*)radio_burst->getVector()->begin(), radio_burst->getVector()->size() * 2 * sizeof(float)); - outfile.close(); + if (estimateQuality) { + /* "aligned" burst has samples exactly between bits. + * Delay it by 1/2 bit more to get samples aligned to bit positions. */ + bit_aligned = delayVector(aligned, NULL, 0.5); + + /* Debug: dump bursts to disk */ + if (needWriteBurstToDisk(wTime, chan)) + writeToFile(bit_aligned, wTime, chan, "_aligned"); + } + + bits = demodulateBurst(*aligned, mSPSRx); + + if (estimateQuality) { + /* Estimate signal quality */ + estimateBurstQuality(bits->segment(0, gSlotLen).sliced(), bit_aligned, wTime, chan); + delete bit_aligned; + } + + delete aligned; + return bits; } /* @@ -679,10 +704,8 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i CorrType type = expectedCorrType(time, chan); /* Debug: dump bursts to disk */ - /* bits 0-7 - chan 0 timeslots - * bits 8-15 - chan 1 timeslots */ - if (mWriteBurstToDiskMask & ((1<getVector(), time, chan); /* No processing if the timeslot is off. * Not even power level or noise calculation. */ @@ -754,7 +777,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i if (equalize && (type != TSC)) equalize = false; - bits = demodulate(state, *burst, amp, toa, time.TN(), equalize); + bits = demodulate(state, *burst, amp, toa, time.TN(), equalize, time, chan); delete radio_burst; return bits; @@ -978,6 +1001,89 @@ void Transceiver::driveReceiveRadio() } } +inline float wrapAngle2Pi(float angle) +{ + const float twoPi = 2.0 * M_PI; + return angle - twoPi * floor( angle / twoPi ); +} + +inline float wrapAnglePi(float angle) +{ + const float twoPi = 2.0 * M_PI; + return angle - twoPi * floor( (angle+M_PI) / twoPi); +} + +inline float rad2deg(float rad) +{ + return rad*180/M_PI; +} + +inline int vectorMaxAbs(const Vector &vec) +{ + int max_idx = 0; + float max = 0.0; + for (size_t i=1; i max) { + max_idx = i; + max = fabs(vec[i]); + } + } + return max_idx; +} + +inline float vectorRMS(const Vector &vec) +{ + float rms = 0; + for (size_t i=1; i phase_err(148); // 148 bits - burst length including guard bits + Vector phase_err_deg(148); // 148 bits - burst length including guard bits + int phase_err_max; + float phase_err_rms; + + // this code supports only 4 SPS modulation + // we also assume that received vector is 1 SPS + assert(mSPSTx==4); + + burst = modulateBurst(wBits, 8 + (wTime.TN() % 4 == 0), mSPSTx); + + /* Debug: dump bursts to disk */ + if (needWriteBurstToDisk(wTime, chan)) + writeToFile(burst, wTime, chan, "_demod"); + + // flip values to align modulated format with the received format + for (size_t i=0; isize(); i++) { + (*burst)[i] = complex((*burst)[i].imag(), -(*burst)[i].real()); + } + + // calculate phase error for each bit + for (size_t i=0; igetEnergy() << " bits: " << *rxBurst; char burstString[gSlotLen+10]; diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h index bd8ec4f..29427ca 100644 --- a/Transceiver52M/Transceiver.h +++ b/Transceiver52M/Transceiver.h @@ -221,7 +221,8 @@ private: /** Demodulat burst and output soft bits */ SoftVector *demodulate(TransceiverState *state, signalVector &burst, complex amp, - float toa, size_t tn, bool equalize); + float toa, size_t tn, bool equalize, + GSM::Time &wTime, size_t chan); int mSPSTx; ///< number of samples per Tx symbol int mSPSRx; ///< number of samples per Rx symbol @@ -235,6 +236,15 @@ private: unsigned mMaxExpectedDelay; ///< maximum expected time-of-arrival offset in GSM symbols unsigned mWriteBurstToDiskMask; ///< debug: bitmask to indicate which timeslots to dump to disk + + bool needWriteBurstToDisk(const GSM::Time &wTime, size_t chan) + { + /* Debug: dump bursts to disk */ + /* bits 0-7 - chan 0 timeslots + * bits 8-15 - chan 1 timeslots */ + return mWriteBurstToDiskMask & ((1< mStates; /** Start and stop I/O threads through the control socket API */ @@ -245,6 +255,10 @@ private: Mutex mLock; protected: + + /** Estimate received burst quality and print it to debug output */ + void estimateBurstQuality(const BitVector &wBits, signalVector *received, const GSM::Time &wTime, size_t chan); + /** drive lower receive I/O and burst generation */ void driveReceiveRadio(); diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp index b5160ca..351a7a1 100644 --- a/Transceiver52M/sigProcLib.cpp +++ b/Transceiver52M/sigProcLib.cpp @@ -1523,35 +1523,40 @@ signalVector *decimateVector(signalVector &wVector, size_t factor) return dec; } -SoftVector *demodulateBurst(signalVector &rxBurst, int sps, - complex channel, float TOA) +signalVector *alignBurst(signalVector &rxBurst, complex channel, float TOA) { - signalVector *delay, *dec = NULL; - SoftVector *bits; + signalVector *delay; scaleVector(rxBurst, ((complex) 1.0) / channel); delay = delayVector(&rxBurst, NULL, -TOA); + return delay; +} + +SoftVector *demodulateBurst(signalVector &rxBurst, int sps) +{ + signalVector *burst, *dec = NULL; + SoftVector *bits; + /* Shift up by a quarter of a frequency */ - GMSKReverseRotate(*delay, sps); + GMSKReverseRotate(rxBurst, sps); /* Decimate and slice */ if (sps > 1) { - dec = decimateVector(*delay, sps); - delete delay; - delay = NULL; + dec = decimateVector(rxBurst, sps); + burst = dec; } else { - dec = delay; + burst = &rxBurst; } - vectorSlicer(dec); + vectorSlicer(burst); - bits = new SoftVector(dec->size()); + bits = new SoftVector(burst->size()); SoftVector::iterator bit_itr = bits->begin(); - signalVector::iterator burst_itr = dec->begin(); + signalVector::iterator burst_itr = burst->begin(); - for (; burst_itr < dec->end(); burst_itr++) + for (; burst_itr < burst->end(); burst_itr++) *bit_itr++ = burst_itr->real(); delete dec; diff --git a/Transceiver52M/sigProcLib.h b/Transceiver52M/sigProcLib.h index 8685f2d..89a5194 100644 --- a/Transceiver52M/sigProcLib.h +++ b/Transceiver52M/sigProcLib.h @@ -229,16 +229,21 @@ int analyzeTrafficBurst(signalVector &rxBurst, signalVector *decimateVector(signalVector &wVector, size_t factor); /** - Demodulates a received burst using a soft-slicer. - @param rxBurst The burst to be demodulated. - @param gsmPulse The GSM pulse. - @param sps The number of samples per GSM symbol. + Applies time of arrival to align burst with bit positions + @param rxBurst The burst to be aligned @param channel The amplitude estimate of the received burst. @param TOA The time-of-arrival of the received burst. + @return The aligned burst. +*/ +signalVector *alignBurst(signalVector &rxBurst, complex channel, float TOA); + +/** + Demodulates a received burst using a soft-slicer. + @param rxBurst The burst to be demodulated. + @param sps The number of samples per GSM symbol. @return The demodulated bit sequence. */ -SoftVector *demodulateBurst(signalVector &rxBurst, int sps, - complex channel, float TOA); +SoftVector *demodulateBurst(signalVector &rxBurst, int sps); /** Design the necessary filters for a decision-feedback equalizer. -- cgit v1.2.3