blob: 4ba55c30bbf6c08acab9252c35a332675f8fa8f9 [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 Erlbeck409f9802015-11-30 18:06:50 +010028 } uplink, downlink;
Jacob Erlbeck392a5452015-12-14 10:38:29 +010029 unsigned int data_bytes;
30 unsigned int num_blocks;
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 Erlbeck392a5452015-12-14 10:38:29 +010034 {{0, 0}, {0, 0}, 0, 0, "UNKNOWN", GprsCodingScheme::HEADER_INVALID},
35 {{23, 0}, {23, 0}, 20, 1, "CS-1", GprsCodingScheme::HEADER_GPRS_DATA},
36 {{33, 7}, {33, 7}, 30, 1, "CS-2", GprsCodingScheme::HEADER_GPRS_DATA},
37 {{39, 3}, {39, 3}, 36, 1, "CS-3", GprsCodingScheme::HEADER_GPRS_DATA},
38 {{53, 7}, {53, 7}, 50, 1, "CS-4", GprsCodingScheme::HEADER_GPRS_DATA},
Jacob Erlbeck409f9802015-11-30 18:06:50 +010039
Jacob Erlbeck392a5452015-12-14 10:38:29 +010040 {{26, 1}, {26, 1}, 22, 1, "MCS-1", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
41 {{32, 1}, {32, 1}, 28, 1, "MCS-2", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
42 {{41, 1}, {41, 1}, 37, 1, "MCS-3", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
43 {{48, 1}, {48, 1}, 44, 1, "MCS-4", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
Jacob Erlbeck409f9802015-11-30 18:06:50 +010044
Jacob Erlbeck392a5452015-12-14 10:38:29 +010045 {{60, 7}, {59, 6}, 56, 1, "MCS-5", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2},
46 {{78, 7}, {77, 6}, 74, 1, "MCS-6", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2},
47 {{118, 2}, {117, 4}, 56, 2, "MCS-7", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
48 {{142, 2}, {141, 4}, 68, 2, "MCS-8", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
49 {{154, 2}, {153, 4}, 74, 2, "MCS-9", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
Jacob Erlbeck409f9802015-11-30 18:06:50 +010050};
51
52
53GprsCodingScheme GprsCodingScheme::getBySizeUL(unsigned size)
54{
55 switch (size) {
56 case 23: return GprsCodingScheme(CS1);
57 case 27: return GprsCodingScheme(MCS1);
58 case 33: return GprsCodingScheme(MCS2);
59 case 34: return GprsCodingScheme(CS2);
60 case 40: return GprsCodingScheme(CS3);
61 case 42: return GprsCodingScheme(MCS3);
62 case 49: return GprsCodingScheme(MCS4);
63 case 54: return GprsCodingScheme(CS4);
64 case 61: return GprsCodingScheme(MCS5);
65 case 79: return GprsCodingScheme(MCS6);
66 case 119: return GprsCodingScheme(MCS7);
67 case 143: return GprsCodingScheme(MCS8);
68 case 155: return GprsCodingScheme(MCS9);
69 }
70
71 return GprsCodingScheme(UNKNOWN);
72}
73
74unsigned int GprsCodingScheme::sizeUL() const
75{
76 return maxBytesUL() + (spareBitsUL() ? 1 : 0);
77}
78
79unsigned int GprsCodingScheme::maxBytesUL() const
80{
81 return mcs_info[m_scheme].uplink.bytes;
82}
83
84unsigned int GprsCodingScheme::spareBitsUL() const
85{
86 return mcs_info[m_scheme].uplink.ext_bits;
87}
88
89unsigned int GprsCodingScheme::sizeDL() const
90{
91 return maxBytesDL() + (spareBitsDL() ? 1 : 0);
92}
93
94unsigned int GprsCodingScheme::maxBytesDL() const
95{
96 return mcs_info[m_scheme].downlink.bytes;
97}
98
99unsigned int GprsCodingScheme::spareBitsDL() const
100{
101 return mcs_info[m_scheme].downlink.ext_bits;
102}
103
Jacob Erlbeck392a5452015-12-14 10:38:29 +0100104unsigned int GprsCodingScheme::maxDataBlockBytes() const
105{
106 return mcs_info[m_scheme].data_bytes;
107}
108
109unsigned int GprsCodingScheme::numDataBlocks() const
110{
111 return mcs_info[m_scheme].num_blocks;
112}
113
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100114const char *GprsCodingScheme::name() const
115{
116 return mcs_info[m_scheme].name;
117}
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100118
119GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeData() const
120{
121 return mcs_info[m_scheme].data_hdr;
122}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100123
124void GprsCodingScheme::inc(Mode mode)
125{
126 if (!isCompatible(mode))
127 /* This should not happen. TODO: Use assert? */
128 return;
129
130 Scheme new_cs(Scheme(m_scheme + 1));
131 if (!GprsCodingScheme(new_cs).isCompatible(mode))
132 /* Clipping, do not change the value */
133 return;
134
135 m_scheme = new_cs;
136}
137
138void GprsCodingScheme::dec(Mode mode)
139{
140 if (!isCompatible(mode))
141 /* This should not happen. TODO: Use assert? */
142 return;
143
144 Scheme new_cs(Scheme(m_scheme - 1));
145 if (!GprsCodingScheme(new_cs).isCompatible(mode))
146 /* Clipping, do not change the value */
147 return;
148
149 m_scheme = new_cs;
150}
151
152void GprsCodingScheme::inc()
153{
154 if (isGprs() && m_scheme == CS4)
155 return;
156
157 if (isEgprs() && m_scheme == MCS9)
158 return;
159
160 if (!isValid())
161 return;
162
163 m_scheme = Scheme(m_scheme + 1);
164}
165
166void GprsCodingScheme::dec()
167{
168 if (isGprs() && m_scheme == CS1)
169 return;
170
171 if (isEgprs() && m_scheme == MCS1)
172 return;
173
174 if (!isValid())
175 return;
176
177 m_scheme = Scheme(m_scheme - 1);
178}
Jacob Erlbeck7b579972016-01-05 15:54:24 +0100179
180const char *GprsCodingScheme::modeName(Mode mode)
181{
182 switch (mode) {
183 case GPRS: return "GPRS";
184 case EGPRS_GMSK: return "EGPRS_GMSK-only";
185 case EGPRS: return "EGPRS";
186 default: return "???";
187 }
188}