1 /*
2  * Copyright (c) 2007 - 2015 Joseph Gaeddert
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 //
24 // modem_utilities.c : common utilities not specific to precision
25 //
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "liquid.internal.h"
32 
33 // full modulation type descriptor
34 const struct modulation_type_s modulation_types[LIQUID_MODEM_NUM_SCHEMES] = {
35     // name       fullname        scheme          bps
36 
37     // unknown
38     {"unknown",   "unkown",       LIQUID_MODEM_UNKNOWN, 0},
39 
40     // phase-shift keying
41     {"psk2",      "phase-shift keying (2)",   LIQUID_MODEM_PSK2,  1},
42     {"psk4",      "phase-shift keying (4)",   LIQUID_MODEM_PSK4,  2},
43     {"psk8",      "phase-shift keying (8)",   LIQUID_MODEM_PSK8,  3},
44     {"psk16",     "phase-shift keying (16)",  LIQUID_MODEM_PSK16, 4},
45     {"psk32",     "phase-shift keying (32)",  LIQUID_MODEM_PSK32, 5},
46     {"psk64",     "phase-shift keying (64)",  LIQUID_MODEM_PSK64, 6},
47     {"psk128",    "phase-shift keying (128)", LIQUID_MODEM_PSK128, 7},
48     {"psk256",    "phase-shift keying (256)", LIQUID_MODEM_PSK256, 8},
49 
50     // differential phase-shift keying
51     {"dpsk2",     "differential phase-shift keying (2)",   LIQUID_MODEM_DPSK2,  1},
52     {"dpsk4",     "differential phase-shift keying (4)",   LIQUID_MODEM_DPSK4,  2},
53     {"dpsk8",     "differential phase-shift keying (8)",   LIQUID_MODEM_DPSK8,  3},
54     {"dpsk16",    "differential phase-shift keying (16)",  LIQUID_MODEM_DPSK16, 4},
55     {"dpsk32",    "differential phase-shift keying (32)",  LIQUID_MODEM_DPSK32, 5},
56     {"dpsk64",    "differential phase-shift keying (64)",  LIQUID_MODEM_DPSK64, 6},
57     {"dpsk128",   "differential phase-shift keying (128)", LIQUID_MODEM_DPSK128, 7},
58     {"dpsk256",   "differential phase-shift keying (256)", LIQUID_MODEM_DPSK256, 8},
59 
60     // amplitude-shift keying
61     {"ask2",      "amplitude-shift keying (2)",   LIQUID_MODEM_ASK2,  1},
62     {"ask4",      "amplitude-shift keying (4)",   LIQUID_MODEM_ASK4,  2},
63     {"ask8",      "amplitude-shift keying (8)",   LIQUID_MODEM_ASK8,  3},
64     {"ask16",     "amplitude-shift keying (16)",  LIQUID_MODEM_ASK16, 4},
65     {"ask32",     "amplitude-shift keying (32)",  LIQUID_MODEM_ASK32, 5},
66     {"ask64",     "amplitude-shift keying (64)",  LIQUID_MODEM_ASK64, 6},
67     {"ask128",    "amplitude-shift keying (128)", LIQUID_MODEM_ASK128, 7},
68     {"ask256",    "amplitude-shift keying (256)", LIQUID_MODEM_ASK256, 8},
69 
70     // quadrature amplitude-shift keying
71     {"qam4",      "quadrature amplitude-shift keying (4)",   LIQUID_MODEM_QAM4,   2},
72     {"qam8",      "quadrature amplitude-shift keying (8)",   LIQUID_MODEM_QAM8,   3},
73     {"qam16",     "quadrature amplitude-shift keying (16)",  LIQUID_MODEM_QAM16,  4},
74     {"qam32",     "quadrature amplitude-shift keying (32)",  LIQUID_MODEM_QAM32,  5},
75     {"qam64",     "quadrature amplitude-shift keying (64)",  LIQUID_MODEM_QAM64,  6},
76     {"qam128",    "quadrature amplitude-shift keying (128)", LIQUID_MODEM_QAM128, 7},
77     {"qam256",    "quadrature amplitude-shift keying (256)", LIQUID_MODEM_QAM256, 8},
78 
79     // amplitude/phase-shift keying
80     {"apsk4",     "amplitude/phase-shift keying (4)",   LIQUID_MODEM_APSK4,   2},
81     {"apsk8",     "amplitude/phase-shift keying (8)",   LIQUID_MODEM_APSK8,   3},
82     {"apsk16",    "amplitude/phase-shift keying (16)",  LIQUID_MODEM_APSK16,  4},
83     {"apsk32",    "amplitude/phase-shift keying (32)",  LIQUID_MODEM_APSK32,  5},
84     {"apsk64",    "amplitude/phase-shift keying (64)",  LIQUID_MODEM_APSK64,  6},
85     {"apsk128",   "amplitude/phase-shift keying (128)", LIQUID_MODEM_APSK128, 7},
86     {"apsk256",   "amplitude/phase-shift keying (256)", LIQUID_MODEM_APSK256, 8},
87 
88     // specific modem types
89     {"bpsk",      "binary phase-shift keying",     LIQUID_MODEM_BPSK,      1},
90     {"qpsk",      "quaternary phase-shift keying", LIQUID_MODEM_QPSK,      2},
91     {"ook",       "ook (on/off keying)",           LIQUID_MODEM_OOK,       1},
92     {"sqam32",    "'square' 32-QAM",               LIQUID_MODEM_SQAM32,    5},
93     {"sqam128",   "'square' 128-QAM",              LIQUID_MODEM_SQAM128,   7},
94     {"V29",       "V.29",                          LIQUID_MODEM_V29,       4},
95     {"arb16opt",  "arb16opt (optimal 16-qam)",     LIQUID_MODEM_ARB16OPT,  4},
96     {"arb32opt",  "arb32opt (optimal 32-qam)",     LIQUID_MODEM_ARB32OPT,  5},
97     {"arb64opt",  "arb64opt (optimal 64-qam)",     LIQUID_MODEM_ARB64OPT,  6},
98     {"arb128opt", "arb128opt (optimal 128-qam)",   LIQUID_MODEM_ARB128OPT, 7},
99     {"arb256opt", "arb256opt (optimal 256-qam)",   LIQUID_MODEM_ARB256OPT, 8},
100     {"arb64vt",   "arb64vt (64-qam vt logo)",      LIQUID_MODEM_ARB64VT,   6},
101 
102     // arbitrary modem type
103     {"arb",       "arbitrary constellation",       LIQUID_MODEM_ARB,       0},
104 };
105 
106 
107 
liquid_getopt_str2mod(const char * _str)108 modulation_scheme liquid_getopt_str2mod(const char * _str)
109 {
110     // compare each string to short name
111     unsigned int i;
112     for (i=0; i<LIQUID_MODEM_NUM_SCHEMES; i++) {
113         if (strcmp(_str,modulation_types[i].name)==0)
114             return i;
115     }
116     fprintf(stderr,"warning: liquid_getopt_str2mod(), unknown/unsupported mod scheme : %s\n", _str);
117     return LIQUID_MODEM_UNKNOWN;
118 }
119 
120 // Print compact list of existing and available modulation schemes
liquid_print_modulation_schemes()121 void liquid_print_modulation_schemes()
122 {
123     unsigned int i;
124     unsigned int len = 10;
125 
126     // print all available modem schemes
127     printf("          ");
128     for (i=1; i<LIQUID_MODEM_NUM_SCHEMES; i++) {
129         printf("%s", modulation_types[i].name);
130 
131         if (i != LIQUID_MODEM_NUM_SCHEMES-1)
132             printf(", ");
133 
134         len += strlen(modulation_types[i].name);
135         if (len > 48 && i != LIQUID_MODEM_NUM_SCHEMES-1) {
136             len = 10;
137             printf("\n          ");
138         }
139     }
140     printf("\n");
141 }
142 
143 // query basic modulation types
liquid_modem_is_psk(modulation_scheme _ms)144 int liquid_modem_is_psk(modulation_scheme _ms)
145 {
146     switch (_ms) {
147     // Phase-shift keying (PSK)
148     case LIQUID_MODEM_PSK2:
149     case LIQUID_MODEM_PSK4:
150     case LIQUID_MODEM_PSK8:
151     case LIQUID_MODEM_PSK16:
152     case LIQUID_MODEM_PSK32:
153     case LIQUID_MODEM_PSK64:
154     case LIQUID_MODEM_PSK128:
155     case LIQUID_MODEM_PSK256:
156         return 1;
157     default:
158         return 0;
159     }
160 
161     return 0;
162 }
163 
liquid_modem_is_dpsk(modulation_scheme _ms)164 int liquid_modem_is_dpsk(modulation_scheme _ms)
165 {
166     switch (_ms) {
167     // Differential phase-shift keying (DPSK)
168     case LIQUID_MODEM_DPSK2:
169     case LIQUID_MODEM_DPSK4:
170     case LIQUID_MODEM_DPSK8:
171     case LIQUID_MODEM_DPSK16:
172     case LIQUID_MODEM_DPSK32:
173     case LIQUID_MODEM_DPSK64:
174     case LIQUID_MODEM_DPSK128:
175     case LIQUID_MODEM_DPSK256:
176         return 1;
177     default:
178         return 0;
179     }
180 
181     return 0;
182 }
183 
liquid_modem_is_ask(modulation_scheme _ms)184 int liquid_modem_is_ask(modulation_scheme _ms)
185 {
186     switch (_ms) {
187     // amplitude-shift keying (ASK)
188     case LIQUID_MODEM_ASK2:
189     case LIQUID_MODEM_ASK4:
190     case LIQUID_MODEM_ASK8:
191     case LIQUID_MODEM_ASK16:
192     case LIQUID_MODEM_ASK32:
193     case LIQUID_MODEM_ASK64:
194     case LIQUID_MODEM_ASK128:
195     case LIQUID_MODEM_ASK256:
196         return 1;
197     default:
198         return 0;
199     }
200 
201     return 0;
202 }
203 
liquid_modem_is_qam(modulation_scheme _ms)204 int liquid_modem_is_qam(modulation_scheme _ms)
205 {
206     switch (_ms) {
207     // rectangular quadrature amplitude-shift keying (QAM)
208     case LIQUID_MODEM_QAM4:
209     case LIQUID_MODEM_QAM8:
210     case LIQUID_MODEM_QAM16:
211     case LIQUID_MODEM_QAM32:
212     case LIQUID_MODEM_QAM64:
213     case LIQUID_MODEM_QAM128:
214     case LIQUID_MODEM_QAM256:
215         return 1;
216     default:
217         return 0;
218     }
219 
220     return 0;
221 }
222 
liquid_modem_is_apsk(modulation_scheme _ms)223 int liquid_modem_is_apsk(modulation_scheme _ms)
224 {
225     switch (_ms) {
226     // amplitude phase-shift keying (APSK)
227     case LIQUID_MODEM_APSK4:
228     case LIQUID_MODEM_APSK8:
229     case LIQUID_MODEM_APSK16:
230     case LIQUID_MODEM_APSK32:
231     case LIQUID_MODEM_APSK64:
232     case LIQUID_MODEM_APSK128:
233     case LIQUID_MODEM_APSK256:
234         return 1;
235     default:
236         return 0;
237     }
238 
239     return 0;
240 }
241 
242 
243 // gray encoding
gray_encode(unsigned int symbol_in)244 unsigned int gray_encode(unsigned int symbol_in)
245 {
246     return symbol_in ^ (symbol_in >> 1);
247 }
248 
249 // gray decoding
gray_decode(unsigned int symbol_in)250 unsigned int gray_decode(unsigned int symbol_in)
251 {
252     unsigned int mask = symbol_in;
253     unsigned int symbol_out = symbol_in;
254     unsigned int i;
255 
256     // Run loop in blocks of 4 to reduce number of comparisons. Running
257     // loop more times than MAX_MOD_BITS_PER_SYMBOL will not result in
258     // decoding errors.
259     for (i=0; i<MAX_MOD_BITS_PER_SYMBOL; i+=4) {
260         symbol_out ^= (mask >> 1);
261         symbol_out ^= (mask >> 2);
262         symbol_out ^= (mask >> 3);
263         symbol_out ^= (mask >> 4);
264         mask >>= 4;
265     }
266 
267     return symbol_out;
268 }
269 
270 // pack soft bits into symbol
271 //  _soft_bits  :   soft input bits [size: _bps x 1]
272 //  _bps        :   bits per symbol
273 //  _sym_out    :   output symbol, value in [0,2^_bps)
liquid_pack_soft_bits(unsigned char * _soft_bits,unsigned int _bps,unsigned int * _sym_out)274 void liquid_pack_soft_bits(unsigned char * _soft_bits,
275                            unsigned int _bps,
276                            unsigned int * _sym_out)
277 {
278     // validate input
279     if (_bps > MAX_MOD_BITS_PER_SYMBOL) {
280         fprintf(stderr,"error: liquid_unpack_soft_bits(), bits/symbol exceeds maximum (%u)\n", MAX_MOD_BITS_PER_SYMBOL);
281         exit(1);
282     }
283 
284     unsigned int i;
285     unsigned int s=0;
286     for (i=0; i<_bps; i++) {
287         s <<= 1;
288         s |= _soft_bits[i] > LIQUID_SOFTBIT_ERASURE ? 1 : 0;
289     }
290     *_sym_out = s;
291 }
292 
293 // unpack soft bits into symbol
294 //  _sym_in     :   input symbol, value in [0,2^_bps)
295 //  _bps        :   bits per symbol
296 //  _soft_bits  :   soft output bits [size: _bps x 1]
liquid_unpack_soft_bits(unsigned int _sym_in,unsigned int _bps,unsigned char * _soft_bits)297 void liquid_unpack_soft_bits(unsigned int _sym_in,
298                              unsigned int _bps,
299                              unsigned char * _soft_bits)
300 {
301     // validate input
302     if (_bps > MAX_MOD_BITS_PER_SYMBOL) {
303         fprintf(stderr,"error: liquid_unpack_soft_bits(), bits/symbol exceeds maximum (%u)\n", MAX_MOD_BITS_PER_SYMBOL);
304         exit(1);
305     }
306 
307     unsigned int i;
308     for (i=0; i<_bps; i++)
309         _soft_bits[i] = ((_sym_in >> (_bps-i-1)) & 0x0001) ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0;
310 }
311 
312 
313