mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 21:40:52 -05:00 
			
		
		
		
	Add code for QRA64 with fast fading.
git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7295 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
		
							parent
							
								
									354cebbb5e
								
							
						
					
					
						commit
						8d78c58697
					
				@ -494,6 +494,7 @@ set (qra_CSRCS
 | 
			
		||||
  lib/qra/qracodes/qra12_63_64_irr_b.c
 | 
			
		||||
  lib/qra/qracodes/qra13_64_64_irr_e.c
 | 
			
		||||
  lib/qra/qracodes/qracodes.c
 | 
			
		||||
  lib/qra/qracodes/normrnd.c
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
set (wsjt_CSRCS
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										327
									
								
								lib/qra/qra64/fadampgauss.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								lib/qra/qra64/fadampgauss.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,327 @@
 | 
			
		||||
/* 
 | 
			
		||||
fadampgauss.c
 | 
			
		||||
Gaussian fading tables for QRA64 modes
 | 
			
		||||
 | 
			
		||||
(c) 2016 - Nico Palermo, IV3NWV
 | 
			
		||||
 | 
			
		||||
This file is part of the qracodes project, a Forward Error Control
 | 
			
		||||
encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
   qracodes is free software: you can redistribute it and/or modify
 | 
			
		||||
   it under the terms of the GNU General Public License as published by
 | 
			
		||||
   the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
   (at your option) any later version.
 | 
			
		||||
   qracodes is distributed in the hope that it will be useful,
 | 
			
		||||
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
   GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
   You should have received a copy of the GNU General Public License
 | 
			
		||||
   along with qracodes source distribution.  
 | 
			
		||||
   If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
static const int hlen_tab_gauss[64] = {
 | 
			
		||||
  2,   2,   2,   2,   2,   2,   2,   2, 
 | 
			
		||||
  2,   2,   2,   2,   2,   2,   2,   2, 
 | 
			
		||||
  3,   3,   3,   3,   3,   3,   3,   3, 
 | 
			
		||||
  4,   4,   4,   4,   5,   5,   5,   6, 
 | 
			
		||||
  6,   6,   7,   7,   8,   8,   9,  10, 
 | 
			
		||||
 10,  11,  12,  13,  14,  15,  17,  18, 
 | 
			
		||||
 19,  21,  23,  25,  27,  29,  32,  34, 
 | 
			
		||||
 37,  41,  44,  48,  52,  57,  62,  65
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss1[2] = {
 | 
			
		||||
0.1722f, 0.9540f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss2[2] = {
 | 
			
		||||
0.1870f, 0.9463f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss3[2] = {
 | 
			
		||||
0.2028f, 0.9374f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss4[2] = {
 | 
			
		||||
0.2198f, 0.9273f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss5[2] = {
 | 
			
		||||
0.2378f, 0.9158f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss6[2] = {
 | 
			
		||||
0.2569f, 0.9030f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss7[2] = {
 | 
			
		||||
0.2769f, 0.8887f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss8[2] = {
 | 
			
		||||
0.2977f, 0.8730f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss9[2] = {
 | 
			
		||||
0.3190f, 0.8559f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss10[2] = {
 | 
			
		||||
0.3405f, 0.8374f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss11[2] = {
 | 
			
		||||
0.3619f, 0.8177f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss12[2] = {
 | 
			
		||||
0.3828f, 0.7970f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss13[2] = {
 | 
			
		||||
0.4026f, 0.7755f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss14[2] = {
 | 
			
		||||
0.4208f, 0.7533f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss15[2] = {
 | 
			
		||||
0.4371f, 0.7307f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss16[2] = {
 | 
			
		||||
0.4510f, 0.7078f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss17[3] = {
 | 
			
		||||
0.1729f, 0.4621f, 0.6849f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss18[3] = {
 | 
			
		||||
0.1920f, 0.4704f, 0.6620f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss19[3] = {
 | 
			
		||||
0.2131f, 0.4757f, 0.6393f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss20[3] = {
 | 
			
		||||
0.2350f, 0.4782f, 0.6170f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss21[3] = {
 | 
			
		||||
0.2565f, 0.4779f, 0.5949f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss22[3] = {
 | 
			
		||||
0.2767f, 0.4752f, 0.5733f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss23[3] = {
 | 
			
		||||
0.2948f, 0.4703f, 0.5522f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss24[3] = {
 | 
			
		||||
0.3102f, 0.4635f, 0.5316f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss25[4] = {
 | 
			
		||||
0.1874f, 0.3226f, 0.4551f, 0.5115f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss26[4] = {
 | 
			
		||||
0.2071f, 0.3319f, 0.4454f, 0.4919f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss27[4] = {
 | 
			
		||||
0.2253f, 0.3383f, 0.4347f, 0.4730f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss28[4] = {
 | 
			
		||||
0.2413f, 0.3419f, 0.4232f, 0.4546f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss29[5] = {
 | 
			
		||||
0.1701f, 0.2546f, 0.3429f, 0.4110f, 0.4368f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss30[5] = {
 | 
			
		||||
0.1874f, 0.2652f, 0.3417f, 0.3985f, 0.4196f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss31[5] = {
 | 
			
		||||
0.2028f, 0.2729f, 0.3386f, 0.3857f, 0.4029f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss32[6] = {
 | 
			
		||||
0.1569f, 0.2158f, 0.2780f, 0.3338f, 0.3728f, 0.3868f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss33[6] = {
 | 
			
		||||
0.1723f, 0.2263f, 0.2807f, 0.3278f, 0.3599f, 0.3713f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss34[6] = {
 | 
			
		||||
0.1857f, 0.2343f, 0.2812f, 0.3207f, 0.3471f, 0.3564f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss35[7] = {
 | 
			
		||||
0.1550f, 0.1968f, 0.2398f, 0.2799f, 0.3128f, 0.3344f, 0.3420f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss36[7] = {
 | 
			
		||||
0.1677f, 0.2055f, 0.2430f, 0.2770f, 0.3043f, 0.3220f, 0.3281f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss37[8] = {
 | 
			
		||||
0.1456f, 0.1783f, 0.2118f, 0.2442f, 0.2728f, 0.2953f, 0.3098f, 0.3147f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss38[8] = {
 | 
			
		||||
0.1572f, 0.1866f, 0.2160f, 0.2436f, 0.2675f, 0.2861f, 0.2979f, 0.3019f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss39[9] = {
 | 
			
		||||
0.1410f, 0.1667f, 0.1928f, 0.2182f, 0.2416f, 0.2615f, 0.2767f, 0.2863f, 
 | 
			
		||||
0.2895f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss40[10] = {
 | 
			
		||||
0.1288f, 0.1511f, 0.1741f, 0.1970f, 0.2187f, 0.2383f, 0.2547f, 0.2672f, 
 | 
			
		||||
0.2750f, 0.2776f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss41[10] = {
 | 
			
		||||
0.1391f, 0.1592f, 0.1795f, 0.1992f, 0.2176f, 0.2340f, 0.2476f, 0.2578f, 
 | 
			
		||||
0.2641f, 0.2662f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss42[11] = {
 | 
			
		||||
0.1298f, 0.1475f, 0.1654f, 0.1830f, 0.1999f, 0.2153f, 0.2289f, 0.2401f, 
 | 
			
		||||
0.2484f, 0.2535f, 0.2552f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss43[12] = {
 | 
			
		||||
0.1227f, 0.1382f, 0.1540f, 0.1696f, 0.1848f, 0.1991f, 0.2120f, 0.2232f, 
 | 
			
		||||
0.2324f, 0.2391f, 0.2433f, 0.2447f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss44[13] = {
 | 
			
		||||
0.1173f, 0.1309f, 0.1448f, 0.1587f, 0.1722f, 0.1851f, 0.1971f, 0.2078f, 
 | 
			
		||||
0.2171f, 0.2246f, 0.2301f, 0.2334f, 0.2346f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss45[14] = {
 | 
			
		||||
0.1132f, 0.1253f, 0.1375f, 0.1497f, 0.1617f, 0.1732f, 0.1841f, 0.1941f, 
 | 
			
		||||
0.2030f, 0.2106f, 0.2167f, 0.2212f, 0.2239f, 0.2248f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss46[15] = {
 | 
			
		||||
0.1102f, 0.1208f, 0.1315f, 0.1423f, 0.1529f, 0.1632f, 0.1730f, 0.1821f, 
 | 
			
		||||
0.1904f, 0.1978f, 0.2040f, 0.2089f, 0.2126f, 0.2148f, 0.2155f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss47[17] = {
 | 
			
		||||
0.0987f, 0.1079f, 0.1173f, 0.1267f, 0.1362f, 0.1455f, 0.1546f, 0.1634f, 
 | 
			
		||||
0.1716f, 0.1792f, 0.1861f, 0.1921f, 0.1972f, 0.2012f, 0.2042f, 0.2059f, 
 | 
			
		||||
0.2065f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss48[18] = {
 | 
			
		||||
0.0980f, 0.1062f, 0.1145f, 0.1228f, 0.1311f, 0.1393f, 0.1474f, 0.1551f, 
 | 
			
		||||
0.1624f, 0.1693f, 0.1756f, 0.1813f, 0.1862f, 0.1904f, 0.1936f, 0.1960f, 
 | 
			
		||||
0.1975f, 0.1979f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss49[19] = {
 | 
			
		||||
0.0976f, 0.1049f, 0.1122f, 0.1195f, 0.1268f, 0.1341f, 0.1411f, 0.1479f, 
 | 
			
		||||
0.1544f, 0.1606f, 0.1663f, 0.1715f, 0.1762f, 0.1802f, 0.1836f, 0.1862f, 
 | 
			
		||||
0.1881f, 0.1893f, 0.1897f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss50[21] = {
 | 
			
		||||
0.0911f, 0.0974f, 0.1038f, 0.1103f, 0.1167f, 0.1232f, 0.1295f, 0.1357f, 
 | 
			
		||||
0.1417f, 0.1474f, 0.1529f, 0.1580f, 0.1627f, 0.1670f, 0.1708f, 0.1741f, 
 | 
			
		||||
0.1768f, 0.1790f, 0.1805f, 0.1815f, 0.1818f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss51[23] = {
 | 
			
		||||
0.0861f, 0.0916f, 0.0973f, 0.1029f, 0.1086f, 0.1143f, 0.1199f, 0.1255f, 
 | 
			
		||||
0.1309f, 0.1361f, 0.1412f, 0.1460f, 0.1505f, 0.1548f, 0.1587f, 0.1622f, 
 | 
			
		||||
0.1653f, 0.1679f, 0.1702f, 0.1719f, 0.1732f, 0.1739f, 0.1742f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss52[25] = {
 | 
			
		||||
0.0823f, 0.0872f, 0.0922f, 0.0971f, 0.1021f, 0.1071f, 0.1121f, 0.1170f, 
 | 
			
		||||
0.1219f, 0.1266f, 0.1312f, 0.1356f, 0.1398f, 0.1438f, 0.1476f, 0.1511f, 
 | 
			
		||||
0.1543f, 0.1572f, 0.1597f, 0.1619f, 0.1637f, 0.1651f, 0.1661f, 0.1667f, 
 | 
			
		||||
0.1669f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss53[27] = {
 | 
			
		||||
0.0795f, 0.0838f, 0.0882f, 0.0925f, 0.0969f, 0.1013f, 0.1057f, 0.1101f, 
 | 
			
		||||
0.1144f, 0.1186f, 0.1227f, 0.1267f, 0.1306f, 0.1343f, 0.1378f, 0.1411f, 
 | 
			
		||||
0.1442f, 0.1471f, 0.1497f, 0.1520f, 0.1541f, 0.1558f, 0.1573f, 0.1585f, 
 | 
			
		||||
0.1593f, 0.1598f, 0.1599f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss54[29] = {
 | 
			
		||||
0.0774f, 0.0812f, 0.0850f, 0.0889f, 0.0928f, 0.0966f, 0.1005f, 0.1043f, 
 | 
			
		||||
0.1081f, 0.1119f, 0.1155f, 0.1191f, 0.1226f, 0.1259f, 0.1292f, 0.1322f, 
 | 
			
		||||
0.1351f, 0.1379f, 0.1404f, 0.1428f, 0.1449f, 0.1468f, 0.1485f, 0.1499f, 
 | 
			
		||||
0.1511f, 0.1520f, 0.1527f, 0.1531f, 0.1532f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss55[32] = {
 | 
			
		||||
0.0726f, 0.0759f, 0.0792f, 0.0826f, 0.0860f, 0.0894f, 0.0928f, 0.0962f, 
 | 
			
		||||
0.0996f, 0.1029f, 0.1062f, 0.1094f, 0.1126f, 0.1157f, 0.1187f, 0.1217f, 
 | 
			
		||||
0.1245f, 0.1271f, 0.1297f, 0.1321f, 0.1343f, 0.1364f, 0.1383f, 0.1401f, 
 | 
			
		||||
0.1416f, 0.1430f, 0.1442f, 0.1451f, 0.1459f, 0.1464f, 0.1467f, 0.1468f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss56[34] = {
 | 
			
		||||
0.0718f, 0.0747f, 0.0777f, 0.0807f, 0.0836f, 0.0866f, 0.0896f, 0.0926f, 
 | 
			
		||||
0.0956f, 0.0985f, 0.1014f, 0.1043f, 0.1071f, 0.1098f, 0.1125f, 0.1151f, 
 | 
			
		||||
0.1176f, 0.1201f, 0.1224f, 0.1246f, 0.1267f, 0.1287f, 0.1305f, 0.1322f, 
 | 
			
		||||
0.1338f, 0.1352f, 0.1365f, 0.1376f, 0.1385f, 0.1393f, 0.1399f, 0.1403f, 
 | 
			
		||||
0.1406f, 0.1407f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss57[37] = {
 | 
			
		||||
0.0687f, 0.0712f, 0.0738f, 0.0765f, 0.0791f, 0.0817f, 0.0843f, 0.0870f, 
 | 
			
		||||
0.0896f, 0.0922f, 0.0948f, 0.0973f, 0.0998f, 0.1023f, 0.1047f, 0.1071f, 
 | 
			
		||||
0.1094f, 0.1117f, 0.1138f, 0.1159f, 0.1179f, 0.1199f, 0.1217f, 0.1234f, 
 | 
			
		||||
0.1250f, 0.1265f, 0.1279f, 0.1292f, 0.1304f, 0.1314f, 0.1323f, 0.1330f, 
 | 
			
		||||
0.1337f, 0.1341f, 0.1345f, 0.1347f, 0.1348f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss58[41] = {
 | 
			
		||||
0.0640f, 0.0663f, 0.0686f, 0.0709f, 0.0732f, 0.0755f, 0.0778f, 0.0801f, 
 | 
			
		||||
0.0824f, 0.0847f, 0.0870f, 0.0893f, 0.0915f, 0.0938f, 0.0960f, 0.0982f, 
 | 
			
		||||
0.1003f, 0.1024f, 0.1044f, 0.1064f, 0.1083f, 0.1102f, 0.1120f, 0.1137f, 
 | 
			
		||||
0.1154f, 0.1170f, 0.1185f, 0.1199f, 0.1212f, 0.1224f, 0.1236f, 0.1246f, 
 | 
			
		||||
0.1255f, 0.1264f, 0.1271f, 0.1277f, 0.1282f, 0.1286f, 0.1289f, 0.1291f, 
 | 
			
		||||
0.1291f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss59[44] = {
 | 
			
		||||
0.0625f, 0.0645f, 0.0665f, 0.0685f, 0.0705f, 0.0726f, 0.0746f, 0.0767f, 
 | 
			
		||||
0.0787f, 0.0807f, 0.0827f, 0.0847f, 0.0867f, 0.0887f, 0.0907f, 0.0926f, 
 | 
			
		||||
0.0945f, 0.0964f, 0.0982f, 0.1000f, 0.1017f, 0.1034f, 0.1051f, 0.1067f, 
 | 
			
		||||
0.1083f, 0.1097f, 0.1112f, 0.1125f, 0.1138f, 0.1151f, 0.1162f, 0.1173f, 
 | 
			
		||||
0.1183f, 0.1192f, 0.1201f, 0.1208f, 0.1215f, 0.1221f, 0.1226f, 0.1230f, 
 | 
			
		||||
0.1233f, 0.1235f, 0.1237f, 0.1237f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss60[48] = {
 | 
			
		||||
0.0596f, 0.0614f, 0.0631f, 0.0649f, 0.0667f, 0.0685f, 0.0703f, 0.0721f, 
 | 
			
		||||
0.0738f, 0.0756f, 0.0774f, 0.0792f, 0.0810f, 0.0827f, 0.0845f, 0.0862f, 
 | 
			
		||||
0.0879f, 0.0896f, 0.0912f, 0.0929f, 0.0945f, 0.0960f, 0.0976f, 0.0991f, 
 | 
			
		||||
0.1005f, 0.1019f, 0.1033f, 0.1046f, 0.1059f, 0.1071f, 0.1083f, 0.1094f, 
 | 
			
		||||
0.1105f, 0.1115f, 0.1124f, 0.1133f, 0.1141f, 0.1149f, 0.1156f, 0.1162f, 
 | 
			
		||||
0.1167f, 0.1172f, 0.1176f, 0.1179f, 0.1182f, 0.1184f, 0.1185f, 0.1185f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss61[52] = {
 | 
			
		||||
0.0575f, 0.0590f, 0.0606f, 0.0621f, 0.0637f, 0.0652f, 0.0668f, 0.0684f, 
 | 
			
		||||
0.0700f, 0.0715f, 0.0731f, 0.0747f, 0.0762f, 0.0778f, 0.0793f, 0.0809f, 
 | 
			
		||||
0.0824f, 0.0839f, 0.0854f, 0.0868f, 0.0883f, 0.0897f, 0.0911f, 0.0925f, 
 | 
			
		||||
0.0938f, 0.0951f, 0.0964f, 0.0976f, 0.0988f, 0.1000f, 0.1011f, 0.1022f, 
 | 
			
		||||
0.1033f, 0.1043f, 0.1053f, 0.1062f, 0.1070f, 0.1079f, 0.1086f, 0.1093f, 
 | 
			
		||||
0.1100f, 0.1106f, 0.1112f, 0.1116f, 0.1121f, 0.1125f, 0.1128f, 0.1131f, 
 | 
			
		||||
0.1133f, 0.1134f, 0.1135f, 0.1135f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss62[57] = {
 | 
			
		||||
0.0545f, 0.0558f, 0.0572f, 0.0586f, 0.0599f, 0.0613f, 0.0627f, 0.0641f, 
 | 
			
		||||
0.0654f, 0.0668f, 0.0682f, 0.0696f, 0.0710f, 0.0723f, 0.0737f, 0.0751f, 
 | 
			
		||||
0.0764f, 0.0778f, 0.0791f, 0.0804f, 0.0817f, 0.0830f, 0.0843f, 0.0855f, 
 | 
			
		||||
0.0868f, 0.0880f, 0.0892f, 0.0903f, 0.0915f, 0.0926f, 0.0937f, 0.0948f, 
 | 
			
		||||
0.0958f, 0.0968f, 0.0977f, 0.0987f, 0.0996f, 0.1004f, 0.1013f, 0.1020f, 
 | 
			
		||||
0.1028f, 0.1035f, 0.1042f, 0.1048f, 0.1054f, 0.1059f, 0.1064f, 0.1068f, 
 | 
			
		||||
0.1072f, 0.1076f, 0.1079f, 0.1082f, 0.1084f, 0.1085f, 0.1087f, 0.1087f, 
 | 
			
		||||
0.1088f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss63[62] = {
 | 
			
		||||
0.0522f, 0.0534f, 0.0546f, 0.0558f, 0.0570f, 0.0582f, 0.0594f, 0.0606f, 
 | 
			
		||||
0.0619f, 0.0631f, 0.0643f, 0.0655f, 0.0667f, 0.0679f, 0.0691f, 0.0703f, 
 | 
			
		||||
0.0715f, 0.0727f, 0.0739f, 0.0751f, 0.0763f, 0.0774f, 0.0786f, 0.0797f, 
 | 
			
		||||
0.0808f, 0.0819f, 0.0830f, 0.0841f, 0.0851f, 0.0861f, 0.0872f, 0.0882f, 
 | 
			
		||||
0.0891f, 0.0901f, 0.0910f, 0.0919f, 0.0928f, 0.0936f, 0.0944f, 0.0952f, 
 | 
			
		||||
0.0960f, 0.0967f, 0.0974f, 0.0981f, 0.0987f, 0.0994f, 0.0999f, 0.1005f, 
 | 
			
		||||
0.1010f, 0.1014f, 0.1019f, 0.1023f, 0.1026f, 0.1030f, 0.1033f, 0.1035f, 
 | 
			
		||||
0.1037f, 0.1039f, 0.1040f, 0.1041f, 0.1042f, 0.1042f
 | 
			
		||||
};
 | 
			
		||||
static const float hgauss64[65] = {
 | 
			
		||||
0.0526f, 0.0537f, 0.0547f, 0.0558f, 0.0569f, 0.0579f, 0.0590f, 0.0601f, 
 | 
			
		||||
0.0611f, 0.0622f, 0.0633f, 0.0643f, 0.0654f, 0.0665f, 0.0675f, 0.0686f, 
 | 
			
		||||
0.0696f, 0.0707f, 0.0717f, 0.0727f, 0.0737f, 0.0748f, 0.0758f, 0.0767f, 
 | 
			
		||||
0.0777f, 0.0787f, 0.0796f, 0.0806f, 0.0815f, 0.0824f, 0.0833f, 0.0842f, 
 | 
			
		||||
0.0850f, 0.0859f, 0.0867f, 0.0875f, 0.0883f, 0.0891f, 0.0898f, 0.0905f, 
 | 
			
		||||
0.0912f, 0.0919f, 0.0925f, 0.0932f, 0.0938f, 0.0943f, 0.0949f, 0.0954f, 
 | 
			
		||||
0.0959f, 0.0964f, 0.0968f, 0.0972f, 0.0976f, 0.0979f, 0.0983f, 0.0986f, 
 | 
			
		||||
0.0988f, 0.0991f, 0.0993f, 0.0994f, 0.0996f, 0.0997f, 0.0998f, 0.0998f, 
 | 
			
		||||
0.0998f
 | 
			
		||||
};
 | 
			
		||||
static const float *hptr_tab_gauss[64] = {
 | 
			
		||||
hgauss1, hgauss2, hgauss3, hgauss4, 
 | 
			
		||||
hgauss5, hgauss6, hgauss7, hgauss8, 
 | 
			
		||||
hgauss9, hgauss10, hgauss11, hgauss12, 
 | 
			
		||||
hgauss13, hgauss14, hgauss15, hgauss16, 
 | 
			
		||||
hgauss17, hgauss18, hgauss19, hgauss20, 
 | 
			
		||||
hgauss21, hgauss22, hgauss23, hgauss24, 
 | 
			
		||||
hgauss25, hgauss26, hgauss27, hgauss28, 
 | 
			
		||||
hgauss29, hgauss30, hgauss31, hgauss32, 
 | 
			
		||||
hgauss33, hgauss34, hgauss35, hgauss36, 
 | 
			
		||||
hgauss37, hgauss38, hgauss39, hgauss40, 
 | 
			
		||||
hgauss41, hgauss42, hgauss43, hgauss44, 
 | 
			
		||||
hgauss45, hgauss46, hgauss47, hgauss48, 
 | 
			
		||||
hgauss49, hgauss50, hgauss51, hgauss52, 
 | 
			
		||||
hgauss53, hgauss54, hgauss55, hgauss56, 
 | 
			
		||||
hgauss57, hgauss58, hgauss59, hgauss60, 
 | 
			
		||||
hgauss61, hgauss62, hgauss63, hgauss64
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										329
									
								
								lib/qra/qra64/fadamplorentz.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										329
									
								
								lib/qra/qra64/fadamplorentz.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,329 @@
 | 
			
		||||
/*
 | 
			
		||||
fadamplorentz.c
 | 
			
		||||
Lorentz fading tables for QRA64 modes
 | 
			
		||||
 | 
			
		||||
(c) 2016 - Nico Palermo, IV3NWV
 | 
			
		||||
 | 
			
		||||
This file is part of the qracodes project, a Forward Error Control
 | 
			
		||||
encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
   qracodes is free software: you can redistribute it and/or modify
 | 
			
		||||
   it under the terms of the GNU General Public License as published by
 | 
			
		||||
   the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
   (at your option) any later version.
 | 
			
		||||
   qracodes is distributed in the hope that it will be useful,
 | 
			
		||||
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
   GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
   You should have received a copy of the GNU General Public License
 | 
			
		||||
   along with qracodes source distribution.  
 | 
			
		||||
   If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
-----------------------------------------------------------------------------
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
static const int hlen_tab_lorentz[64] = {
 | 
			
		||||
  2,   2,   2,   2,   2,   2,   2,   2, 
 | 
			
		||||
  2,   2,   2,   2,   2,   2,   3,   3, 
 | 
			
		||||
  3,   3,   3,   3,   3,   4,   4,   4, 
 | 
			
		||||
  4,   4,   5,   5,   5,   5,   6,   6, 
 | 
			
		||||
  7,   7,   7,   8,   8,   9,  10,  10, 
 | 
			
		||||
 11,  12,  13,  14,  15,  16,  17,  19, 
 | 
			
		||||
 20,  22,  23,  25,  27,  30,  32,  35, 
 | 
			
		||||
 38,  41,  45,  49,  53,  57,  62,  65
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz1[2] = {
 | 
			
		||||
0.1464f, 0.9543f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz2[2] = {
 | 
			
		||||
0.1563f, 0.9503f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz3[2] = {
 | 
			
		||||
0.1672f, 0.9461f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz4[2] = {
 | 
			
		||||
0.1773f, 0.9415f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz5[2] = {
 | 
			
		||||
0.1868f, 0.9367f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz6[2] = {
 | 
			
		||||
0.1970f, 0.9314f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz7[2] = {
 | 
			
		||||
0.2063f, 0.9258f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz8[2] = {
 | 
			
		||||
0.2151f, 0.9197f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz9[2] = {
 | 
			
		||||
0.2236f, 0.9132f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz10[2] = {
 | 
			
		||||
0.2320f, 0.9061f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz11[2] = {
 | 
			
		||||
0.2406f, 0.8986f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz12[2] = {
 | 
			
		||||
0.2494f, 0.8905f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz13[2] = {
 | 
			
		||||
0.2584f, 0.8819f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz14[2] = {
 | 
			
		||||
0.2674f, 0.8727f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz15[3] = {
 | 
			
		||||
0.1400f, 0.2765f, 0.8629f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz16[3] = {
 | 
			
		||||
0.1451f, 0.2857f, 0.8525f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz17[3] = {
 | 
			
		||||
0.1504f, 0.2949f, 0.8414f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz18[3] = {
 | 
			
		||||
0.1557f, 0.3041f, 0.8298f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz19[3] = {
 | 
			
		||||
0.1611f, 0.3133f, 0.8174f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz20[3] = {
 | 
			
		||||
0.1666f, 0.3223f, 0.8045f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz21[3] = {
 | 
			
		||||
0.1721f, 0.3312f, 0.7909f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz22[4] = {
 | 
			
		||||
0.1195f, 0.1778f, 0.3399f, 0.7766f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz23[4] = {
 | 
			
		||||
0.1235f, 0.1835f, 0.3483f, 0.7618f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz24[4] = {
 | 
			
		||||
0.1277f, 0.1893f, 0.3564f, 0.7463f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz25[4] = {
 | 
			
		||||
0.1319f, 0.1952f, 0.3641f, 0.7303f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz26[4] = {
 | 
			
		||||
0.1362f, 0.2011f, 0.3712f, 0.7138f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz27[5] = {
 | 
			
		||||
0.1062f, 0.1407f, 0.2071f, 0.3779f, 0.6967f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz28[5] = {
 | 
			
		||||
0.1097f, 0.1452f, 0.2132f, 0.3839f, 0.6793f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz29[5] = {
 | 
			
		||||
0.1134f, 0.1499f, 0.2193f, 0.3891f, 0.6615f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz30[5] = {
 | 
			
		||||
0.1172f, 0.1546f, 0.2254f, 0.3936f, 0.6434f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz31[6] = {
 | 
			
		||||
0.0974f, 0.1211f, 0.1595f, 0.2314f, 0.3973f, 0.6251f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz32[6] = {
 | 
			
		||||
0.1007f, 0.1251f, 0.1645f, 0.2374f, 0.4000f, 0.6066f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz33[7] = {
 | 
			
		||||
0.0872f, 0.1042f, 0.1292f, 0.1695f, 0.2434f, 0.4017f, 0.5880f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz34[7] = {
 | 
			
		||||
0.0902f, 0.1077f, 0.1335f, 0.1747f, 0.2491f, 0.4025f, 0.5694f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz35[7] = {
 | 
			
		||||
0.0934f, 0.1114f, 0.1379f, 0.1799f, 0.2547f, 0.4022f, 0.5509f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz36[8] = {
 | 
			
		||||
0.0832f, 0.0967f, 0.1152f, 0.1423f, 0.1851f, 0.2600f, 0.4008f, 0.5325f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz37[8] = {
 | 
			
		||||
0.0862f, 0.1001f, 0.1192f, 0.1469f, 0.1903f, 0.2649f, 0.3985f, 0.5143f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz38[9] = {
 | 
			
		||||
0.0784f, 0.0893f, 0.1036f, 0.1232f, 0.1515f, 0.1955f, 0.2694f, 0.3950f, 
 | 
			
		||||
0.4964f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz39[10] = {
 | 
			
		||||
0.0724f, 0.0813f, 0.0925f, 0.1072f, 0.1273f, 0.1562f, 0.2005f, 0.2733f, 
 | 
			
		||||
0.3906f, 0.4787f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz40[10] = {
 | 
			
		||||
0.0751f, 0.0842f, 0.0958f, 0.1109f, 0.1315f, 0.1609f, 0.2054f, 0.2767f, 
 | 
			
		||||
0.3853f, 0.4614f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz41[11] = {
 | 
			
		||||
0.0703f, 0.0779f, 0.0873f, 0.0992f, 0.1148f, 0.1358f, 0.1656f, 0.2101f, 
 | 
			
		||||
0.2794f, 0.3790f, 0.4444f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz42[12] = {
 | 
			
		||||
0.0665f, 0.0730f, 0.0808f, 0.0905f, 0.1027f, 0.1187f, 0.1401f, 0.1702f, 
 | 
			
		||||
0.2145f, 0.2813f, 0.3720f, 0.4278f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz43[13] = {
 | 
			
		||||
0.0634f, 0.0690f, 0.0757f, 0.0838f, 0.0938f, 0.1063f, 0.1226f, 0.1444f, 
 | 
			
		||||
0.1747f, 0.2185f, 0.2824f, 0.3643f, 0.4117f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz44[14] = {
 | 
			
		||||
0.0609f, 0.0658f, 0.0716f, 0.0785f, 0.0869f, 0.0971f, 0.1100f, 0.1266f, 
 | 
			
		||||
0.1487f, 0.1791f, 0.2220f, 0.2826f, 0.3559f, 0.3960f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz45[15] = {
 | 
			
		||||
0.0588f, 0.0632f, 0.0683f, 0.0743f, 0.0814f, 0.0900f, 0.1005f, 0.1137f, 
 | 
			
		||||
0.1306f, 0.1529f, 0.1831f, 0.2250f, 0.2820f, 0.3470f, 0.3808f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz46[16] = {
 | 
			
		||||
0.0571f, 0.0611f, 0.0657f, 0.0709f, 0.0771f, 0.0844f, 0.0932f, 0.1040f, 
 | 
			
		||||
0.1175f, 0.1346f, 0.1570f, 0.1869f, 0.2274f, 0.2804f, 0.3377f, 0.3660f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz47[17] = {
 | 
			
		||||
0.0557f, 0.0594f, 0.0635f, 0.0682f, 0.0736f, 0.0800f, 0.0875f, 0.0965f, 
 | 
			
		||||
0.1076f, 0.1212f, 0.1385f, 0.1609f, 0.1903f, 0.2292f, 0.2781f, 0.3281f, 
 | 
			
		||||
0.3517f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz48[19] = {
 | 
			
		||||
0.0516f, 0.0546f, 0.0579f, 0.0617f, 0.0659f, 0.0708f, 0.0764f, 0.0829f, 
 | 
			
		||||
0.0906f, 0.0999f, 0.1111f, 0.1249f, 0.1423f, 0.1645f, 0.1933f, 0.2302f, 
 | 
			
		||||
0.2748f, 0.3182f, 0.3379f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz49[20] = {
 | 
			
		||||
0.0509f, 0.0537f, 0.0567f, 0.0602f, 0.0640f, 0.0684f, 0.0734f, 0.0792f, 
 | 
			
		||||
0.0859f, 0.0938f, 0.1032f, 0.1146f, 0.1286f, 0.1460f, 0.1679f, 0.1957f, 
 | 
			
		||||
0.2305f, 0.2709f, 0.3082f, 0.3245f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz50[22] = {
 | 
			
		||||
0.0480f, 0.0504f, 0.0529f, 0.0558f, 0.0589f, 0.0625f, 0.0665f, 0.0710f, 
 | 
			
		||||
0.0761f, 0.0821f, 0.0889f, 0.0970f, 0.1066f, 0.1181f, 0.1321f, 0.1494f, 
 | 
			
		||||
0.1709f, 0.1976f, 0.2300f, 0.2662f, 0.2981f, 0.3115f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz51[23] = {
 | 
			
		||||
0.0477f, 0.0499f, 0.0523f, 0.0550f, 0.0580f, 0.0612f, 0.0649f, 0.0690f, 
 | 
			
		||||
0.0736f, 0.0789f, 0.0850f, 0.0920f, 0.1002f, 0.1099f, 0.1215f, 0.1355f, 
 | 
			
		||||
0.1526f, 0.1735f, 0.1989f, 0.2288f, 0.2609f, 0.2880f, 0.2991f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz52[25] = {
 | 
			
		||||
0.0456f, 0.0475f, 0.0496f, 0.0519f, 0.0544f, 0.0572f, 0.0602f, 0.0636f, 
 | 
			
		||||
0.0673f, 0.0715f, 0.0763f, 0.0817f, 0.0879f, 0.0951f, 0.1034f, 0.1132f, 
 | 
			
		||||
0.1248f, 0.1387f, 0.1554f, 0.1755f, 0.1995f, 0.2268f, 0.2550f, 0.2779f, 
 | 
			
		||||
0.2870f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz53[27] = {
 | 
			
		||||
0.0438f, 0.0456f, 0.0474f, 0.0494f, 0.0516f, 0.0539f, 0.0565f, 0.0594f, 
 | 
			
		||||
0.0625f, 0.0660f, 0.0698f, 0.0742f, 0.0790f, 0.0846f, 0.0909f, 0.0981f, 
 | 
			
		||||
0.1065f, 0.1164f, 0.1279f, 0.1416f, 0.1579f, 0.1771f, 0.1994f, 0.2242f, 
 | 
			
		||||
0.2487f, 0.2680f, 0.2754f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz54[30] = {
 | 
			
		||||
0.0410f, 0.0424f, 0.0440f, 0.0456f, 0.0474f, 0.0493f, 0.0513f, 0.0536f, 
 | 
			
		||||
0.0560f, 0.0587f, 0.0616f, 0.0648f, 0.0684f, 0.0724f, 0.0768f, 0.0818f, 
 | 
			
		||||
0.0874f, 0.0938f, 0.1011f, 0.1096f, 0.1194f, 0.1308f, 0.1442f, 0.1599f, 
 | 
			
		||||
0.1781f, 0.1987f, 0.2208f, 0.2421f, 0.2582f, 0.2643f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz55[32] = {
 | 
			
		||||
0.0400f, 0.0413f, 0.0427f, 0.0441f, 0.0457f, 0.0474f, 0.0492f, 0.0512f, 
 | 
			
		||||
0.0533f, 0.0557f, 0.0582f, 0.0609f, 0.0639f, 0.0672f, 0.0709f, 0.0749f, 
 | 
			
		||||
0.0795f, 0.0845f, 0.0902f, 0.0967f, 0.1041f, 0.1125f, 0.1222f, 0.1334f, 
 | 
			
		||||
0.1464f, 0.1614f, 0.1785f, 0.1973f, 0.2169f, 0.2351f, 0.2485f, 0.2535f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz56[35] = {
 | 
			
		||||
0.0380f, 0.0391f, 0.0403f, 0.0416f, 0.0429f, 0.0444f, 0.0459f, 0.0475f, 
 | 
			
		||||
0.0493f, 0.0512f, 0.0532f, 0.0554f, 0.0578f, 0.0604f, 0.0632f, 0.0663f, 
 | 
			
		||||
0.0697f, 0.0734f, 0.0775f, 0.0821f, 0.0873f, 0.0930f, 0.0995f, 0.1069f, 
 | 
			
		||||
0.1153f, 0.1248f, 0.1358f, 0.1483f, 0.1624f, 0.1782f, 0.1952f, 0.2125f, 
 | 
			
		||||
0.2280f, 0.2391f, 0.2432f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz57[38] = {
 | 
			
		||||
0.0364f, 0.0374f, 0.0384f, 0.0395f, 0.0407f, 0.0419f, 0.0432f, 0.0446f, 
 | 
			
		||||
0.0461f, 0.0477f, 0.0494f, 0.0512f, 0.0531f, 0.0552f, 0.0575f, 0.0599f, 
 | 
			
		||||
0.0626f, 0.0655f, 0.0686f, 0.0721f, 0.0759f, 0.0801f, 0.0848f, 0.0899f, 
 | 
			
		||||
0.0957f, 0.1022f, 0.1095f, 0.1178f, 0.1271f, 0.1377f, 0.1496f, 0.1629f, 
 | 
			
		||||
0.1774f, 0.1926f, 0.2076f, 0.2207f, 0.2299f, 0.2332f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz58[41] = {
 | 
			
		||||
0.0351f, 0.0360f, 0.0369f, 0.0379f, 0.0389f, 0.0400f, 0.0411f, 0.0423f, 
 | 
			
		||||
0.0436f, 0.0450f, 0.0464f, 0.0479f, 0.0496f, 0.0513f, 0.0532f, 0.0552f, 
 | 
			
		||||
0.0573f, 0.0596f, 0.0621f, 0.0648f, 0.0678f, 0.0710f, 0.0745f, 0.0784f, 
 | 
			
		||||
0.0826f, 0.0873f, 0.0925f, 0.0983f, 0.1048f, 0.1120f, 0.1201f, 0.1291f, 
 | 
			
		||||
0.1392f, 0.1505f, 0.1628f, 0.1759f, 0.1894f, 0.2023f, 0.2134f, 0.2209f, 
 | 
			
		||||
0.2237f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz59[45] = {
 | 
			
		||||
0.0333f, 0.0341f, 0.0349f, 0.0357f, 0.0366f, 0.0375f, 0.0384f, 0.0394f, 
 | 
			
		||||
0.0405f, 0.0416f, 0.0428f, 0.0440f, 0.0453f, 0.0467f, 0.0482f, 0.0498f, 
 | 
			
		||||
0.0515f, 0.0532f, 0.0552f, 0.0572f, 0.0594f, 0.0618f, 0.0643f, 0.0671f, 
 | 
			
		||||
0.0701f, 0.0734f, 0.0770f, 0.0809f, 0.0851f, 0.0898f, 0.0950f, 0.1008f, 
 | 
			
		||||
0.1071f, 0.1142f, 0.1221f, 0.1307f, 0.1403f, 0.1508f, 0.1621f, 0.1739f, 
 | 
			
		||||
0.1857f, 0.1968f, 0.2060f, 0.2123f, 0.2145f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz60[49] = {
 | 
			
		||||
0.0319f, 0.0325f, 0.0332f, 0.0339f, 0.0347f, 0.0355f, 0.0363f, 0.0371f, 
 | 
			
		||||
0.0380f, 0.0390f, 0.0400f, 0.0410f, 0.0421f, 0.0432f, 0.0444f, 0.0457f, 
 | 
			
		||||
0.0471f, 0.0485f, 0.0500f, 0.0517f, 0.0534f, 0.0552f, 0.0572f, 0.0593f, 
 | 
			
		||||
0.0615f, 0.0640f, 0.0666f, 0.0694f, 0.0724f, 0.0757f, 0.0793f, 0.0833f, 
 | 
			
		||||
0.0875f, 0.0922f, 0.0974f, 0.1030f, 0.1093f, 0.1161f, 0.1237f, 0.1319f, 
 | 
			
		||||
0.1409f, 0.1506f, 0.1608f, 0.1713f, 0.1816f, 0.1910f, 0.1987f, 0.2038f, 
 | 
			
		||||
0.2056f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz61[53] = {
 | 
			
		||||
0.0307f, 0.0313f, 0.0319f, 0.0325f, 0.0332f, 0.0338f, 0.0346f, 0.0353f, 
 | 
			
		||||
0.0361f, 0.0369f, 0.0377f, 0.0386f, 0.0395f, 0.0405f, 0.0415f, 0.0426f, 
 | 
			
		||||
0.0437f, 0.0449f, 0.0462f, 0.0475f, 0.0489f, 0.0504f, 0.0519f, 0.0536f, 
 | 
			
		||||
0.0553f, 0.0572f, 0.0592f, 0.0614f, 0.0637f, 0.0661f, 0.0688f, 0.0716f, 
 | 
			
		||||
0.0747f, 0.0780f, 0.0816f, 0.0856f, 0.0898f, 0.0945f, 0.0996f, 0.1051f, 
 | 
			
		||||
0.1111f, 0.1177f, 0.1249f, 0.1327f, 0.1410f, 0.1499f, 0.1590f, 0.1683f, 
 | 
			
		||||
0.1771f, 0.1851f, 0.1915f, 0.1957f, 0.1971f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz62[57] = {
 | 
			
		||||
0.0297f, 0.0302f, 0.0308f, 0.0313f, 0.0319f, 0.0325f, 0.0332f, 0.0338f, 
 | 
			
		||||
0.0345f, 0.0352f, 0.0359f, 0.0367f, 0.0375f, 0.0384f, 0.0392f, 0.0401f, 
 | 
			
		||||
0.0411f, 0.0421f, 0.0432f, 0.0443f, 0.0454f, 0.0466f, 0.0479f, 0.0493f, 
 | 
			
		||||
0.0507f, 0.0522f, 0.0538f, 0.0555f, 0.0573f, 0.0592f, 0.0613f, 0.0635f, 
 | 
			
		||||
0.0658f, 0.0683f, 0.0710f, 0.0738f, 0.0769f, 0.0803f, 0.0839f, 0.0878f, 
 | 
			
		||||
0.0920f, 0.0965f, 0.1015f, 0.1069f, 0.1127f, 0.1190f, 0.1258f, 0.1330f, 
 | 
			
		||||
0.1406f, 0.1486f, 0.1568f, 0.1648f, 0.1724f, 0.1791f, 0.1844f, 0.1878f, 
 | 
			
		||||
0.1890f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz63[62] = {
 | 
			
		||||
0.0284f, 0.0289f, 0.0294f, 0.0299f, 0.0304f, 0.0309f, 0.0315f, 0.0320f, 
 | 
			
		||||
0.0326f, 0.0332f, 0.0338f, 0.0345f, 0.0352f, 0.0359f, 0.0366f, 0.0374f, 
 | 
			
		||||
0.0382f, 0.0390f, 0.0399f, 0.0408f, 0.0417f, 0.0427f, 0.0437f, 0.0448f, 
 | 
			
		||||
0.0459f, 0.0471f, 0.0484f, 0.0497f, 0.0511f, 0.0525f, 0.0541f, 0.0557f, 
 | 
			
		||||
0.0575f, 0.0593f, 0.0612f, 0.0633f, 0.0655f, 0.0679f, 0.0704f, 0.0731f, 
 | 
			
		||||
0.0760f, 0.0791f, 0.0824f, 0.0859f, 0.0898f, 0.0939f, 0.0984f, 0.1032f, 
 | 
			
		||||
0.1083f, 0.1139f, 0.1198f, 0.1261f, 0.1328f, 0.1398f, 0.1469f, 0.1541f, 
 | 
			
		||||
0.1610f, 0.1675f, 0.1731f, 0.1774f, 0.1802f, 0.1811f
 | 
			
		||||
};
 | 
			
		||||
static const float hlorentz64[65] = {
 | 
			
		||||
0.0283f, 0.0287f, 0.0291f, 0.0296f, 0.0301f, 0.0306f, 0.0311f, 0.0316f, 
 | 
			
		||||
0.0322f, 0.0327f, 0.0333f, 0.0339f, 0.0345f, 0.0352f, 0.0359f, 0.0366f, 
 | 
			
		||||
0.0373f, 0.0381f, 0.0388f, 0.0397f, 0.0405f, 0.0414f, 0.0423f, 0.0433f, 
 | 
			
		||||
0.0443f, 0.0454f, 0.0465f, 0.0476f, 0.0489f, 0.0501f, 0.0515f, 0.0529f, 
 | 
			
		||||
0.0544f, 0.0560f, 0.0576f, 0.0594f, 0.0613f, 0.0632f, 0.0653f, 0.0676f, 
 | 
			
		||||
0.0699f, 0.0724f, 0.0751f, 0.0780f, 0.0811f, 0.0843f, 0.0879f, 0.0916f, 
 | 
			
		||||
0.0956f, 0.0999f, 0.1046f, 0.1095f, 0.1147f, 0.1202f, 0.1261f, 0.1321f, 
 | 
			
		||||
0.1384f, 0.1447f, 0.1510f, 0.1569f, 0.1624f, 0.1670f, 0.1706f, 0.1728f, 
 | 
			
		||||
0.1736f
 | 
			
		||||
};
 | 
			
		||||
static const float *hptr_tab_lorentz[64] = {
 | 
			
		||||
hlorentz1, hlorentz2, hlorentz3, hlorentz4, 
 | 
			
		||||
hlorentz5, hlorentz6, hlorentz7, hlorentz8, 
 | 
			
		||||
hlorentz9, hlorentz10, hlorentz11, hlorentz12, 
 | 
			
		||||
hlorentz13, hlorentz14, hlorentz15, hlorentz16, 
 | 
			
		||||
hlorentz17, hlorentz18, hlorentz19, hlorentz20, 
 | 
			
		||||
hlorentz21, hlorentz22, hlorentz23, hlorentz24, 
 | 
			
		||||
hlorentz25, hlorentz26, hlorentz27, hlorentz28, 
 | 
			
		||||
hlorentz29, hlorentz30, hlorentz31, hlorentz32, 
 | 
			
		||||
hlorentz33, hlorentz34, hlorentz35, hlorentz36, 
 | 
			
		||||
hlorentz37, hlorentz38, hlorentz39, hlorentz40, 
 | 
			
		||||
hlorentz41, hlorentz42, hlorentz43, hlorentz44, 
 | 
			
		||||
hlorentz45, hlorentz46, hlorentz47, hlorentz48, 
 | 
			
		||||
hlorentz49, hlorentz50, hlorentz51, hlorentz52, 
 | 
			
		||||
hlorentz53, hlorentz54, hlorentz55, hlorentz56, 
 | 
			
		||||
hlorentz57, hlorentz58, hlorentz59, hlorentz60, 
 | 
			
		||||
hlorentz61, hlorentz62, hlorentz63, hlorentz64
 | 
			
		||||
};
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
main.c 
 | 
			
		||||
QRA64 mode encode/decode test
 | 
			
		||||
QRA64 mode encode/decode tests
 | 
			
		||||
 | 
			
		||||
(c) 2016 - Nico Palermo, IV3NWV
 | 
			
		||||
 | 
			
		||||
@ -145,6 +145,7 @@ symbol.
 | 
			
		||||
  normrnd_s(rp,NSAMPLES,0,sigma);
 | 
			
		||||
  normrnd_s(rq,NSAMPLES,0,sigma);
 | 
			
		||||
 | 
			
		||||
  if(EbNodB>-15) 
 | 
			
		||||
	if (channel_type == CHANNEL_AWGN) 
 | 
			
		||||
	    for (k=0;k<QRA64_N;k++) 
 | 
			
		||||
		  rp[k*QRA64_M+x[k]]+=A;
 | 
			
		||||
@ -342,7 +343,7 @@ a particular type decode among the above 6 cases succeded.
 | 
			
		||||
 | 
			
		||||
  int ndecok[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 | 
			
		||||
  int nundet = 0;
 | 
			
		||||
  int ntx = 100,ndec=0;
 | 
			
		||||
  int ntx = 200,ndec=0;
 | 
			
		||||
 | 
			
		||||
  qra64codec *codec_iv3nwv = qra64_init(mode);   // codec for IV3NWV
 | 
			
		||||
  qra64codec *codec_k1jt   = qra64_init(mode);     // codec for K1JT
 | 
			
		||||
@ -351,16 +352,16 @@ a particular type decode among the above 6 cases succeded.
 | 
			
		||||
		   QRA64_SNR_EBNO_OFFSET);
 | 
			
		||||
 | 
			
		||||
// This will enable K1JT's decoder to look for calls directed to him [K1JT ? ?/b]
 | 
			
		||||
  printf("K1JT decoder enabled for [K1JT  ?     ?/blank]\n");
 | 
			
		||||
  qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_MYCALL);
 | 
			
		||||
//  printf("K1JT decoder enabled for [K1JT  ?     ?/blank]\n");
 | 
			
		||||
//  qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_MYCALL);
 | 
			
		||||
 | 
			
		||||
// This will enable K1JT's decoder to look for IV3NWV calls directed to him [K1JT IV3NWV ?/b]
 | 
			
		||||
  printf("K1JT decoder enabled for [K1JT IV3NWV ?]\n");
 | 
			
		||||
  qra64_apset(codec_k1jt, CALL_K1JT,CALL_IV3NWV,0,APTYPE_BOTHCALLS);
 | 
			
		||||
//  printf("K1JT decoder enabled for [K1JT IV3NWV ?]\n");
 | 
			
		||||
//  qra64_apset(codec_k1jt, CALL_CQ,CALL_IV3NWV,0,APTYPE_BOTHCALLS);
 | 
			
		||||
 | 
			
		||||
// This will enable K1JT's decoder to look for msges sent by IV3NWV [? IV3NWV ?]
 | 
			
		||||
  printf("K1JT decoder enabled for [?    IV3NWV ?/blank]\n");
 | 
			
		||||
  qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_BLANK,APTYPE_HISCALL);
 | 
			
		||||
//  printf("K1JT decoder enabled for [?    IV3NWV ?/blank]\n");
 | 
			
		||||
//  qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_BLANK,APTYPE_HISCALL);
 | 
			
		||||
 | 
			
		||||
// This will enable K1JT's decoder to look for full-knowledge [K1JT IV3NWV JN66] msgs
 | 
			
		||||
  printf("K1JT decoder enabled for [K1JT IV3NWV JN66]\n");
 | 
			
		||||
@ -372,8 +373,12 @@ a particular type decode among the above 6 cases succeded.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Dx station IV3NWV calls
 | 
			
		||||
  printf("\nIV3NWV encoder sends msg: [CQ IV3NWV JN66]\n\n");
 | 
			
		||||
  printf("\nIV3NWV encoder sends msg: [K1JT IV3NWV JN66]\n\n");
 | 
			
		||||
  encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_JN66);
 | 
			
		||||
 | 
			
		||||
//  printf("\nIV3NWV encoder sends msg: [CQ IV3NWV JN66]\n\n");
 | 
			
		||||
//  encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_JN66);
 | 
			
		||||
 | 
			
		||||
//  printf("\nIV3NWV encoder sends msg: [CQ IV3NWV]\n\n");
 | 
			
		||||
//  encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_BLANK);
 | 
			
		||||
  qra64_encode(codec_iv3nwv, y, x);
 | 
			
		||||
@ -409,6 +414,88 @@ a particular type decode among the above 6 cases succeded.
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int test_fastfading(float EbNodB, float B90, int fadingModel, int submode, int apmode)
 | 
			
		||||
{
 | 
			
		||||
  int x[QRA64_K], xdec[QRA64_K];
 | 
			
		||||
  int y[QRA64_N];
 | 
			
		||||
  float *rx;
 | 
			
		||||
  float ebnodbest, ebnodbavg=0;
 | 
			
		||||
  int rc,k;
 | 
			
		||||
 | 
			
		||||
  int ndecok[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 | 
			
		||||
  int nundet = 0;
 | 
			
		||||
  int ntx = 100,ndec=0;
 | 
			
		||||
 | 
			
		||||
  qra64codec *codec_iv3nwv; 
 | 
			
		||||
  qra64codec *codec_k1jt; 
 | 
			
		||||
 | 
			
		||||
  codec_iv3nwv=qra64_init(QRA_NOAP);  
 | 
			
		||||
  codec_k1jt  =qra64_init(apmode);  
 | 
			
		||||
 | 
			
		||||
  printf("\nSimulating the QRA64 decoder with fast-fading metric\n");
 | 
			
		||||
  printf("B90=%.2f Hz - Fading Model=%s - Submode=QRA64%c\n\n",B90,fadingModel?"Lorentz":"Gauss",submode+'A');
 | 
			
		||||
 | 
			
		||||
  if (apmode==QRA_USERAP) {
 | 
			
		||||
	// This will enable K1JT's decoder to look for calls directed to him [K1JT ? ?/b]
 | 
			
		||||
	printf("K1JT decoder enabled for [K1JT  ?     ?/blank]\n");
 | 
			
		||||
	qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_MYCALL);
 | 
			
		||||
 | 
			
		||||
	// This will enable K1JT's decoder to look for IV3NWV calls directed to him [K1JT IV3NWV ?/b]
 | 
			
		||||
	printf("K1JT decoder enabled for [K1JT IV3NWV ?]\n");
 | 
			
		||||
	qra64_apset(codec_k1jt, CALL_CQ,CALL_IV3NWV,0,APTYPE_BOTHCALLS);
 | 
			
		||||
 | 
			
		||||
	// This will enable K1JT's decoder to look for msges sent by IV3NWV [? IV3NWV ?]
 | 
			
		||||
	printf("K1JT decoder enabled for [?    IV3NWV ?/blank]\n");
 | 
			
		||||
	qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_BLANK,APTYPE_HISCALL);
 | 
			
		||||
 | 
			
		||||
	// This will enable K1JT's decoder to look for full-knowledge [K1JT IV3NWV JN66] msgs
 | 
			
		||||
	printf("K1JT decoder enabled for [K1JT IV3NWV JN66]\n");
 | 
			
		||||
	qra64_apset(codec_k1jt, CALL_K1JT,CALL_IV3NWV,GRID_JN66,APTYPE_FULL);
 | 
			
		||||
 | 
			
		||||
	// This will enable K1JT's decoder to look for calls from IV3NWV [CQ IV3NWV ?/b] msgs
 | 
			
		||||
	printf("K1JT decoder enabled for [CQ   IV3NWV ?/b/JN66]\n");
 | 
			
		||||
	qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_JN66,APTYPE_CQHISCALL);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  printf("\nEncoding msg: [K1JT IV3NWV JN66]\n");
 | 
			
		||||
  encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV,GRID_JN66);
 | 
			
		||||
  qra64_encode(codec_iv3nwv, y, x);
 | 
			
		||||
 | 
			
		||||
  printf("Decoding with K1JT's decoder\n");
 | 
			
		||||
  for (k=0;k<ntx;k++) {
 | 
			
		||||
    printf(".");
 | 
			
		||||
	rc = qra64_fastfading_channel(&rx,y,submode,EbNodB,B90,fadingModel);
 | 
			
		||||
	if (rc<0) {
 | 
			
		||||
		printf("qra64_fastfading_channel error. rc=%d\n",rc);
 | 
			
		||||
		return -1;
 | 
			
		||||
		}
 | 
			
		||||
    rc = qra64_decode_fastfading(codec_k1jt,&ebnodbest,xdec,rx,submode,B90,fadingModel);
 | 
			
		||||
	if (rc>=0) {
 | 
			
		||||
	  ebnodbavg +=ebnodbest;
 | 
			
		||||
	  if (memcmp(xdec,x,12*sizeof(int))==0)
 | 
			
		||||
		ndecok[rc]++;
 | 
			
		||||
	  else
 | 
			
		||||
	    nundet++;
 | 
			
		||||
	}
 | 
			
		||||
  }
 | 
			
		||||
  printf("\n\n");
 | 
			
		||||
 | 
			
		||||
  printf("Transimtted msgs:%d\nDecoded msgs:\n\n",ntx);
 | 
			
		||||
  for (k=0;k<12;k++) {
 | 
			
		||||
    printf("%3d with %s\n",ndecok[k],decode_type[k]);
 | 
			
		||||
    ndec += ndecok[k];
 | 
			
		||||
  }
 | 
			
		||||
  printf("\nTotal: %d/%d (%d undetected errors)\n\n",ndec,ntx,nundet);
 | 
			
		||||
  printf("");
 | 
			
		||||
 | 
			
		||||
  ebnodbavg/=(ndec+nundet);
 | 
			
		||||
  printf("Estimated SNR (average in dB) = %.2f dB\n\n",ebnodbavg-QRA64_SNR_EBNO_OFFSET);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void syntax(void)
 | 
			
		||||
{
 | 
			
		||||
  printf("\nQRA64 Mode Tests\n");
 | 
			
		||||
@ -421,6 +508,11 @@ void syntax(void)
 | 
			
		||||
  printf("       -a<ap-type> : set decode type 0=NOAP 1=AUTOAP (default) 2=USERAP\n");
 | 
			
		||||
  printf("       -t<testtype>: 0=simulate seq of msgs between IV3NWV and K1JT (default)\n");
 | 
			
		||||
  printf("                     1=simulate K1JT receiving K1JT IV3NWV JN66\n");
 | 
			
		||||
  printf("                     2=simulate fast-fading routines (option -c ignored)\n");
 | 
			
		||||
  printf("Options used only for fast-fading simulations:\n");
 | 
			
		||||
  printf("       -b          : 90%% fading bandwidth in Hz [1..230 Hz] (default = 2.5 Hz)\n");
 | 
			
		||||
  printf("       -m          : fading model. 0=Gauss, 1=Lorentz (default = Lorentz)\n");
 | 
			
		||||
  printf("       -q          : qra64 submode. 0=QRA64A,... 4=QRA64E (default = QRA64A)\n");
 | 
			
		||||
  printf("       -h: this help\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -433,14 +525,19 @@ int main(int argc, char* argv[])
 | 
			
		||||
  unsigned int testtype=0;
 | 
			
		||||
  int   nqso = 100;
 | 
			
		||||
  float EbNodB;
 | 
			
		||||
  float B90 = 2.5;
 | 
			
		||||
  int fadingModel = 1;
 | 
			
		||||
  int submode = 0;
 | 
			
		||||
 | 
			
		||||
// Parse the command line
 | 
			
		||||
  while(--argc) {
 | 
			
		||||
    argv++;
 | 
			
		||||
 | 
			
		||||
    if (strncmp(*argv,"-h",2)==0) {
 | 
			
		||||
      syntax();
 | 
			
		||||
      return 0;
 | 
			
		||||
    } else {
 | 
			
		||||
	  } 
 | 
			
		||||
	else 
 | 
			
		||||
	if (strncmp(*argv,"-a",2)==0) {
 | 
			
		||||
		mode = ( int)atoi((*argv)+2);
 | 
			
		||||
		if (mode>2) {
 | 
			
		||||
@ -448,23 +545,26 @@ int main(int argc, char* argv[])
 | 
			
		||||
			syntax();
 | 
			
		||||
			return -1;
 | 
			
		||||
			}
 | 
			
		||||
      } else {
 | 
			
		||||
		} 
 | 
			
		||||
	else
 | 
			
		||||
	if (strncmp(*argv,"-s",2)==0) {
 | 
			
		||||
		SNRdB = (float)atof((*argv)+2);
 | 
			
		||||
	  if (SNRdB>20 || SNRdB<-40) {
 | 
			
		||||
	    printf("SNR should be in the range [-40..20]\n");
 | 
			
		||||
		if (SNRdB>20 || SNRdB<-50) {
 | 
			
		||||
			printf("SNR should be in the range [-50..20]\n");
 | 
			
		||||
			syntax();
 | 
			
		||||
			return -1;
 | 
			
		||||
			}
 | 
			
		||||
	} else {
 | 
			
		||||
		} 
 | 
			
		||||
	else 
 | 
			
		||||
	if (strncmp(*argv,"-t",2)==0) {
 | 
			
		||||
	    testtype = ( int)atoi((*argv)+2);
 | 
			
		||||
	    if (testtype>1) {
 | 
			
		||||
	    if (testtype>2) {
 | 
			
		||||
			printf("Invalid test type\n");
 | 
			
		||||
			syntax();
 | 
			
		||||
			return -1;
 | 
			
		||||
			}
 | 
			
		||||
	  } else {
 | 
			
		||||
		}
 | 
			
		||||
	else 
 | 
			
		||||
	if (strncmp(*argv,"-c",2)==0) {
 | 
			
		||||
		channel = ( int)atoi((*argv)+2);
 | 
			
		||||
	    if (channel>CHANNEL_RAYLEIGH) {
 | 
			
		||||
@ -472,16 +572,41 @@ int main(int argc, char* argv[])
 | 
			
		||||
			syntax();
 | 
			
		||||
			return -1;
 | 
			
		||||
			}
 | 
			
		||||
	    } else {
 | 
			
		||||
	    } 
 | 
			
		||||
	else
 | 
			
		||||
	if (strncmp(*argv,"-b",2)==0) {
 | 
			
		||||
	    B90 = (float)atof((*argv)+2);
 | 
			
		||||
	    if (B90<1 || B90>230) {
 | 
			
		||||
			printf("Invalid B90\n");
 | 
			
		||||
			syntax();
 | 
			
		||||
			return -1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	else
 | 
			
		||||
	if (strncmp(*argv,"-m",2)==0) {
 | 
			
		||||
	    fadingModel = (int)atoi((*argv)+2);
 | 
			
		||||
	    if (fadingModel<0 || fadingModel>1) {
 | 
			
		||||
			printf("Invalid fading model\n");
 | 
			
		||||
			syntax();
 | 
			
		||||
			return -1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	else
 | 
			
		||||
	if (strncmp(*argv,"-q",2)==0) {
 | 
			
		||||
	    submode = (int)atoi((*argv)+2);
 | 
			
		||||
	    if (submode<0 || submode>4) {
 | 
			
		||||
			printf("Invalid submode\n");
 | 
			
		||||
			syntax();
 | 
			
		||||
			return -1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	else {
 | 
			
		||||
	    printf("Invalid option\n");
 | 
			
		||||
	    syntax();
 | 
			
		||||
	    return -1;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  EbNodB = SNRdB+QRA64_SNR_EBNO_OFFSET;	
 | 
			
		||||
  
 | 
			
		||||
@ -497,14 +622,26 @@ int main(int argc, char* argv[])
 | 
			
		||||
			nok++;
 | 
			
		||||
		}
 | 
			
		||||
	printf("\n\n%d/%d QSOs to end without repetitions\n",nok,nqso);
 | 
			
		||||
  } else {
 | 
			
		||||
    test_proc_2(channel, EbNodB, mode);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
	printf("Input SNR = %.1fdB channel=%s ap-mode=%s\n\n",
 | 
			
		||||
		SNRdB,
 | 
			
		||||
		channel==CHANNEL_AWGN?"AWGN":"RAYLEIGH",
 | 
			
		||||
		apmode_type[mode]
 | 
			
		||||
		);
 | 
			
		||||
	} 
 | 
			
		||||
  else if (testtype==1) {
 | 
			
		||||
	test_proc_2(channel, EbNodB, mode);
 | 
			
		||||
	printf("Input SNR = %.1fdB channel=%s ap-mode=%s\n\n",
 | 
			
		||||
		SNRdB,
 | 
			
		||||
		channel==CHANNEL_AWGN?"AWGN":"RAYLEIGH",
 | 
			
		||||
		apmode_type[mode]
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
  else {
 | 
			
		||||
	test_fastfading(EbNodB,B90,fadingModel,submode,mode);
 | 
			
		||||
	printf("Input SNR = %.1fdB ap-mode=%s\n\n",
 | 
			
		||||
	 SNRdB,
 | 
			
		||||
	 apmode_type[mode]
 | 
			
		||||
	 );
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,7 @@ Encoding/decoding functions for the QRA64 mode
 | 
			
		||||
 | 
			
		||||
-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Code used in this sowftware release:
 | 
			
		||||
QRA code used in this sowftware release:
 | 
			
		||||
 | 
			
		||||
QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in 
 | 
			
		||||
qra13_64_64_irr_e.h /.c)
 | 
			
		||||
@ -34,13 +34,13 @@ resulting code is a (12,63) code
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "qra64.h"
 | 
			
		||||
#include "../qracodes/qracodes.h"
 | 
			
		||||
#include "../qracodes/qra13_64_64_irr_e.h"
 | 
			
		||||
#include "../qracodes/pdmath.h"
 | 
			
		||||
#include "../qracodes/normrnd.h"
 | 
			
		||||
 | 
			
		||||
// Code parameters of the QRA64 mode 
 | 
			
		||||
#define QRA64_CODE  qra_13_64_64_irr_e
 | 
			
		||||
@ -54,8 +54,28 @@ resulting code is a (12,63) code
 | 
			
		||||
static int  calc_crc6(const int *x, int sz);
 | 
			
		||||
static void ix_mask(float *dst, const float *src, const int *mask, 
 | 
			
		||||
		    const int *x);
 | 
			
		||||
static int qra64_decode_attempts(qra64codec *pcodec, int *xdec, const float *ix);
 | 
			
		||||
static int qra64_do_decode(int *x, const float *pix, const int *ap_mask, 
 | 
			
		||||
			    const int *ap_x);
 | 
			
		||||
static float qra64_fastfading_estim_noise_std(
 | 
			
		||||
				float *rxen, 
 | 
			
		||||
				const float esnometric, 
 | 
			
		||||
				const int submode);
 | 
			
		||||
static void qra64_fastfading_intrinsics(
 | 
			
		||||
				float *pix, 
 | 
			
		||||
				const float *rxamp, 
 | 
			
		||||
				const float *hptr, 
 | 
			
		||||
				const int    hlen, 
 | 
			
		||||
				const float cmetric, 
 | 
			
		||||
				const int submode);
 | 
			
		||||
static float qra64_fastfading_msg_esno(
 | 
			
		||||
			const int *ydec,
 | 
			
		||||
			const float *rxamp, 
 | 
			
		||||
			const float sigma,
 | 
			
		||||
			const float EsNoMetric,
 | 
			
		||||
			const int hlen, 
 | 
			
		||||
			const int submode);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// a-priori information masks for fields in JT65-like msgs --------------------
 | 
			
		||||
#define MASK_CQQRZ      0xFFFFFFC // CQ/QRZ calls common bits
 | 
			
		||||
@ -259,101 +279,13 @@ int qra64_decode(qra64codec *pcodec, float *ebno, int *x, const float *rxen)
 | 
			
		||||
  // Initialize crc prob to a uniform distribution
 | 
			
		||||
  pd_init(dsttmp,pd_uniform(QRA64_m),QRA64_M);
 | 
			
		||||
 | 
			
		||||
  // Attempt to decode without a-priori info --------------------------------
 | 
			
		||||
  rc = qra64_do_decode(xdec, ix, NULL, NULL);
 | 
			
		||||
  if (rc>=0) {
 | 
			
		||||
	  rc = 0; // successfull decode with AP0
 | 
			
		||||
	  goto decode_end;                        
 | 
			
		||||
	  }
 | 
			
		||||
  else
 | 
			
		||||
	  if (pcodec->apflags==QRA_NOAP) 
 | 
			
		||||
		  // nothing more to do
 | 
			
		||||
		  return rc; // rc<0 = unsuccessful decode
 | 
			
		||||
  // Try to decode using all AP cases if required
 | 
			
		||||
  rc = qra64_decode_attempts(pcodec, xdec, ix);
 | 
			
		||||
 | 
			
		||||
  // Here we handle decoding with AP knowledge
 | 
			
		||||
  if (rc<0)
 | 
			
		||||
	  return rc;	// no success
 | 
			
		||||
 | 
			
		||||
  // Attempt to decode CQ calls
 | 
			
		||||
  rc = qra64_do_decode(xdec,ix,pcodec->apmask_cqqrz, pcodec->apmsg_cqqrz); 
 | 
			
		||||
  if (rc>=0) { rc = 1; goto decode_end; };    // decoded [cq/qrz ? ?]
 | 
			
		||||
  rc = qra64_do_decode(xdec, ix, pcodec->apmask_cqqrz_ooo, 
 | 
			
		||||
		       pcodec->apmsg_cqqrz);	                        
 | 
			
		||||
  if (rc>=0) { rc = 2; goto decode_end; };    // decoded [cq ? ooo]
 | 
			
		||||
 | 
			
		||||
  // attempt to decode calls directed to us 
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_MYCALL]) {
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1, 
 | 
			
		||||
		       pcodec->apmsg_call1);		                
 | 
			
		||||
	if (rc>=0) { rc = 3; goto decode_end; };    // decoded [mycall ? ?]
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_ooo, 
 | 
			
		||||
		       pcodec->apmsg_call1);	                    
 | 
			
		||||
	if (rc>=0) { rc = 4; goto decode_end; };    // decoded [mycall ? ooo]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // attempt to decode [mycall srccall ?] msgs
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_BOTHCALLS]) {
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2, 
 | 
			
		||||
		       pcodec->apmsg_call1_call2);	                
 | 
			
		||||
	if (rc>=0) { rc = 5; goto decode_end; };    // decoded [mycall srccall ?]	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // attempt to decode [? hiscall ?/b] msgs
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_HISCALL]) {
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2, 
 | 
			
		||||
		       pcodec->apmsg_call2);		                
 | 
			
		||||
	if (rc>=0) { rc = 6; goto decode_end; };    // decoded [? hiscall ?]
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2_ooo, 
 | 
			
		||||
		       pcodec->apmsg_call2);	                    
 | 
			
		||||
	if (rc>=0) { rc = 7; goto decode_end; };    // decoded [? hiscall ooo]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // attempt to decode [cq/qrz hiscall ?/b/grid] msgs
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_CQHISCALL]) {
 | 
			
		||||
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2, 
 | 
			
		||||
				pcodec->apmsg_cq_call2);		                
 | 
			
		||||
	if (rc>=0) { rc = 9; goto decode_end; };    // decoded [cq/qrz hiscall ?]
 | 
			
		||||
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo, 
 | 
			
		||||
		       pcodec->apmsg_cq_call2_grid);	
 | 
			
		||||
	if (rc>=0) {
 | 
			
		||||
		// Full AP mask need special handling
 | 
			
		||||
		// To minimize false decodes we check the decoded message
 | 
			
		||||
		// with what passed in the ap_set call
 | 
			
		||||
		if (memcmp(pcodec->apmsg_cq_call2_grid,xdec, QRA64_K*sizeof(int))!=0) 
 | 
			
		||||
			return -1;
 | 
			
		||||
		rc = 11; goto decode_end; 
 | 
			
		||||
		};    // decoded [cq/qrz hiscall grid]
 | 
			
		||||
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo, 
 | 
			
		||||
		       pcodec->apmsg_cq_call2);	                    
 | 
			
		||||
	if (rc>=0) { 
 | 
			
		||||
		// Full AP mask need special handling
 | 
			
		||||
		// To minimize false decodes we check the decoded message
 | 
			
		||||
		// with what passed in the ap_set call
 | 
			
		||||
		if (memcmp(pcodec->apmsg_cq_call2,xdec, QRA64_K*sizeof(int))!=0) 
 | 
			
		||||
			return -1;
 | 
			
		||||
		rc = 10; goto decode_end; };    // decoded [cq/qrz hiscall ]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // attempt to decode [mycall hiscall grid]
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_FULL]) {
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2_grid, 
 | 
			
		||||
		       pcodec->apmsg_call1_call2_grid); 
 | 
			
		||||
	if (rc>=0) { 
 | 
			
		||||
		// Full AP mask need special handling
 | 
			
		||||
		// All the three msg fields were given.
 | 
			
		||||
		// To minimize false decodes we check the decoded message
 | 
			
		||||
		// with what passed in the ap_set call
 | 
			
		||||
		if (memcmp(pcodec->apmsg_call1_call2_grid,xdec, QRA64_K*sizeof(int))!=0) 
 | 
			
		||||
			return -1;
 | 
			
		||||
		rc = 8; goto decode_end; 
 | 
			
		||||
		};    // decoded [mycall hiscall grid]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // all decoding attempts failed
 | 
			
		||||
  return rc;
 | 
			
		||||
 | 
			
		||||
decode_end: // successfull decode 
 | 
			
		||||
  // successfull decode --------------------------------
 | 
			
		||||
  
 | 
			
		||||
  // copy decoded message (without crc) to output buffer
 | 
			
		||||
  memcpy(x,xdec,QRA64_K*sizeof(int));
 | 
			
		||||
@ -404,8 +336,585 @@ decode_end: // successfull decode
 | 
			
		||||
  return rc;	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tables of fading amplitudes coefficients for QRA64 (Ts=6912/12000)
 | 
			
		||||
// As the fading is assumed to be symmetric around the nominal frequency
 | 
			
		||||
// only the leftmost and the central coefficient are stored in the tables.
 | 
			
		||||
// (files have been generated with the Matlab code efgengauss.m and efgenlorentz.m)
 | 
			
		||||
#include "fadampgauss.c"
 | 
			
		||||
#include "fadamplorentz.c"
 | 
			
		||||
 | 
			
		||||
int qra64_decode_fastfading(
 | 
			
		||||
				qra64codec *pcodec,		// ptr to the codec structure
 | 
			
		||||
				float *ebno,			// ptr to where the estimated Eb/No value will be saved
 | 
			
		||||
				int *x,					// ptr to decoded message 
 | 
			
		||||
				float *rxen,		    // ptr to received symbol energies array
 | 
			
		||||
				const int submode,		// submode idx (0=QRA64A ... 4=QRA64E)
 | 
			
		||||
				const float B90,	    // spread bandwidth (90% fractional energy)
 | 
			
		||||
				const int fadingModel)  // 0=Gaussian 1=Lorentzian fade model
 | 
			
		||||
 | 
			
		||||
// Decode a QRA64 msg using a fast-fading metric
 | 
			
		||||
//
 | 
			
		||||
// rxen: The array of the received bin energies
 | 
			
		||||
//       Bins must be spaced by integer multiples of the symbol rate (1/Ts Hz)
 | 
			
		||||
//       The array must be an array of total length U = L x N where:
 | 
			
		||||
//			L: is the number of frequency bins per message symbol (see after)
 | 
			
		||||
//          N: is the number of symbols in a QRA64 msg (63)
 | 
			
		||||
 | 
			
		||||
//       The number of bins/symbol L depends on the selected submode accordingly to 
 | 
			
		||||
//		 the following rule:
 | 
			
		||||
//			L = (64+64*2^submode+64) = 64*(2+2^submode)
 | 
			
		||||
//		 Tone 0 is always supposed to be at offset 64 in the array.
 | 
			
		||||
//		 The m-th tone nominal frequency is located at offset 64 + m*2^submode (m=0..63)
 | 
			
		||||
//
 | 
			
		||||
//		 Submode A: (2^submode = 1)
 | 
			
		||||
//          L = 64*3 = 196 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 192*63 = 12096 floats
 | 
			
		||||
//
 | 
			
		||||
//		 Submode B: (2^submode = 2)
 | 
			
		||||
//          L = 64*4 = 256 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 256*63 = 16128 floats
 | 
			
		||||
//
 | 
			
		||||
//		 Submode C: (2^submode = 4)
 | 
			
		||||
//          L = 64*6 = 384 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 384*63 = 24192 floats
 | 
			
		||||
//
 | 
			
		||||
//		 Submode D: (2^submode = 8)
 | 
			
		||||
//          L = 64*10 = 640 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 640*63 = 40320 floats
 | 
			
		||||
//
 | 
			
		||||
//		 Submode E: (2^submode = 16)
 | 
			
		||||
//          L = 64*18 = 1152 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 1152*63 = 72576 floats
 | 
			
		||||
//
 | 
			
		||||
//		Note: The rxen array is modified and reused for internal calculations.
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//	B90: spread fading bandwidth in Hz (90% fractional average energy)
 | 
			
		||||
//
 | 
			
		||||
//			B90 should be in the range 1 Hz ... 238 Hz
 | 
			
		||||
//			The value passed to the call is rounded to the closest value among the 
 | 
			
		||||
//			64 available values:
 | 
			
		||||
//				B = 1.09^k Hz, with k=0,1,...,63
 | 
			
		||||
//
 | 
			
		||||
//			I.e. B90=27 Hz will be approximated in this way:
 | 
			
		||||
//				k = rnd(log(27)/log(1.09)) = 38
 | 
			
		||||
//              B90 = 1.09^k = 1.09^38 = 26.4 Hz
 | 
			
		||||
//
 | 
			
		||||
//          For any input value the maximum rounding error is not larger than +/- 5%
 | 
			
		||||
//          
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  int k;
 | 
			
		||||
  float *srctmp, *dsttmp;
 | 
			
		||||
  float ix[QRA64_NC*QRA64_M];		// (depunctured) intrisic information
 | 
			
		||||
  int   xdec[QRA64_KC];				// decoded message (with crc)
 | 
			
		||||
  int   ydec[QRA64_NC];				// re-encoded message (for snr calculations)
 | 
			
		||||
  float noisestd;					// estimated noise std
 | 
			
		||||
  float esno,ebnoval;				// estimated Eb/No
 | 
			
		||||
  float tempf;
 | 
			
		||||
  float EsNoMetric, cmetric;
 | 
			
		||||
  int rc;
 | 
			
		||||
  int hidx, hlen;
 | 
			
		||||
  const float *hptr;
 | 
			
		||||
  
 | 
			
		||||
	if (QRA64_NMSG!=QRA64_CODE.NMSG)
 | 
			
		||||
		return -16;					// QRA64_NMSG define is wrong
 | 
			
		||||
 | 
			
		||||
	if (submode<0 || submode>4)
 | 
			
		||||
		return -17;				// invalid submode
 | 
			
		||||
 | 
			
		||||
	if (B90<1.0f || B90>238.0f)	
 | 
			
		||||
		return -18;				// B90 out of range
 | 
			
		||||
 | 
			
		||||
	// compute index to most appropriate amplitude weighting function coefficients
 | 
			
		||||
    hidx = (int)(log((float)B90)/log(1.09f) - 0.499f);
 | 
			
		||||
 | 
			
		||||
	if (hidx<0 || hidx > 64) 
 | 
			
		||||
		return -19;				// index of weighting function out of range
 | 
			
		||||
 | 
			
		||||
	if (fadingModel==0) {	 // gaussian fading model
 | 
			
		||||
		// point to gaussian weighting taps
 | 
			
		||||
		hlen = hlen_tab_gauss[hidx];	 // hlen = (L+1)/2 (where L=(odd) number of taps of w fun)
 | 
			
		||||
		hptr = hptr_tab_gauss[hidx];     // pointer to the first (L+1)/2 coefficients of w fun
 | 
			
		||||
		}
 | 
			
		||||
	else if (fadingModel==1) {
 | 
			
		||||
		// point to lorentzian weighting taps
 | 
			
		||||
		hlen = hlen_tab_lorentz[hidx];	 // hlen = (L+1)/2 (where L=(odd) number of taps of w fun)
 | 
			
		||||
		hptr = hptr_tab_lorentz[hidx];     // pointer to the first (L+1)/2 coefficients of w fun
 | 
			
		||||
		}
 | 
			
		||||
	else 
 | 
			
		||||
		return -20;			// invalid fading model index
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// compute (euristically) the optimal decoder metric accordingly the given spread amount
 | 
			
		||||
	// We assume that the decoder threshold is:
 | 
			
		||||
	//		Es/No(dB) = Es/No(AWGN)(dB) + 8*log(B90)/log(240)(dB)
 | 
			
		||||
	// that's to say, at the maximum Doppler spread bandwidth (240 Hz) there's a ~8 dB Es/No degradation
 | 
			
		||||
	// over the AWGN case
 | 
			
		||||
	tempf = 8.0f*(float)log((float)B90)/(float)log(240.0f);
 | 
			
		||||
	EsNoMetric = pcodec->decEsNoMetric*(float)pow(10.0f,tempf/10.0f);
 | 
			
		||||
 | 
			
		||||
	// Step 1 ----------------------------------------------------------------------------------- 
 | 
			
		||||
	// Evaluate the noise stdev from the received energies at nominal tone frequencies
 | 
			
		||||
    // and transform energies to amplitudes
 | 
			
		||||
	tempf = hptr[hlen-1];				// amplitude weigth at nominal freq;
 | 
			
		||||
	tempf = tempf*tempf;				// fractional energy at nominal freq. bin
 | 
			
		||||
	
 | 
			
		||||
	noisestd = qra64_fastfading_estim_noise_std(rxen, EsNoMetric, submode);
 | 
			
		||||
	cmetric = (float)sqrt(M_PI_2*EsNoMetric)/noisestd;
 | 
			
		||||
 | 
			
		||||
	// Step 2 -----------------------------------------------------------------------------------
 | 
			
		||||
	// Compute message symbols probability distributions
 | 
			
		||||
	qra64_fastfading_intrinsics(ix, rxen, hptr, hlen, cmetric, submode);
 | 
			
		||||
 | 
			
		||||
	// Step 3 ---------------------------------------------------------------------------
 | 
			
		||||
	// De-puncture observations adding a uniform distribution for the crc symbol
 | 
			
		||||
	// Move check symbols distributions one symbol towards the end
 | 
			
		||||
	dsttmp = PD_ROWADDR(ix,QRA64_M, QRA64_NC-1);	//Point to last symbol prob dist
 | 
			
		||||
	srctmp = dsttmp-QRA64_M;              // source is the previous pd
 | 
			
		||||
	for (k=0;k<QRA64_C;k++) {
 | 
			
		||||
		pd_init(dsttmp,srctmp,QRA64_M);
 | 
			
		||||
		dsttmp -=QRA64_M;
 | 
			
		||||
		srctmp -=QRA64_M;
 | 
			
		||||
		}
 | 
			
		||||
	// Initialize crc prob to a uniform distribution
 | 
			
		||||
	pd_init(dsttmp,pd_uniform(QRA64_m),QRA64_M);
 | 
			
		||||
 | 
			
		||||
	// Step 4 ---------------------------------------------------------------------------
 | 
			
		||||
	// Attempt to decode
 | 
			
		||||
	rc = qra64_decode_attempts(pcodec, xdec, ix);
 | 
			
		||||
	if (rc<0)
 | 
			
		||||
	  return rc;	// no success
 | 
			
		||||
 | 
			
		||||
	// copy decoded message (without crc) to output buffer
 | 
			
		||||
	memcpy(x,xdec,QRA64_K*sizeof(int));
 | 
			
		||||
 | 
			
		||||
	// Step 5 ----------------------------------------------------------------------------
 | 
			
		||||
	// Estimate the message Eb/No
 | 
			
		||||
 | 
			
		||||
	if (ebno==0)	// null pointer indicates we are not interested in the Eb/No estimate
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
	// reencode message to estimate Eb/No
 | 
			
		||||
	qra_encode(&QRA64_CODE, ydec, xdec);	 
 | 
			
		||||
	// puncture crc
 | 
			
		||||
	memmove(ydec+QRA64_K,ydec+QRA64_KC,QRA64_C*sizeof(int)); 
 | 
			
		||||
 | 
			
		||||
	// compute Es/N0 of decoded message
 | 
			
		||||
	esno = qra64_fastfading_msg_esno(ydec,rxen,noisestd, EsNoMetric, hlen,submode);
 | 
			
		||||
 | 
			
		||||
	// as the weigthing function include about 90% of the energy
 | 
			
		||||
	// we could compute the unbiased esno with:
 | 
			
		||||
	// esno = esno/0.9;
 | 
			
		||||
	
 | 
			
		||||
	// this would be the exact value if the noisestd were not overestimated at high Eb/No
 | 
			
		||||
	ebnoval = 1.0f/(1.0f*QRA64_K/QRA64_N*QRA64_m)*esno; 
 | 
			
		||||
 | 
			
		||||
	// compute value in dB
 | 
			
		||||
	if (ebnoval<=0)
 | 
			
		||||
	  ebnoval = EBNO_MIN; // assume a minimum, positive value
 | 
			
		||||
	else
 | 
			
		||||
	  ebnoval = 10.0f*(float)log10(ebnoval);
 | 
			
		||||
	  if (ebnoval<EBNO_MIN)
 | 
			
		||||
		  ebnoval = EBNO_MIN;
 | 
			
		||||
  
 | 
			
		||||
	*ebno = ebnoval;
 | 
			
		||||
 | 
			
		||||
  return rc;	
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int qra64_fastfading_channel(float **rxen, const int *xmsg, const int submode, const float EbN0dB, const float B90, const int fadingModel)
 | 
			
		||||
{
 | 
			
		||||
	// Simulate transmission over a fading channel and non coherent detection
 | 
			
		||||
 | 
			
		||||
	// Set rxen to point to an array of bin energies formatted as required 
 | 
			
		||||
	// by the (fast-fading) decoding routine
 | 
			
		||||
 | 
			
		||||
	// returns 0 on success or negative values on error conditions
 | 
			
		||||
 | 
			
		||||
	static float *channel_out = NULL;
 | 
			
		||||
	static int    channel_submode = -1;
 | 
			
		||||
 | 
			
		||||
	int bpt = (1<<submode);			// bins per tone 
 | 
			
		||||
	int bps = QRA64_M*(2+bpt);		// total number of bins per symbols
 | 
			
		||||
	int bpm = bps*QRA64_N;			// total number of bins in a message
 | 
			
		||||
	int n,j,hidx, hlen;
 | 
			
		||||
	const float *hptr;
 | 
			
		||||
	float *cursym,*curtone;
 | 
			
		||||
 | 
			
		||||
	float iq[2];
 | 
			
		||||
	float *curi, *curq;
 | 
			
		||||
 | 
			
		||||
//	float tote=0;	// debug
 | 
			
		||||
 | 
			
		||||
	float N0, EsN0, Es, A, sigmanoise, sigmasig;
 | 
			
		||||
 | 
			
		||||
	if (rxen==NULL)
 | 
			
		||||
		return -1;		// rxen must be a non-null ptr 
 | 
			
		||||
 | 
			
		||||
	// allocate output buffer if not yet done or if submode changed
 | 
			
		||||
	if (channel_out==NULL || submode!=channel_submode) {
 | 
			
		||||
 | 
			
		||||
		// unallocate previous buffer
 | 
			
		||||
		if (channel_out)
 | 
			
		||||
			free(channel_out);
 | 
			
		||||
 | 
			
		||||
		// allocate new buffer
 | 
			
		||||
		// we allocate twice the mem so that we can store/compute complex amplitudes
 | 
			
		||||
		channel_out = (float*)malloc(bpm*sizeof(float)*2);	
 | 
			
		||||
		if (channel_out==NULL)
 | 
			
		||||
			return -2;	// error allocating memory
 | 
			
		||||
 | 
			
		||||
		channel_submode = submode;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if (B90<1.0f || B90>238.0f)	
 | 
			
		||||
		return -18;				// B90 out of range
 | 
			
		||||
 | 
			
		||||
	// compute index to most appropriate amplitude weighting function coefficients
 | 
			
		||||
    hidx = (int)(log((float)B90)/log(1.09f) - 0.499f);
 | 
			
		||||
 | 
			
		||||
	if (hidx<0 || hidx > 64) 
 | 
			
		||||
		return -19;				// index of weighting function out of range
 | 
			
		||||
 | 
			
		||||
	if (fadingModel==0) {	 // gaussian fading model
 | 
			
		||||
		// point to gaussian weighting taps
 | 
			
		||||
		hlen = hlen_tab_gauss[hidx];	 // hlen = (L+1)/2 (where L=(odd) number of taps of w fun)
 | 
			
		||||
		hptr = hptr_tab_gauss[hidx];     // pointer to the first (L+1)/2 coefficients of w fun
 | 
			
		||||
		}
 | 
			
		||||
	else if (fadingModel==1) {
 | 
			
		||||
		// point to lorentzian weighting taps
 | 
			
		||||
		hlen = hlen_tab_lorentz[hidx];	 // hlen = (L+1)/2 (where L=(odd) number of taps of w fun)
 | 
			
		||||
		hptr = hptr_tab_lorentz[hidx];     // pointer to the first (L+1)/2 coefficients of w fun
 | 
			
		||||
		}
 | 
			
		||||
	else 
 | 
			
		||||
		return -20;			// invalid fading model index
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Compute the unfaded tone amplitudes from the Eb/No value passed to the call
 | 
			
		||||
	N0 = 1.0f;	// assume unitary noise PSD
 | 
			
		||||
	sigmanoise = (float)sqrt(N0/2);
 | 
			
		||||
	EsN0 = (float)pow(10.0f,EbN0dB/10.0f)*QRA64_m*QRA64_K/QRA64_N; // Es/No = m*R*Eb/No
 | 
			
		||||
	Es   = EsN0*N0;
 | 
			
		||||
	A    = (float)sqrt(Es/2.0f);	// unfaded tone amplitude (i^2+q^2 = Es/2+Es/2 = Es)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Generate gaussian noise iq components
 | 
			
		||||
	normrnd_s(channel_out, bpm*2, 0 , sigmanoise);
 | 
			
		||||
 | 
			
		||||
	// Add message symbols energies
 | 
			
		||||
	for (n=0;n<QRA64_N;n++) {					
 | 
			
		||||
 | 
			
		||||
		cursym  = channel_out+n*bps + QRA64_M; // point to n-th symbol
 | 
			
		||||
		curtone = cursym+xmsg[n]*bpt;	 // point to encoded tone 
 | 
			
		||||
		curi    = curtone-hlen+1;		 // point to real part of first bin
 | 
			
		||||
		curq    = curtone-hlen+1+bpm;	 // point to imag part of first bin
 | 
			
		||||
		
 | 
			
		||||
		// generate Rayleigh faded bins with given average energy and add to noise
 | 
			
		||||
		for (j=0;j<hlen;j++) {	
 | 
			
		||||
			sigmasig = A*hptr[j];
 | 
			
		||||
			normrnd_s(iq, 2, 0 , sigmasig);
 | 
			
		||||
//			iq[0]=sigmasig*sqrt(2); iq[1]=0;	debug: used to verify Eb/No 
 | 
			
		||||
			*curi++ += iq[0];
 | 
			
		||||
			*curq++ += iq[1];
 | 
			
		||||
//			tote +=iq[0]*iq[0]+iq[1]*iq[1];		// debug
 | 
			
		||||
			}
 | 
			
		||||
		for (j=hlen-2;j>=0;j--) {	
 | 
			
		||||
			sigmasig = A*hptr[j];
 | 
			
		||||
			normrnd_s(iq, 2, 0 , sigmasig);
 | 
			
		||||
//			iq[0]=sigmasig*sqrt(2); iq[1]=0;	debug: used to verify Eb/No
 | 
			
		||||
			*curi++ += iq[0];
 | 
			
		||||
			*curq++ += iq[1];
 | 
			
		||||
//			tote +=iq[0]*iq[0]+iq[1]*iq[1];		// debug
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
//	tote = tote/QRA64_N;	// debug
 | 
			
		||||
 | 
			
		||||
	// compute total bin energies (S+N) and store in first half of buffer
 | 
			
		||||
	curi = channel_out;
 | 
			
		||||
	curq = channel_out+bpm;
 | 
			
		||||
	for (n=0;n<bpm;n++) 					
 | 
			
		||||
		channel_out[n] = curi[n]*curi[n] + curq[n]*curq[n];
 | 
			
		||||
 | 
			
		||||
	// set rxen to point to the channel output energies
 | 
			
		||||
	*rxen = channel_out;
 | 
			
		||||
 | 
			
		||||
	return 0;	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Static functions definitions ----------------------------------------------
 | 
			
		||||
 | 
			
		||||
// fast-fading static functions --------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
static float qra64_fastfading_estim_noise_std(float *rxen, const float esnometric, const int submode)
 | 
			
		||||
{
 | 
			
		||||
	// estimate the noise standard deviation from nominal frequency symbol bins
 | 
			
		||||
	// transform energies to amplitudes
 | 
			
		||||
 | 
			
		||||
	// rxen = message symbols energies (overwritten with symbols amplitudes)
 | 
			
		||||
	// esnometric = Es/No at nominal frequency bin for which we compute the decoder metric
 | 
			
		||||
	// submode = submode used (0=A...4=E)
 | 
			
		||||
 | 
			
		||||
	int bpt = (1<<submode);			// bins per tone 
 | 
			
		||||
	int bps = QRA64_M*(2+bpt);		// total number of bins per symbols
 | 
			
		||||
	int bpm = bps*QRA64_N;			// total number of bins in a message
 | 
			
		||||
	int k;
 | 
			
		||||
	float sigmaest;
 | 
			
		||||
 | 
			
		||||
	// estimate noise std
 | 
			
		||||
	sigmaest = 0;
 | 
			
		||||
	for (k=0;k<bpm;k++) {
 | 
			
		||||
		sigmaest += rxen[k];
 | 
			
		||||
		// convert energies to amplitudes for later use
 | 
			
		||||
		rxen[k] = (float)sqrt(rxen[k]);	// we do it in place to avoid memory allocations
 | 
			
		||||
		}
 | 
			
		||||
	sigmaest = sigmaest/bpm;
 | 
			
		||||
	sigmaest = (float)sqrt(sigmaest/(1.0f+esnometric/bps)/2.0f); 
 | 
			
		||||
 | 
			
		||||
	// Note: sigma is overestimated by the (unknown) factor sqrt((1+esno(true)/bps)/(1+esnometric/bps))
 | 
			
		||||
 | 
			
		||||
	return sigmaest;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qra64_fastfading_intrinsics(
 | 
			
		||||
				float *pix, 
 | 
			
		||||
				const float *rxamp, 
 | 
			
		||||
				const float *hptr, 
 | 
			
		||||
				const int    hlen, 
 | 
			
		||||
				const float cmetric, 
 | 
			
		||||
				const int submode)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	// For each symbol in a message:
 | 
			
		||||
	// a) Compute tones loglikelihoods as a sum of products between of the expected 
 | 
			
		||||
	// amplitude fading coefficient and received amplitudes.
 | 
			
		||||
	// Each product is computed as log(I0(hk*xk*cmetric)) where hk is the average fading amplitude,
 | 
			
		||||
	// xk is the received amplitude at bin offset k, and cmetric is a constant dependend on the
 | 
			
		||||
	// Eb/N0 value for which the metric is optimized
 | 
			
		||||
	// The function y = log(I0(x)) is approximated as y = x^2/(x+e)
 | 
			
		||||
	// b) Compute intrinsic symbols probability distributions from symbols loglikelihoods
 | 
			
		||||
 | 
			
		||||
	int n,k,j, bps, bpt;
 | 
			
		||||
	const float *cursym, *curbin;
 | 
			
		||||
	float *curix;
 | 
			
		||||
	float u, maxloglh, loglh, sumix;
 | 
			
		||||
 | 
			
		||||
	bpt = 1<<submode;				// bins per tone
 | 
			
		||||
	bps = QRA64_M*(2+bpt);			// bins per symbol
 | 
			
		||||
 | 
			
		||||
	for (n=0;n<QRA64_N;n++) {			// for each symbol in the message
 | 
			
		||||
		cursym = rxamp+n*bps + QRA64_M;	// point to current symbol nominal bin
 | 
			
		||||
		maxloglh = 0;
 | 
			
		||||
		curix  = pix+n*QRA64_M;		
 | 
			
		||||
		for (k=0;k<QRA64_M;k++) {   // for each tone in the current symbol
 | 
			
		||||
			curbin = cursym + k*bpt -hlen+1;	// ptr to lowest bin of the current tone
 | 
			
		||||
			// compute tone loglikelihood as a weighted sum of bins loglikelihoods
 | 
			
		||||
			loglh = 0.f;
 | 
			
		||||
			for (j=0;j<hlen;j++) {	
 | 
			
		||||
				u = *curbin++ * hptr[j]*cmetric;
 | 
			
		||||
				u = u*u/(u+(float)M_E);	// log(I0(u)) approx.
 | 
			
		||||
				loglh = loglh + u;	
 | 
			
		||||
				}
 | 
			
		||||
			for (j=hlen-2;j>=0;j--) {	
 | 
			
		||||
				u = *curbin++ * hptr[j]*cmetric;
 | 
			
		||||
				u = u*u/(u+(float)M_E);	// log(I0(u)) approx.
 | 
			
		||||
				loglh = loglh + u;
 | 
			
		||||
				}
 | 
			
		||||
			if (loglh>maxloglh)		// keep track of the max loglikelihood
 | 
			
		||||
				maxloglh = loglh;
 | 
			
		||||
			curix[k]=loglh;
 | 
			
		||||
			}
 | 
			
		||||
		// scale to likelihoods
 | 
			
		||||
		sumix = 0.f;
 | 
			
		||||
		for (k=0;k<QRA64_M;k++) {   
 | 
			
		||||
			u = (float)exp(curix[k]-maxloglh);
 | 
			
		||||
			curix[k]=u;
 | 
			
		||||
			sumix +=u;
 | 
			
		||||
			}
 | 
			
		||||
		// scale to probabilities
 | 
			
		||||
		sumix = 1.0f/sumix;
 | 
			
		||||
		for (k=0;k<QRA64_M;k++) 
 | 
			
		||||
			curix[k] = curix[k]*sumix;
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static float qra64_fastfading_msg_esno(
 | 
			
		||||
			const int *ydec,
 | 
			
		||||
			const float *rxamp, 
 | 
			
		||||
			const float sigma,
 | 
			
		||||
			const float EsNoMetric,
 | 
			
		||||
			const int hlen, 
 | 
			
		||||
			const int submode)
 | 
			
		||||
{
 | 
			
		||||
	// Estimate msg Es/N0
 | 
			
		||||
 | 
			
		||||
	int n,j, bps, bpt;
 | 
			
		||||
	const float *cursym, *curtone, *curbin;
 | 
			
		||||
	float u, msgsn,esno;
 | 
			
		||||
	int tothlen = 2*hlen-1;
 | 
			
		||||
 | 
			
		||||
	bpt = 1<<submode;				// bins per tone
 | 
			
		||||
	bps = QRA64_M*(2+bpt);			// bins per symbol
 | 
			
		||||
 | 
			
		||||
	msgsn = 0;
 | 
			
		||||
	for (n=0;n<QRA64_N;n++) {					
 | 
			
		||||
		cursym  = rxamp+n*bps + QRA64_M; // point to n-th symbol amplitudes
 | 
			
		||||
		curtone = cursym+ydec[n]*bpt;	 // point to decoded tone amplitudes
 | 
			
		||||
		curbin  = curtone-hlen+1;		 // point to first bin amplitude
 | 
			
		||||
		
 | 
			
		||||
		// sum bin energies
 | 
			
		||||
		for (j=0;j<hlen;j++) {	
 | 
			
		||||
			u = *curbin++; 
 | 
			
		||||
			msgsn += u*u;	
 | 
			
		||||
			}
 | 
			
		||||
		for (j=hlen-2;j>=0;j--) {	
 | 
			
		||||
			u = *curbin++; 
 | 
			
		||||
			msgsn += u*u;	
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	msgsn =  msgsn/(QRA64_N*tothlen);	// avg msg energy per bin (noise included)
 | 
			
		||||
 | 
			
		||||
	// as sigma is overestimated (sigmatrue = sigma*sqrt((1+EsNoMetric/bps)/(1+EsNo/bps))
 | 
			
		||||
	// we have: msgsn = (1+x/hlen)/(1+x/bps)*2*sigma^2*(1+EsnoMetric/bps), where x = Es/N0(true)
 | 
			
		||||
	//
 | 
			
		||||
	// we can then write:
 | 
			
		||||
	// u = msgsn/2.0f/(sigma*sigma)/(1.0f+EsNoMetric/bps);
 | 
			
		||||
	// (1+x/hlen)/(1+x/bps) = u
 | 
			
		||||
 | 
			
		||||
	u = msgsn/(2.0f*sigma*sigma)/(1.0f+EsNoMetric/bps);
 | 
			
		||||
 | 
			
		||||
	// check u>1 
 | 
			
		||||
	if (u<1)
 | 
			
		||||
		return 0.f;
 | 
			
		||||
 | 
			
		||||
	// check u<bps/tot hlen
 | 
			
		||||
	if (u>(bps/tothlen))
 | 
			
		||||
		return 10000.f;
 | 
			
		||||
 | 
			
		||||
	// solve for Es/No
 | 
			
		||||
	esno = (u-1.0f)/(1.0f/tothlen-u/bps);
 | 
			
		||||
 | 
			
		||||
	return esno;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Attempt to decode given intrisic information
 | 
			
		||||
static int qra64_decode_attempts(qra64codec *pcodec, int *xdec, const float *ix)
 | 
			
		||||
{
 | 
			
		||||
  int rc;
 | 
			
		||||
 | 
			
		||||
  // Attempt to decode without a-priori info --------------------------------
 | 
			
		||||
  rc = qra64_do_decode(xdec, ix, NULL, NULL);
 | 
			
		||||
  if (rc>=0) 
 | 
			
		||||
	  return 0; // successfull decode with AP0
 | 
			
		||||
  else
 | 
			
		||||
	  if (pcodec->apflags==QRA_NOAP) 
 | 
			
		||||
		  // nothing more to do
 | 
			
		||||
		  return rc; // rc<0 = unsuccessful decode
 | 
			
		||||
 | 
			
		||||
  // Here we handle decoding with AP knowledge
 | 
			
		||||
 | 
			
		||||
  // Attempt to decode CQ calls
 | 
			
		||||
  rc = qra64_do_decode(xdec,ix,pcodec->apmask_cqqrz, pcodec->apmsg_cqqrz); 
 | 
			
		||||
  if (rc>=0) return 1;    // decoded [cq/qrz ? ?]
 | 
			
		||||
 | 
			
		||||
  rc = qra64_do_decode(xdec, ix, pcodec->apmask_cqqrz_ooo, 
 | 
			
		||||
		       pcodec->apmsg_cqqrz);	                        
 | 
			
		||||
  if (rc>=0) return 2;    // decoded [cq ? ooo]
 | 
			
		||||
 | 
			
		||||
  // attempt to decode calls directed to us 
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_MYCALL]) {
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1, 
 | 
			
		||||
		       pcodec->apmsg_call1);		                
 | 
			
		||||
	if (rc>=0) return 3;    // decoded [mycall ? ?]
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_ooo, 
 | 
			
		||||
		       pcodec->apmsg_call1);	                    
 | 
			
		||||
	if (rc>=0) return 4;    // decoded [mycall ? ooo]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // attempt to decode [mycall srccall ?] msgs
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_BOTHCALLS]) {
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2, 
 | 
			
		||||
		       pcodec->apmsg_call1_call2);	                
 | 
			
		||||
	if (rc>=0) return 5;    // decoded [mycall srccall ?]	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // attempt to decode [? hiscall ?/b] msgs
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_HISCALL]) {
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2, 
 | 
			
		||||
		       pcodec->apmsg_call2);		                
 | 
			
		||||
	if (rc>=0) return 6;    // decoded [? hiscall ?]
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2_ooo, 
 | 
			
		||||
		       pcodec->apmsg_call2);	                    
 | 
			
		||||
	if (rc>=0) return 7;    // decoded [? hiscall ooo]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // attempt to decode [cq/qrz hiscall ?/b/grid] msgs
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_CQHISCALL]) {
 | 
			
		||||
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2, 
 | 
			
		||||
				pcodec->apmsg_cq_call2);		                
 | 
			
		||||
	if (rc>=0) return 9;	// decoded [cq/qrz hiscall ?]
 | 
			
		||||
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo, 
 | 
			
		||||
		       pcodec->apmsg_cq_call2_grid);	
 | 
			
		||||
	if (rc>=0) {
 | 
			
		||||
		// Full AP mask need special handling
 | 
			
		||||
		// To minimize false decodes we check the decoded message
 | 
			
		||||
		// with what passed in the ap_set call
 | 
			
		||||
		if (memcmp(pcodec->apmsg_cq_call2_grid,xdec, QRA64_K*sizeof(int))!=0) 
 | 
			
		||||
			return -1;
 | 
			
		||||
		else
 | 
			
		||||
			return 11;		// decoded [cq/qrz hiscall grid]
 | 
			
		||||
		};    
 | 
			
		||||
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo, 
 | 
			
		||||
		       pcodec->apmsg_cq_call2);	                    
 | 
			
		||||
	if (rc>=0) { 
 | 
			
		||||
		// Full AP mask need special handling
 | 
			
		||||
		// To minimize false decodes we check the decoded message
 | 
			
		||||
		// with what passed in the ap_set call
 | 
			
		||||
		if (memcmp(pcodec->apmsg_cq_call2,xdec, QRA64_K*sizeof(int))!=0) 
 | 
			
		||||
			return -1;
 | 
			
		||||
		else
 | 
			
		||||
			return 10;    // decoded [cq/qrz hiscall ]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // attempt to decode [mycall hiscall grid]
 | 
			
		||||
  if (pcodec->apmsg_set[APTYPE_FULL]) {
 | 
			
		||||
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2_grid, 
 | 
			
		||||
		       pcodec->apmsg_call1_call2_grid); 
 | 
			
		||||
	if (rc>=0) { 
 | 
			
		||||
		// Full AP mask need special handling
 | 
			
		||||
		// All the three msg fields were given.
 | 
			
		||||
		// To minimize false decodes we check the decoded message
 | 
			
		||||
		// with what passed in the ap_set call
 | 
			
		||||
		if (memcmp(pcodec->apmsg_call1_call2_grid,xdec, QRA64_K*sizeof(int))!=0) 
 | 
			
		||||
			return -1;
 | 
			
		||||
		else
 | 
			
		||||
			return 8;	   // decoded [mycall hiscall grid]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  // all decoding attempts failed
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Decode with given a-priori information 
 | 
			
		||||
static int qra64_do_decode(int *xdec, const float *pix, const int *ap_mask, 
 | 
			
		||||
			   const int *ap_x)
 | 
			
		||||
@ -441,6 +950,8 @@ static int qra64_do_decode(int *xdec, const float *pix, const int *ap_mask,
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// crc functions --------------------------------------------------------------
 | 
			
		||||
// crc-6 generator polynomial
 | 
			
		||||
// g(x) = x^6 + a5*x^5 + ... + a1*x + a0
 | 
			
		||||
 | 
			
		||||
@ -140,6 +140,83 @@ int  qra64_decode(qra64codec *pcodec, float *ebno, int *x, const float *r);
 | 
			
		||||
//  return codes in the range 1-10 indicate the amount and the type of a-priori 
 | 
			
		||||
//  information was required to decode the received message.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Decode a QRA64 msg using a fast-fading metric
 | 
			
		||||
int qra64_decode_fastfading(
 | 
			
		||||
				qra64codec *pcodec,		// ptr to the codec structure
 | 
			
		||||
				float *ebno,			// ptr to where the estimated Eb/No value will be saved
 | 
			
		||||
				int *x,					// ptr to decoded message 
 | 
			
		||||
				float *rxen,		    // ptr to received symbol energies array
 | 
			
		||||
				const int submode,		// submode idx (0=QRA64A ... 4=QRA64E)
 | 
			
		||||
				const float B90,	    // spread bandwidth (90% fractional energy)
 | 
			
		||||
				const int fadingModel); // 0=Gaussian 1=Lorentzian fade model
 | 
			
		||||
//
 | 
			
		||||
// rxen: The array of the received bin energies
 | 
			
		||||
//       Bins must be spaced by integer multiples of the symbol rate (1/Ts Hz)
 | 
			
		||||
//       The array must be an array of total length U = L x N where:
 | 
			
		||||
//			L: is the number of frequency bins per message symbol (see after)
 | 
			
		||||
//          N: is the number of symbols in a QRA64 msg (63)
 | 
			
		||||
//
 | 
			
		||||
//       The number of bins/symbol L depends on the selected submode accordingly to 
 | 
			
		||||
//		 the following rule:
 | 
			
		||||
//			L = (64+64*2^submode+64) = 64*(2+2^submode)
 | 
			
		||||
//		 Tone 0 is always supposed to be at offset 64 in the array.
 | 
			
		||||
//		 The m-th tone nominal frequency is located at offset 64 + m*2^submode (m=0..63)
 | 
			
		||||
//
 | 
			
		||||
//		 Submode A: (2^submode = 1)
 | 
			
		||||
//          L = 64*3 = 196 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 192*63 = 12096 floats
 | 
			
		||||
//
 | 
			
		||||
//		 Submode B: (2^submode = 2)
 | 
			
		||||
//          L = 64*4 = 256 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 256*63 = 16128 floats
 | 
			
		||||
//
 | 
			
		||||
//		 Submode C: (2^submode = 4)
 | 
			
		||||
//          L = 64*6 = 384 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 384*63 = 24192 floats
 | 
			
		||||
//
 | 
			
		||||
//		 Submode D: (2^submode = 8)
 | 
			
		||||
//          L = 64*10 = 640 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 640*63 = 40320 floats
 | 
			
		||||
//
 | 
			
		||||
//		 Submode E: (2^submode = 16)
 | 
			
		||||
//          L = 64*18 = 1152 bins/symbol
 | 
			
		||||
//          Total length of the energies array: U = 1152*63 = 72576 floats
 | 
			
		||||
//
 | 
			
		||||
//		Note: The rxen array is modified and reused for internal calculations.
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//	B90: spread fading bandwidth in Hz (90% fractional average energy)
 | 
			
		||||
//
 | 
			
		||||
//			B90 should be in the range 1 Hz ... 238 Hz
 | 
			
		||||
//			The value passed to the call is rounded to the closest value among the 
 | 
			
		||||
//			64 available values:
 | 
			
		||||
//				B = 1.09^k Hz, with k=0,1,...,63
 | 
			
		||||
//
 | 
			
		||||
//			I.e. B90=27 Hz will be approximated in this way:
 | 
			
		||||
//				k = rnd(log(27)/log(1.09)) = 38
 | 
			
		||||
//              B90 = 1.09^k = 1.09^38 = 26.4 Hz
 | 
			
		||||
//
 | 
			
		||||
//          For any input value the maximum rounding error is not larger than +/- 5%
 | 
			
		||||
//          
 | 
			
		||||
// return codes: same return codes of qra64_decode (+some additional error codes)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Simulate the fast-fading channel (to be used with qra64_decode_fastfading)
 | 
			
		||||
int qra64_fastfading_channel(
 | 
			
		||||
				float **rxen, 
 | 
			
		||||
				const int *xmsg, 
 | 
			
		||||
				const int submode,
 | 
			
		||||
				const float EbN0dB, 
 | 
			
		||||
				const float B90, 
 | 
			
		||||
				const int fadingModel);
 | 
			
		||||
// Simulate transmission over a fading channel with given B90, fading model and submode
 | 
			
		||||
// and non coherent detection.
 | 
			
		||||
// Sets rxen to point to an array of bin energies formatted as required 
 | 
			
		||||
// by the (fast-fading) decoding routine.
 | 
			
		||||
// returns 0 on success or negative values on error conditions
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int qra64_apset(qra64codec *pcodec, const int mycall, const int hiscall, const int grid, const int aptype);
 | 
			
		||||
// Set decoder a-priori knowledge accordingly to the type of the message to 
 | 
			
		||||
// look up for
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										50
									
								
								lib/qra/qra64/qra64example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								lib/qra/qra64/qra64example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
			
		||||
Example:
 | 
			
		||||
 | 
			
		||||
qra64 -a2 -t2 -b10.0 -m1 -q2 -s-28.0
 | 
			
		||||
 | 
			
		||||
Simulate fast-fading decoding (-t2) with 
 | 
			
		||||
USER_AP (-a2)
 | 
			
		||||
B90 = 10.0 Hz (-b10.0)
 | 
			
		||||
Lorentz model (-m1)
 | 
			
		||||
submode QRA64C (-q2)
 | 
			
		||||
Input SNR = -28.0 dB (-s-28.0)
 | 
			
		||||
 | 
			
		||||
(type qra64 -h for command syntax)
 | 
			
		||||
 | 
			
		||||
Command Output:
 | 
			
		||||
 | 
			
		||||
Simulating the QRA64 decoder with fast-fading metric
 | 
			
		||||
B90=10.00 Hz - Fading Model=Lorentz - Submode=QRA64C
 | 
			
		||||
 | 
			
		||||
K1JT decoder enabled for [K1JT  ?     ?/blank]
 | 
			
		||||
K1JT decoder enabled for [K1JT IV3NWV ?]
 | 
			
		||||
K1JT decoder enabled for [?    IV3NWV ?/blank]
 | 
			
		||||
K1JT decoder enabled for [K1JT IV3NWV JN66]
 | 
			
		||||
K1JT decoder enabled for [CQ   IV3NWV ?/b/JN66]
 | 
			
		||||
 | 
			
		||||
Encoding msg: [K1JT IV3NWV JN66]
 | 
			
		||||
Decoding with K1JT's decoder
 | 
			
		||||
....................................................................................................
 | 
			
		||||
 | 
			
		||||
Transimtted msgs:100
 | 
			
		||||
Decoded msgs:
 | 
			
		||||
 | 
			
		||||
  0 with [?    ?    ?] AP0
 | 
			
		||||
  0 with [CQ   ?    ?] AP27
 | 
			
		||||
  0 with [CQ   ?     ] AP42
 | 
			
		||||
  4 with [CALL ?    ?] AP29
 | 
			
		||||
  0 with [CALL ?     ] AP44
 | 
			
		||||
  0 with [CALL CALL ?] AP57
 | 
			
		||||
  2 with [?    CALL ?] AP29
 | 
			
		||||
  0 with [?    CALL  ] AP44
 | 
			
		||||
 91 with [CALL CALL G] AP72
 | 
			
		||||
  0 with [CQ   CALL ?] AP55
 | 
			
		||||
  0 with [CQ   CALL  ] AP70
 | 
			
		||||
  0 with [CQ   CALL G] AP70
 | 
			
		||||
 | 
			
		||||
Total: 97/100 (0 undetected errors)
 | 
			
		||||
 | 
			
		||||
Estimated SNR (average in dB) = -28.39 dB
 | 
			
		||||
 | 
			
		||||
Input SNR = -28.0dB ap-mode=USER AP
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user