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