/*
* Copyright 2008 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Public License.
* See the COPYING file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#define NDEBUG
#include "GSML1FEC.h"
#include "GSMCommon.h"
#include "RxBurst.h"
//#include "GSMSAPMux.h"
//#include "GSMConfig.h"
#include "GSMTDMA.h"
#include "GSM610Tables.h"
#include "GSM660Tables.h"
#include "GSM690Tables.h"
#include "Assert.h"
using namespace std;
using namespace GSM;
/*
Compilation flags:
NOCONTROL Compile without referencing control layer functions.
*/
/*
Notes on reading the GSM specifications.
Every FEC section in GSM 05.03 uses standard names for the bits at
different stages of the encoding/decoding process.
This is all described formally in GSM 05.03 2.2.
"d" -- data bits. The actual payloads from L2 and the vocoders.
"p" -- parity bits. These are calculated from d.
"u" -- uncoded bits. A concatenation of d, p and inner tail bits.
"c" -- coded bits. These are the convolutionally encoded from u.
"i" -- interleaved bits. These are the output of the interleaver.
"e" -- "encrypted" bits. These are the channel bits in the radio bursts.
The "e" bits are call "encrypted" even when encryption is not used.
The encoding process is:
L2 -> d -> -> calc p -> u -> c -> i -> e -> radio bursts
The decoding process is:
radio bursts -> e -> i -> c -> u -> check p -> d -> L2
Bit ordering in d is LSB-first in each octet.
Bit ordering everywhere else in the OpenBTS code is MSB-first
in every field to give contiguous fields across byte boundaries.
We use the BitVector::LSB8MSB() method to translate.
*/
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), mMode(MODE_SPEECH_FR)
{
for (int i = 0; i < 8; i++) {
mI[i] = SoftVector(114);
}
}
void TCHFACCHL1Decoder::writeLowSide(const RxBurst& inBurst)
{
OBJDCOUT("TCHFACCHL1Decoder::writeLowSide " << inBurst);
// If the channel is closed, ignore the burst.
// if (!active()) {
// OBJDCOUT("TCHFACCHL1Decoder::writeLowSide not active, ignoring input");
// return;
// }
processBurst(inBurst);
}
bool TCHFACCHL1Decoder::processBurst( const RxBurst& inBurst)
{
// Accept the burst into the deinterleaving buffer.
// Return true if we are ready to interleave.
// TODO -- One quick test of burst validity is to look at the tail bits.
// We could do that as a double-check against putting garbage into
// the interleaver or accepting bad parameters.
// Get the physical parameters of the burst.
// RSSI is dB wrt full scale.
// mRSSI = inBurst.RSSI();
// Timing error is a float in symbol intervals.
// mTimingError = inBurst.timingError();
// This flag is used as a half-ass semaphore.
// It is cleared when the new value is read.
// mPhyNew = true;
// The reverse index runs 0..3 as the bursts arrive.
// It is the "B" index of GSM 05.03 3.1.3 and 3.1.4.
int B = mMapping.reverseMapping(inBurst.time().FN()) % 8;
// A negative value means that the demux is misconfigured.
assert(B >= 0);
OBJDCOUT("TCHFACCHL1Decoder::processBurst B=" << B << " " << inBurst);
// Pull the data fields (e-bits) out of the burst and put them into i[B][].
// GSM 05.03 3.1.4
inBurst.data1().copyToSegment(mI[B], 0);
inBurst.data2().copyToSegment(mI[B], 57);
// Every 4th frame is the start of a new block.
// So if this isn't a "4th" frame, return now.
if (B % 4 != 3) return false;
// Deinterleave according to the diagonal "phase" of B.
// See GSM 05.03 3.1.3.
// Deinterleaves i[] to c[]
if (B == 3) deinterleave(4);
else deinterleave(0);
// See if this was the end of a stolen frame, GSM 05.03 4.2.5.
bool stolen = inBurst.Hl();
OBJDCOUT("TCHFACCHL!Decoder::processBurst Hl=" << inBurst.Hl() << " Hu=" << inBurst.Hu());
/* if (stolen) {
if (decode()) {
OBJDCOUT("TCHFACCHL1Decoder::processBurst good FACCH frame");
countGoodFrame();
handleGoodFrame();
} else {
OBJDCOUT("TCHFACCHL1Decoder::processBurst bad FACCH frame");
countBadFrame();
}
}*/
// Always feed the traffic channel, even on a stolen frame.
// decodeTCH will handle the GSM 06.11 bad frmae processing.
bool traffic = decodeTCH(stolen);
// if (traffic) {
OBJDCOUT("TCHFACCHL1Decoder::processBurst good TCH frame");
// countGoodFrame();
// Don't let the channel timeout.
// mLock.lock();
// mT3109.set();
// mLock.unlock();
// }
// else countBadFrame();
return traffic;
}
void TCHFACCHL1Decoder::deinterleave(int blockOffset )
{
OBJDCOUT("TCHFACCHL1Decoder::deinterleave blockOffset=" << blockOffset);
for (int k = 0; k < 456; k++) {
int B = ( k + blockOffset ) % 8;
int j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
mC[k] = mI[B][j];
mI[B][j] = 0.5F;
//OBJDCOUT("deinterleave k="<