1 /******************************************************************************\
2 * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
3 * Copyright (c) 2001
4 *
5 * Author(s):
6 * Volker Fischer
7 *
8 * Adapted for ham sstv use Ties Bos - PA0MBO
9 *
10 *
11 * Description:
12 * Multi-level-channel (de)coder (MLC)
13 *
14 ******************************************************************************
15 *
16 * This program is free software; you can redistribute it and/or modify it under
17 * the terms of the GNU General Public License as published by the Free Software
18 * Foundation; either version 2 of the License, or (at your option) any later
19 * version.
20 *
21 * This program is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
24 * details.
25 *
26 * You should have received a copy of the GNU General Public License along with
27 * this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 \******************************************************************************/
31
32 #include "MLC.h"
33
34 #define NUM_FAC_CELLS 45
35
36
37 /* Implementation *************************************************************/
38 /******************************************************************************\
39 * MLC-encoder *
40 \******************************************************************************/
ProcessDataInternal(CParameter &)41 void CMLCEncoder::ProcessDataInternal(CParameter&)
42 {
43 int i, j;
44 int iElementCounter;
45
46 /* Energy dispersal ----------------------------------------------------- */
47 /* VSPP is treated as a separate part for energy dispersal */
48 EnergyDisp.ProcessData(pvecInputData);
49
50
51 /* Partitioning of input-stream ----------------------------------------- */
52 iElementCounter = 0;
53
54 if (iL[2] == 0)
55 {
56 /* Standard departitioning */
57 /* Protection level A */
58 for (j = 0; j < iLevels; j++)
59 {
60 /* Bits */
61 for (i = 0; i < iM[j][0]; i++)
62 {
63 vecEncInBuffer[j][i] =
64 // BitToSoft((*pvecInputData)[iElementCounter]);
65 (*pvecInputData)[iElementCounter];
66
67 iElementCounter++;
68 }
69 }
70
71 /* Protection level B */
72 for (j = 0; j < iLevels; j++)
73 {
74 /* Bits */
75 for (i = 0; i < iM[j][1]; i++)
76 {
77 vecEncInBuffer[j][iM[j][0] + i] =
78 // BitToSoft((*pvecInputData)[iElementCounter]);
79 (*pvecInputData)[iElementCounter];
80
81 iElementCounter++;
82 }
83 }
84 }
85 else
86 {
87 /* Special partitioning with hierarchical modulation. First set
88 hierarchical bits at the beginning, then append the rest */
89 /* Hierarchical frame (always "iM[0][1]"). "iM[0][0]" is always "0" in
90 this case */
91 for (i = 0; i < iM[0][1]; i++)
92 {
93 vecEncInBuffer[0][i] =
94 // BitToSoft((*pvecInputData)[iElementCounter]);
95 (*pvecInputData)[iElementCounter];
96
97 iElementCounter++;
98 }
99
100
101 /* Protection level A (higher protected part) */
102 for (j = 1; j < iLevels; j++)
103 {
104 /* Bits */
105 for (i = 0; i < iM[j][0]; i++)
106 {
107 vecEncInBuffer[j][i] =
108 // BitToSoft((*pvecInputData)[iElementCounter]);
109 (*pvecInputData)[iElementCounter];
110
111 iElementCounter++;
112 }
113 }
114
115 /* Protection level B (lower protected part) */
116 for (j = 1; j < iLevels; j++)
117 {
118 /* Bits */
119 for (i = 0; i < iM[j][1]; i++)
120 {
121 vecEncInBuffer[j][iM[j][0] + i] =
122 // BitToSoft((*pvecInputData)[iElementCounter]);
123 (*pvecInputData)[iElementCounter];
124
125 iElementCounter++;
126 }
127 }
128 }
129
130
131 /* Convolutional encoder ------------------------------------------------ */
132 for (j = 0; j < iLevels; j++)
133 ConvEncoder[j].Encode(vecEncInBuffer[j], vecEncOutBuffer[j]);
134
135
136 /* Bit interleaver ------------------------------------------------------ */
137 for (j = 0; j < iLevels; j++)
138 if (piInterlSequ[j] != -1)
139 BitInterleaver[piInterlSequ[j]].Interleave(vecEncOutBuffer[j]);
140
141
142 /* QAM mapping ---------------------------------------------------------- */
143 QAMMapping.Map(vecEncOutBuffer[0],
144 vecEncOutBuffer[1],
145 vecEncOutBuffer[2],
146 vecEncOutBuffer[3],
147 vecEncOutBuffer[4],
148 vecEncOutBuffer[5], pvecOutputData);
149 }
150
InitInternal(CParameter & TransmParam)151 void CMLCEncoder::InitInternal(CParameter& TransmParam)
152 {
153 int i;
154 int iNumInBits;
155
156 TransmParam.Lock();
157 CalculateParam(TransmParam, eChannelType);
158 TransmParam.Unlock();
159
160 iNumInBits = iL[0] + iL[1] + iL[2];
161
162
163 /* Init modules --------------------------------------------------------- */
164 /* Energy dispersal */
165 EnergyDisp.Init(iNumInBits, iL[2]);
166
167 /* Encoder */
168 for (i = 0; i < iLevels; i++)
169 ConvEncoder[i].Init(eCodingScheme, eChannelType, iN[0], iN[1],
170 iM[i][0], iM[i][1], iCodeRate[i][0], iCodeRate[i][1], i);
171
172 /* Bit interleaver */
173 /* First init all possible interleaver (According table "TableMLC.h" ->
174 "Interleaver sequence") */
175 if (eCodingScheme == CS_3_HMMIX)
176 {
177 BitInterleaver[0].Init(iN[0], iN[1], 13);
178 BitInterleaver[1].Init(iN[0], iN[1], 21);
179 }
180 else
181 {
182 BitInterleaver[0].Init(2 * iN[0], 2 * iN[1], 13);
183 BitInterleaver[1].Init(2 * iN[0], 2 * iN[1], 21);
184 }
185
186 /* QAM-mapping */
187 QAMMapping.Init(iN_mux, eCodingScheme);
188
189
190 /* Allocate memory for internal bit-buffers ----------------------------- */
191 for (i = 0; i < iLevels; i++)
192 {
193 /* Buffers for each encoder on all different levels */
194 /* Add bits from higher protected and lower protected part */
195 vecEncInBuffer[i].Init(iM[i][0] + iM[i][1]);
196
197 /* Encoder output buffers for all levels. Must have the same length */
198 vecEncOutBuffer[i].Init(iNumEncBits);
199 }
200
201 /* Define block-size for input and output */
202 iInputBlockSize = iNumInBits;
203 iOutputBlockSize = iN_mux;
204 // printf("In init MSCMLCEnc inputblk = %d outpublk = %d\n",
205 // iInputBlockSize, iOutputBlockSize);
206
207 }
208
209
210
211
212 /******************************************************************************\
213 * MLC base class *
214 \******************************************************************************/
CalculateParam(CParameter & Parameter,int iNewChannelType)215 void CMLC::CalculateParam(CParameter& Parameter, int iNewChannelType)
216 {
217 int i;
218 // int iMSCDataLenPartA;
219
220 switch (iNewChannelType)
221 {
222 /* FAC ********************************************************************/
223 case CT_FAC:
224 eCodingScheme = CS_1_SM;
225 iN_mux = NUM_FAC_CELLS;
226
227 iNumEncBits = NUM_FAC_CELLS * 2;
228
229 iLevels = 1;
230
231 /* Code rates for prot.-Level A and B for each level */
232 /* Protection Level A */
233 iCodeRate[0][0] = 0;
234
235 /* Protection Level B */
236 iCodeRate[0][1] = iCodRateCombFDC4SM;
237
238 /* Define interleaver sequence for all levels */
239 piInterlSequ = iInterlSequ4SM;
240
241
242 /* iN: Number of OFDM-cells of each protection level ---------------- */
243 iN[0] = 0;
244 iN[1] = iN_mux;
245
246
247 /* iM: Number of bits each level ------------------------------------ */
248 iM[0][0] = 0;
249 iM[0][1] = NUM_FAC_BITS_PER_BLOCK;
250
251
252 /* iL: Number of bits each protection level ------------------------- */
253 /* Higher protected part */
254 iL[0] = 0;
255
256 /* Lower protected part */
257 iL[1] = iM[0][1];
258
259 /* Very strong protected part (VSPP) */
260 iL[2] = 0;
261 break;
262
263
264
265 /* MSC ********************************************************************/
266 case CT_MSC:
267 eCodingScheme = Parameter.eMSCCodingScheme;
268 iN_mux = Parameter.CellMappingTable.iNumUsefMSCCellsPerFrame;
269 // printf("iN_mux %d \n", iN_mux);
270
271 /* Data length for part A is the sum of all lengths of the streams */
272
273 // iMSCDataLenPartA = 0; // for hamversion
274
275 /* iMSCDataLenPartA = Parameter.Stream[0].iLenPartA +
276 Parameter.Stream[1].iLenPartA +
277 Parameter.Stream[2].iLenPartA +
278 Parameter.Stream[3].iLenPartA; */
279
280 switch (eCodingScheme)
281 {
282 case CS_1_SM:
283 iLevels = 1;
284
285 /* Code rates for prot.-Level A and B for each level */
286 /* Protection Level A */
287 iCodeRate[0][0] = 0;
288
289 /* Protection Level B */
290 iCodeRate[0][1] = iCodRateCombMSC4SM;
291
292 /* Define interleaver sequence for all levels */
293 piInterlSequ = iInterlSequ4SM;
294 iNumEncBits = iN_mux * 2;
295
296 /* iN: Number of OFDM-cells of each protection level ---------------- */
297 iN[0] = 0;
298 iN[1] = iN_mux;
299
300 /* iM: Number of bits each level ------------------------------------ */
301 iM[0][0] = 0;
302
303 /* M_p,2 = RX_p * floor((2 * N_2 - 12) / RY_p) */
304 iM[0][1] = iPuncturingPatterns[iCodRateCombMSC4SM][0] *
305 (int) ((_REAL) (2 * iN_mux - 12) /
306 iPuncturingPatterns[iCodRateCombMSC4SM][1]);
307
308 /* iL: Number of bits each protection level ------------------------- */
309 /* Higher protected part */
310 iL[0] = 0;
311
312 /* Lower protected part */
313 iL[1] = iM[0][1];
314
315 /* Very strong protected part (VSPP) */
316 iL[2] = 0;
317 /* printf("in CalcuPar CS_1_SM iN[0]= %d iN[1]= %d iM[0][0] = %d iM[0][1] = %d\n",
318 iN[0], iN[1], iM[0][0], iM[0][1] );
319 printf("in CalcuPar iL[o]= %d iL[1]= %d iL[2] = %d\n",
320 iL[0], iL[1], iL[1]); */
321 break;
322
323 case CS_2_SM:
324 iLevels = 2;
325
326 /* Code rates for prot.-Level A and B for each level */
327 for (i = 0; i < 2; i++)
328 {
329 /* Protection Level A */
330 iCodeRate[i][0] = 0 ; // hamversion
331
332 /* iCodeRate[i][0] =
333 iCodRateCombMSC16SM[Parameter.MSCPrLe.iPartA][i]; */
334
335 /* Protection Level B */
336 iCodeRate[i][1] =
337 iCodRateCombMSC16SM[Parameter.MSCPrLe.iPartB][i];
338 }
339
340 /* Define interleaver sequence for all levels */
341 piInterlSequ = iInterlSequ16SM;
342
343 iNumEncBits = iN_mux * 2;
344
345
346 /* iN: Number of OFDM-cells of each protection level ------------ */
347 /* N_1 = ceil(8 * X / (2 * RY_Icm * sum(R_p)) * RY_Icm */
348 iN[0] = 0; // hamversion
349
350 /* iN[0] = (int) ceil(8 * (_REAL) iMSCDataLenPartA / (2 *
351 (_REAL) iCodRateCombMSC16SM[Parameter.MSCPrLe.iPartA][2] *
352 (
353 (_REAL) iPuncturingPatterns[iCodRateCombMSC16SM[
354 Parameter.MSCPrLe.iPartA][0]][0] /
355 iPuncturingPatterns[iCodRateCombMSC16SM[
356 Parameter.MSCPrLe.iPartA][0]][1] +
357 (_REAL) iPuncturingPatterns[iCodRateCombMSC16SM[
358 Parameter.MSCPrLe.iPartA][1]][0] /
359 iPuncturingPatterns[iCodRateCombMSC16SM[
360 Parameter.MSCPrLe.iPartA][1]][1]))) *
361 iCodRateCombMSC16SM[Parameter.MSCPrLe.iPartA][2];
362 */
363 /* Check if result can be possible, if not -> correct. This can
364 happen, if a wrong number is in "Param.Stream[x].iLenPartA" */
365 if (iN[0] > iN_mux)
366 iN[0] = 0;
367
368 iN[1] = iN_mux - iN[0];
369
370
371 /* iM: Number of bits each level -------------------------------- */
372 for (i = 0; i < 2; i++)
373 {
374 /* M_p,1 = 2 * N_1 * R_p */
375 iM[i][0] = 0;
376 /* iM[i][0] = (int) (2 * iN[0] *
377 (_REAL) iPuncturingPatterns[iCodRateCombMSC16SM[
378 Parameter.MSCPrLe.iPartA][i]][0] /
379 iPuncturingPatterns[iCodRateCombMSC16SM[
380 Parameter.MSCPrLe.iPartA][i]][1]); */
381
382 /* M_p,2 = RX_p * floor((2 * N_2 - 12) / RY_p) */
383 iM[i][1] =
384 iPuncturingPatterns[iCodRateCombMSC16SM[
385 Parameter.MSCPrLe.iPartB][i]][0] *
386 (int) ((_REAL) (2 * iN[1] - 12) /
387 iPuncturingPatterns[iCodRateCombMSC16SM[
388 Parameter.MSCPrLe.iPartB][i]][1]);
389 // printf("In calcparam iM[%d][0] = %d iM[%d][1] = %d \n", i, iM[i][0], i, iM[i][1]);
390 }
391
392
393 /* iL: Number of bits each protection level --------------------- */
394 /* Higher protected part */
395 iL[0] = iM[0][0] + iM[1][0];
396
397 /* Lower protected part */
398 iL[1] = iM[0][1] + iM[1][1];
399
400 /* Very strong protected part (VSPP) */
401 iL[2] = 0;
402 /* printf("in CalcuPar CS_2_SM iN[0]= %d iN[1]= %d iM[0][0] = %d iM[0][1] = %d\n",
403 iN[0], iN[1], iM[0][0], iM[0][1] );
404 printf("in CalcuPar iL[o]= %d iL[1]= %d iL[2] = %d\n",
405 iL[0], iL[1], iL[1]); */
406 break;
407
408 case CS_3_SM:
409 iLevels = 3;
410
411 /* Code rates for prot.-Level A and B for each level */
412 for (i = 0; i < 3; i++)
413 {
414 /* Protection Level A */
415 iCodeRate[i][0] = 0;
416 /* iCodeRate[i][0] =
417 iCodRateCombMSC64SM[Parameter.MSCPrLe.iPartA][i]; */
418
419 /* Protection Level B */
420 iCodeRate[i][1] =
421 iCodRateCombMSC64SM[Parameter.MSCPrLe.iPartB][i];
422 }
423
424 /* Define interleaver sequence for all levels */
425 piInterlSequ = iInterlSequ64SM;
426
427 iNumEncBits = iN_mux * 2;
428
429
430 /* iN: Number of OFDM-cells of each protection level ------------ */
431 /* N_1 = ceil(8 * X / (2 * RY_Icm * sum(R_p)) * RY_Icm */
432 iN[0] = 0;
433
434 /* Check if result can be possible, if not -> correct. This can
435 happen, if a wrong number is in "Param.Stream[x].iLenPartA" */
436 if (iN[0] > iN_mux)
437 iN[0] = 0;
438
439 iN[1] = iN_mux - iN[0];
440
441
442 /* iM: Number of bits each level -------------------------------- */
443 for (i = 0; i < 3; i++)
444 {
445 /* M_p,1 = 2 * N_1 * R_p */
446 iM[i][0] = 0;
447 /* iM[i][0] = (int) (2 * iN[0] *
448 (_REAL) iPuncturingPatterns[iCodRateCombMSC64SM[
449 Parameter.MSCPrLe.iPartA][i]][0] /
450 iPuncturingPatterns[iCodRateCombMSC64SM[
451 Parameter.MSCPrLe.iPartA][i]][1]); */
452
453 /* M_p,2 = RX_p * floor((2 * N_2 - 12) / RY_p) */
454 iM[i][1] =
455 iPuncturingPatterns[iCodRateCombMSC64SM[
456 Parameter.MSCPrLe.iPartB][i]][0] *
457 (int) ((_REAL) (2 * iN[1] - 12) /
458 iPuncturingPatterns[iCodRateCombMSC64SM[
459 Parameter.MSCPrLe.iPartB][i]][1]);
460 }
461
462
463 /* iL: Number of bits each protection level --------------------- */
464 /* Higher protected part */
465 iL[0] = iM[0][0] + iM[1][0] + iM[2][0];
466
467 /* Lower protected part */
468 iL[1] = iM[0][1] + iM[1][1] + iM[2][1];
469
470 /* Very strong protected part (VSPP) */
471 iL[2] = 0;
472 /* printf("in CalcuPar CS_3_SM iN[0]= %d iN[1]= %d iM[0][0] = %d iM[0][1] = %d\n",
473 iN[0], iN[1], iM[0][0], iM[0][1] );
474 printf("in CalcuPar iL[o]= %d iL[1]= %d iL[2] = %d\n",
475 iL[0], iL[1], iL[2]); */
476 break;
477
478
479 default:
480 break;
481 }
482
483 /* Set number of output bits for next module */
484 Parameter.SetNumDecodedBitsMSC(iL[0] + iL[1] + iL[2]);
485
486 /* Set total number of bits for hiearchical frame (needed for MSC
487 demultiplexer module) */
488 Parameter.SetNumBitsHieraFrTot(iL[2]);
489 // Parameter.DataParam.iPacketLen = 1234;
490 break;
491 }
492 }
493