1 /*
2 * Copyright (C) 2013
3 * Jan van Katwijk (J.vanKatwijk@gmail.com)
4 * Lazy Chair Programming
5 *
6 * This file is part of the SDR-J (JSDR).
7 * SDR-J is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * SDR-J is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with SDR-J; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * The deconvolution for both uep and eep
22 */
23 #include "dab-constants.h"
24 #include "uep-protection.h"
25 #include "protTables.h"
26
27 struct protectionProfile {
28 int16_t bitRate;
29 int16_t protLevel;
30 int16_t L1;
31 int16_t L2;
32 int16_t L3;
33 int16_t L4;
34 int16_t PI1;
35 int16_t PI2;
36 int16_t PI3;
37 int16_t PI4;
38 } profileTable[] = {
39 {32, 5, 3, 4, 17, 0, 5, 3, 2, -1},
40 {32, 4, 3, 3, 18, 0, 11, 6, 5, -1},
41 {32, 3, 3, 4, 14, 3, 15, 9, 6, 8},
42 {32, 2, 3, 4, 14, 3, 22, 13, 8, 13},
43 {32, 1, 3, 5, 13, 3, 24, 17, 12, 17},
44
45 {48, 5, 4, 3, 26, 3, 5, 4, 2, 3},
46 {48, 4, 3, 4, 26, 3, 9, 6, 4, 6},
47 {48, 3, 3, 4, 26, 3, 15, 10, 6, 9},
48 {48, 2, 3, 4, 26, 3, 24, 14, 8, 15},
49 {48, 1, 3, 5, 25, 3, 24, 18, 13, 18},
50
51 {56, 5, 6, 10, 23, 3, 5, 4, 2, 3},
52 {56, 4, 6, 10, 23, 3, 9, 6, 4, 5},
53 {56, 3, 6, 12, 21, 3, 16, 7, 6, 9},
54 {56, 2, 6, 10, 23, 3, 23, 13, 8, 13},
55
56 {64, 5, 6, 9, 31, 2, 5, 3, 2, 3},
57 {64, 4, 6, 9, 33, 0, 11, 6, 5, -1},
58 {64, 3, 6, 12, 27, 3, 16, 8, 6, 9},
59 {64, 2, 6, 10, 29, 3, 23, 13, 8, 13},
60 {64, 1, 6, 11, 28, 3, 24, 18, 12, 18},
61
62 {80, 5, 6, 10, 41, 3, 6, 3, 2, 3},
63 {80, 4, 6, 10, 41, 3, 11, 6, 5, 6},
64 {80, 3, 6, 11, 40, 3, 16, 8, 6, 7},
65 {80, 2, 6, 10, 41, 3, 23, 13, 8, 13},
66 {80, 1, 6, 10, 41, 3, 24, 7, 12, 18},
67
68 {96, 5, 7, 9, 53, 3, 5, 4, 2, 4},
69 {96, 4, 7, 10, 52, 3, 9, 6, 4, 6},
70 {96, 3, 6, 12, 51, 3, 16, 9, 6, 10},
71 {96, 2, 6, 10, 53, 3, 22, 12, 9, 12},
72 {96, 1, 6, 13, 50, 3, 24, 18, 13, 19},
73 //
74 // Thanks to Kalle Riis, who found that the "112" was missing
75 {112, 5, 14, 17, 50, 3, 5, 4, 2, 5},
76 {112, 4, 11, 21, 49, 3, 9, 6, 4, 8},
77 {112, 3, 11, 23, 47, 3, 16, 8, 6, 9},
78 {112, 2, 11, 21, 49, 3, 23, 12, 9, 14},
79
80 {128, 5, 12, 19, 62, 3, 5, 3, 2, 4},
81 {128, 4, 11, 21, 61, 3, 11, 6, 5, 7},
82 {128, 3, 11, 22, 60, 3, 16, 9, 6, 10},
83 {128, 2, 11, 21, 61, 3, 22, 12, 9, 14},
84 {128, 1, 11, 20, 62, 3, 24, 17, 13, 19},
85
86 {160, 5, 11, 19, 87, 3, 5, 4, 2, 4},
87 {160, 4, 11, 23, 83, 3, 11, 6, 5, 9},
88 {160, 3, 11, 24, 82, 3, 16, 8, 6, 11},
89 {160, 2, 11, 21, 85, 3, 22, 11, 9, 13},
90 {160, 1, 11, 22, 84, 3, 24, 18, 12, 19},
91
92 {192, 5, 11, 20, 110, 3, 6, 4, 2, 5},
93 {192, 4, 11, 22, 108, 3, 10, 6, 4, 9},
94 {192, 3, 11, 24, 106, 3, 16, 10, 6, 11},
95 {192, 2, 11, 20, 110, 3, 22, 13, 9, 13},
96 {192, 1, 11, 21, 109, 3, 24, 20, 13, 24},
97
98 {224, 5, 12, 22, 131, 3, 8, 6, 2, 6},
99 {224, 4, 12, 26, 127, 3, 12, 8, 4, 11},
100 {224, 3, 11, 20, 134, 3, 16, 10, 7, 9},
101 {224, 2, 11, 22, 132, 3, 24, 16, 10, 15},
102 {224, 1, 11, 24, 130, 3, 24, 20, 12, 20},
103
104 {256, 5, 11, 24, 154, 3, 6, 5, 2, 5},
105 {256, 4, 11, 24, 154, 3, 12, 9, 5, 10},
106 {256, 3, 11, 27, 151, 3, 16, 10, 7, 10},
107 {256, 2, 11, 22, 156, 3, 24, 14, 10, 13},
108 {256, 1, 11, 26, 152, 3, 24, 19, 14, 18},
109
110 {320, 5, 11, 26, 200, 3, 8, 5, 2, 6},
111 {320, 4, 11, 25, 201, 3, 13, 9, 5, 10},
112 {320, 2, 11, 26, 200, 3, 24, 17, 9, 17},
113
114 {384, 5, 11, 27, 247, 3, 8, 6, 2, 7},
115 {384, 3, 11, 24, 250, 3, 16, 9, 7, 10},
116 {384, 1, 12, 28, 245, 3, 24, 20, 14, 23},
117 {0, -1, -1, -1, -1, -1, -1, -1, -1, -1}
118 };
119
120 static
findIndex(int16_t bitRate,int16_t protLevel)121 int16_t findIndex(int16_t bitRate, int16_t protLevel)
122 {
123 int16_t i;
124
125 for (i = 0; profileTable[i].bitRate != 0; i ++) {
126 if ( (profileTable[i].bitRate == bitRate) &&
127 (profileTable[i].protLevel == protLevel)) {
128 return i;
129 }
130 }
131
132 return -1;
133 }
134
135 /**
136 * the table is based on chapter 11 of the DAB standard.
137 *
138 * \brief uep_deconvolve
139 *
140 * The bitRate and the protectionLevel determine the
141 * depuncturing scheme.
142 */
UEPProtection(int16_t bitRate,int16_t protLevel)143 UEPProtection::UEPProtection(
144 int16_t bitRate,
145 int16_t protLevel) :
146 Viterbi(24 * bitRate),
147 outSize(24 * bitRate),
148 viterbiBlock(outSize * 4 + 24)
149 {
150 int16_t index = findIndex (bitRate, protLevel);
151 if (index == -1) {
152 fprintf(stderr, "UEP: %d (%d) has a problem\n", bitRate, protLevel);
153 index = 1;
154 }
155 L1 = profileTable[index].L1;
156 L2 = profileTable[index].L2;
157 L3 = profileTable[index].L3;
158 L4 = profileTable[index].L4;
159
160 PI1 = getPCodes(profileTable[index].PI1 -1);
161 PI2 = getPCodes(profileTable[index].PI2 -1);
162 PI3 = getPCodes(profileTable[index].PI3 -1);
163 if ((profileTable[index].PI4 - 1) != -1)
164 PI4 = getPCodes(profileTable[index].PI4 -1);
165 else
166 PI4 = nullptr;
167 }
168
deconvolve(const softbit_t * v,int32_t size,uint8_t * outBuffer)169 bool UEPProtection::deconvolve(const softbit_t *v, int32_t size, uint8_t *outBuffer)
170 {
171 int16_t i, j;
172 int16_t inputCounter = 0;
173 int32_t viterbiCounter = 0;
174 (void)size; // currently unused
175
176 // according to the standard we process the logical frame
177 // with a pair of tuples
178 // (L1, PI1), (L2, PI2), (L3, PI3), (L4, PI4)
179
180 /// clear the bits in the viterbiBlock,
181 /// only the non-punctured ones are set
182 memset(viterbiBlock.data(), 0, (outSize * 4 + 24) * sizeof(softbit_t));
183
184 for (i = 0; i < L1; i ++) {
185 for (j = 0; j < 128; j ++) {
186 if (PI1[j % 32] != 0) {
187 viterbiBlock[viterbiCounter] = v[inputCounter ++];
188 }
189 viterbiCounter++;
190 }
191 }
192
193 for (i = 0; i < L2; i ++) {
194 for (j = 0; j < 128; j ++) {
195 if (PI2[j % 32] != 0) {
196 viterbiBlock[viterbiCounter] = v[inputCounter ++];
197 }
198 viterbiCounter++;
199 }
200 }
201
202 for (i = 0; i < L3; i ++) {
203 for (j = 0; j < 128; j ++) {
204 if (PI3[j % 32] != 0) {
205 viterbiBlock[viterbiCounter] = v[inputCounter ++];
206 }
207 viterbiCounter++;
208 }
209 }
210
211 for (i = 0; i < L4; i ++) {
212 if (PI4 == nullptr) {
213 throw std::logic_error("Invalid usage of NULL PI4");
214 }
215
216 for (j = 0; j < 128; j ++) {
217 if (PI4[j % 32] != 0) {
218 viterbiBlock[viterbiCounter] = v[inputCounter ++];
219 }
220 viterbiCounter++;
221 }
222 }
223
224 /**
225 * we have a final block of 24 bits with puncturing according to PI_X
226 * This block constitues the 6 * 4 bits of the register itself.
227 */
228 for (i = 0; i < 24; i ++) {
229 if (PI_X[i] != 0) {
230 viterbiBlock[viterbiCounter] = v[inputCounter ++];
231 }
232 viterbiCounter++;
233 }
234
235 /// The actual deconvolution is done by the viterbi decoder
236
237 Viterbi::deconvolve(viterbiBlock.data(), outBuffer);
238 return true;
239 }
240
241