blob: aec37623776dfe8b850025c4c49850502a3d5bc0 [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:
29 enum Scheme {
30 UNKNOWN,
31 CS1, CS2, CS3, CS4,
32 MCS1, MCS2, MCS3, MCS4,
33 MCS5, MCS6, MCS7, MCS8, MCS9,
34 NUM_SCHEMES
35 };
36
37 enum Mode {
38 GPRS,
39 EGPRS_GMSK,
40 EGPRS,
41 };
42
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +010043 enum HeaderType {
44 HEADER_INVALID,
45 HEADER_GPRS_CONTROL,
46 HEADER_GPRS_DATA,
47 HEADER_EGPRS_DATA_TYPE_1,
48 HEADER_EGPRS_DATA_TYPE_2,
49 HEADER_EGPRS_DATA_TYPE_3,
Jacob Erlbeck22f80872016-01-11 10:56:50 +010050 NUM_HEADER_TYPES
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +010051 };
52
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010053 enum Family {
54 FAMILY_INVALID,
55 FAMILY_A,
56 FAMILY_B,
57 FAMILY_C,
58 };
59
Jacob Erlbeck409f9802015-11-30 18:06:50 +010060 GprsCodingScheme(Scheme s = UNKNOWN);
61
62 operator bool() const {return m_scheme != UNKNOWN;}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010063 operator Scheme() const {return m_scheme;}
64 unsigned int to_num() const;
65
66 GprsCodingScheme& operator =(Scheme s);
67 GprsCodingScheme& operator =(GprsCodingScheme o);
68
Jacob Erlbeck409f9802015-11-30 18:06:50 +010069 bool isValid() const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;}
70 bool isGprs() const {return CS1 <= m_scheme && m_scheme <= CS4;}
71 bool isEgprs() const {return m_scheme >= MCS1;}
72 bool isEgprsGmsk() const {return isEgprs() && m_scheme <= MCS4;}
73 bool isCompatible(Mode mode) const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010074 bool isCompatible(GprsCodingScheme o) const;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010075 bool isFamilyCompatible(GprsCodingScheme o) const;
76 bool isCombinable(GprsCodingScheme o) const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010077
78 void inc(Mode mode);
79 void dec(Mode mode);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010080 void inc();
81 void dec();
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010082 void decToSingleBlock(bool *needStuffing);
Jacob Erlbeck409f9802015-11-30 18:06:50 +010083
84 unsigned int sizeUL() const;
85 unsigned int sizeDL() const;
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010086 unsigned int usedSizeUL() const;
87 unsigned int usedSizeDL() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010088 unsigned int maxBytesUL() const;
89 unsigned int maxBytesDL() const;
90 unsigned int spareBitsUL() const;
91 unsigned int spareBitsDL() const;
Jacob Erlbeck392a5452015-12-14 10:38:29 +010092 unsigned int maxDataBlockBytes() const;
93 unsigned int numDataBlocks() const;
Jacob Erlbeck22f80872016-01-11 10:56:50 +010094 unsigned int numDataHeaderBitsUL() const;
95 unsigned int numDataHeaderBitsDL() const;
96 unsigned int numDataBlockHeaderBits() const;
Jacob Erlbeck215e18c2016-02-03 18:22:34 +010097 unsigned int optionalPaddingBits() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010098 const char *name() const;
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +010099 HeaderType headerTypeData() const;
100 HeaderType headerTypeControl() const;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +0100101 Family family() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100102
103 static GprsCodingScheme getBySizeUL(unsigned size);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100104 static GprsCodingScheme getGprsByNum(unsigned num);
105 static GprsCodingScheme getEgprsByNum(unsigned num);
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100106
Jacob Erlbeck7b579972016-01-05 15:54:24 +0100107 static const char *modeName(Mode mode);
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100108private:
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100109 GprsCodingScheme(int s); /* fail on use */
110 GprsCodingScheme& operator =(int s); /* fail on use */
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100111 enum Scheme m_scheme;
112};
113
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100114inline unsigned int GprsCodingScheme::to_num() const
115{
116 if (isGprs())
117 return (m_scheme - CS1) + 1;
118
119 if (isEgprs())
120 return (m_scheme - MCS1) + 1;
121
122 return 0;
123}
124
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100125inline bool GprsCodingScheme::isCompatible(Mode mode) const
126{
127 switch (mode) {
128 case GPRS: return isGprs();
129 case EGPRS_GMSK: return isEgprsGmsk();
130 case EGPRS: return isEgprs();
131 }
132
133 return false;
134}
135
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100136inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100137{
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100138 return (isGprs() && o.isGprs()) || (isEgprs() && o.isEgprs());
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100139}
140
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100141inline GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeControl() const
142{
143 return HEADER_GPRS_CONTROL;
144}
145
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100146inline GprsCodingScheme::GprsCodingScheme(Scheme s)
147 : m_scheme(s)
148{
149 if (!isValid())
150 m_scheme = UNKNOWN;
151}
152
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100153inline GprsCodingScheme& GprsCodingScheme::operator =(Scheme s)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100154{
155 m_scheme = s;
156
157 if (!isValid())
158 m_scheme = UNKNOWN;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100159
160 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100161}
162
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100163inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100164{
165 m_scheme = o.m_scheme;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100166 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100167}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100168
169inline GprsCodingScheme GprsCodingScheme::getGprsByNum(unsigned num)
170{
171 if (num < 1 || num > 4)
172 return GprsCodingScheme();
173
174 return GprsCodingScheme(Scheme(CS1 + (num - 1)));
175}
176
177inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
178{
179 if (num < 1 || num > 9)
180 return GprsCodingScheme();
181
182 return GprsCodingScheme(Scheme(MCS1 + (num - 1)));
183}
184
185/* The coding schemes form a partial ordering */
186inline bool operator ==(GprsCodingScheme a, GprsCodingScheme b)
187{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100188 return GprsCodingScheme::Scheme(a) == GprsCodingScheme::Scheme(b);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100189}
190
191inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
192{
193 return !(a == b);
194}
195
196inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
197{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100198 return a.isCompatible(b) &&
199 GprsCodingScheme::Scheme(a) < GprsCodingScheme::Scheme(b);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100200}
201
202inline bool operator >(GprsCodingScheme a, GprsCodingScheme b)
203{
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +0100204 return b < a;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100205}
206
207inline bool operator <=(GprsCodingScheme a, GprsCodingScheme b)
208{
209 return a == b || a < b;
210}
211
212inline bool operator >=(GprsCodingScheme a, GprsCodingScheme b)
213{
214 return a == b || a > b;
215}
216