blob: 76cab0f2ddcd09b74d1a29fccd87b7da62a70efd [file] [log] [blame]
Jacob Erlbeck409f9802015-11-30 18:06:50 +01001/* gprs_coding_scheme.h
2 *
3 * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
4 * Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#pragma once
22
23#include <stdint.h>
24#include <stddef.h>
25
Max19621362017-09-08 12:33:34 +020026extern "C" {
27 #include <osmocom/core/utils.h>
28}
Jacob Erlbeck409f9802015-11-30 18:06:50 +010029
30class GprsCodingScheme {
31public:
Aravind Sirsikar91495522016-07-12 14:17:12 +053032
33#define MAX_NUM_ARQ 2 /* max. number of ARQ */
34#define MAX_NUM_MCS 9 /* max. number of MCS */
35#define EGPRS_ARQ1 0x0
36#define EGPRS_ARQ2 0x1
37
Jacob Erlbeck409f9802015-11-30 18:06:50 +010038 enum Scheme {
39 UNKNOWN,
40 CS1, CS2, CS3, CS4,
41 MCS1, MCS2, MCS3, MCS4,
42 MCS5, MCS6, MCS7, MCS8, MCS9,
43 NUM_SCHEMES
44 };
45
46 enum Mode {
47 GPRS,
48 EGPRS_GMSK,
49 EGPRS,
50 };
51
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +010052 enum HeaderType {
53 HEADER_INVALID,
54 HEADER_GPRS_CONTROL,
55 HEADER_GPRS_DATA,
56 HEADER_EGPRS_DATA_TYPE_1,
57 HEADER_EGPRS_DATA_TYPE_2,
58 HEADER_EGPRS_DATA_TYPE_3,
Jacob Erlbeck22f80872016-01-11 10:56:50 +010059 NUM_HEADER_TYPES
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +010060 };
61
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010062 enum Family {
63 FAMILY_INVALID,
64 FAMILY_A,
65 FAMILY_B,
66 FAMILY_C,
67 };
68
Jacob Erlbeck409f9802015-11-30 18:06:50 +010069 GprsCodingScheme(Scheme s = UNKNOWN);
70
71 operator bool() const {return m_scheme != UNKNOWN;}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010072 operator Scheme() const {return m_scheme;}
Maxb3a17d62017-12-21 12:11:33 +010073 uint8_t to_num() const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010074
75 GprsCodingScheme& operator =(Scheme s);
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +053076 bool operator == (Scheme s) const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010077 GprsCodingScheme& operator =(GprsCodingScheme o);
78
Jacob Erlbeck409f9802015-11-30 18:06:50 +010079 bool isValid() const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;}
80 bool isGprs() const {return CS1 <= m_scheme && m_scheme <= CS4;}
81 bool isEgprs() const {return m_scheme >= MCS1;}
82 bool isEgprsGmsk() const {return isEgprs() && m_scheme <= MCS4;}
83 bool isCompatible(Mode mode) const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010084 bool isCompatible(GprsCodingScheme o) const;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010085 bool isFamilyCompatible(GprsCodingScheme o) const;
86 bool isCombinable(GprsCodingScheme o) const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010087
88 void inc(Mode mode);
89 void dec(Mode mode);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010090 void inc();
91 void dec();
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010092 void decToSingleBlock(bool *needStuffing);
Jacob Erlbeck409f9802015-11-30 18:06:50 +010093
Maxb3a17d62017-12-21 12:11:33 +010094 uint8_t sizeUL() const;
95 uint8_t sizeDL() const;
96 uint8_t usedSizeUL() const;
97 uint8_t usedSizeDL() const;
98 uint8_t maxBytesUL() const;
99 uint8_t maxBytesDL() const;
100 uint8_t spareBitsUL() const;
101 uint8_t spareBitsDL() const;
102 uint8_t maxDataBlockBytes() const;
103 uint8_t numDataBlocks() const;
104 uint8_t numDataHeaderBitsUL() const;
105 uint8_t numDataHeaderBitsDL() const;
106 uint8_t numDataBlockHeaderBits() const;
107 uint8_t optionalPaddingBits() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100108 const char *name() const;
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100109 HeaderType headerTypeData() const;
110 HeaderType headerTypeControl() const;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +0100111 Family family() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100112
113 static GprsCodingScheme getBySizeUL(unsigned size);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100114 static GprsCodingScheme getGprsByNum(unsigned num);
115 static GprsCodingScheme getEgprsByNum(unsigned num);
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100116
Jacob Erlbeck7b579972016-01-05 15:54:24 +0100117 static const char *modeName(Mode mode);
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530118 static Scheme get_retx_mcs(const GprsCodingScheme mcs,
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530119 const GprsCodingScheme retx_mcs,
120 const unsigned arq_type);
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530121
Aravind Sirsikar91495522016-07-12 14:17:12 +0530122 static enum Scheme egprs_mcs_retx_tbl[MAX_NUM_ARQ]
123 [MAX_NUM_MCS][MAX_NUM_MCS];
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100124private:
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100125 GprsCodingScheme(int s); /* fail on use */
126 GprsCodingScheme& operator =(int s); /* fail on use */
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100127 enum Scheme m_scheme;
128};
129
Maxb3a17d62017-12-21 12:11:33 +0100130inline uint8_t GprsCodingScheme::to_num() const
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100131{
132 if (isGprs())
133 return (m_scheme - CS1) + 1;
134
135 if (isEgprs())
136 return (m_scheme - MCS1) + 1;
137
138 return 0;
139}
140
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100141inline bool GprsCodingScheme::isCompatible(Mode mode) const
142{
143 switch (mode) {
144 case GPRS: return isGprs();
145 case EGPRS_GMSK: return isEgprsGmsk();
146 case EGPRS: return isEgprs();
147 }
148
149 return false;
150}
151
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100152inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100153{
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100154 return (isGprs() && o.isGprs()) || (isEgprs() && o.isEgprs());
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100155}
156
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100157inline GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeControl() const
158{
159 return HEADER_GPRS_CONTROL;
160}
161
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100162inline GprsCodingScheme::GprsCodingScheme(Scheme s)
163 : m_scheme(s)
164{
165 if (!isValid())
166 m_scheme = UNKNOWN;
167}
168
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100169inline GprsCodingScheme& GprsCodingScheme::operator =(Scheme s)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100170{
171 m_scheme = s;
172
173 if (!isValid())
174 m_scheme = UNKNOWN;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100175
176 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100177}
178
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100179inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100180{
181 m_scheme = o.m_scheme;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100182 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100183}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100184
185inline GprsCodingScheme GprsCodingScheme::getGprsByNum(unsigned num)
186{
187 if (num < 1 || num > 4)
188 return GprsCodingScheme();
189
190 return GprsCodingScheme(Scheme(CS1 + (num - 1)));
191}
192
193inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
194{
195 if (num < 1 || num > 9)
196 return GprsCodingScheme();
197
198 return GprsCodingScheme(Scheme(MCS1 + (num - 1)));
199}
200
201/* The coding schemes form a partial ordering */
202inline bool operator ==(GprsCodingScheme a, GprsCodingScheme b)
203{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100204 return GprsCodingScheme::Scheme(a) == GprsCodingScheme::Scheme(b);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100205}
206
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530207inline bool GprsCodingScheme::operator == (Scheme scheme) const
208{
209 return this->m_scheme == scheme;
210}
211
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100212inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
213{
214 return !(a == b);
215}
216
217inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
218{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100219 return a.isCompatible(b) &&
220 GprsCodingScheme::Scheme(a) < GprsCodingScheme::Scheme(b);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100221}
222
223inline bool operator >(GprsCodingScheme a, GprsCodingScheme b)
224{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100225 return b < a;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100226}
227
228inline bool operator <=(GprsCodingScheme a, GprsCodingScheme b)
229{
230 return a == b || a < b;
231}
232
233inline bool operator >=(GprsCodingScheme a, GprsCodingScheme b)
234{
235 return a == b || a > b;
236}
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530237inline GprsCodingScheme::Scheme GprsCodingScheme::get_retx_mcs(
238 const GprsCodingScheme mcs,
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530239 const GprsCodingScheme demanded_mcs,
240 const unsigned arq_type)
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530241{
Max19621362017-09-08 12:33:34 +0200242 OSMO_ASSERT(mcs.to_num() > 0);
243 OSMO_ASSERT(demanded_mcs.to_num() > 0);
244
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530245 return egprs_mcs_retx_tbl[arq_type][mcs.to_num() - 1]
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530246 [demanded_mcs.to_num() - 1];
247}