blob: c31f58fbccfee71c7c8959a7f77905e678ec8eae [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>
Maxbea2edb2019-03-06 17:04:59 +010028 #include "coding_scheme.h"
Max19621362017-09-08 12:33:34 +020029}
Jacob Erlbeck409f9802015-11-30 18:06:50 +010030
31class GprsCodingScheme {
32public:
Aravind Sirsikar91495522016-07-12 14:17:12 +053033
Aravind Sirsikar91495522016-07-12 14:17:12 +053034#define EGPRS_ARQ1 0x0
35#define EGPRS_ARQ2 0x1
36
Maxbea2edb2019-03-06 17:04:59 +010037 GprsCodingScheme(CodingScheme s = UNKNOWN);
Jacob Erlbeck409f9802015-11-30 18:06:50 +010038
39 operator bool() const {return m_scheme != UNKNOWN;}
Maxbea2edb2019-03-06 17:04:59 +010040 operator CodingScheme() const {return m_scheme;}
Maxb3a17d62017-12-21 12:11:33 +010041 uint8_t to_num() const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010042
Maxbea2edb2019-03-06 17:04:59 +010043 GprsCodingScheme& operator =(CodingScheme s);
44 bool operator == (CodingScheme s) const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010045 GprsCodingScheme& operator =(GprsCodingScheme o);
46
Jacob Erlbeck409f9802015-11-30 18:06:50 +010047 bool isValid() const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;}
Max8a8e0fb2019-03-25 16:32:50 +010048
Maxa4de02d2019-03-13 16:35:09 +010049 bool isCompatible(enum mcs_kind mode) const;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010050 bool isCompatible(GprsCodingScheme o) const;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010051 bool isFamilyCompatible(GprsCodingScheme o) const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010052
Maxa4de02d2019-03-13 16:35:09 +010053 void inc(enum mcs_kind mode);
54 void dec(enum mcs_kind mode);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010055 void inc();
56 void dec();
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010057 void decToSingleBlock(bool *needStuffing);
Jacob Erlbeck409f9802015-11-30 18:06:50 +010058
Maxb3a17d62017-12-21 12:11:33 +010059 uint8_t sizeUL() const;
60 uint8_t sizeDL() const;
61 uint8_t usedSizeUL() const;
62 uint8_t usedSizeDL() const;
63 uint8_t maxBytesUL() const;
64 uint8_t maxBytesDL() const;
65 uint8_t spareBitsUL() const;
66 uint8_t spareBitsDL() const;
67 uint8_t maxDataBlockBytes() const;
Maxb3a17d62017-12-21 12:11:33 +010068 uint8_t optionalPaddingBits() const;
Max136ebcc2019-03-05 14:59:03 +010069
Max51754b62019-03-13 17:14:13 +010070 enum HeaderType headerTypeData() const;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010071
72 static GprsCodingScheme getBySizeUL(unsigned size);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010073 static GprsCodingScheme getGprsByNum(unsigned num);
74 static GprsCodingScheme getEgprsByNum(unsigned num);
Jacob Erlbeck409f9802015-11-30 18:06:50 +010075
76private:
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +010077 GprsCodingScheme(int s); /* fail on use */
78 GprsCodingScheme& operator =(int s); /* fail on use */
Maxbea2edb2019-03-06 17:04:59 +010079 enum CodingScheme m_scheme;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010080};
81
Max898dddb2019-03-12 15:50:57 +010082// FIXME: remove once < comparison operator below is no longer necessary
Maxb3a17d62017-12-21 12:11:33 +010083inline uint8_t GprsCodingScheme::to_num() const
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010084{
Max8a8e0fb2019-03-25 16:32:50 +010085 if (mcs_is_gprs(m_scheme))
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010086 return (m_scheme - CS1) + 1;
87
Max8a8e0fb2019-03-25 16:32:50 +010088 if (mcs_is_edge(m_scheme))
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010089 return (m_scheme - MCS1) + 1;
90
91 return 0;
92}
93
Maxa4de02d2019-03-13 16:35:09 +010094inline bool GprsCodingScheme::isCompatible(enum mcs_kind mode) const
Jacob Erlbeck409f9802015-11-30 18:06:50 +010095{
96 switch (mode) {
Max8a8e0fb2019-03-25 16:32:50 +010097 case GPRS: return mcs_is_gprs(m_scheme);
98 case EGPRS_GMSK: return mcs_is_edge_gmsk(m_scheme);
99 case EGPRS: return mcs_is_edge(m_scheme);
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100100 }
101
102 return false;
103}
104
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100105inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100106{
Max8a8e0fb2019-03-25 16:32:50 +0100107 return (mcs_is_gprs(m_scheme) && mcs_is_gprs(o)) || (mcs_is_edge(m_scheme) && mcs_is_edge(o));
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100108}
109
Maxbea2edb2019-03-06 17:04:59 +0100110inline GprsCodingScheme::GprsCodingScheme(CodingScheme s)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100111 : m_scheme(s)
112{
113 if (!isValid())
114 m_scheme = UNKNOWN;
115}
116
Maxbea2edb2019-03-06 17:04:59 +0100117inline GprsCodingScheme& GprsCodingScheme::operator =(CodingScheme s)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100118{
119 m_scheme = s;
120
121 if (!isValid())
122 m_scheme = UNKNOWN;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100123
124 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100125}
126
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100127inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100128{
129 m_scheme = o.m_scheme;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100130 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100131}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100132
133inline GprsCodingScheme GprsCodingScheme::getGprsByNum(unsigned num)
134{
135 if (num < 1 || num > 4)
136 return GprsCodingScheme();
137
Maxbea2edb2019-03-06 17:04:59 +0100138 return GprsCodingScheme(CodingScheme(CS1 + (num - 1)));
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100139}
140
141inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
142{
143 if (num < 1 || num > 9)
144 return GprsCodingScheme();
145
Maxbea2edb2019-03-06 17:04:59 +0100146 return GprsCodingScheme(CodingScheme(MCS1 + (num - 1)));
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100147}
148
149/* The coding schemes form a partial ordering */
Maxbea2edb2019-03-06 17:04:59 +0100150inline bool GprsCodingScheme::operator == (CodingScheme scheme) const
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530151{
152 return this->m_scheme == scheme;
153}
154
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100155inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
156{
157 return !(a == b);
158}
159
160inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
161{
Maxbea2edb2019-03-06 17:04:59 +0100162 return a.isCompatible(b) && a.to_num() < b.to_num();
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100163}