summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp66
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h20
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h18
3 files changed, 78 insertions, 26 deletions
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
personal git repositories of Harald Welte. Your mileage may vary