blob: 3b1537241627d90b1b0c0e4a1d4eb1318920d0db [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
26
27class GprsCodingScheme {
28public:
Aravind Sirsikar91495522016-07-12 14:17:12 +053029
30#define MAX_NUM_ARQ 2 /* max. number of ARQ */
31#define MAX_NUM_MCS 9 /* max. number of MCS */
32#define EGPRS_ARQ1 0x0
33#define EGPRS_ARQ2 0x1
34
Jacob Erlbeck409f9802015-11-30 18:06:50 +010035 enum Scheme {
36 UNKNOWN,
37 CS1, CS2, CS3, CS4,
38 MCS1, MCS2, MCS3, MCS4,
39 MCS5, MCS6, MCS7, MCS8, MCS9,
40 NUM_SCHEMES
41 };
42
43 enum Mode {
44 GPRS,
45 EGPRS_GMSK,
46 EGPRS,
47 };
48
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +010049 enum HeaderType {
50 HEADER_INVALID,
51 HEADER_GPRS_CONTROL,
52 HEADER_GPRS_DATA,
53 HEADER_EGPRS_DATA_TYPE_1,
54 HEADER_EGPRS_DATA_TYPE_2,
55 HEADER_EGPRS_DATA_TYPE_3,
Jacob Erlbeck22f80872016-01-11 10:56:50 +010056 NUM_HEADER_TYPES
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +010057 };
58
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010059 enum Family {
60 FAMILY_INVALID,
61 FAMILY_A,
62 FAMILY_B,
63 FAMILY_C,
64 };
65
Jacob Erlbeck409f9802015-11-30 18:06:50 +010066 GprsCodingScheme(Scheme s = UNKNOWN);
67
68 operator bool() const {return m_scheme != UNKNOWN;}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010069 operator Scheme() const {return m_scheme;}
70 unsigned int to_num() const;
71
72 GprsCodingScheme& operator =(Scheme s);
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +053073 bool operator == (Scheme s) const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010074 GprsCodingScheme& operator =(GprsCodingScheme o);
75
Jacob Erlbeck409f9802015-11-30 18:06:50 +010076 bool isValid() const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;}
77 bool isGprs() const {return CS1 <= m_scheme && m_scheme <= CS4;}
78 bool isEgprs() const {return m_scheme >= MCS1;}
79 bool isEgprsGmsk() const {return isEgprs() && m_scheme <= MCS4;}
80 bool isCompatible(Mode mode) const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010081 bool isCompatible(GprsCodingScheme o) const;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010082 bool isFamilyCompatible(GprsCodingScheme o) const;
83 bool isCombinable(GprsCodingScheme o) const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010084
85 void inc(Mode mode);
86 void dec(Mode mode);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010087 void inc();
88 void dec();
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010089 void decToSingleBlock(bool *needStuffing);
Jacob Erlbeck409f9802015-11-30 18:06:50 +010090
91 unsigned int sizeUL() const;
92 unsigned int sizeDL() const;
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010093 unsigned int usedSizeUL() const;
94 unsigned int usedSizeDL() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010095 unsigned int maxBytesUL() const;
96 unsigned int maxBytesDL() const;
97 unsigned int spareBitsUL() const;
98 unsigned int spareBitsDL() const;
Jacob Erlbeck392a5452015-12-14 10:38:29 +010099 unsigned int maxDataBlockBytes() const;
100 unsigned int numDataBlocks() const;
Jacob Erlbeck22f80872016-01-11 10:56:50 +0100101 unsigned int numDataHeaderBitsUL() const;
102 unsigned int numDataHeaderBitsDL() const;
103 unsigned int numDataBlockHeaderBits() const;
Jacob Erlbeck215e18c2016-02-03 18:22:34 +0100104 unsigned int optionalPaddingBits() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100105 const char *name() const;
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100106 HeaderType headerTypeData() const;
107 HeaderType headerTypeControl() const;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +0100108 Family family() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100109
110 static GprsCodingScheme getBySizeUL(unsigned size);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100111 static GprsCodingScheme getGprsByNum(unsigned num);
112 static GprsCodingScheme getEgprsByNum(unsigned num);
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100113
Jacob Erlbeck7b579972016-01-05 15:54:24 +0100114 static const char *modeName(Mode mode);
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530115 static Scheme get_retx_mcs(const GprsCodingScheme mcs,
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530116 const GprsCodingScheme retx_mcs,
117 const unsigned arq_type);
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530118
Aravind Sirsikar91495522016-07-12 14:17:12 +0530119 static enum Scheme egprs_mcs_retx_tbl[MAX_NUM_ARQ]
120 [MAX_NUM_MCS][MAX_NUM_MCS];
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100121private:
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100122 GprsCodingScheme(int s); /* fail on use */
123 GprsCodingScheme& operator =(int s); /* fail on use */
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100124 enum Scheme m_scheme;
125};
126
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100127inline unsigned int GprsCodingScheme::to_num() const
128{
129 if (isGprs())
130 return (m_scheme - CS1) + 1;
131
132 if (isEgprs())
133 return (m_scheme - MCS1) + 1;
134
135 return 0;
136}
137
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100138inline bool GprsCodingScheme::isCompatible(Mode mode) const
139{
140 switch (mode) {
141 case GPRS: return isGprs();
142 case EGPRS_GMSK: return isEgprsGmsk();
143 case EGPRS: return isEgprs();
144 }
145
146 return false;
147}
148
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100149inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100150{
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100151 return (isGprs() && o.isGprs()) || (isEgprs() && o.isEgprs());
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100152}
153
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100154inline GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeControl() const
155{
156 return HEADER_GPRS_CONTROL;
157}
158
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100159inline GprsCodingScheme::GprsCodingScheme(Scheme s)
160 : m_scheme(s)
161{
162 if (!isValid())
163 m_scheme = UNKNOWN;
164}
165
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100166inline GprsCodingScheme& GprsCodingScheme::operator =(Scheme s)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100167{
168 m_scheme = s;
169
170 if (!isValid())
171 m_scheme = UNKNOWN;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100172
173 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100174}
175
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100176inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100177{
178 m_scheme = o.m_scheme;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100179 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100180}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100181
182inline GprsCodingScheme GprsCodingScheme::getGprsByNum(unsigned num)
183{
184 if (num < 1 || num > 4)
185 return GprsCodingScheme();
186
187 return GprsCodingScheme(Scheme(CS1 + (num - 1)));
188}
189
190inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
191{
192 if (num < 1 || num > 9)
193 return GprsCodingScheme();
194
195 return GprsCodingScheme(Scheme(MCS1 + (num - 1)));
196}
197
198/* The coding schemes form a partial ordering */
199inline bool operator ==(GprsCodingScheme a, GprsCodingScheme b)
200{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100201 return GprsCodingScheme::Scheme(a) == GprsCodingScheme::Scheme(b);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100202}
203
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530204inline bool GprsCodingScheme::operator == (Scheme scheme) const
205{
206 return this->m_scheme == scheme;
207}
208
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100209inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
210{
211 return !(a == b);
212}
213
214inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
215{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100216 return a.isCompatible(b) &&
217 GprsCodingScheme::Scheme(a) < GprsCodingScheme::Scheme(b);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100218}
219
220inline bool operator >(GprsCodingScheme a, GprsCodingScheme b)
221{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100222 return b < a;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100223}
224
225inline bool operator <=(GprsCodingScheme a, GprsCodingScheme b)
226{
227 return a == b || a < b;
228}
229
230inline bool operator >=(GprsCodingScheme a, GprsCodingScheme b)
231{
232 return a == b || a > b;
233}
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530234inline GprsCodingScheme::Scheme GprsCodingScheme::get_retx_mcs(
235 const GprsCodingScheme mcs,
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530236 const GprsCodingScheme demanded_mcs,
237 const unsigned arq_type)
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530238{
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530239 return egprs_mcs_retx_tbl[arq_type][mcs.to_num() - 1]
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530240 [demanded_mcs.to_num() - 1];
241}