blob: 728ffd665362dcbcdd2b3ae3f58fb5679e510fc0 [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
Maxbea2edb2019-03-06 17:04:59 +010076 static CodingScheme get_retx_mcs(const GprsCodingScheme mcs,
Aravind Sirsikar50b09702016-08-22 17:21:10 +053077 const GprsCodingScheme retx_mcs,
78 const unsigned arq_type);
Jacob Erlbeck409f9802015-11-30 18:06:50 +010079private:
Jacob Erlbeck7e7a2612016-01-07 18:07:54 +010080 GprsCodingScheme(int s); /* fail on use */
81 GprsCodingScheme& operator =(int s); /* fail on use */
Maxbea2edb2019-03-06 17:04:59 +010082 enum CodingScheme m_scheme;
Jacob Erlbeck409f9802015-11-30 18:06:50 +010083};
84
Maxb3a17d62017-12-21 12:11:33 +010085inline uint8_t GprsCodingScheme::to_num() const
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010086{
Max8a8e0fb2019-03-25 16:32:50 +010087 if (mcs_is_gprs(m_scheme))
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010088 return (m_scheme - CS1) + 1;
89
Max8a8e0fb2019-03-25 16:32:50 +010090 if (mcs_is_edge(m_scheme))
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +010091 return (m_scheme - MCS1) + 1;
92
93 return 0;
94}
95
Maxa4de02d2019-03-13 16:35:09 +010096inline bool GprsCodingScheme::isCompatible(enum mcs_kind mode) const
Jacob Erlbeck409f9802015-11-30 18:06:50 +010097{
98 switch (mode) {
Max8a8e0fb2019-03-25 16:32:50 +010099 case GPRS: return mcs_is_gprs(m_scheme);
100 case EGPRS_GMSK: return mcs_is_edge_gmsk(m_scheme);
101 case EGPRS: return mcs_is_edge(m_scheme);
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100102 }
103
104 return false;
105}
106
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100107inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100108{
Max8a8e0fb2019-03-25 16:32:50 +0100109 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 +0100110}
111
Maxbea2edb2019-03-06 17:04:59 +0100112inline GprsCodingScheme::GprsCodingScheme(CodingScheme s)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100113 : m_scheme(s)
114{
115 if (!isValid())
116 m_scheme = UNKNOWN;
117}
118
Maxbea2edb2019-03-06 17:04:59 +0100119inline GprsCodingScheme& GprsCodingScheme::operator =(CodingScheme s)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100120{
121 m_scheme = s;
122
123 if (!isValid())
124 m_scheme = UNKNOWN;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100125
126 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100127}
128
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100129inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100130{
131 m_scheme = o.m_scheme;
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100132 return *this;
Jacob Erlbeck409f9802015-11-30 18:06:50 +0100133}
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100134
135inline GprsCodingScheme GprsCodingScheme::getGprsByNum(unsigned num)
136{
137 if (num < 1 || num > 4)
138 return GprsCodingScheme();
139
Maxbea2edb2019-03-06 17:04:59 +0100140 return GprsCodingScheme(CodingScheme(CS1 + (num - 1)));
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100141}
142
143inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
144{
145 if (num < 1 || num > 9)
146 return GprsCodingScheme();
147
Maxbea2edb2019-03-06 17:04:59 +0100148 return GprsCodingScheme(CodingScheme(MCS1 + (num - 1)));
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100149}
150
151/* The coding schemes form a partial ordering */
Maxbea2edb2019-03-06 17:04:59 +0100152inline bool GprsCodingScheme::operator == (CodingScheme scheme) const
Aravind Sirsikare8ccafc2016-07-13 11:37:47 +0530153{
154 return this->m_scheme == scheme;
155}
156
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100157inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
158{
159 return !(a == b);
160}
161
162inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
163{
Maxbea2edb2019-03-06 17:04:59 +0100164 return a.isCompatible(b) && a.to_num() < b.to_num();
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100165}