248 lines
5.9 KiB
C++
248 lines
5.9 KiB
C++
/* gprs_coding_scheme.h
|
|
*
|
|
* Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
|
|
* Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
|
|
*
|
|
* 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
extern "C" {
|
|
#include <osmocom/core/utils.h>
|
|
}
|
|
|
|
class GprsCodingScheme {
|
|
public:
|
|
|
|
#define MAX_NUM_ARQ 2 /* max. number of ARQ */
|
|
#define MAX_NUM_MCS 9 /* max. number of MCS */
|
|
#define EGPRS_ARQ1 0x0
|
|
#define EGPRS_ARQ2 0x1
|
|
|
|
enum Scheme {
|
|
UNKNOWN,
|
|
CS1, CS2, CS3, CS4,
|
|
MCS1, MCS2, MCS3, MCS4,
|
|
MCS5, MCS6, MCS7, MCS8, MCS9,
|
|
NUM_SCHEMES
|
|
};
|
|
|
|
enum Mode {
|
|
GPRS,
|
|
EGPRS_GMSK,
|
|
EGPRS,
|
|
};
|
|
|
|
enum HeaderType {
|
|
HEADER_INVALID,
|
|
HEADER_GPRS_CONTROL,
|
|
HEADER_GPRS_DATA,
|
|
HEADER_EGPRS_DATA_TYPE_1,
|
|
HEADER_EGPRS_DATA_TYPE_2,
|
|
HEADER_EGPRS_DATA_TYPE_3,
|
|
NUM_HEADER_TYPES
|
|
};
|
|
|
|
enum Family {
|
|
FAMILY_INVALID,
|
|
FAMILY_A,
|
|
FAMILY_B,
|
|
FAMILY_C,
|
|
};
|
|
|
|
GprsCodingScheme(Scheme s = UNKNOWN);
|
|
|
|
operator bool() const {return m_scheme != UNKNOWN;}
|
|
operator Scheme() const {return m_scheme;}
|
|
uint8_t to_num() const;
|
|
|
|
GprsCodingScheme& operator =(Scheme s);
|
|
bool operator == (Scheme s) const;
|
|
GprsCodingScheme& operator =(GprsCodingScheme o);
|
|
|
|
bool isValid() const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;}
|
|
bool isGprs() const {return CS1 <= m_scheme && m_scheme <= CS4;}
|
|
bool isEgprs() const {return m_scheme >= MCS1;}
|
|
bool isEgprsGmsk() const {return isEgprs() && m_scheme <= MCS4;}
|
|
bool isCompatible(Mode mode) const;
|
|
bool isCompatible(GprsCodingScheme o) const;
|
|
bool isFamilyCompatible(GprsCodingScheme o) const;
|
|
bool isCombinable(GprsCodingScheme o) const;
|
|
|
|
void inc(Mode mode);
|
|
void dec(Mode mode);
|
|
void inc();
|
|
void dec();
|
|
void decToSingleBlock(bool *needStuffing);
|
|
|
|
uint8_t sizeUL() const;
|
|
uint8_t sizeDL() const;
|
|
uint8_t usedSizeUL() const;
|
|
uint8_t usedSizeDL() const;
|
|
uint8_t maxBytesUL() const;
|
|
uint8_t maxBytesDL() const;
|
|
uint8_t spareBitsUL() const;
|
|
uint8_t spareBitsDL() const;
|
|
uint8_t maxDataBlockBytes() const;
|
|
uint8_t numDataBlocks() const;
|
|
uint8_t numDataHeaderBitsUL() const;
|
|
uint8_t numDataHeaderBitsDL() const;
|
|
uint8_t numDataBlockHeaderBits() const;
|
|
uint8_t optionalPaddingBits() const;
|
|
const char *name() const;
|
|
HeaderType headerTypeData() const;
|
|
HeaderType headerTypeControl() const;
|
|
Family family() const;
|
|
|
|
static GprsCodingScheme getBySizeUL(unsigned size);
|
|
static GprsCodingScheme getGprsByNum(unsigned num);
|
|
static GprsCodingScheme getEgprsByNum(unsigned num);
|
|
|
|
static const char *modeName(Mode mode);
|
|
static Scheme get_retx_mcs(const GprsCodingScheme mcs,
|
|
const GprsCodingScheme retx_mcs,
|
|
const unsigned arq_type);
|
|
|
|
static enum Scheme egprs_mcs_retx_tbl[MAX_NUM_ARQ]
|
|
[MAX_NUM_MCS][MAX_NUM_MCS];
|
|
private:
|
|
GprsCodingScheme(int s); /* fail on use */
|
|
GprsCodingScheme& operator =(int s); /* fail on use */
|
|
enum Scheme m_scheme;
|
|
};
|
|
|
|
inline uint8_t GprsCodingScheme::to_num() const
|
|
{
|
|
if (isGprs())
|
|
return (m_scheme - CS1) + 1;
|
|
|
|
if (isEgprs())
|
|
return (m_scheme - MCS1) + 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline bool GprsCodingScheme::isCompatible(Mode mode) const
|
|
{
|
|
switch (mode) {
|
|
case GPRS: return isGprs();
|
|
case EGPRS_GMSK: return isEgprsGmsk();
|
|
case EGPRS: return isEgprs();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
|
|
{
|
|
return (isGprs() && o.isGprs()) || (isEgprs() && o.isEgprs());
|
|
}
|
|
|
|
inline GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeControl() const
|
|
{
|
|
return HEADER_GPRS_CONTROL;
|
|
}
|
|
|
|
inline GprsCodingScheme::GprsCodingScheme(Scheme s)
|
|
: m_scheme(s)
|
|
{
|
|
if (!isValid())
|
|
m_scheme = UNKNOWN;
|
|
}
|
|
|
|
inline GprsCodingScheme& GprsCodingScheme::operator =(Scheme s)
|
|
{
|
|
m_scheme = s;
|
|
|
|
if (!isValid())
|
|
m_scheme = UNKNOWN;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
|
|
{
|
|
m_scheme = o.m_scheme;
|
|
return *this;
|
|
}
|
|
|
|
inline GprsCodingScheme GprsCodingScheme::getGprsByNum(unsigned num)
|
|
{
|
|
if (num < 1 || num > 4)
|
|
return GprsCodingScheme();
|
|
|
|
return GprsCodingScheme(Scheme(CS1 + (num - 1)));
|
|
}
|
|
|
|
inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
|
|
{
|
|
if (num < 1 || num > 9)
|
|
return GprsCodingScheme();
|
|
|
|
return GprsCodingScheme(Scheme(MCS1 + (num - 1)));
|
|
}
|
|
|
|
/* The coding schemes form a partial ordering */
|
|
inline bool operator ==(GprsCodingScheme a, GprsCodingScheme b)
|
|
{
|
|
return GprsCodingScheme::Scheme(a) == GprsCodingScheme::Scheme(b);
|
|
}
|
|
|
|
inline bool GprsCodingScheme::operator == (Scheme scheme) const
|
|
{
|
|
return this->m_scheme == scheme;
|
|
}
|
|
|
|
inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
|
|
{
|
|
return !(a == b);
|
|
}
|
|
|
|
inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
|
|
{
|
|
return a.isCompatible(b) &&
|
|
GprsCodingScheme::Scheme(a) < GprsCodingScheme::Scheme(b);
|
|
}
|
|
|
|
inline bool operator >(GprsCodingScheme a, GprsCodingScheme b)
|
|
{
|
|
return b < a;
|
|
}
|
|
|
|
inline bool operator <=(GprsCodingScheme a, GprsCodingScheme b)
|
|
{
|
|
return a == b || a < b;
|
|
}
|
|
|
|
inline bool operator >=(GprsCodingScheme a, GprsCodingScheme b)
|
|
{
|
|
return a == b || a > b;
|
|
}
|
|
inline GprsCodingScheme::Scheme GprsCodingScheme::get_retx_mcs(
|
|
const GprsCodingScheme mcs,
|
|
const GprsCodingScheme demanded_mcs,
|
|
const unsigned arq_type)
|
|
{
|
|
OSMO_ASSERT(mcs.to_num() > 0);
|
|
OSMO_ASSERT(demanded_mcs.to_num() > 0);
|
|
|
|
return egprs_mcs_retx_tbl[arq_type][mcs.to_num() - 1]
|
|
[demanded_mcs.to_num() - 1];
|
|
}
|