blob: aaa8b2058b4fff3460413286c4b611662595d996 [file] [log] [blame]
Jacob Erlbeck409f9802015-11-30 18:06:50 +01001/* gprs_coding_scheme.cpp
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
22#include "gprs_coding_scheme.h"
23
24static struct {
25 struct {
Jacob Erlbeck392a5452015-12-14 10:38:29 +010026 unsigned int bytes;
27 unsigned int ext_bits;
Jacob Erlbeck22f80872016-01-11 10:56:50 +010028 unsigned int data_header_bits;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010029 } uplink, downlink;
Jacob Erlbeck392a5452015-12-14 10:38:29 +010030 unsigned int data_bytes;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010031 const char *name;
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +010032 GprsCodingScheme::HeaderType data_hdr;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010033} mcs_info[GprsCodingScheme::NUM_SCHEMES] = {
Jacob Erlbeck22f80872016-01-11 10:56:50 +010034 {{0, 0}, {0, 0}, 0, "UNKNOWN", GprsCodingScheme::HEADER_INVALID},
35 {{23, 0}, {23, 0}, 20, "CS-1", GprsCodingScheme::HEADER_GPRS_DATA},
36 {{33, 7}, {33, 7}, 30, "CS-2", GprsCodingScheme::HEADER_GPRS_DATA},
37 {{39, 3}, {39, 3}, 36, "CS-3", GprsCodingScheme::HEADER_GPRS_DATA},
38 {{53, 7}, {53, 7}, 50, "CS-4", GprsCodingScheme::HEADER_GPRS_DATA},
Jacob Erlbeck409f9802015-11-30 18:06:50 +010039
Jacob Erlbeck22f80872016-01-11 10:56:50 +010040 {{26, 1}, {26, 1}, 22, "MCS-1", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
41 {{32, 1}, {32, 1}, 28, "MCS-2", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
42 {{41, 1}, {41, 1}, 37, "MCS-3", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
43 {{48, 1}, {48, 1}, 44, "MCS-4", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
Jacob Erlbeck409f9802015-11-30 18:06:50 +010044
Jacob Erlbeck22f80872016-01-11 10:56:50 +010045 {{60, 7}, {59, 6}, 56, "MCS-5", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2},
46 {{78, 7}, {77, 6}, 74, "MCS-6", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2},
47 {{118, 2}, {117, 4}, 56, "MCS-7", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
48 {{142, 2}, {141, 4}, 68, "MCS-8", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
49 {{154, 2}, {153, 4}, 74, "MCS-9", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
Jacob Erlbeck409f9802015-11-30 18:06:50 +010050};
51
Jacob Erlbeck22f80872016-01-11 10:56:50 +010052static struct {
53 struct {
54 int data_header_bits;
55 } uplink, downlink;
56 unsigned int data_block_header_bits;
57 unsigned int num_blocks;
58 const char *name;
59} hdr_type_info[GprsCodingScheme::NUM_HEADER_TYPES] = {
60 {{0}, {0}, 0, 0, "INVALID"},
61 {{1*8 + 0}, {1*8 + 0}, 0, 0, "CONTROL"},
62 {{3*8 + 0}, {3*8 + 0}, 0, 1, "GPRS_DATA"},
63 {{5*8 + 6}, {5*8 + 0}, 2, 2, "EGPRS_DATA_TYPE1"},
64 {{4*8 + 5}, {3*8 + 4}, 2, 1, "EGPRS_DATA_TYPE2"},
65 {{3*8 + 7}, {3*8 + 7}, 2, 1, "EGPRS_DATA_TYPE3"},
66};
Jacob Erlbeck409f9802015-11-30 18:06:50 +010067
68GprsCodingScheme GprsCodingScheme::getBySizeUL(unsigned size)
69{
70 switch (size) {
71 case 23: return GprsCodingScheme(CS1);
72 case 27: return GprsCodingScheme(MCS1);
73 case 33: return GprsCodingScheme(MCS2);
74 case 34: return GprsCodingScheme(CS2);
75 case 40: return GprsCodingScheme(CS3);
76 case 42: return GprsCodingScheme(MCS3);
77 case 49: return GprsCodingScheme(MCS4);
78 case 54: return GprsCodingScheme(CS4);
79 case 61: return GprsCodingScheme(MCS5);
80 case 79: return GprsCodingScheme(MCS6);
81 case 119: return GprsCodingScheme(MCS7);
82 case 143: return GprsCodingScheme(MCS8);
83 case 155: return GprsCodingScheme(MCS9);
84 }
85
86 return GprsCodingScheme(UNKNOWN);
87}
88
89unsigned int GprsCodingScheme::sizeUL() const
90{
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010091 return mcs_info[m_scheme].uplink.bytes + (spareBitsUL() ? 1 : 0);
92}
93
94unsigned int GprsCodingScheme::usedSizeUL() const
95{
96 if (mcs_info[m_scheme].data_hdr == HEADER_GPRS_DATA)
97 return mcs_info[m_scheme].uplink.bytes;
98 else
99 return sizeUL();
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100100}
101
102unsigned int GprsCodingScheme::maxBytesUL() const
103{
104 return mcs_info[m_scheme].uplink.bytes;
105}
106
107unsigned int GprsCodingScheme::spareBitsUL() const
108{
109 return mcs_info[m_scheme].uplink.ext_bits;
110}
111
112unsigned int GprsCodingScheme::sizeDL() const
113{
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +0100114 return mcs_info[m_scheme].downlink.bytes + (spareBitsDL() ? 1 : 0);
115}
116
117unsigned int GprsCodingScheme::usedSizeDL() const
118{
119 if (mcs_info[m_scheme].data_hdr == HEADER_GPRS_DATA)
120 return mcs_info[m_scheme].downlink.bytes;
121 else
122 return sizeDL();
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100123}
124
125unsigned int GprsCodingScheme::maxBytesDL() const
126{
127 return mcs_info[m_scheme].downlink.bytes;
128}
129
130unsigned int GprsCodingScheme::spareBitsDL() const
131{
132 return mcs_info[m_scheme].downlink.ext_bits;
133}
134
Jacob Erlbeck392a5452015-12-14 10:38:29 +0100135unsigned int GprsCodingScheme::maxDataBlockBytes() const
136{
137 return mcs_info[m_scheme].data_bytes;
138}
139
140unsigned int GprsCodingScheme::numDataBlocks() const
141{
Jacob Erlbeck22f80872016-01-11 10:56:50 +0100142 return hdr_type_info[headerTypeData()].num_blocks;
143}
144
145unsigned int GprsCodingScheme::numDataHeaderBitsUL() const
146{
147 return hdr_type_info[headerTypeData()].uplink.data_header_bits;
148}
149
150unsigned int GprsCodingScheme::numDataHeaderBitsDL() const
151{
152 return hdr_type_info[headerTypeData()].downlink.data_header_bits;
153}
154
155unsigned int GprsCodingScheme::numDataBlockHeaderBits() const
156{
157 return hdr_type_info[headerTypeData()].data_block_header_bits;
Jacob Erlbeck392a5452015-12-14 10:38:29 +0100158}
159
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100160const char *GprsCodingScheme::name() const
161{
162 return mcs_info[m_scheme].name;
163}
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100164
165GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeData() const
166{
167 return mcs_info[m_scheme].data_hdr;
168}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100169
170void GprsCodingScheme::inc(Mode mode)
171{
172 if (!isCompatible(mode))
173 /* This should not happen. TODO: Use assert? */
174 return;
175
176 Scheme new_cs(Scheme(m_scheme + 1));
177 if (!GprsCodingScheme(new_cs).isCompatible(mode))
178 /* Clipping, do not change the value */
179 return;
180
181 m_scheme = new_cs;
182}
183
184void GprsCodingScheme::dec(Mode mode)
185{
186 if (!isCompatible(mode))
187 /* This should not happen. TODO: Use assert? */
188 return;
189
190 Scheme new_cs(Scheme(m_scheme - 1));
191 if (!GprsCodingScheme(new_cs).isCompatible(mode))
192 /* Clipping, do not change the value */
193 return;
194
195 m_scheme = new_cs;
196}
197
198void GprsCodingScheme::inc()
199{
200 if (isGprs() && m_scheme == CS4)
201 return;
202
203 if (isEgprs() && m_scheme == MCS9)
204 return;
205
206 if (!isValid())
207 return;
208
209 m_scheme = Scheme(m_scheme + 1);
210}
211
212void GprsCodingScheme::dec()
213{
214 if (isGprs() && m_scheme == CS1)
215 return;
216
217 if (isEgprs() && m_scheme == MCS1)
218 return;
219
220 if (!isValid())
221 return;
222
223 m_scheme = Scheme(m_scheme - 1);
224}
Jacob Erlbeck7b579972016-01-05 15:54:24 +0100225
226const char *GprsCodingScheme::modeName(Mode mode)
227{
228 switch (mode) {
229 case GPRS: return "GPRS";
230 case EGPRS_GMSK: return "EGPRS_GMSK-only";
231 case EGPRS: return "EGPRS";
232 default: return "???";
233 }
234}