From ef32a064f327e8ef3fb6d246eb0e515fa67173ab Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sat, 23 Oct 2010 22:04:17 +0200 Subject: gsm-receiver: EFR support [2/3] Add unmapping support to OpenBTS TCH decoder Signed-off-by: Sylvain Munaut --- .../src/lib/decoder/openbtsstuff/GSML1FEC.cpp | 66 ++++++++++++++-------- .../src/lib/decoder/openbtsstuff/GSML1FEC.h | 20 ++++++- .../src/lib/decoder/openbtsstuff/VocoderFrame.h | 18 ++++++ 3 files changed, 78 insertions(+), 26 deletions(-) (limited to 'gsm-receiver/src/lib/decoder/openbtsstuff') diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp b/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp index 1c99a0f..bbd14b0 100644 --- a/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp +++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp @@ -30,6 +30,8 @@ //#include "GSMConfig.h" #include "GSMTDMA.h" #include "GSM610Tables.h" +#include "GSM660Tables.h" +#include "GSM690Tables.h" #include "Assert.h" @@ -78,7 +80,7 @@ using namespace GSM; TCHFACCHL1Decoder::TCHFACCHL1Decoder(const TDMAMapping& wMapping) : mTCHU(189), mTCHD(260), mC(456), mClass1_c(mC.head(378)), mClass1A_d(mTCHD.head(50)), mClass2_c(mC.segment(378, 78)), - mTCHParity(0x0b, 3, 50), mMapping(wMapping) + mTCHParity(0x0b, 3, 50), mMapping(wMapping), mMode(MODE_SPEECH_FR) { for (int i = 0; i < 8; i++) { mI[i] = SoftVector(114); @@ -186,10 +188,6 @@ bool TCHFACCHL1Decoder::decodeTCH(bool stolen) // If the frame wasn't stolen, we'll update this with parity later. bool good = !stolen; - // Good or bad, we will be sending *something* to the speech channel. - // Allocate it in this scope. - unsigned char * newFrame = new unsigned char[33]; - if (!stolen) { // 3.1.2.2 @@ -226,29 +224,47 @@ bool TCHFACCHL1Decoder::decodeTCH(bool stolen) << " calcParity=" << calcParity << " tail=" << tail); good = (sentParity == calcParity) && (tail == 0); if (good) { - // Undo Um's importance-sorted bit ordering. - // See GSM 05.03 3.1 and Tablee 2. - BitVector payload = mVFrame.payload(); - mTCHD.unmap(g610BitOrder, 260, payload); - mVFrame.pack(newFrame); - // Save a copy for bad frame processing. - memcpy(mPrevGoodFrame, newFrame, 33); - return true; - } - } + if (mMode == MODE_SPEECH_FR) { + // Undo Um's importance-sorted bit ordering. + // See GSM 05.03 3.1 and Tablee 2. + BitVector payload = mVFrame.payload(); + mTCHD.unmap(g610BitOrder, 260, payload); + mVFrame.pack(mPrevGoodFrame); + mPrevGoodFrameLength = 33; + } else if (mMode == MODE_SPEECH_EFR) { + BitVector payload = mVFrameAMR.payload(); + BitVector TCHW(260), EFRBits(244); - if (!good) { - // TODO -- Bad frame processing, GSM 06.11. - // For now, just repeat the last good frame. - // TODO -- Need to apply attenuation and randomization of grid positions. - memcpy(newFrame, mPrevGoodFrame, 33); - //d_gsm_file.write((char *)newFrame, 33); - } + // Undo Um's EFR bit ordering. + mTCHD.unmap(g660BitOrder, 260, TCHW); + + // Remove repeating bits and CRC to get raw EFR frame (244 bits) + for (unsigned k=0; k<71; k++) + EFRBits[k] = TCHW[k] & 1; + + for (unsigned k=73; k<123; k++) + EFRBits[k-2] = TCHW[k] & 1; - - // Good or bad, we must feed the speech channel. -// mSpeechQ.write(newFrame); + for (unsigned k=125; k<178; k++) + EFRBits[k-4] = TCHW[k] & 1; + for (unsigned k=180; k<230; k++) + EFRBits[k-6] = TCHW[k] & 1; + + for (unsigned k=232; k<252; k++) + EFRBits[k-8] = TCHW[k] & 1; + + // Map bits as AMR 12.2k + EFRBits.map(g690_12_2_BitOrder, 244, payload); + + // Put the whole frame (hdr + payload) + mVFrameAMR.pack(mPrevGoodFrame); + mPrevGoodFrameLength = 32; + } + + return true; + } + } return false; } diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h b/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h index c367681..ce9b5d4 100644 --- a/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h +++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h @@ -58,6 +58,10 @@ namespace GSM */ + enum TCHMode { + MODE_SPEECH_FR, + MODE_SPEECH_EFR, + }; /** L1 decoder used for full rate TCH and FACCH -- mostly from GSM 05.03 3.1 and 4.2 */ @@ -75,8 +79,10 @@ namespace GSM SoftVector mClass2_c; ///< the class 2 part of c[] ViterbiR2O4 mVCoder; - VocoderFrame mVFrame; ///< unpacking buffer for vocoder frame + VocoderFrame mVFrame; ///< buffer for FR vocoder frame + VocoderAMRFrame mVFrameAMR; ///< buffer for EFR vocoder frame packed in AMR container unsigned char mPrevGoodFrame[33]; ///< previous good frame. + unsigned int mPrevGoodFrameLength; Parity mTCHParity; const TDMAMapping& mMapping; ///< multiplexing description @@ -85,6 +91,7 @@ namespace GSM static const unsigned mMaxQSize = 3; + enum TCHMode mMode; public: @@ -94,6 +101,14 @@ namespace GSM return FACCHType; } + enum TCHMode mode() const { + return mMode; + } + + void setMode(enum TCHMode mode) { + mMode = mode; + } + /** TCH/FACCH has a special-case writeLowSide. */ void writeLowSide(const RxBurst& inBurst); @@ -118,6 +133,9 @@ namespace GSM unsigned char * get_voice_frame(){ return mPrevGoodFrame; } + unsigned int get_voice_frame_length(){ + return mPrevGoodFrameLength; + } /** Receive a traffic frame. Non-blocking. Returns NULL if queue is dry. diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h b/gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h index c0e51c0..0c80973 100644 --- a/gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h +++ b/gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h @@ -22,4 +22,22 @@ class VocoderFrame : public BitVector { }; +class VocoderAMRFrame : public BitVector { + + public: + + VocoderAMRFrame() + :BitVector(244+8) + { fillField(0,0x3c,8); /* AMR-NB 12.2 */ } + + /** Construct by unpacking a char[32]. */ + VocoderAMRFrame(const unsigned char *src) + :BitVector(244+8) + { unpack(src); } + + BitVector payload() { return tail(8); } + const BitVector payload() const { return tail(8); } + +}; + #endif -- cgit v1.2.3