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