From b248ceb121987b04784a6a16f409371ed141e717 Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 00:43:49 -0500 Subject: [PATCH 01/10] WIP chore: wsprd lib update partial --- rtlsdr_wsprd.c | 4 +- wsprd/fano.c | 11 +- wsprd/metric_tables.h | 239 ++++++++++-------- wsprd/nhash.c | 7 - wsprd/nhash.h | 1 - wsprd/wsprd.c | 567 ++++++++++++++++++++++++++++-------------- wsprd/wsprd.h | 48 +++- wsprd/wsprd_utils.c | 65 ++--- wsprd/wsprd_utils.h | 2 +- wsprd/wsprsim_utils.c | 108 ++++---- wsprd/wsprsim_utils.h | 6 +- 11 files changed, 639 insertions(+), 419 deletions(-) diff --git a/rtlsdr_wsprd.c b/rtlsdr_wsprd.c index 5b1f763..bec6a5c 100644 --- a/rtlsdr_wsprd.c +++ b/rtlsdr_wsprd.c @@ -612,10 +612,10 @@ int32_t decoderSelfTest() { unsigned char symbols[162]; char message[] = "K1JT FN20QI 20"; char hashtab[32768*13] = {0}; - //char loctab[32768*5] = {0}; // EVAL: code update from wsprd + char loctab[32768*5] = {0}; // EVAL: code update from wsprd // Compute sympbols from the message - get_wspr_channel_symbols(message, hashtab, symbols); + get_wspr_channel_symbols(message, hashtab, loctab, symbols); float f0 = 50.0; float t0 = 2.0; // Caution!! Possible buffer overflow with the index calculation (no user input here!) diff --git a/wsprd/fano.c b/wsprd/fano.c index 1a7a546..2a124d2 100644 --- a/wsprd/fano.c +++ b/wsprd/fano.c @@ -166,8 +166,7 @@ int fano(unsigned int *metric, // Final path metric (returned value) */ while (ngamma >= t + delta) t += delta; } - // Move forward - np[1].gamma = ngamma; + np[1].gamma = ngamma; // Move forward np[1].encstate = np->encstate << 1; if (++np == (lastnode + 1)) { break; // Done! @@ -194,14 +193,11 @@ int fano(unsigned int *metric, // Final path metric (returned value) np->encstate++; // Set low bit } } - np->i = 0; - // Start with best branch + np->i = 0; // Start with best branch continue; } - // Threshold violated, can't go forward - for (;;) { - // Look backward + for (;;) { // Look backward if (np == nodes || np[-1].gamma < t) { /* Can't back up either. * Relax threshold and and look @@ -214,7 +210,6 @@ int fano(unsigned int *metric, // Final path metric (returned value) } break; } - // Back up if (--np < tail && np->i != 1) { np->i++; // Search next best branch diff --git a/wsprd/metric_tables.h b/wsprd/metric_tables.h index d51d156..a86a956 100644 --- a/wsprd/metric_tables.h +++ b/wsprd/metric_tables.h @@ -7,111 +7,138 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-braces" -// float symbol_scale[4]={42.6, 53.3, 72.7, 100.2}; -static const float metric_tables[4][256] = { - 0.9782, 0.9695, 0.9689, 0.9669, 0.9666, 0.9653, 0.9638, 0.9618, 0.9599, 0.9601, - 0.9592, 0.9570, 0.9556, 0.9540, 0.9525, 0.9527, 0.9486, 0.9477, 0.9450, 0.9436, - 0.9424, 0.9400, 0.9381, 0.9360, 0.9340, 0.9316, 0.9301, 0.9272, 0.9254, 0.9224, - 0.9196, 0.9171, 0.9154, 0.9123, 0.9076, 0.9061, 0.9030, 0.9000, 0.8965, 0.8934, - 0.8903, 0.8874, 0.8834, 0.8792, 0.8760, 0.8726, 0.8685, 0.8639, 0.8599, 0.8550, - 0.8504, 0.8459, 0.8422, 0.8364, 0.8320, 0.8262, 0.8215, 0.8159, 0.8111, 0.8052, - 0.7996, 0.7932, 0.7878, 0.7812, 0.7745, 0.7685, 0.7616, 0.7550, 0.7479, 0.7405, - 0.7336, 0.7255, 0.7184, 0.7102, 0.7016, 0.6946, 0.6860, 0.6769, 0.6687, 0.6598, - 0.6503, 0.6416, 0.6325, 0.6219, 0.6122, 0.6016, 0.5920, 0.5818, 0.5711, 0.5606, - 0.5487, 0.5374, 0.5266, 0.5142, 0.5020, 0.4908, 0.4784, 0.4663, 0.4532, 0.4405, - 0.4271, 0.4144, 0.4006, 0.3865, 0.3731, 0.3594, 0.3455, 0.3304, 0.3158, 0.3009, - 0.2858, 0.2708, 0.2560, 0.2399, 0.2233, 0.2074, 0.1919, 0.1756, 0.1590, 0.1427, - 0.1251, 0.1074, 0.0905, 0.0722, 0.0550, 0.0381, 0.0183, 0.0000, -0.0185, -0.0391, - -0.0571, -0.0760, -0.0966, -0.1160, -0.1370, -0.1584, -0.1787, -0.1999, -0.2214, -0.2423, - -0.2643, -0.2879, -0.3114, -0.3336, -0.3568, -0.3806, -0.4050, -0.4293, -0.4552, -0.4798, - -0.5046, -0.5296, -0.5564, -0.5836, -0.6093, -0.6372, -0.6645, -0.6933, -0.7208, -0.7495, - -0.7763, -0.8065, -0.8378, -0.8660, -0.8964, -0.9293, -0.9592, -0.9907, -1.0214, -1.0509, - -1.0850, -1.1168, -1.1528, -1.1847, -1.2157, -1.2511, -1.2850, -1.3174, -1.3540, -1.3900, - -1.4201, -1.4580, -1.4956, -1.5292, -1.5683, -1.6030, -1.6411, -1.6789, -1.7147, -1.7539, - -1.7887, -1.8289, -1.8699, -1.9043, -1.9469, -1.9849, -2.0267, -2.0610, -2.1028, -2.1391, - -2.1855, -2.2215, -2.2712, -2.3033, -2.3440, -2.3870, -2.4342, -2.4738, -2.5209, -2.5646, - -2.6016, -2.6385, -2.6868, -2.7356, -2.7723, -2.8111, -2.8524, -2.9009, -2.9428, -2.9879, - -3.0103, -3.0832, -3.1340, -3.1628, -3.2049, -3.2557, -3.3101, -3.3453, -3.4025, -3.4317, - -3.4828, -3.5270, -3.5745, -3.6181, -3.6765, -3.7044, -3.7410, -3.8118, -3.8368, -3.9549, - -3.9488, -3.9941, -4.0428, -4.0892, -4.1648, -4.1965, -4.1892, -4.2565, -4.3356, -4.3948, - -4.4481, -4.4607, -4.5533, -4.5809, -4.5927, -5.1047, - 0.9978, 0.9962, 0.9961, 0.9959, 0.9958, 0.9954, 0.9949, 0.9950, 0.9947, 0.9942, - 0.9940, 0.9939, 0.9933, 0.9931, 0.9928, 0.9924, 0.9921, 0.9916, 0.9911, 0.9909, - 0.9903, 0.9900, 0.9892, 0.9887, 0.9883, 0.9877, 0.9869, 0.9863, 0.9857, 0.9848, - 0.9842, 0.9835, 0.9825, 0.9817, 0.9808, 0.9799, 0.9791, 0.9777, 0.9767, 0.9757, - 0.9744, 0.9729, 0.9716, 0.9704, 0.9690, 0.9674, 0.9656, 0.9641, 0.9625, 0.9609, - 0.9587, 0.9567, 0.9548, 0.9524, 0.9501, 0.9478, 0.9453, 0.9426, 0.9398, 0.9371, - 0.9339, 0.9311, 0.9277, 0.9242, 0.9206, 0.9168, 0.9131, 0.9087, 0.9043, 0.8999, - 0.8953, 0.8907, 0.8857, 0.8803, 0.8747, 0.8690, 0.8632, 0.8572, 0.8507, 0.8439, - 0.8368, 0.8295, 0.8217, 0.8138, 0.8058, 0.7972, 0.7883, 0.7784, 0.7694, 0.7597, - 0.7489, 0.7378, 0.7269, 0.7152, 0.7030, 0.6911, 0.6782, 0.6643, 0.6506, 0.6371, - 0.6211, 0.6054, 0.5897, 0.5740, 0.5565, 0.5393, 0.5214, 0.5027, 0.4838, 0.4643, - 0.4436, 0.4225, 0.4004, 0.3787, 0.3562, 0.3324, 0.3089, 0.2839, 0.2584, 0.2321, - 0.2047, 0.1784, 0.1499, 0.1213, 0.0915, 0.0628, 0.0314, 0.0000, -0.0321, -0.0657, - -0.0977, -0.1324, -0.1673, -0.2036, -0.2387, -0.2768, -0.3150, -0.3538, -0.3936, -0.4327, - -0.4739, -0.5148, -0.5561, -0.6000, -0.6438, -0.6889, -0.7331, -0.7781, -0.8247, -0.8712, - -0.9177, -0.9677, -1.0142, -1.0631, -1.1143, -1.1686, -1.2169, -1.2680, -1.3223, -1.3752, - -1.4261, -1.4806, -1.5356, -1.5890, -1.6462, -1.7041, -1.7591, -1.8124, -1.8735, -1.9311, - -1.9891, -2.0459, -2.1048, -2.1653, -2.2248, -2.2855, -2.3466, -2.4079, -2.4668, -2.5263, - -2.5876, -2.6507, -2.7142, -2.7761, -2.8366, -2.8995, -2.9620, -3.0279, -3.0973, -3.1576, - -3.2238, -3.2890, -3.3554, -3.4215, -3.4805, -3.5518, -3.6133, -3.6812, -3.7473, -3.8140, - -3.8781, -3.9450, -4.0184, -4.0794, -4.1478, -4.2241, -4.2853, -4.3473, -4.4062, -4.4839, - -4.5539, -4.6202, -4.6794, -4.7478, -4.8309, -4.9048, -4.9669, -5.0294, -5.1194, -5.1732, - -5.2378, -5.3094, -5.3742, -5.4573, -5.5190, -5.5728, -5.6637, -5.7259, -5.7843, -5.8854, - -5.9553, -6.0054, -6.0656, -6.1707, -6.2241, -6.3139, -6.3393, -6.4356, -6.5153, -6.5758, - -6.6506, -6.7193, -6.7542, -6.8942, -6.9219, -6.9605, -7.1013, -7.1895, -7.1549, -7.2799, - -7.4119, -7.4608, -7.5256, -7.5879, -7.7598, -8.4120, - 0.9999, 0.9998, 0.9998, 0.9998, 0.9998, 0.9998, 0.9997, 0.9997, 0.9997, 0.9997, - 0.9997, 0.9996, 0.9996, 0.9996, 0.9995, 0.9995, 0.9994, 0.9994, 0.9994, 0.9993, - 0.9993, 0.9992, 0.9991, 0.9991, 0.9990, 0.9989, 0.9988, 0.9988, 0.9988, 0.9986, - 0.9985, 0.9984, 0.9983, 0.9982, 0.9980, 0.9979, 0.9977, 0.9976, 0.9974, 0.9971, - 0.9969, 0.9968, 0.9965, 0.9962, 0.9960, 0.9957, 0.9953, 0.9950, 0.9947, 0.9941, - 0.9937, 0.9933, 0.9928, 0.9922, 0.9917, 0.9911, 0.9904, 0.9897, 0.9890, 0.9882, - 0.9874, 0.9863, 0.9855, 0.9843, 0.9832, 0.9819, 0.9806, 0.9792, 0.9777, 0.9760, - 0.9743, 0.9724, 0.9704, 0.9683, 0.9659, 0.9634, 0.9609, 0.9581, 0.9550, 0.9516, - 0.9481, 0.9446, 0.9406, 0.9363, 0.9317, 0.9270, 0.9218, 0.9160, 0.9103, 0.9038, - 0.8972, 0.8898, 0.8822, 0.8739, 0.8647, 0.8554, 0.8457, 0.8357, 0.8231, 0.8115, - 0.7984, 0.7854, 0.7704, 0.7556, 0.7391, 0.7210, 0.7038, 0.6840, 0.6633, 0.6408, - 0.6174, 0.5939, 0.5678, 0.5410, 0.5137, 0.4836, 0.4524, 0.4193, 0.3850, 0.3482, - 0.3132, 0.2733, 0.2315, 0.1891, 0.1435, 0.0980, 0.0493, 0.0000, -0.0510, -0.1052, - -0.1593, -0.2177, -0.2759, -0.3374, -0.4005, -0.4599, -0.5266, -0.5935, -0.6626, -0.7328, - -0.8051, -0.8757, -0.9498, -1.0271, -1.1019, -1.1816, -1.2642, -1.3459, -1.4295, -1.5077, - -1.5958, -1.6818, -1.7647, -1.8548, -1.9387, -2.0295, -2.1152, -2.2154, -2.3011, -2.3904, - -2.4820, -2.5786, -2.6730, -2.7652, -2.8616, -2.9546, -3.0526, -3.1445, -3.2445, -3.3416, - -3.4357, -3.5325, -3.6324, -3.7313, -3.8225, -3.9209, -4.0248, -4.1278, -4.2261, -4.3193, - -4.4220, -4.5262, -4.6214, -4.7242, -4.8234, -4.9245, -5.0298, -5.1250, -5.2232, -5.3267, - -5.4332, -5.5342, -5.6431, -5.7270, -5.8401, -5.9350, -6.0407, -6.1418, -6.2363, -6.3384, - -6.4536, -6.5429, -6.6582, -6.7433, -6.8438, -6.9478, -7.0789, -7.1894, -7.2714, -7.3815, - -7.4810, -7.5575, -7.6852, -7.8071, -7.8580, -7.9724, -8.1000, -8.2207, -8.2867, -8.4017, - -8.5287, -8.6347, -8.7082, -8.8319, -8.9448, -9.0355, -9.1885, -9.2095, -9.2863, -9.4186, - -9.5064, -9.6386, -9.7207, -9.8286, -9.9453, -10.0701, -10.1735, -10.3001, -10.2858, -10.5427, - -10.5982, -10.7361, -10.7042, -10.9212, -11.0097, -11.0469, -11.1155, -11.2812, -11.3472, -11.4988, - -11.5327, -11.6692, -11.9376, -11.8606, -12.1372, -13.2539, - 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, - 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, - 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, - 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, - 0.9999, 0.9998, 0.9998, 0.9998, 0.9998, 0.9997, 0.9997, 0.9997, 0.9997, 0.9996, - 0.9996, 0.9995, 0.9995, 0.9994, 0.9994, 0.9993, 0.9992, 0.9991, 0.9991, 0.9989, - 0.9988, 0.9986, 0.9985, 0.9983, 0.9981, 0.9980, 0.9977, 0.9974, 0.9971, 0.9968, - 0.9965, 0.9962, 0.9956, 0.9950, 0.9948, 0.9941, 0.9933, 0.9926, 0.9919, 0.9910, - 0.9899, 0.9889, 0.9877, 0.9863, 0.9845, 0.9829, 0.9811, 0.9791, 0.9769, 0.9741, - 0.9716, 0.9684, 0.9645, 0.9611, 0.9563, 0.9519, 0.9463, 0.9406, 0.9344, 0.9272, - 0.9197, 0.9107, 0.9016, 0.8903, 0.8791, 0.8653, 0.8523, 0.8357, 0.8179, 0.7988, - 0.7779, 0.7562, 0.7318, 0.7024, 0.6753, 0.6435, 0.6089, 0.5700, 0.5296, 0.4860, - 0.4366, 0.3855, 0.3301, 0.2735, 0.2114, 0.1443, 0.0682, 0.0000, -0.0715, -0.1604, - -0.2478, -0.3377, -0.4287, -0.5277, -0.6291, -0.7384, -0.8457, -0.9559, -1.0742, -1.1913, - -1.3110, -1.4238, -1.5594, -1.6854, -1.8093, -1.9414, -2.0763, -2.2160, -2.3611, -2.4876, - -2.6374, -2.7710, -2.9225, -3.0591, -3.2077, -3.3452, -3.4916, -3.6316, -3.7735, -3.9296, - -4.0682, -4.2334, -4.3607, -4.5270, -4.6807, -4.8108, -4.9753, -5.1212, -5.2631, -5.4042, - -5.5510, -5.7227, -5.8794, -6.0244, -6.1677, -6.3271, -6.4862, -6.6130, -6.7449, -6.9250, - -7.1232, -7.1736, -7.3628, -7.5596, -7.6906, -7.8129, -7.9817, -8.1440, -8.3016, -8.4797, - -8.5734, -8.7692, -8.9198, -9.0610, -9.1746, -9.3536, -9.5939, -9.6957, -9.8475, -9.9639, - -10.1730, -10.2427, -10.4573, -10.5413, -10.7303, -10.9339, -11.0215, -11.2047, -11.2894, -11.4572, - -11.6256, -11.7794, -11.8801, -12.1717, -12.2354, -12.3686, -12.6195, -12.6527, -12.8247, -12.9560, - -13.3265, -13.1667, -13.4274, -13.6064, -13.5515, -13.9501, -13.9926, -14.4049, -14.1653, -14.4348, - -14.7983, -14.7807, -15.2349, -15.3536, -15.3026, -15.2739, -15.7170, -16.2161, -15.9185, -15.9490, - -16.6258, -16.5568, -16.4318, -16.7999, -16.4101, -17.6393, -17.7643, -17.2644, -17.5973, -17.0403, - -17.7039, -18.0073, -18.1840, -18.3848, -18.6286, -20.7063}; +//float symbol_scale[5]={42.6, 53.3, 72.7, 100.2, 125.4}; +float metric_tables[5][256]={ + {0.9782, 0.9695, 0.9689, 0.9669, 0.9666, 0.9653, 0.9638, 0.9618, 0.9599, 0.9601, + 0.9592, 0.9570, 0.9556, 0.9540, 0.9525, 0.9527, 0.9486, 0.9477, 0.9450, 0.9436, + 0.9424, 0.9400, 0.9381, 0.9360, 0.9340, 0.9316, 0.9301, 0.9272, 0.9254, 0.9224, + 0.9196, 0.9171, 0.9154, 0.9123, 0.9076, 0.9061, 0.9030, 0.9000, 0.8965, 0.8934, + 0.8903, 0.8874, 0.8834, 0.8792, 0.8760, 0.8726, 0.8685, 0.8639, 0.8599, 0.8550, + 0.8504, 0.8459, 0.8422, 0.8364, 0.8320, 0.8262, 0.8215, 0.8159, 0.8111, 0.8052, + 0.7996, 0.7932, 0.7878, 0.7812, 0.7745, 0.7685, 0.7616, 0.7550, 0.7479, 0.7405, + 0.7336, 0.7255, 0.7184, 0.7102, 0.7016, 0.6946, 0.6860, 0.6769, 0.6687, 0.6598, + 0.6503, 0.6416, 0.6325, 0.6219, 0.6122, 0.6016, 0.5920, 0.5818, 0.5711, 0.5606, + 0.5487, 0.5374, 0.5266, 0.5142, 0.5020, 0.4908, 0.4784, 0.4663, 0.4532, 0.4405, + 0.4271, 0.4144, 0.4006, 0.3865, 0.3731, 0.3594, 0.3455, 0.3304, 0.3158, 0.3009, + 0.2858, 0.2708, 0.2560, 0.2399, 0.2233, 0.2074, 0.1919, 0.1756, 0.1590, 0.1427, + 0.1251, 0.1074, 0.0905, 0.0722, 0.0550, 0.0381, 0.0183, 0.0000, -0.0185, -0.0391, + -0.0571, -0.0760, -0.0966, -0.1160, -0.1370, -0.1584, -0.1787, -0.1999, -0.2214, -0.2423, + -0.2643, -0.2879, -0.3114, -0.3336, -0.3568, -0.3806, -0.4050, -0.4293, -0.4552, -0.4798, + -0.5046, -0.5296, -0.5564, -0.5836, -0.6093, -0.6372, -0.6645, -0.6933, -0.7208, -0.7495, + -0.7763, -0.8065, -0.8378, -0.8660, -0.8964, -0.9293, -0.9592, -0.9907, -1.0214, -1.0509, + -1.0850, -1.1168, -1.1528, -1.1847, -1.2157, -1.2511, -1.2850, -1.3174, -1.3540, -1.3900, + -1.4201, -1.4580, -1.4956, -1.5292, -1.5683, -1.6030, -1.6411, -1.6789, -1.7147, -1.7539, + -1.7887, -1.8289, -1.8699, -1.9043, -1.9469, -1.9849, -2.0267, -2.0610, -2.1028, -2.1391, + -2.1855, -2.2215, -2.2712, -2.3033, -2.3440, -2.3870, -2.4342, -2.4738, -2.5209, -2.5646, + -2.6016, -2.6385, -2.6868, -2.7356, -2.7723, -2.8111, -2.8524, -2.9009, -2.9428, -2.9879, + -3.0103, -3.0832, -3.1340, -3.1628, -3.2049, -3.2557, -3.3101, -3.3453, -3.4025, -3.4317, + -3.4828, -3.5270, -3.5745, -3.6181, -3.6765, -3.7044, -3.7410, -3.8118, -3.8368, -3.9549, + -3.9488, -3.9941, -4.0428, -4.0892, -4.1648, -4.1965, -4.1892, -4.2565, -4.3356, -4.3948, + -4.4481, -4.4607, -4.5533, -4.5809, -4.5927, -5.1047}, + {0.9978, 0.9962, 0.9961, 0.9959, 0.9958, 0.9954, 0.9949, 0.9950, 0.9947, 0.9942, + 0.9940, 0.9939, 0.9933, 0.9931, 0.9928, 0.9924, 0.9921, 0.9916, 0.9911, 0.9909, + 0.9903, 0.9900, 0.9892, 0.9887, 0.9883, 0.9877, 0.9869, 0.9863, 0.9857, 0.9848, + 0.9842, 0.9835, 0.9825, 0.9817, 0.9808, 0.9799, 0.9791, 0.9777, 0.9767, 0.9757, + 0.9744, 0.9729, 0.9716, 0.9704, 0.9690, 0.9674, 0.9656, 0.9641, 0.9625, 0.9609, + 0.9587, 0.9567, 0.9548, 0.9524, 0.9501, 0.9478, 0.9453, 0.9426, 0.9398, 0.9371, + 0.9339, 0.9311, 0.9277, 0.9242, 0.9206, 0.9168, 0.9131, 0.9087, 0.9043, 0.8999, + 0.8953, 0.8907, 0.8857, 0.8803, 0.8747, 0.8690, 0.8632, 0.8572, 0.8507, 0.8439, + 0.8368, 0.8295, 0.8217, 0.8138, 0.8058, 0.7972, 0.7883, 0.7784, 0.7694, 0.7597, + 0.7489, 0.7378, 0.7269, 0.7152, 0.7030, 0.6911, 0.6782, 0.6643, 0.6506, 0.6371, + 0.6211, 0.6054, 0.5897, 0.5740, 0.5565, 0.5393, 0.5214, 0.5027, 0.4838, 0.4643, + 0.4436, 0.4225, 0.4004, 0.3787, 0.3562, 0.3324, 0.3089, 0.2839, 0.2584, 0.2321, + 0.2047, 0.1784, 0.1499, 0.1213, 0.0915, 0.0628, 0.0314, 0.0000, -0.0321, -0.0657, + -0.0977, -0.1324, -0.1673, -0.2036, -0.2387, -0.2768, -0.3150, -0.3538, -0.3936, -0.4327, + -0.4739, -0.5148, -0.5561, -0.6000, -0.6438, -0.6889, -0.7331, -0.7781, -0.8247, -0.8712, + -0.9177, -0.9677, -1.0142, -1.0631, -1.1143, -1.1686, -1.2169, -1.2680, -1.3223, -1.3752, + -1.4261, -1.4806, -1.5356, -1.5890, -1.6462, -1.7041, -1.7591, -1.8124, -1.8735, -1.9311, + -1.9891, -2.0459, -2.1048, -2.1653, -2.2248, -2.2855, -2.3466, -2.4079, -2.4668, -2.5263, + -2.5876, -2.6507, -2.7142, -2.7761, -2.8366, -2.8995, -2.9620, -3.0279, -3.0973, -3.1576, + -3.2238, -3.2890, -3.3554, -3.4215, -3.4805, -3.5518, -3.6133, -3.6812, -3.7473, -3.8140, + -3.8781, -3.9450, -4.0184, -4.0794, -4.1478, -4.2241, -4.2853, -4.3473, -4.4062, -4.4839, + -4.5539, -4.6202, -4.6794, -4.7478, -4.8309, -4.9048, -4.9669, -5.0294, -5.1194, -5.1732, + -5.2378, -5.3094, -5.3742, -5.4573, -5.5190, -5.5728, -5.6637, -5.7259, -5.7843, -5.8854, + -5.9553, -6.0054, -6.0656, -6.1707, -6.2241, -6.3139, -6.3393, -6.4356, -6.5153, -6.5758, + -6.6506, -6.7193, -6.7542, -6.8942, -6.9219, -6.9605, -7.1013, -7.1895, -7.1549, -7.2799, + -7.4119, -7.4608, -7.5256, -7.5879, -7.7598, -8.4120}, + {0.9999, 0.9998, 0.9998, 0.9998, 0.9998, 0.9998, 0.9997, 0.9997, 0.9997, 0.9997, + 0.9997, 0.9996, 0.9996, 0.9996, 0.9995, 0.9995, 0.9994, 0.9994, 0.9994, 0.9993, + 0.9993, 0.9992, 0.9991, 0.9991, 0.9990, 0.9989, 0.9988, 0.9988, 0.9988, 0.9986, + 0.9985, 0.9984, 0.9983, 0.9982, 0.9980, 0.9979, 0.9977, 0.9976, 0.9974, 0.9971, + 0.9969, 0.9968, 0.9965, 0.9962, 0.9960, 0.9957, 0.9953, 0.9950, 0.9947, 0.9941, + 0.9937, 0.9933, 0.9928, 0.9922, 0.9917, 0.9911, 0.9904, 0.9897, 0.9890, 0.9882, + 0.9874, 0.9863, 0.9855, 0.9843, 0.9832, 0.9819, 0.9806, 0.9792, 0.9777, 0.9760, + 0.9743, 0.9724, 0.9704, 0.9683, 0.9659, 0.9634, 0.9609, 0.9581, 0.9550, 0.9516, + 0.9481, 0.9446, 0.9406, 0.9363, 0.9317, 0.9270, 0.9218, 0.9160, 0.9103, 0.9038, + 0.8972, 0.8898, 0.8822, 0.8739, 0.8647, 0.8554, 0.8457, 0.8357, 0.8231, 0.8115, + 0.7984, 0.7854, 0.7704, 0.7556, 0.7391, 0.7210, 0.7038, 0.6840, 0.6633, 0.6408, + 0.6174, 0.5939, 0.5678, 0.5410, 0.5137, 0.4836, 0.4524, 0.4193, 0.3850, 0.3482, + 0.3132, 0.2733, 0.2315, 0.1891, 0.1435, 0.0980, 0.0493, 0.0000, -0.0510, -0.1052, + -0.1593, -0.2177, -0.2759, -0.3374, -0.4005, -0.4599, -0.5266, -0.5935, -0.6626, -0.7328, + -0.8051, -0.8757, -0.9498, -1.0271, -1.1019, -1.1816, -1.2642, -1.3459, -1.4295, -1.5077, + -1.5958, -1.6818, -1.7647, -1.8548, -1.9387, -2.0295, -2.1152, -2.2154, -2.3011, -2.3904, + -2.4820, -2.5786, -2.6730, -2.7652, -2.8616, -2.9546, -3.0526, -3.1445, -3.2445, -3.3416, + -3.4357, -3.5325, -3.6324, -3.7313, -3.8225, -3.9209, -4.0248, -4.1278, -4.2261, -4.3193, + -4.4220, -4.5262, -4.6214, -4.7242, -4.8234, -4.9245, -5.0298, -5.1250, -5.2232, -5.3267, + -5.4332, -5.5342, -5.6431, -5.7270, -5.8401, -5.9350, -6.0407, -6.1418, -6.2363, -6.3384, + -6.4536, -6.5429, -6.6582, -6.7433, -6.8438, -6.9478, -7.0789, -7.1894, -7.2714, -7.3815, + -7.4810, -7.5575, -7.6852, -7.8071, -7.8580, -7.9724, -8.1000, -8.2207, -8.2867, -8.4017, + -8.5287, -8.6347, -8.7082, -8.8319, -8.9448, -9.0355, -9.1885, -9.2095, -9.2863, -9.4186, + -9.5064, -9.6386, -9.7207, -9.8286, -9.9453, -10.0701, -10.1735, -10.3001, -10.2858, -10.5427, + -10.5982, -10.7361, -10.7042, -10.9212, -11.0097, -11.0469, -11.1155, -11.2812, -11.3472, -11.4988, + -11.5327, -11.6692, -11.9376, -11.8606, -12.1372, -13.2539}, + {1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, + 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, + 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, + 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, + 0.9999, 0.9998, 0.9998, 0.9998, 0.9998, 0.9997, 0.9997, 0.9997, 0.9997, 0.9996, + 0.9996, 0.9995, 0.9995, 0.9994, 0.9994, 0.9993, 0.9992, 0.9991, 0.9991, 0.9989, + 0.9988, 0.9986, 0.9985, 0.9983, 0.9981, 0.9980, 0.9977, 0.9974, 0.9971, 0.9968, + 0.9965, 0.9962, 0.9956, 0.9950, 0.9948, 0.9941, 0.9933, 0.9926, 0.9919, 0.9910, + 0.9899, 0.9889, 0.9877, 0.9863, 0.9845, 0.9829, 0.9811, 0.9791, 0.9769, 0.9741, + 0.9716, 0.9684, 0.9645, 0.9611, 0.9563, 0.9519, 0.9463, 0.9406, 0.9344, 0.9272, + 0.9197, 0.9107, 0.9016, 0.8903, 0.8791, 0.8653, 0.8523, 0.8357, 0.8179, 0.7988, + 0.7779, 0.7562, 0.7318, 0.7024, 0.6753, 0.6435, 0.6089, 0.5700, 0.5296, 0.4860, + 0.4366, 0.3855, 0.3301, 0.2735, 0.2114, 0.1443, 0.0682, 0.0000, -0.0715, -0.1604, + -0.2478, -0.3377, -0.4287, -0.5277, -0.6291, -0.7384, -0.8457, -0.9559, -1.0742, -1.1913, + -1.3110, -1.4238, -1.5594, -1.6854, -1.8093, -1.9414, -2.0763, -2.2160, -2.3611, -2.4876, + -2.6374, -2.7710, -2.9225, -3.0591, -3.2077, -3.3452, -3.4916, -3.6316, -3.7735, -3.9296, + -4.0682, -4.2334, -4.3607, -4.5270, -4.6807, -4.8108, -4.9753, -5.1212, -5.2631, -5.4042, + -5.5510, -5.7227, -5.8794, -6.0244, -6.1677, -6.3271, -6.4862, -6.6130, -6.7449, -6.9250, + -7.1232, -7.1736, -7.3628, -7.5596, -7.6906, -7.8129, -7.9817, -8.1440, -8.3016, -8.4797, + -8.5734, -8.7692, -8.9198, -9.0610, -9.1746, -9.3536, -9.5939, -9.6957, -9.8475, -9.9639, + -10.1730, -10.2427, -10.4573, -10.5413, -10.7303, -10.9339, -11.0215, -11.2047, -11.2894, -11.4572, + -11.6256, -11.7794, -11.8801, -12.1717, -12.2354, -12.3686, -12.6195, -12.6527, -12.8247, -12.9560, + -13.3265, -13.1667, -13.4274, -13.6064, -13.5515, -13.9501, -13.9926, -14.4049, -14.1653, -14.4348, + -14.7983, -14.7807, -15.2349, -15.3536, -15.3026, -15.2739, -15.7170, -16.2161, -15.9185, -15.9490, + -16.6258, -16.5568, -16.4318, -16.7999, -16.4101, -17.6393, -17.7643, -17.2644, -17.5973, -17.0403, + -17.7039, -18.0073, -18.1840, -18.3848, -18.6286, -20.7063}, + {1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, + 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, + 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, + 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, + 0.9999, 0.9998, 0.9998, 0.9998, 0.9998, 0.9997, 0.9997, 0.9997, 0.9997, 0.9996, + 0.9996, 0.9995, 0.9995, 0.9994, 0.9994, 0.9993, 0.9992, 0.9991, 0.9991, 0.9989, + 0.9988, 0.9986, 0.9985, 0.9983, 0.9981, 0.9980, 0.9977, 0.9974, 0.9971, 0.9968, + 0.9965, 0.9962, 0.9956, 0.9950, 0.9948, 0.9941, 0.9933, 0.9926, 0.9919, 0.9910, + 0.9899, 0.9889, 0.9877, 0.9863, 0.9845, 0.9829, 0.9811, 0.9791, 0.9769, 0.9741, + 0.9716, 0.9684, 0.9645, 0.9611, 0.9563, 0.9519, 0.9463, 0.9406, 0.9344, 0.9272, + 0.9197, 0.9107, 0.9016, 0.8903, 0.8791, 0.8653, 0.8523, 0.8357, 0.8179, 0.7988, + 0.7779, 0.7562, 0.7318, 0.7024, 0.6753, 0.6435, 0.6089, 0.5700, 0.5296, 0.4860, + 0.4366, 0.3855, 0.3301, 0.2735, 0.2114, 0.1443, 0.0682, 0.0000, -0.0715, -0.1604, + -0.2478, -0.3377, -0.4287, -0.5277, -0.6291, -0.7384, -0.8457, -0.9559, -1.0742, -1.1913, + -1.3110, -1.4238, -1.5594, -1.6854, -1.8093, -1.9414, -2.0763, -2.2160, -2.3611, -2.4876, + -2.6374, -2.7710, -2.9225, -3.0591, -3.2077, -3.3452, -3.4916, -3.6316, -3.7735, -3.9296, + -4.0682, -4.2334, -4.3607, -4.5270, -4.6807, -4.8108, -4.9753, -5.1212, -5.2631, -5.4042, + -5.5510, -5.7227, -5.8794, -6.0244, -6.1677, -6.3271, -6.4862, -6.6130, -6.7449, -6.9250, + -7.1232, -7.1736, -7.3628, -7.5596, -7.6906, -7.8129, -7.9817, -8.1440, -8.3016, -8.4797, + -8.5734, -8.7692, -8.9198, -9.0610, -9.1746, -9.3536, -9.5939, -9.6957, -9.8475, -9.9639, + -10.1730, -10.2427, -10.4573, -11.7794, -11.8801, -12.1717, -12.2354, -12.3686, -12.6195, -12.6527, + -12.8247, -12.9560, -13.3265, -13.1667, -13.4274, -13.6064, -13.5515, -13.9501, -13.9926, -14.4049, + -14.1653, -14.4348, -14.7983, -14.7807, -15.2349, -15.3536, -15.3026, -15.2739, -15.7170, -16.2161, + -15.9185, -15.9490, -16.6258, -16.5568, -16.4318, -16.7999, -16.4101, -17.6393, -17.7643, -17.2644, + -17.5973, -17.0403, -17.7039, -18.0073, -18.1840, -18.3848, -18.6286, -20.7063, 1.43370769e-019, + 2.64031087e-006, 6.6908396e+031, 1.77537994e+028, 2.79322819e+020, 1.94326e-019, + 0.00019371575, 2.80722121e-041}}; #pragma GCC diagnostic pop \ No newline at end of file diff --git a/wsprd/nhash.c b/wsprd/nhash.c index 18125fa..b5f8677 100644 --- a/wsprd/nhash.c +++ b/wsprd/nhash.c @@ -449,10 +449,3 @@ uint32_t nhash(const void *key, size_t length, uint32_t initval) { return c; } - -/* - * Fortran argument compatible wrapper - */ -uint32_t nhash_(const void *key, size_t const *length, uint32_t const *initval) { - return nhash(key, *length, *initval); -} diff --git a/wsprd/nhash.h b/wsprd/nhash.h index a5bab49..cbe8b41 100644 --- a/wsprd/nhash.h +++ b/wsprd/nhash.h @@ -1,4 +1,3 @@ #pragma once uint32_t nhash(const void* key, size_t length, uint32_t initval); -uint32_t nhash_(void const* key, size_t const* length, uint32_t const* initval); diff --git a/wsprd/wsprd.c b/wsprd/wsprd.c index d509741..f4ea1b5 100644 --- a/wsprd/wsprd.c +++ b/wsprd/wsprd.c @@ -44,22 +44,26 @@ #include "./wsprsim_utils.h" #include "./metric_tables.h" -#define DF 375.0 / 256.0 -#define DT 1.0 / 375.0 -#define TWOPIDT 2.0 * M_PI * DT -#define NIQ 45000 -#define NBITS 81 -#define NSYM 162 -#define NSPERSYM 256 -#define NFILT 256 -#define NSIG NSYM * NSPERSYM +#define SIGNAL_LENGHT 120 +#define SIGNAL_SAMPLE_RATE 375 +#define SIGNAL_SAMPLES SIGNAL_LENGHT * SIGNAL_SAMPLE_RATE +#define NBITS 81 +#define NSYM 162 +#define NSPERSYM 256 +#define DF 375.0 / 256.0 +#define DT 1.0 / 375.0 +#define DF05 DF * 0.5 +#define DF15 DF * 1.5 +#define TWOPIDT 2.0 * M_PI * DT + +#define NFILT 256 +#define NSIG NSYM * NSPERSYM + /* Possible PATIENCE options: FFTW_ESTIMATE, FFTW_ESTIMATE_PATIENT, FFTW_MEASURE, FFTW_PATIENT, FFTW_EXHAUSTIVE */ #define PATIENCE FFTW_ESTIMATE -fftwf_plan PLAN1, - PLAN2, - PLAN3; +fftwf_plan PLAN; int32_t printdata = 0; uint8_t pr3vector[NSYM] = { @@ -73,82 +77,83 @@ uint8_t pr3vector[NSYM] = { 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0}; -/*********************************************************************** - * mode = 0: no frequency or drift search. find best time lag. * - * 1: no time lag or drift search. find best frequency. * - * 2: no frequency or time lag search. calculate soft-decision * - * symbols using passed frequency and shift. * - ************************************************************************/ + +//*************************************************************************** void sync_and_demodulate(float *id, float *qd, long np, - uint8_t *symbols, float *freq1, float fstep, - int32_t *shift1, int32_t lagmin, int32_t lagmax, int32_t lagstep, - float *drift1, int32_t symfac, float *sync, int32_t mode) { - float fbest = 0.0; - float f0 = 0.0, fp, ss; - int32_t lag; + unsigned char *symbols, float *f1, int ifmin, int ifmax, float fstep, + int *shift1, int lagmin, int lagmax, int lagstep, + float *drift1, int symfac, float *sync, int mode) { + /*********************************************************************** + * mode = 0: no frequency or drift search. find best time lag. * + * 1: no time lag or drift search. find best frequency. * + * 2: no frequency or time lag search. calculate soft-decision * + * symbols using passed frequency and shift. * + ************************************************************************/ + static float fplast = -10000.0; - float i0[NSYM], q0[NSYM], - i1[NSYM], q1[NSYM], - i2[NSYM], q2[NSYM], + float f0 = 0.0, fp, ss, + fbest = 0.0, + fsum = 0.0, + f2sum = 0.0, + fsymb[NSYM]; + int best_shift = 0; + float i0[NSYM], q0[NSYM], + i1[NSYM], q1[NSYM], + i2[NSYM], q2[NSYM], i3[NSYM], q3[NSYM]; float p0, p1, p2, p3, cmet, totp, syncmax, fac; - float c0[NSPERSYM], s0[NSPERSYM], - c1[NSPERSYM], s1[NSPERSYM], - c2[NSPERSYM], s2[NSPERSYM], + float c0[NSPERSYM], s0[NSPERSYM], + c1[NSPERSYM], s1[NSPERSYM], + c2[NSPERSYM], s2[NSPERSYM], c3[NSPERSYM], s3[NSPERSYM]; - float dphi0, cdphi0, sdphi0, - dphi1, cdphi1, sdphi1, + float dphi0, cdphi0, sdphi0, + dphi1, cdphi1, sdphi1, dphi2, cdphi2, sdphi2, dphi3, cdphi3, sdphi3; - float fsum = 0.0, f2sum = 0.0, fsymb[NSYM]; - int32_t best_shift = 0; - int32_t ifmin = 0, ifmax = 0; syncmax = -1e30; if (mode == 0) { ifmin = 0; ifmax = 0; fstep = 0.0; - f0 = *freq1; + f0 = *f1; } if (mode == 1) { lagmin = *shift1; lagmax = *shift1; - ifmin = -5; - ifmax = 5; - f0 = *freq1; + f0 = *f1; } if (mode == 2) { lagmin = *shift1; lagmax = *shift1; ifmin = 0; ifmax = 0; - f0 = *freq1; + f0 = *f1; } - for (int32_t ifreq = ifmin; ifreq <= ifmax; ifreq++) { - f0 = *freq1 + ifreq * fstep; - for (lag = lagmin; lag <= lagmax; lag = lag + lagstep) { + for (int ifreq = ifmin; ifreq <= ifmax; ifreq++) { + f0 = *f1 + ifreq * fstep; + for (int lag = lagmin; lag <= lagmax; lag = lag + lagstep) { ss = 0.0; totp = 0.0; - for (int32_t i = 0; i < NSYM; i++) { - fp = f0 + ((float)*drift1 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; + for (int i = 0; i < NSYM; i++) { + fp = f0 + (*drift1 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; if (i == 0 || (fp != fplast)) { // only calculate sin/cos if necessary - dphi0 = TWOPIDT * (fp - 1.5 * DF); - cdphi0 = cosf(dphi0); - sdphi0 = sinf(dphi0); + dphi0 = TWOPIDT * (fp - DF15); + cdphi0 = cos(dphi0); + sdphi0 = sin(dphi0); - dphi1 = TWOPIDT * (fp - 0.5 * DF); - cdphi1 = cosf(dphi1); - sdphi1 = sinf(dphi1); + dphi1 = TWOPIDT * (fp - DF05); + cdphi1 = cos(dphi1); + sdphi1 = sin(dphi1); - dphi2 = TWOPIDT * (fp + 0.5 * DF); - cdphi2 = cosf(dphi2); - sdphi2 = sinf(dphi2); + dphi2 = TWOPIDT * (fp + DF05); + cdphi2 = cos(dphi2); + sdphi2 = sin(dphi2); - dphi3 = TWOPIDT * (fp + 1.5 * DF); - cdphi3 = cosf(dphi3); - sdphi3 = sinf(dphi3); + dphi3 = TWOPIDT * (fp + DF15); + cdphi3 = cos(dphi3); + sdphi3 = sin(dphi3); c0[0] = 1; s0[0] = 0; @@ -159,7 +164,7 @@ void sync_and_demodulate(float *id, float *qd, long np, c3[0] = 1; s3[0] = 0; - for (int32_t j = 1; j < NSPERSYM; j++) { + for (int j = 1; j < NSPERSYM; j++) { c0[j] = c0[j - 1] * cdphi0 - s0[j - 1] * sdphi0; s0[j] = c0[j - 1] * sdphi0 + s0[j - 1] * cdphi0; c1[j] = c1[j - 1] * cdphi1 - s1[j - 1] * sdphi1; @@ -181,9 +186,9 @@ void sync_and_demodulate(float *id, float *qd, long np, i3[i] = 0.0; q3[i] = 0.0; - for (int32_t j = 0; j < NSPERSYM; j++) { - int32_t k = lag + i * NSPERSYM + j; - if ((k > 0) & (k < np)) { + for (int j = 0; j < NSPERSYM; j++) { + int k = lag + i * NSPERSYM + j; + if ((k > 0) && (k < np)) { i0[i] = i0[i] + id[k] * c0[j] + qd[k] * s0[j]; q0[i] = q0[i] - id[k] * s0[j] + qd[k] * c0[j]; i1[i] = i1[i] + id[k] * c1[j] + qd[k] * s1[j]; @@ -199,25 +204,25 @@ void sync_and_demodulate(float *id, float *qd, long np, p2 = i2[i] * i2[i] + q2[i] * q2[i]; p3 = i3[i] * i3[i] + q3[i] * q3[i]; - p0 = sqrtf(p0); - p1 = sqrtf(p1); - p2 = sqrtf(p2); - p3 = sqrtf(p3); + p0 = sqrt(p0); + p1 = sqrt(p1); + p2 = sqrt(p2); + p3 = sqrt(p3); totp = totp + p0 + p1 + p2 + p3; cmet = (p1 + p3) - (p0 + p2); - ss = ss + cmet * (2 * pr3vector[i] - 1); + ss = (pr3vector[i] == 1) ? ss + cmet : ss - cmet; if (mode == 2) { // Compute soft symbols - if (pr3vector[i]) { + if (pr3vector[i] == 1) { fsymb[i] = p3 - p1; } else { fsymb[i] = p2 - p0; } } } - - if (ss / totp > syncmax) { // Save best parameters - syncmax = ss / totp; + ss = ss / totp; + if (ss > syncmax) { // Save best parameters + syncmax = ss; best_shift = lag; fbest = f0; } @@ -227,18 +232,18 @@ void sync_and_demodulate(float *id, float *qd, long np, if (mode <= 1) { // Send best params back to caller *sync = syncmax; *shift1 = best_shift; - *freq1 = fbest; + *f1 = fbest; return; } if (mode == 2) { *sync = syncmax; - for (int32_t i = 0; i < NSYM; i++) { // Normalize the soft symbols - fsum = fsum + fsymb[i] / (float)NSYM; - f2sum = f2sum + fsymb[i] * fsymb[i] / (float)NSYM; + for (int i = 0; i < NSYM; i++) { // Normalize the soft symbols + fsum = fsum + fsymb[i] / NSYM; + f2sum = f2sum + fsymb[i] * fsymb[i] / NSYM; } - fac = sqrtf(f2sum - fsum * fsum); - for (int32_t i = 0; i < NSYM; i++) { + fac = sqrt(f2sum - fsum * fsum); + for (int i = 0; i < NSYM; i++) { fsymb[i] = symfac * fsymb[i] / fac; if (fsymb[i] > 127) fsymb[i] = 127.0; if (fsymb[i] < -128) fsymb[i] = -128.0; @@ -249,35 +254,196 @@ void sync_and_demodulate(float *id, float *qd, long np, return; } +void noncoherent_sequence_detection(float *id, float *qd, long np, + unsigned char *symbols, float *f1, int *shift1, + float *drift1, int symfac, int *nblocksize, int *bitmetric) { + /************************************************************************ + * Noncoherent sequence detection for wspr. * + * Allowed block lengths are nblock=1,2,3,6, or 9 symbols. * + * Longer block lengths require longer channel coherence time. * + * The whole block is estimated at once. * + * nblock=1 corresponds to noncoherent detection of individual symbols * + * like the original wsprd symbol demodulator. * + ************************************************************************/ + static float fplast = -10000.0; + + int i, j, k, lag, itone, ib, b, nblock, nseq, imask; + float xi[512], xq[512]; + float is[4][NSYM], qs[4][NSYM], + cf[4][NSYM], sf[4][NSYM], + cm, sm, cmp, smp; + float p[512], fac, xm1, xm0; + float c0[NSPERSYM+1], s0[NSPERSYM+1], + c1[NSPERSYM+1], s1[NSPERSYM+1], + c2[NSPERSYM+1], s2[NSPERSYM+1], + c3[NSPERSYM+1], s3[NSPERSYM+1]; + float dphi0, cdphi0, sdphi0, + dphi1, cdphi1, sdphi1, + dphi2, cdphi2, sdphi2, + dphi3, cdphi3, sdphi3; + float f0, fp, fsum = 0.0, f2sum = 0.0, fsymb[NSYM]; + + f0 = *f1; + lag = *shift1; + nblock = *nblocksize; + nseq = 1 << nblock; + int bitbybit = *bitmetric; + + for (i = 0; i < NSYM; i++) { + fp = f0 + (*drift1 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; + if (i == 0 || (fp != fplast)) { // only calculate sin/cos if necessary + dphi0 = TWOPIDT * (fp - DF15); + cdphi0 = cos(dphi0); + sdphi0 = sin(dphi0); + + dphi1 = TWOPIDT * (fp - DF05); + cdphi1 = cos(dphi1); + sdphi1 = sin(dphi1); + + dphi2 = TWOPIDT * (fp + DF05); + cdphi2 = cos(dphi2); + sdphi2 = sin(dphi2); + + dphi3 = TWOPIDT * (fp + DF15); + cdphi3 = cos(dphi3); + sdphi3 = sin(dphi3); + + c0[0] = 1; + s0[0] = 0; + c1[0] = 1; + s1[0] = 0; + c2[0] = 1; + s2[0] = 0; + c3[0] = 1; + s3[0] = 0; + + for (j = 1; j < (NSPERSYM+1); j++) { + c0[j] = c0[j - 1] * cdphi0 - s0[j - 1] * sdphi0; + s0[j] = c0[j - 1] * sdphi0 + s0[j - 1] * cdphi0; + c1[j] = c1[j - 1] * cdphi1 - s1[j - 1] * sdphi1; + s1[j] = c1[j - 1] * sdphi1 + s1[j - 1] * cdphi1; + c2[j] = c2[j - 1] * cdphi2 - s2[j - 1] * sdphi2; + s2[j] = c2[j - 1] * sdphi2 + s2[j - 1] * cdphi2; + c3[j] = c3[j - 1] * cdphi3 - s3[j - 1] * sdphi3; + s3[j] = c3[j - 1] * sdphi3 + s3[j - 1] * cdphi3; + } + + fplast = fp; + } + + cf[0][i] = c0[NSPERSYM]; + sf[0][i] = s0[NSPERSYM]; + cf[1][i] = c1[NSPERSYM]; + sf[1][i] = s1[NSPERSYM]; + cf[2][i] = c2[NSPERSYM]; + sf[2][i] = s2[NSPERSYM]; + cf[3][i] = c3[NSPERSYM]; + sf[3][i] = s3[NSPERSYM]; + + is[0][i] = 0.0; + qs[0][i] = 0.0; + is[1][i] = 0.0; + qs[1][i] = 0.0; + is[2][i] = 0.0; + qs[2][i] = 0.0; + is[3][i] = 0.0; + qs[3][i] = 0.0; + + for (j = 0; j < NSPERSYM; j++) { + k = lag + i * NSPERSYM + j; + if ((k > 0) && (k < np)) { + is[0][i] = is[0][i] + id[k] * c0[j] + qd[k] * s0[j]; + qs[0][i] = qs[0][i] - id[k] * s0[j] + qd[k] * c0[j]; + is[1][i] = is[1][i] + id[k] * c1[j] + qd[k] * s1[j]; + qs[1][i] = qs[1][i] - id[k] * s1[j] + qd[k] * c1[j]; + is[2][i] = is[2][i] + id[k] * c2[j] + qd[k] * s2[j]; + qs[2][i] = qs[2][i] - id[k] * s2[j] + qd[k] * c2[j]; + is[3][i] = is[3][i] + id[k] * c3[j] + qd[k] * s3[j]; + qs[3][i] = qs[3][i] - id[k] * s3[j] + qd[k] * c3[j]; + } + } + } + + for (i = 0; i < NSYM; i = i + nblock) { + for (j = 0; j < nseq; j++) { + xi[j] = 0.0; + xq[j] = 0.0; + cm = 1; + sm = 0; + for (ib = 0; ib < nblock; ib++) { + b = (j & (1 << (nblock - 1 - ib))) >> (nblock - 1 - ib); + itone = pr3vector[i + ib] + 2 * b; + xi[j] = xi[j] + is[itone][i + ib] * cm + qs[itone][i + ib] * sm; + xq[j] = xq[j] + qs[itone][i + ib] * cm - is[itone][i + ib] * sm; + cmp = cf[itone][i + ib] * cm - sf[itone][i + ib] * sm; + smp = sf[itone][i + ib] * cm + cf[itone][i + ib] * sm; + cm = cmp; + sm = smp; + } + p[j] = xi[j] * xi[j] + xq[j] * xq[j]; + p[j] = sqrt(p[j]); + } + for (ib = 0; ib < nblock; ib++) { + imask = 1 << (nblock - 1 - ib); + xm1 = 0.0; + xm0 = 0.0; + for (j = 0; j < nseq; j++) { + if ((j & imask) != 0) { + if (p[j] > xm1) xm1 = p[j]; + } + if ((j & imask) == 0) { + if (p[j] > xm0) xm0 = p[j]; + } + } + fsymb[i + ib] = xm1 - xm0; + if (bitbybit == 1) { + fsymb[i + ib] = fsymb[i + ib] / (xm1 > xm0 ? xm1 : xm0); + } + } + } + for (i = 0; i < NSYM; i++) { // Normalize the soft symbols + fsum = fsum + fsymb[i] / NSYM; + f2sum = f2sum + fsymb[i] * fsymb[i] / NSYM; + } + fac = sqrt(f2sum - fsum * fsum); + for (i = 0; i < NSYM; i++) { + fsymb[i] = symfac * fsymb[i] / fac; + if (fsymb[i] > 127) fsymb[i] = 127.0; + if (fsymb[i] < -128) fsymb[i] = -128.0; + symbols[i] = fsymb[i] + 128; + } + return; +} + /*************************************************************************** symbol-by-symbol signal subtraction ****************************************************************************/ void subtract_signal(float *id, float *qd, long np, - float f0, int32_t shift0, float drift0, uint8_t *channel_symbols) { - float i0, q0; + float f0, int shift0, float drift0, unsigned char *channel_symbols) { + float c0[NSPERSYM], s0[NSPERSYM]; float dphi, cdphi, sdphi; - for (int32_t i = 0; i < NSYM; i++) { + for (int i = 0; i < NSYM; i++) { float fp = f0 + ((float)drift0 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; - dphi = TWOPIDT * (fp + ((float)channel_symbols[i] - 1.5) * DF); - cdphi = cosf(dphi); - sdphi = sinf(dphi); + dphi = TWOPIDT * (fp + ((float)channel_symbols[i] - 1.5) * DF); + cdphi = cos(dphi); + sdphi = sin(dphi); c0[0] = 1; s0[0] = 0; - for (int32_t j = 1; j < NSPERSYM; j++) { + for (int j = 1; j < NSPERSYM; j++) { c0[j] = c0[j - 1] * cdphi - s0[j - 1] * sdphi; s0[j] = c0[j - 1] * sdphi + s0[j - 1] * cdphi; } - i0 = 0.0; - q0 = 0.0; + float i0 = 0.0; + float q0 = 0.0; - for (int32_t j = 0; j < NSPERSYM; j++) { - int32_t k = shift0 + i * NSPERSYM + j; + for (int j = 0; j < NSPERSYM; j++) { + int k = shift0 + i * NSPERSYM + j; if ((k > 0) & (k < np)) { i0 = i0 + id[k] * c0[j] + qd[k] * s0[j]; q0 = q0 - id[k] * s0[j] + qd[k] * c0[j]; @@ -285,11 +451,12 @@ void subtract_signal(float *id, float *qd, long np, } // subtract the signal here. + i0 = i0 / (float)NSPERSYM; // will be wrong for partial symbols at the edges... q0 = q0 / (float)NSPERSYM; - for (int32_t j = 0; j < NSPERSYM; j++) { - int32_t k = shift0 + i * NSPERSYM + j; + for (int j = 0; j < NSPERSYM; j++) { + int k = shift0 + i * NSPERSYM + j; if ((k > 0) & (k < np)) { id[k] = id[k] - (i0 * c0[j] - q0 * s0[j]); qd[k] = qd[k] - (q0 * c0[j] + i0 * s0[j]); @@ -299,15 +466,24 @@ void subtract_signal(float *id, float *qd, long np, return; } + /****************************************************************************** - Fully coherent signal subtraction + Subtract the coherent component of a signal *******************************************************************************/ -void subtract_signal2(float *id, float *qd, long np, - float f0, int32_t shift0, float drift0, uint8_t *channel_symbols) { - float phi = 0, dphi, cs; - float refi[NIQ] = {0}, refq[NIQ] = {0}, - ci[NIQ] = {0}, cq[NIQ] = {0}, - cfi[NIQ] = {0}, cfq[NIQ] = {0}; +void subtract_signal2(float *id, + float *qd, + long np, + float f0, + int shift0, + float drift0, + unsigned char *channel_symbols) { + + float phi = 0; + const int nfilt = 360; // nfilt must be even number. + + float refi[SIGNAL_SAMPLES] = {0}, refq[SIGNAL_SAMPLES] = {0}, + ci[SIGNAL_SAMPLES] = {0}, cq[SIGNAL_SAMPLES] = {0}, + cfi[SIGNAL_SAMPLES] = {0}, cfq[SIGNAL_SAMPLES] = {0}; /****************************************************************************** Measured signal: s(t)=a(t)*exp( j*theta(t) ) @@ -319,72 +495,74 @@ void subtract_signal2(float *id, float *qd, long np, // create reference wspr signal vector, centered on f0. // - for (int32_t i = 0; i < NSYM; i++) { - cs = (float)channel_symbols[i]; + for (int i = 0; i < NSYM; i++) { + float cs = (float)channel_symbols[i]; - dphi = TWOPIDT * (f0 + - ((float)drift0 / 2.0) * ((float)i - (float)NSYM / 2.0) / ((float)NSYM / 2.0) + - (cs - 1.5) * DF); + float dphi = TWOPIDT * (f0 + (drift0 / 2.0) * ((float)i - (float)NSYM / 2.0) / ((float)NSYM / 2.0) + (cs - 1.5) * DF); - for (int32_t j = 0; j < NSPERSYM; j++) { - int32_t ii = NSPERSYM * i + j; - refi[ii] = refi[ii] + cosf(phi); // cannot precompute sin/cos because dphi is changing - refq[ii] = refq[ii] + sinf(phi); + for (int j = 0; j < NSPERSYM; j++) { + int ii = NSPERSYM * i + j; + refi[ii] = cos(phi); // cannot precompute sin/cos because dphi is changing + refq[ii] = sin(phi); phi = phi + dphi; } } + float w[nfilt], norm = 0, partialsum[nfilt]; + + // lowpass filter and remove startup transient + for (int i = 0; i < nfilt; i++) { + partialsum[i] = 0.0; + } + for (int i = 0; i < nfilt; i++) { + w[i] = sin(M_PI * (float)i / (float)(nfilt - 1)); + norm = norm + w[i]; + } + for (int i = 0; i < nfilt; i++) { + w[i] = w[i] / norm; + } + for (int i = 1; i < nfilt; i++) { + partialsum[i] = partialsum[i - 1] + w[i]; + } + // s(t) * conjugate(r(t)) // beginning of first symbol in reference signal is at i=0 // beginning of first symbol in received data is at shift0. // filter transient lasts nfilt samples // leave nfilt zeros as a pad at the beginning of the unfiltered reference signal - for (int32_t i = 0; i < NSYM * NSPERSYM; i++) { - int32_t k = shift0 + i; - if ((k > 0) & (k < np)) { - ci[i + NFILT] = id[k] * refi[i] + qd[k] * refq[i]; - cq[i + NFILT] = qd[k] * refi[i] - id[k] * refq[i]; + for (int i = 0; i < NSYM * NSPERSYM; i++) { + int k = shift0 + i; + if ((k > 0) && (k < np)) { + ci[i + nfilt] = id[k] * refi[i] + qd[k] * refq[i]; + cq[i + nfilt] = qd[k] * refi[i] - id[k] * refq[i]; } } - // quick and dirty filter - may want to do better - float w[NFILT] = {0}, norm = 0, partialsum[NFILT] = {0}; - for (int32_t i = 0; i < NFILT; i++) { - w[i] = sinf(M_PI * (float)i / (float)(NFILT - 1)); - norm = norm + w[i]; - } - for (int32_t i = 0; i < NFILT; i++) { - w[i] = w[i] / norm; - } - for (int32_t i = 1; i < NFILT; i++) { - partialsum[i] = partialsum[i - 1] + w[i]; - } - // LPF - for (int32_t i = NFILT / 2; i < NIQ - NFILT / 2; i++) { + for (int i = nfilt / 2; i < SIGNAL_SAMPLES - nfilt / 2; i++) { cfi[i] = 0.0; cfq[i] = 0.0; - for (int32_t j = 0; j < NFILT; j++) { - cfi[i] = cfi[i] + w[j] * ci[i - NFILT / 2 + j]; - cfq[i] = cfq[i] + w[j] * cq[i - NFILT / 2 + j]; + for (int j = 0; j < nfilt; j++) { + cfi[i] = cfi[i] + w[j] * ci[i - nfilt / 2 + j]; + cfq[i] = cfq[i] + w[j] * cq[i - nfilt / 2 + j]; } } // subtract c(t)*r(t) here - // (ci+j*cq)(refi+j*refq)=(ci*refi-cq*refq)+j(ci*refq)+cq*refi) - // beginning of first symbol in reference signal is at i=NFILT + // (ci+j*cq)(refi+j*refq)=(ci*refi-cq*refq)+j(ci*refq+cq*refi) + // beginning of first symbol in reference signal is at i=nfilt // beginning of first symbol in received data is at shift0. - for (int32_t i = 0; i < NSIG; i++) { - if (i < NFILT / 2) { // take care of the end effect (LPF step response) here - norm = partialsum[NFILT / 2 + i]; - } else if (i > (NSIG - 1 - NFILT / 2)) { - norm = partialsum[NFILT / 2 + NSIG - 1 - i]; + for (int i = 0; i < NSYM * NSPERSYM; i++) { + if (i < nfilt / 2) { // take care of the end effect (LPF step response) here + norm = partialsum[nfilt / 2 + i]; + } else if (i > (NSYM * NSPERSYM - 1 - nfilt / 2)) { + norm = partialsum[nfilt / 2 + NSYM * NSPERSYM - 1 - i]; } else { norm = 1.0; } - int32_t k = shift0 + i; - int32_t j = i + NFILT; - if ((k > 0) & (k < np)) { + int k = shift0 + i; + int j = i + nfilt; + if ((k > 0) && (k < np)) { id[k] = id[k] - (cfi[j] * refi[i] - cfq[j] * refq[i]) / norm; qd[k] = qd[k] - (cfi[j] * refq[i] + cfq[j] * refi[i]) / norm; } @@ -392,6 +570,24 @@ void subtract_signal2(float *id, float *qd, long np, return; } + +unsigned int count_hard_errors(unsigned char *symbols, unsigned char *channel_symbols) { + int i, is; + unsigned char cw[162]; + unsigned int nerrors; + for (i = 0; i < 162; i++) { + cw[i] = channel_symbols[i] >= 2 ? 1 : 0; + } + deinterleave(cw); + nerrors = 0; + for (i = 0; i < 162; i++) { + is = symbols[i] > 127 ? 1 : 0; + nerrors = nerrors + (is == cw[i] ? 0 : 1); + } + return nerrors; +} + + int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, struct decoder_options options, struct decoder_results *decodes, int32_t *n_results) { @@ -405,6 +601,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, float sync0[200], sync1 = 0.0; float snr0[200]; int32_t shift0[200], shift1 = 0; + int32_t ifmin, ifmax; char callsign[13] = {0}; char call_loc_pow[23] = {0}; @@ -420,6 +617,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Hash table char hashtab[32768 * 13] = {0}; + char loctab[32768 * 5] = {0}; int32_t nh; // Parameters used for performance-tuning: @@ -441,7 +639,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Setup metric table int32_t mettab[2][256]; float bias = 0.42; - for (i = 0; i < 256; i++) { + for (int i = 0; i < 256; i++) { mettab[0][i] = round(10 * (metric_tables[2][i] - bias)); mettab[1][i] = round(10 * (metric_tables[2][255 - i] - bias)); } @@ -459,11 +657,11 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, int32_t nffts = 4 * floor(npoints / 512) - 1; fftin = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * 512); fftout = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * 512); - PLAN3 = fftwf_plan_dft_1d(512, fftin, fftout, FFTW_FORWARD, PATIENCE); + PLAN = fftwf_plan_dft_1d(512, fftin, fftout, FFTW_FORWARD, PATIENCE); float ps[512][nffts]; float w[512]; - for (i = 0; i < 512; i++) { + for (int i = 0; i < 512; i++) { w[i] = sinf(0.006147931 * i); } @@ -479,23 +677,23 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, } // Main loop starts here - for (int32_t ipass = 0; ipass < options.npasses; ipass++) { + for (int ipass = 0; ipass < options.npasses; ipass++) { if (ipass == 1 && uniques == 0) break; if (ipass == 1) // otherwise we bog down on the second pass options.quickmode = 1; memset(ps, 0.0, sizeof(float) * 512 * nffts); - for (i = 0; i < nffts; i++) { + for (int i = 0; i < nffts; i++) { for (j = 0; j < 512; j++) { k = i * 128 + j; fftin[j][0] = idat[k] * w[j]; fftin[j][1] = qdat[k] * w[j]; } - fftwf_execute(PLAN3); + fftwf_execute(PLAN); - for (j = 0; j < 512; j++) { + for (int j = 0; j < 512; j++) { k = j + 256; if (k > 511) k = k - 512; @@ -505,7 +703,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Compute average spectrum float psavg[512] = {0}; - for (i = 0; i < nffts; i++) { + for (int i = 0; i < nffts; i++) { for (j = 0; j < 512; j++) { psavg[j] = psavg[j] + ps[j][i]; } @@ -514,7 +712,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Smooth with 7-point window and limit spectrum to +/-150 Hz int32_t window[7] = {1, 1, 1, 1, 1, 1, 1}; float smspec[411]; - for (i = 0; i < 411; i++) { + for (int i = 0; i < 411; i++) { smspec[i] = 0.0; for (j = -3; j <= 3; j++) { k = 256 - 205 + i + j; @@ -524,7 +722,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Sort spectrum values, then pick off noise level as a percentile float tmpsort[411]; - for (j = 0; j < 411; j++) { + for (int j = 0; j < 411; j++) { tmpsort[j] = smspec[j]; } qsort(tmpsort, 411, sizeof(float), floatcomp); @@ -540,14 +738,14 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, float min_snr = powf(10.0, -7.0 / 10.0); // this is min snr in wspr bw float snr_scaling_factor = 26.3; - for (j = 0; j < 411; j++) { + for (int j = 0; j < 411; j++) { smspec[j] = smspec[j] / noise_level - 1.0; if (smspec[j] < min_snr) smspec[j] = 0.1; continue; } // Find all local maxima in smoothed spectrum. - for (i = 0; i < 200; i++) { + for (int i = 0; i < 200; i++) { freq0[i] = 0.0; snr0[i] = 0.0; drift0[i] = 0.0; @@ -556,7 +754,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, } int32_t npk = 0; - for (j = 1; j < 410; j++) { + for (int j = 1; j < 410; j++) { if ((smspec[j] > smspec[j - 1]) && (smspec[j] > smspec[j + 1]) && (npk < 200)) { freq0[npk] = (j - 205) * (DF / 2.0); snr0[npk] = 10.0 * log10f(smspec[j]) - snr_scaling_factor; @@ -572,7 +770,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Don't waste time on signals outside of the range [fmin,fmax]. i = 0; - for (j = 0; j < npk; j++) { + for (int j = 0; j < npk; j++) { if (freq0[j] >= fmin && freq0[j] <= fmax) { freq0[i] = freq0[j]; snr0[i] = snr0[j]; @@ -582,9 +780,8 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, npk = i; // bubble sort on snr, bringing freq along for the ride - int32_t pass; float tmp; - for (pass = 1; pass <= npk - 1; pass++) { + for (int pass = 1; pass <= npk - 1; pass++) { for (k = 0; k < npk - pass; k++) { if (snr0[k] < snr0[k + 1]) { tmp = snr0[k]; @@ -610,31 +807,22 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, span of 162 symbols, with deviation equal to 0 at the center of the signal vector. */ - - int32_t idrift, ifr, if0, ifd, k0; - int32_t kindex; - float smax, ss, pow, p0, p1, p2, p3; - for (j = 0; j < npk; j++) { // For each candidate... - smax = -1e30; - if0 = freq0[j] / (DF / 2.0) + NSPERSYM; - for (ifr = if0 - 1; ifr <= if0 + 1; ifr++) { // Freq search - for (k0 = -10; k0 < 22; k0++) { // Time search - for (idrift = -maxdrift; idrift <= maxdrift; idrift++) { // Drift search - ss = 0.0; - pow = 0.0; + for (int j = 0; j < npk; j++) { // For each candidate... + float smax = -1e30; + int if0 = freq0[j] / (DF / 2.0) + NSPERSYM; + for (int ifr = if0 - 1; ifr <= if0 + 1; ifr++) { // Freq search + for (int k0 = -10; k0 < 22; k0++) { // Time search + for (int idrift = -maxdrift; idrift <= maxdrift; idrift++) { // Drift search + float ss = 0.0; + float pow = 0.0; for (k = 0; k < NSYM; k++) { // Sum over symbols - ifd = ifr + ((float)k - (float)NBITS) / (float)NBITS * ((float)idrift) / DF; - kindex = k0 + 2 * k; + int ifd = ifr + ((float)k - (float)NBITS) / (float)NBITS * ((float)idrift) / DF; + int kindex = k0 + 2 * k; if (kindex < nffts) { - p0 = ps[ifd - 3][kindex]; - p1 = ps[ifd - 1][kindex]; - p2 = ps[ifd + 1][kindex]; - p3 = ps[ifd + 3][kindex]; - - p0 = sqrtf(p0); - p1 = sqrtf(p1); - p2 = sqrtf(p2); - p3 = sqrtf(p3); + float p0 = sqrtf(ps[ifd - 3][kindex]); + float p1 = sqrtf(ps[ifd - 1][kindex]); + float p2 = sqrtf(ps[ifd + 1][kindex]); + float p3 = sqrtf(ps[ifd + 3][kindex]); ss = ss + (2 * pr3vector[k] - 1) * ((p1 + p3) - (p0 + p2)); pow = pow + p0 + p1 + p2 + p3; @@ -670,7 +858,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, could each work on one candidate at a time. */ - for (j = 0; j < npk; j++) { + for (int j = 0; j < npk; j++) { memset(symbols, 0, sizeof(char) * NBITS * 2); memset(callsign, 0, sizeof(char) * 13); memset(call_loc_pow, 0, sizeof(char) * 23); @@ -678,26 +866,31 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, memset(loc, 0, sizeof(char) * 7); memset(pwr, 0, sizeof(char) * 3); - freq1 = freq0[j]; + freq1 = freq0[j]; drift1 = drift0[j]; shift1 = shift0[j]; - sync1 = sync0[j]; + sync1 = sync0[j]; // Fine search for best sync lag (mode 0) float fstep = 0.0; int32_t lagmin = shift1 - 144; int32_t lagmax = shift1 + 144; int32_t lagstep = 8; + ifmin = 0; + ifmax = 0; if (options.quickmode) lagstep = 16; - sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, fstep, &shift1, + sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, &shift1, lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 0); // Fine search for frequency peak (mode 1) fstep = 0.1; - sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, fstep, &shift1, + ifmin = 0; + ifmin = -2; + ifmax = 2; + sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, &shift1, lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 1); if (sync1 > minsync1) { @@ -717,7 +910,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, jiggered_shift = shift1 + ii; // Use mode 2 to get soft-decision symbols - sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, fstep, + sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, &jiggered_shift, lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 2); sq = 0.0; @@ -748,12 +941,12 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Unpack the decoded message, update the hashtable, apply // sanity checks on grid and power, and return // call_loc_pow string and also callsign (for de-duping). - int32_t noprint = unpk_(message, hashtab, call_loc_pow, call, loc, pwr, callsign); - + int32_t noprint = unpk_(message, hashtab, loctab, call_loc_pow, call, loc, pwr, callsign); if (options.subtraction && (ipass == 0) && !noprint) { unsigned char channel_symbols[NSYM]; - if (get_wspr_channel_symbols(call_loc_pow, hashtab, channel_symbols)) { + //if (get_wspr_channel_symbols(call_loc_pow, hashtab, channel_symbols)) { + if (get_wspr_channel_symbols(call_loc_pow, hashtab, loctab, channel_symbols)) { subtract_signal2(idat, qdat, npoints, freq1, shift1, drift1, channel_symbols); } else { break; @@ -816,9 +1009,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, fclose(fp_fftw_wisdom_file); } - fftwf_destroy_plan(PLAN1); - fftwf_destroy_plan(PLAN2); - fftwf_destroy_plan(PLAN3); + fftwf_destroy_plan(PLAN); if (options.usehashtable) { fhash = fopen("hashtable.txt", "w"); diff --git a/wsprd/wsprd.h b/wsprd/wsprd.h index 386452b..ec3b7c5 100644 --- a/wsprd/wsprd.h +++ b/wsprd/wsprd.h @@ -44,6 +44,14 @@ struct decoder_options { uint32_t subtraction; // '' }; +struct cand { + float freq; + float snr; + int shift; + float drift; + float sync; +}; + struct decoder_results { double freq; float sync; @@ -58,14 +66,44 @@ struct decoder_results { uint32_t cycles; }; +// struct result { +// char date[7]; +// char time[5]; +// float sync; +// float snr; +// float dt; +// double freq; +// char message[23]; +// float drift; +// unsigned int cycles; +// int jitter; +// int blocksize; +// unsigned int metric; +// int nhardmin; +// int ipass; +// int decodetype; +// }; + void sync_and_demodulate(float *id, float *qd, long np, - uint8_t *symbols, float *freq1, float fstep, - int32_t *shift1, int32_t lagmin, int32_t lagmax, int32_t lagstep, - float *drift1, int32_t symfac, float *sync, int32_t mode); + unsigned char *symbols, float *f1, int ifmin, int ifmax, float fstep, + int *shift1, int lagmin, int lagmax, int lagstep, + float *drift1, int symfac, float *sync, int mode); +void noncoherent_sequence_detection(float *id, float *qd, long np, + unsigned char *symbols, float *f1, int *shift1, + float *drift1, int symfac, int *nblocksize, int *bitmetric); void subtract_signal(float *id, float *qd, long np, - float f0, int32_t shift0, float drift0, uint8_t *channel_symbols); + float f0, int shift0, float drift0, unsigned char *channel_symbols); void subtract_signal2(float *id, float *qd, long np, - float f0, int32_t shift0, float drift0, uint8_t *channel_symbols); + float f0, int shift0, float drift0, unsigned char *channel_symbols); +unsigned int count_hard_errors(unsigned char *symbols, unsigned char *channel_symbols); int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, struct decoder_options options, struct decoder_results *decodes, int32_t *n_results); + + + + + + + + diff --git a/wsprd/wsprd_utils.c b/wsprd/wsprd_utils.c index 65fb572..96e54fa 100644 --- a/wsprd/wsprd_utils.c +++ b/wsprd/wsprd_utils.c @@ -152,7 +152,7 @@ int unpackgrid(int32_t ngrid, char *grid) { } int unpackpfx(int32_t nprefix, char *call) { - char nc, pfx[4] = "", tmpcall[7] = ""; + char nc, pfx[4] = {'\0'}, tmpcall[7]; int i; int32_t n; @@ -172,7 +172,8 @@ int unpackpfx(int32_t nprefix, char *call) { n = n / 37; } - strcpy(call, pfx); + char *p = strrchr(pfx, ' '); + strcpy(call, p ? p + 1 : pfx); strncat(call, "/", 1); strncat(call, tmpcall, strlen(tmpcall)); @@ -234,9 +235,9 @@ int floatcomp(const void *elem1, const void *elem2) { return *(const float *)elem1 > *(const float *)elem2; } -int unpk_(signed char *message, char *hashtab, char *call_loc_pow, char *call, char *loc, char *pwr, char *callsign) { +int unpk_(signed char *message, char *hashtab, char *loctab, char *call_loc_pow, char *call, char *loc, char *pwr, char *callsign) { int n1, n2, n3, ndbm, ihash, nadd, noprint = 0; - char grid[5], grid6[7], cdbm[3]; + char grid[5], grid6[7], cdbm[4]; unpack50(message, &n1, &n2); if (!unpackcall(n1, callsign)) @@ -250,13 +251,10 @@ int unpk_(signed char *message, char *hashtab, char *call_loc_pow, char *call, c /* Based on the value of ntype, decide whether this is a Type 1, 2, or 3 message. - * Type 1: 6 digit call, grid, power - ntype is positive and is a member of the set {0,3,7,10,13,17,20...60} - * Type 2: extended callsign, power - ntype is positive but not a member of the set of allowed powers - * Type 3: hash, 6 digit grid, power - ntype is negative. */ @@ -274,26 +272,23 @@ int unpk_(signed char *message, char *hashtab, char *call_loc_pow, char *call, c strncat(call_loc_pow, "\0", 1); ihash = nhash(callsign, strlen(callsign), (uint32_t)146); strcpy(hashtab + ihash * 13, callsign); + strcpy(loctab + ihash * 5, grid); - memset(call, 0, strlen(callsign) + 1); - memset(loc, 0, strlen(grid) + 1); - memset(pwr, 0, 2 + 1); + memset(call, 0, sizeof(char) * strlen(callsign) + 1); + memset(loc, 0, sizeof(char) * strlen(grid) + 1); + memset(pwr, 0, sizeof(char) * 2 + 1); strncat(call, callsign, strlen(callsign)); strncat(call, "\0", 1); strncat(loc, grid, strlen(grid)); strncat(loc, "\0", 1); strncat(pwr, cdbm, 2); strncat(pwr, "\0", 1); - } else { nadd = nu; - if (nu > 3) - nadd = nu - 3; - if (nu > 7) - nadd = nu - 7; + if (nu > 3) nadd = nu - 3; + if (nu > 7) nadd = nu - 7; n3 = n2 / 128 + 32768 * (nadd - 1); - if (!unpackpfx(n3, callsign)) - return 1; + if (!unpackpfx(n3, callsign)) return 1; ndbm = ntype - nadd; memset(call_loc_pow, 0, sizeof(char) * 23); sprintf(cdbm, "%2d", ndbm); @@ -302,36 +297,26 @@ int unpk_(signed char *message, char *hashtab, char *call_loc_pow, char *call, c strncat(call_loc_pow, cdbm, 2); strncat(call_loc_pow, "\0", 1); int nu = ndbm % 10; - if (nu == 0 || nu == 3 || nu == 7) { // make sure power is OK + if (nu == 0 || nu == 3 || nu == 7 || nu == 10) { // make sure power is OK ihash = nhash(callsign, strlen(callsign), (uint32_t)146); strcpy(hashtab + ihash * 13, callsign); - } else { + } else noprint = 1; - } - - memset(call, 0, strlen(callsign) + 1); - memset(loc, 0, 1); - memset(pwr, 0, 2 + 1); - strncat(call, callsign, strlen(callsign)); - strncat(call, "\0", 1); - strncat(loc, "\0", 1); - strncat(pwr, cdbm, 2); - strncat(pwr, "\0", 1); } } else if (ntype < 0) { ndbm = -(ntype + 1); memset(grid6, 0, sizeof(char) * 7); - strncat(grid6, callsign + 5, 1); - strncat(grid6, callsign, 5); + // size_t len=strlen(callsign); + size_t len = 6; + strncat(grid6, callsign + len - 1, 1); + strncat(grid6, callsign, len - 1); int nu = ndbm % 10; - if ((nu == 0 || nu == 3 || nu == 7) && - (isalpha(grid6[0]) && isalpha(grid6[1]) && isdigit(grid6[2]) && isdigit(grid6[3]))) { + if ((nu != 0 && nu != 3 && nu != 7 && nu != 10) || + !isalpha(grid6[0]) || !isalpha(grid6[1]) || + !isdigit(grid6[2]) || !isdigit(grid6[3])) { // not testing 4'th and 5'th chars because of this case: JO33 40 // grid is only 4 chars even though this is a hashed callsign... // isalpha(grid6[4]) && isalpha(grid6[5]) ) ) { - ihash = nhash(callsign, strlen(callsign), (uint32_t)146); - strcpy(hashtab + ihash * 13, callsign); - } else { noprint = 1; } @@ -351,9 +336,9 @@ int unpk_(signed char *message, char *hashtab, char *call_loc_pow, char *call, c strncat(call_loc_pow, cdbm, 2); strncat(call_loc_pow, "\0", 1); - memset(call, 0, strlen(callsign) + 1); - memset(loc, 0, strlen(grid6) + 1); - memset(pwr, 0, 2 + 1); + memset(call, 0, sizeof(char) * strlen(callsign) + 1); + memset(loc, 0, sizeof(char) * strlen(grid6) + 1); + memset(pwr, 0, sizeof(char) * 2 + 1); strncat(call, callsign, strlen(callsign)); strncat(call, "\0", 1); strncat(loc, grid6, strlen(grid6)); @@ -362,7 +347,7 @@ int unpk_(signed char *message, char *hashtab, char *call_loc_pow, char *call, c strncat(pwr, "\0", 1); // I don't know what to do with these... They show up as "A000AA" grids. - if (ntype == -64) + if (ntype == -64) noprint = 1; } return noprint; diff --git a/wsprd/wsprd_utils.h b/wsprd/wsprd_utils.h index f28726e..31e9422 100644 --- a/wsprd/wsprd_utils.h +++ b/wsprd/wsprd_utils.h @@ -39,4 +39,4 @@ void deinterleave(unsigned char *sym); int doublecomp(const void *elem1, const void *elem2); int floatcomp(const void *elem1, const void *elem2); -int unpk_(signed char *message, char *hashtab, char *call_loc_pow, char *call, char *loc, char *pwr, char *callsign); +int unpk_(signed char *message, char *hashtab, char *loctab, char *call_loc_pow, char *call, char *loc, char *pwr, char *callsign); diff --git a/wsprd/wsprsim_utils.c b/wsprd/wsprsim_utils.c index 5f21520..7845cc7 100644 --- a/wsprd/wsprsim_utils.c +++ b/wsprd/wsprsim_utils.c @@ -38,7 +38,7 @@ char get_callsign_character_code(char ch) { return -1; } -long unsigned int pack_grid4_power(char *grid4, int power) { +long unsigned int pack_grid4_power(char const *grid4, int power) { long unsigned int m; m = (179 - 10 * grid4[0] - grid4[2]) * 180 + 10 * grid4[1] + grid4[3]; @@ -46,31 +46,23 @@ long unsigned int pack_grid4_power(char *grid4, int power) { return m; } -long unsigned int pack_call(char *callsign) { - int i; +long unsigned int pack_call(char const *callsign) { + unsigned int i; long unsigned int n; char call6[6]; - memset(call6, 32, sizeof(char) * 6); + memset(call6, ' ', sizeof(call6)); // callsign is 6 characters in length. Exactly. - int call_len = strlen(callsign); + size_t call_len = strlen(callsign); if (call_len > 6) { return 0; } - if (isdigit(*(callsign + 2))) { - for (i = 0; i < 6; i++) { - if (callsign[i] == 0) { - call6[i] = 32; - } else { - call6[i] = *(callsign + i); - } + if (isdigit(callsign[2])) { + for (i = 0; i < call_len; i++) { + call6[i] = callsign[i]; } - } else if (isdigit(*(callsign + 1))) { - for (i = 0; i < 6; i++) { - if (i == 0 || callsign[i - 1] == 0) { - call6[i] = 32; - } else { - call6[i] = *(callsign + i - 1); - } + } else if (isdigit(callsign[1])) { + for (i = 1; i < call_len + 1; i++) { + call6[i] = callsign[i - 1]; } } for (i = 0; i < 6; i++) { @@ -86,17 +78,16 @@ long unsigned int pack_call(char *callsign) { } void pack_prefix(char *callsign, int32_t *n, int32_t *m, int32_t *nadd) { - int i; - char *call6; - call6 = malloc(sizeof(char) * 6); - memset(call6, 32, sizeof(char) * 6); - int i1 = strcspn(callsign, "/"); + size_t i; + char *call6 = calloc(7, sizeof(char)); + size_t i1 = strcspn(callsign, "/"); if (callsign[i1 + 2] == 0) { // single char suffix for (i = 0; i < i1; i++) { call6[i] = callsign[i]; } + call6[i] = '\0'; *n = pack_call(call6); *nadd = 1; int nc = callsign[i1 + 1]; @@ -118,11 +109,10 @@ void pack_prefix(char *callsign, int32_t *n, int32_t *m, int32_t *nadd) { *m = 10 * (callsign[i1 + 1] - 48) + (callsign[i1 + 2] - 48); *m = 60000 + 26 + *m; } else { - char *pfx = strtok(callsign, "/"); - *n = pack_call(strtok(NULL, " ")); - //call6 = strtok(NULL, " "); - //*n = pack_call(call6); - int plen = strlen(pfx); + char const *pfx = strtok(callsign, "/"); + char const *call = strtok(NULL, " "); + *n = pack_call(call); + size_t plen = strlen(pfx); if (plen == 1) { *m = 36; *m = 37 * (*m) + 36; @@ -148,6 +138,7 @@ void pack_prefix(char *callsign, int32_t *n, int32_t *m, int32_t *nadd) { *nadd = 1; } } + free(call6); } void interleave(unsigned char *sym) { @@ -169,19 +160,20 @@ void interleave(unsigned char *sym) { } } -int get_wspr_channel_symbols(char *rawmessage, char *hashtab, unsigned char *symbols) { - int m = 0, n = 0, ntype = 0; +int get_wspr_channel_symbols(char *rawmessage, char *hashtab, char *loctab, unsigned char *symbols) { + int m = 0, ntype = 0; + long unsigned int n = 0; int i, j, ihash; - unsigned char pr3[162] = { - 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, - 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, - 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, - 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, - 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, - 0, 0}; + unsigned char pr3[162] = + {1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, + 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, + 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, + 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0}; int nu[10] = {0, -1, 1, 0, -1, 2, 1, 0, -1, 1}; char *callsign, *grid, *powstr; char grid4[5], message[23]; @@ -193,16 +185,16 @@ int get_wspr_channel_symbols(char *rawmessage, char *hashtab, unsigned char *sym i++; } - int i1 = strcspn(message, " "); - int i2 = strcspn(message, "/"); - int i3 = strcspn(message, "<"); - int i4 = strcspn(message, ">"); - int mlen = strlen(message); + size_t i1 = strcspn(message, " "); + size_t i2 = strcspn(message, "/"); + size_t i3 = strcspn(message, "<"); + size_t i4 = strcspn(message, ">"); + size_t mlen = strlen(message); // Use the presence and/or absence of "<" and "/" to decide what // type of message. No sanity checks! Beware! - if ((i1 > 3) & (i1 < 7) & (i2 == mlen) & (i3 == mlen)) { + if (i1 > 3 && i1 < 7 && i2 == mlen && i3 == mlen) { // Type 1 message: K9AN EN50 33 // xxnxxxx xxnn nn callsign = strtok(message, " "); @@ -232,8 +224,8 @@ int get_wspr_channel_symbols(char *rawmessage, char *hashtab, unsigned char *sym ihash = nhash(callsign, strlen(callsign), (uint32_t)146); m = 128 * ihash + ntype + 64; - char grid6[6]; - memset(grid6, 32, sizeof(char) * 6); + char grid6[7]; + memset(grid6, 0, sizeof(char) * 7); j = strlen(grid); for (i = 0; i < j - 1; i++) { grid6[i] = grid[i + 1]; @@ -243,7 +235,7 @@ int get_wspr_channel_symbols(char *rawmessage, char *hashtab, unsigned char *sym } else if (i2 < mlen) { // just looks for a right slash // Type 2: PJ4/K1ABC 37 callsign = strtok(message, " "); - if (strlen(callsign) < i2) return 0; // guards against pathological case + if (i2 == 0 || i2 > strlen(callsign)) return 0; // guards against pathological case powstr = strtok(NULL, " "); int power = atoi(powstr); if (power < 0) power = 0; @@ -283,8 +275,6 @@ int get_wspr_channel_symbols(char *rawmessage, char *hashtab, unsigned char *sym // make sure that the 11-byte data vector is unpackable // unpack it with the routine that the decoder will use and display // the result. let the operator decide whether it worked. - // char hashtab[32768][13]; - // memset(hashtab,0,sizeof(char)*32768*13); char *check_call_loc_pow, *check_callsign, *call, *loc, *pwr; check_call_loc_pow = malloc(sizeof(char) * 23); @@ -294,13 +284,13 @@ int get_wspr_channel_symbols(char *rawmessage, char *hashtab, unsigned char *sym pwr = malloc(sizeof(char) * 3); signed char check_data[11]; memcpy(check_data, data, sizeof(char) * 11); - unpk_(check_data, hashtab, check_call_loc_pow, call, loc, pwr, check_callsign); + + unpk_(check_data, hashtab, loctab, check_call_loc_pow, call, loc, pwr, check_callsign); // printf("Will decode as: %s\n",check_call_loc_pow); - unsigned int nbytes = 11; // The message with tail is packed into 11 bytes. - unsigned int nencoded = (nbytes * 2 * 8); // This is how much encode() writes - unsigned char channelbits[nencoded]; - memset(channelbits, 0, sizeof(char) * nencoded); + unsigned int nbytes = 11; // The message with tail is packed into almost 11 bytes. + unsigned char channelbits[nbytes * 8 * 2]; /* 162 rounded up */ + memset(channelbits, 0, sizeof(char) * nbytes * 8 * 2); encode(channelbits, data, nbytes); @@ -309,6 +299,8 @@ int get_wspr_channel_symbols(char *rawmessage, char *hashtab, unsigned char *sym for (i = 0; i < 162; i++) { symbols[i] = 2 * channelbits[i] + pr3[i]; } - + free(check_call_loc_pow); + free(check_callsign); return 1; } + diff --git a/wsprd/wsprsim_utils.h b/wsprd/wsprsim_utils.h index e74be73..a6d208f 100644 --- a/wsprd/wsprsim_utils.h +++ b/wsprd/wsprsim_utils.h @@ -2,8 +2,8 @@ char get_locator_character_code(char ch); char get_callsign_character_code(char ch); -long unsigned int pack_grid4_power(char *grid4, int power); -long unsigned int pack_call(char *callsign); +long unsigned int pack_grid4_power(char const *grid4, int power); +long unsigned int pack_call(char const *callsign); void pack_prefix(char *callsign, int32_t *n, int32_t *m, int32_t *nadd); void interleave(unsigned char *sym); -int get_wspr_channel_symbols(char *message, char *hashtab, unsigned char *symbols); +int get_wspr_channel_symbols(char *rawmessage, char *hashtab, char *loctab, unsigned char *symbols); From 1a167c87bf4c93dd585fcd15eeb358486dc60be9 Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 21:22:06 -0500 Subject: [PATCH 02/10] WIP chore: wsprd lib update part2 --- Makefile | 4 +- wsprd/metric_tables.h | 5 - wsprd/wsprd.c | 602 +++++++++++++++--------------------------- wsprd/wsprd.h | 30 --- 4 files changed, 216 insertions(+), 425 deletions(-) diff --git a/Makefile b/Makefile index 14b689b..2672352 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC = clang -CFLAGS = -O3 -std=gnu17 -LIBS = -lusb-1.0 -lrtlsdr -lpthread -lfftw3f -lcurl -lm +CFLAGS = -O3 -std=gnu17 -Wall +LIBS = -lusb-1.0 -lrtlsdr -lpthread -lfftw3f -lcurl -lm -Wall # Note # gcc is a bit faster that clang on this app diff --git a/wsprd/metric_tables.h b/wsprd/metric_tables.h index a86a956..7db6e27 100644 --- a/wsprd/metric_tables.h +++ b/wsprd/metric_tables.h @@ -4,9 +4,6 @@ * should be normalized to have rms amplitude equal to "symbol_scale". ********************************************************************************/ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-braces" - //float symbol_scale[5]={42.6, 53.3, 72.7, 100.2, 125.4}; float metric_tables[5][256]={ {0.9782, 0.9695, 0.9689, 0.9669, 0.9666, 0.9653, 0.9638, 0.9618, 0.9599, 0.9601, @@ -140,5 +137,3 @@ float metric_tables[5][256]={ -17.5973, -17.0403, -17.7039, -18.0073, -18.1840, -18.3848, -18.6286, -20.7063, 1.43370769e-019, 2.64031087e-006, 6.6908396e+031, 1.77537994e+028, 2.79322819e+020, 1.94326e-019, 0.00019371575, 2.80722121e-041}}; - -#pragma GCC diagnostic pop \ No newline at end of file diff --git a/wsprd/wsprd.c b/wsprd/wsprd.c index f4ea1b5..1843a04 100644 --- a/wsprd/wsprd.c +++ b/wsprd/wsprd.c @@ -56,11 +56,14 @@ #define DF15 DF * 1.5 #define TWOPIDT 2.0 * M_PI * DT -#define NFILT 256 -#define NSIG NSYM * NSPERSYM - -/* Possible PATIENCE options: FFTW_ESTIMATE, FFTW_ESTIMATE_PATIENT, FFTW_MEASURE, FFTW_PATIENT, FFTW_EXHAUSTIVE */ +/* Possible PATIENCE options: F + FTW_ESTIMATE, + FFTW_ESTIMATE_PATIENT, + FFTW_MEASURE, + FFTW_PATIENT, + FFTW_EXHAUSTIVE +*/ #define PATIENCE FFTW_ESTIMATE fftwf_plan PLAN; @@ -78,91 +81,88 @@ uint8_t pr3vector[NSYM] = { 0, 0}; -//*************************************************************************** -void sync_and_demodulate(float *id, float *qd, long np, - unsigned char *symbols, float *f1, int ifmin, int ifmax, float fstep, - int *shift1, int lagmin, int lagmax, int lagstep, - float *drift1, int symfac, float *sync, int mode) { - /*********************************************************************** - * mode = 0: no frequency or drift search. find best time lag. * - * 1: no time lag or drift search. find best frequency. * - * 2: no frequency or time lag search. calculate soft-decision * - * symbols using passed frequency and shift. * - ************************************************************************/ +/* mode = 0: no frequency or drift search. find best time lag. + * 1: no time lag or drift search. find best frequency. + * 2: no frequency or time lag search. calculate soft-decision + * symbols using passed frequency and shift. + */ +void sync_and_demodulate(float *id, + float *qd, + long np, + unsigned char *symbols, + float *f1, + int ifmin, + int ifmax, + float fstep, + int *shift1, + int lagmin, + int lagmax, + int lagstep, + float *drift1, + int symfac, + float *sync, + int mode) { - static float fplast = -10000.0; - float f0 = 0.0, fp, ss, - fbest = 0.0, - fsum = 0.0, - f2sum = 0.0, - fsymb[NSYM]; - int best_shift = 0; float i0[NSYM], q0[NSYM], - i1[NSYM], q1[NSYM], - i2[NSYM], q2[NSYM], + i1[NSYM], q1[NSYM], + i2[NSYM], q2[NSYM], i3[NSYM], q3[NSYM]; - float p0, p1, p2, p3, cmet, totp, syncmax, fac; - float c0[NSPERSYM], s0[NSPERSYM], - c1[NSPERSYM], s1[NSPERSYM], - c2[NSPERSYM], s2[NSPERSYM], + float c0[NSPERSYM], s0[NSPERSYM], + c1[NSPERSYM], s1[NSPERSYM], + c2[NSPERSYM], s2[NSPERSYM], c3[NSPERSYM], s3[NSPERSYM]; - float dphi0, cdphi0, sdphi0, - dphi1, cdphi1, sdphi1, - dphi2, cdphi2, sdphi2, - dphi3, cdphi3, sdphi3; + float fsymb[NSYM]; + + float fbest = 0.0, + fsum = 0.0, + f2sum = 0.0; + + int best_shift = 0; + static float fplast = -10000.0; + float syncmax = -1e30; - syncmax = -1e30; if (mode == 0) { ifmin = 0; ifmax = 0; fstep = 0.0; - f0 = *f1; - } - if (mode == 1) { + } else if (mode == 1) { lagmin = *shift1; lagmax = *shift1; - f0 = *f1; - } - if (mode == 2) { + } else if (mode == 2) { lagmin = *shift1; lagmax = *shift1; - ifmin = 0; - ifmax = 0; - f0 = *f1; + ifmin = 0; + ifmax = 0; } for (int ifreq = ifmin; ifreq <= ifmax; ifreq++) { - f0 = *f1 + ifreq * fstep; + float f0 = *f1 + ifreq * fstep; for (int lag = lagmin; lag <= lagmax; lag = lag + lagstep) { - ss = 0.0; - totp = 0.0; + float ss = 0.0; + float totp = 0.0; for (int i = 0; i < NSYM; i++) { - fp = f0 + (*drift1 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; + float fp = f0 + (*drift1 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; if (i == 0 || (fp != fplast)) { // only calculate sin/cos if necessary - dphi0 = TWOPIDT * (fp - DF15); - cdphi0 = cos(dphi0); - sdphi0 = sin(dphi0); + float dphi0 = TWOPIDT * (fp - DF15); + float cdphi0 = cosf(dphi0); + float sdphi0 = sinf(dphi0); - dphi1 = TWOPIDT * (fp - DF05); - cdphi1 = cos(dphi1); - sdphi1 = sin(dphi1); + float dphi1 = TWOPIDT * (fp - DF05); + float cdphi1 = cosf(dphi1); + float sdphi1 = sinf(dphi1); - dphi2 = TWOPIDT * (fp + DF05); - cdphi2 = cos(dphi2); - sdphi2 = sin(dphi2); + float dphi2 = TWOPIDT * (fp + DF05); + float cdphi2 = cosf(dphi2); + float sdphi2 = sinf(dphi2); - dphi3 = TWOPIDT * (fp + DF15); - cdphi3 = cos(dphi3); - sdphi3 = sin(dphi3); + float dphi3 = TWOPIDT * (fp + DF15); + float cdphi3 = cosf(dphi3); + float sdphi3 = sinf(dphi3); - c0[0] = 1; - s0[0] = 0; - c1[0] = 1; - s1[0] = 0; - c2[0] = 1; - s2[0] = 0; - c3[0] = 1; - s3[0] = 0; + c0[0] = 1; s0[0] = 0; + c1[0] = 1; s1[0] = 0; + c2[0] = 1; s2[0] = 0; + c3[0] = 1; s3[0] = 0; for (int j = 1; j < NSPERSYM; j++) { c0[j] = c0[j - 1] * cdphi0 - s0[j - 1] * sdphi0; @@ -177,14 +177,10 @@ void sync_and_demodulate(float *id, float *qd, long np, fplast = fp; } - i0[i] = 0.0; - q0[i] = 0.0; - i1[i] = 0.0; - q1[i] = 0.0; - i2[i] = 0.0; - q2[i] = 0.0; - i3[i] = 0.0; - q3[i] = 0.0; + i0[i] = 0.0; q0[i] = 0.0; + i1[i] = 0.0; q1[i] = 0.0; + i2[i] = 0.0; q2[i] = 0.0; + i3[i] = 0.0; q3[i] = 0.0; for (int j = 0; j < NSPERSYM; j++) { int k = lag + i * NSPERSYM + j; @@ -199,18 +195,14 @@ void sync_and_demodulate(float *id, float *qd, long np, q3[i] = q3[i] - id[k] * s3[j] + qd[k] * c3[j]; } } - p0 = i0[i] * i0[i] + q0[i] * q0[i]; - p1 = i1[i] * i1[i] + q1[i] * q1[i]; - p2 = i2[i] * i2[i] + q2[i] * q2[i]; - p3 = i3[i] * i3[i] + q3[i] * q3[i]; - p0 = sqrt(p0); - p1 = sqrt(p1); - p2 = sqrt(p2); - p3 = sqrt(p3); + float p0 = sqrt(i0[i] * i0[i] + q0[i] * q0[i]); + float p1 = sqrt(i1[i] * i1[i] + q1[i] * q1[i]); + float p2 = sqrt(i2[i] * i2[i] + q2[i] * q2[i]); + float p3 = sqrt(i3[i] * i3[i] + q3[i] * q3[i]); totp = totp + p0 + p1 + p2 + p3; - cmet = (p1 + p3) - (p0 + p2); + float cmet = (p1 + p3) - (p0 + p2); ss = (pr3vector[i] == 1) ? ss + cmet : ss - cmet; if (mode == 2) { // Compute soft symbols if (pr3vector[i] == 1) { @@ -227,7 +219,7 @@ void sync_and_demodulate(float *id, float *qd, long np, fbest = f0; } } // lag loop - } // freq loop + } // freq loop if (mode <= 1) { // Send best params back to caller *sync = syncmax; @@ -239,10 +231,10 @@ void sync_and_demodulate(float *id, float *qd, long np, if (mode == 2) { *sync = syncmax; for (int i = 0; i < NSYM; i++) { // Normalize the soft symbols - fsum = fsum + fsymb[i] / NSYM; - f2sum = f2sum + fsymb[i] * fsymb[i] / NSYM; + fsum += fsymb[i] / NSYM; + f2sum += fsymb[i] * fsymb[i] / NSYM; } - fac = sqrt(f2sum - fsum * fsum); + float fac = sqrt(f2sum - fsum * fsum); for (int i = 0; i < NSYM; i++) { fsymb[i] = symfac * fsymb[i] / fac; if (fsymb[i] > 127) fsymb[i] = 127.0; @@ -254,182 +246,24 @@ void sync_and_demodulate(float *id, float *qd, long np, return; } -void noncoherent_sequence_detection(float *id, float *qd, long np, - unsigned char *symbols, float *f1, int *shift1, - float *drift1, int symfac, int *nblocksize, int *bitmetric) { - /************************************************************************ - * Noncoherent sequence detection for wspr. * - * Allowed block lengths are nblock=1,2,3,6, or 9 symbols. * - * Longer block lengths require longer channel coherence time. * - * The whole block is estimated at once. * - * nblock=1 corresponds to noncoherent detection of individual symbols * - * like the original wsprd symbol demodulator. * - ************************************************************************/ - static float fplast = -10000.0; - int i, j, k, lag, itone, ib, b, nblock, nseq, imask; - float xi[512], xq[512]; - float is[4][NSYM], qs[4][NSYM], - cf[4][NSYM], sf[4][NSYM], - cm, sm, cmp, smp; - float p[512], fac, xm1, xm0; - float c0[NSPERSYM+1], s0[NSPERSYM+1], - c1[NSPERSYM+1], s1[NSPERSYM+1], - c2[NSPERSYM+1], s2[NSPERSYM+1], - c3[NSPERSYM+1], s3[NSPERSYM+1]; - float dphi0, cdphi0, sdphi0, - dphi1, cdphi1, sdphi1, - dphi2, cdphi2, sdphi2, - dphi3, cdphi3, sdphi3; - float f0, fp, fsum = 0.0, f2sum = 0.0, fsymb[NSYM]; - - f0 = *f1; - lag = *shift1; - nblock = *nblocksize; - nseq = 1 << nblock; - int bitbybit = *bitmetric; - - for (i = 0; i < NSYM; i++) { - fp = f0 + (*drift1 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; - if (i == 0 || (fp != fplast)) { // only calculate sin/cos if necessary - dphi0 = TWOPIDT * (fp - DF15); - cdphi0 = cos(dphi0); - sdphi0 = sin(dphi0); - - dphi1 = TWOPIDT * (fp - DF05); - cdphi1 = cos(dphi1); - sdphi1 = sin(dphi1); - - dphi2 = TWOPIDT * (fp + DF05); - cdphi2 = cos(dphi2); - sdphi2 = sin(dphi2); - - dphi3 = TWOPIDT * (fp + DF15); - cdphi3 = cos(dphi3); - sdphi3 = sin(dphi3); - - c0[0] = 1; - s0[0] = 0; - c1[0] = 1; - s1[0] = 0; - c2[0] = 1; - s2[0] = 0; - c3[0] = 1; - s3[0] = 0; - - for (j = 1; j < (NSPERSYM+1); j++) { - c0[j] = c0[j - 1] * cdphi0 - s0[j - 1] * sdphi0; - s0[j] = c0[j - 1] * sdphi0 + s0[j - 1] * cdphi0; - c1[j] = c1[j - 1] * cdphi1 - s1[j - 1] * sdphi1; - s1[j] = c1[j - 1] * sdphi1 + s1[j - 1] * cdphi1; - c2[j] = c2[j - 1] * cdphi2 - s2[j - 1] * sdphi2; - s2[j] = c2[j - 1] * sdphi2 + s2[j - 1] * cdphi2; - c3[j] = c3[j - 1] * cdphi3 - s3[j - 1] * sdphi3; - s3[j] = c3[j - 1] * sdphi3 + s3[j - 1] * cdphi3; - } - - fplast = fp; - } - - cf[0][i] = c0[NSPERSYM]; - sf[0][i] = s0[NSPERSYM]; - cf[1][i] = c1[NSPERSYM]; - sf[1][i] = s1[NSPERSYM]; - cf[2][i] = c2[NSPERSYM]; - sf[2][i] = s2[NSPERSYM]; - cf[3][i] = c3[NSPERSYM]; - sf[3][i] = s3[NSPERSYM]; - - is[0][i] = 0.0; - qs[0][i] = 0.0; - is[1][i] = 0.0; - qs[1][i] = 0.0; - is[2][i] = 0.0; - qs[2][i] = 0.0; - is[3][i] = 0.0; - qs[3][i] = 0.0; - - for (j = 0; j < NSPERSYM; j++) { - k = lag + i * NSPERSYM + j; - if ((k > 0) && (k < np)) { - is[0][i] = is[0][i] + id[k] * c0[j] + qd[k] * s0[j]; - qs[0][i] = qs[0][i] - id[k] * s0[j] + qd[k] * c0[j]; - is[1][i] = is[1][i] + id[k] * c1[j] + qd[k] * s1[j]; - qs[1][i] = qs[1][i] - id[k] * s1[j] + qd[k] * c1[j]; - is[2][i] = is[2][i] + id[k] * c2[j] + qd[k] * s2[j]; - qs[2][i] = qs[2][i] - id[k] * s2[j] + qd[k] * c2[j]; - is[3][i] = is[3][i] + id[k] * c3[j] + qd[k] * s3[j]; - qs[3][i] = qs[3][i] - id[k] * s3[j] + qd[k] * c3[j]; - } - } - } - - for (i = 0; i < NSYM; i = i + nblock) { - for (j = 0; j < nseq; j++) { - xi[j] = 0.0; - xq[j] = 0.0; - cm = 1; - sm = 0; - for (ib = 0; ib < nblock; ib++) { - b = (j & (1 << (nblock - 1 - ib))) >> (nblock - 1 - ib); - itone = pr3vector[i + ib] + 2 * b; - xi[j] = xi[j] + is[itone][i + ib] * cm + qs[itone][i + ib] * sm; - xq[j] = xq[j] + qs[itone][i + ib] * cm - is[itone][i + ib] * sm; - cmp = cf[itone][i + ib] * cm - sf[itone][i + ib] * sm; - smp = sf[itone][i + ib] * cm + cf[itone][i + ib] * sm; - cm = cmp; - sm = smp; - } - p[j] = xi[j] * xi[j] + xq[j] * xq[j]; - p[j] = sqrt(p[j]); - } - for (ib = 0; ib < nblock; ib++) { - imask = 1 << (nblock - 1 - ib); - xm1 = 0.0; - xm0 = 0.0; - for (j = 0; j < nseq; j++) { - if ((j & imask) != 0) { - if (p[j] > xm1) xm1 = p[j]; - } - if ((j & imask) == 0) { - if (p[j] > xm0) xm0 = p[j]; - } - } - fsymb[i + ib] = xm1 - xm0; - if (bitbybit == 1) { - fsymb[i + ib] = fsymb[i + ib] / (xm1 > xm0 ? xm1 : xm0); - } - } - } - for (i = 0; i < NSYM; i++) { // Normalize the soft symbols - fsum = fsum + fsymb[i] / NSYM; - f2sum = f2sum + fsymb[i] * fsymb[i] / NSYM; - } - fac = sqrt(f2sum - fsum * fsum); - for (i = 0; i < NSYM; i++) { - fsymb[i] = symfac * fsymb[i] / fac; - if (fsymb[i] > 127) fsymb[i] = 127.0; - if (fsymb[i] < -128) fsymb[i] = -128.0; - symbols[i] = fsymb[i] + 128; - } - return; -} - -/*************************************************************************** - symbol-by-symbol signal subtraction - ****************************************************************************/ -void subtract_signal(float *id, float *qd, long np, - float f0, int shift0, float drift0, unsigned char *channel_symbols) { +/* symbol-by-symbol signal subtraction */ +void subtract_signal(float *id, + float *qd, + long np, + float f0, + int shift0, + float drift0, + unsigned char *channel_symbols) { float c0[NSPERSYM], s0[NSPERSYM]; - float dphi, cdphi, sdphi; for (int i = 0; i < NSYM; i++) { float fp = f0 + ((float)drift0 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; - dphi = TWOPIDT * (fp + ((float)channel_symbols[i] - 1.5) * DF); - cdphi = cos(dphi); - sdphi = sin(dphi); + float dphi = TWOPIDT * (fp + ((float)channel_symbols[i] - 1.5) * DF); + float cdphi = cosf(dphi); + float sdphi = sinf(dphi); c0[0] = 1; s0[0] = 0; @@ -451,7 +285,6 @@ void subtract_signal(float *id, float *qd, long np, } // subtract the signal here. - i0 = i0 / (float)NSPERSYM; // will be wrong for partial symbols at the edges... q0 = q0 / (float)NSPERSYM; @@ -467,9 +300,7 @@ void subtract_signal(float *id, float *qd, long np, } -/****************************************************************************** - Subtract the coherent component of a signal - *******************************************************************************/ +/* Subtract the coherent component of a signal */ void subtract_signal2(float *id, float *qd, long np, @@ -478,7 +309,7 @@ void subtract_signal2(float *id, float drift0, unsigned char *channel_symbols) { - float phi = 0; + float phi = 0.0; const int nfilt = 360; // nfilt must be even number. float refi[SIGNAL_SAMPLES] = {0}, refq[SIGNAL_SAMPLES] = {0}, @@ -493,8 +324,7 @@ void subtract_signal2(float *id, Multiply r(t) by c(t) and subtract from s(t), i.e. s'(t)=s(t)-c(t)r(t) *******************************************************************************/ - // create reference wspr signal vector, centered on f0. - // + /* create reference wspr signal vector, centered on f0. */ for (int i = 0; i < NSYM; i++) { float cs = (float)channel_symbols[i]; @@ -502,20 +332,20 @@ void subtract_signal2(float *id, for (int j = 0; j < NSPERSYM; j++) { int ii = NSPERSYM * i + j; - refi[ii] = cos(phi); // cannot precompute sin/cos because dphi is changing - refq[ii] = sin(phi); + refi[ii] = cosf(phi); // cannot precompute sin/cos because dphi is changing + refq[ii] = sinf(phi); phi = phi + dphi; } } float w[nfilt], norm = 0, partialsum[nfilt]; - // lowpass filter and remove startup transient + /* lowpass filter and remove startup transient */ for (int i = 0; i < nfilt; i++) { partialsum[i] = 0.0; } for (int i = 0; i < nfilt; i++) { - w[i] = sin(M_PI * (float)i / (float)(nfilt - 1)); + w[i] = sinf(M_PI * (float)i / (float)(nfilt - 1)); norm = norm + w[i]; } for (int i = 0; i < nfilt; i++) { @@ -571,72 +401,54 @@ void subtract_signal2(float *id, } -unsigned int count_hard_errors(unsigned char *symbols, unsigned char *channel_symbols) { - int i, is; - unsigned char cw[162]; - unsigned int nerrors; - for (i = 0; i < 162; i++) { - cw[i] = channel_symbols[i] >= 2 ? 1 : 0; - } - deinterleave(cw); - nerrors = 0; - for (i = 0; i < 162; i++) { - is = symbols[i] > 127 ? 1 : 0; - nerrors = nerrors + (is == cw[i] ? 0 : 1); - } - return nerrors; -} - - int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, struct decoder_options options, struct decoder_results *decodes, int32_t *n_results) { - int32_t i, j, k; + uint8_t symbols[NBITS * 2] = {0}; uint8_t decdata[(NBITS + 7) / 8] = {0}; - int8_t message[12] = {0}; + int8_t message[12] = {0}; - float freq0[200], freq1 = 0.0; - float drift0[200], drift1 = 0.0; - float sync0[200], sync1 = 0.0; - float snr0[200]; + float freq0[200], freq1 = 0.0; + float drift0[200], drift1 = 0.0; + float sync0[200], sync1 = 0.0; + float snr0[200]; int32_t shift0[200], shift1 = 0; - int32_t ifmin, ifmax; - - char callsign[13] = {0}; - char call_loc_pow[23] = {0}; - char call[13] = {0}; - char loc[7] = {0}; - char pwr[3] = {0}; uint32_t metric, cycles, maxnp; int32_t worth_a_try; int32_t uniques = 0; + + // Search tuning parameters + float fstep; + int lagmin; + int lagmax; + int lagstep; + int ifmin; + int ifmax; float fmin = -110.0; float fmax = 110.0; - // Hash table - char hashtab[32768 * 13] = {0}; - char loctab[32768 * 5] = {0}; - int32_t nh; - // Parameters used for performance-tuning: - uint32_t maxcycles = 10000; // Fano timeout limit - double minsync1 = 0.10; // First sync limit - double minsync2 = 0.12; // Second sync limit - int32_t iifac = 3; // Step size in final DT peakup - int32_t symfac = 50; // Soft-symbol normalizing factor - int32_t maxdrift = 4; // Maximum (+/-) drift - double minrms = 52.0 * (symfac / 64.0); // Final test for plausible decoding - int32_t delta = 60; // Fano threshold step + uint32_t maxcycles = 10000; // Fano timeout limit + double minsync1 = 0.10; // First sync limit + double minsync2 = 0.12; // Second sync limit + int32_t iifac = 3; // Step size in final DT peakup + int32_t symfac = 50; // Soft-symbol normalizing factor + int32_t maxdrift = 4; // Maximum (+/-) drift + double minrms = 52.0 * (symfac / 64.0); // Final test for plausible decoding + int32_t delta = 60; // Fano threshold step // Results - float allfreqs[100]; - char allcalls[100][13]; - memset(allfreqs, 0, sizeof(float) * 100); - memset(allcalls, 0, sizeof(char) * 100 * 13); + float allfreqs[100] = {0}; + char allcalls[100][13] = {0}; + char callsign[13] = {0}; + char call_loc_pow[23] = {0}; + char call[13] = {0}; + char loc[7] = {0}; + char pwr[3] = {0}; - // Setup metric table + /* Setup metric table */ int32_t mettab[2][256]; float bias = 0.42; for (int i = 0; i < 256; i++) { @@ -644,57 +456,78 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, mettab[1][i] = round(10 * (metric_tables[2][255 - i] - bias)); } - // FFT buffer - fftwf_complex *fftin, *fftout; - - FILE *fp_fftw_wisdom_file, *fhash; - if ((fp_fftw_wisdom_file = fopen("fftw_wisdom.dat", "r"))) { // Open FFTW wisdom - fftwf_import_wisdom_from_file(fp_fftw_wisdom_file); - fclose(fp_fftw_wisdom_file); - } - - // Do windowed ffts over 2 symbols, stepped by half symbols - int32_t nffts = 4 * floor(npoints / 512) - 1; - fftin = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * 512); - fftout = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * 512); - PLAN = fftwf_plan_dft_1d(512, fftin, fftout, FFTW_FORWARD, PATIENCE); - - float ps[512][nffts]; - float w[512]; - for (int i = 0; i < 512; i++) { - w[i] = sinf(0.006147931 * i); - } + /* Setup/Load hash tables */ + FILE *fhash; + int nh; + char hashtab[32768 * 13] = {0}; + char loctab[32768 * 5] = {0}; if (options.usehashtable) { - char line[80], hcall[12]; + char line[80], hcall[12], hgrid[5];; if ((fhash = fopen("hashtable.txt", "r+"))) { while (fgets(line, sizeof(line), fhash) != NULL) { - sscanf(line, "%d %s", &nh, hcall); + hgrid[0] = '\0'; + sscanf(line, "%d %s %s", &nh, hcall, hgrid); strcpy(hashtab + nh * 13, hcall); + if (strlen(hgrid) > 0) strcpy(loctab + nh * 5, hgrid); } fclose(fhash); } } - // Main loop starts here + /* FFT buffer (512 bins) */ + fftwf_complex *fftin, *fftout; + fftin = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * 512); + fftout = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * 512); + PLAN = fftwf_plan_dft_1d(512, fftin, fftout, FFTW_FORWARD, PATIENCE); + + /* Recover FFTW optimization settings */ + FILE *fp_fftw_wisdom_file; + if ((fp_fftw_wisdom_file = fopen("fftw_wisdom.dat", "r"))) { // Open FFTW wisdom + fftwf_import_wisdom_from_file(fp_fftw_wisdom_file); + fclose(fp_fftw_wisdom_file); + } + + /* Hann function */ + float hann[512]; + for (int i = 0; i < 512; i++) { + hann[i] = sinf(0.006147931 * i); + } + + /* FFT output alloc */ + const int blocks = 4 * floor(npoints / 512) - 1; + float ps[512][blocks]; + memset(ps, 0.0, sizeof(float) * 512 * blocks); + + /* Main loop starts here */ for (int ipass = 0; ipass < options.npasses; ipass++) { if (ipass == 1 && uniques == 0) break; - if (ipass == 1) // otherwise we bog down on the second pass - options.quickmode = 1; + if (ipass < 2) { + maxdrift = 4; + minsync2 = 0.12; + } + if (ipass == 2) { + maxdrift = 0; // no drift for smaller frequency estimator variance + minsync2 = 0.10; + } - memset(ps, 0.0, sizeof(float) * 512 * nffts); - for (int i = 0; i < nffts; i++) { - for (j = 0; j < 512; j++) { - k = i * 128 + j; - fftin[j][0] = idat[k] * w[j]; - fftin[j][1] = qdat[k] * w[j]; + /* Compute FFT + * FFT over 2 symbols, stepped by half symbols + */ + for (int i = 0; i < blocks; i++) { + /* Load samples */ + for (int j = 0; j < 512; j++) { + int k = i * 128 + j; + fftin[j][0] = idat[k] * hann[j]; + fftin[j][1] = qdat[k] * hann[j]; } fftwf_execute(PLAN); + /* Recover frequencies */ for (int j = 0; j < 512; j++) { - k = j + 256; + int k = j + 256; if (k > 511) k = k - 512; ps[j][i] = fftout[k][0] * fftout[k][0] + fftout[k][1] * fftout[k][1]; @@ -703,20 +536,21 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Compute average spectrum float psavg[512] = {0}; - for (int i = 0; i < nffts; i++) { - for (j = 0; j < 512; j++) { - psavg[j] = psavg[j] + ps[j][i]; + for (int i = 0; i < blocks; i++) { + for (int j = 0; j < 512; j++) { + psavg[j] += ps[j][i]; } } + // Already restricted by previous FIR // Smooth with 7-point window and limit spectrum to +/-150 Hz int32_t window[7] = {1, 1, 1, 1, 1, 1, 1}; float smspec[411]; for (int i = 0; i < 411; i++) { smspec[i] = 0.0; - for (j = -3; j <= 3; j++) { - k = 256 - 205 + i + j; - smspec[i] = smspec[i] + window[j + 3] * psavg[k]; + for (int j = -3; j <= 3; j++) { + int k = 256 - 205 + i + j; + smspec[i] += window[j + 3] * psavg[k]; } } @@ -746,30 +580,26 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // Find all local maxima in smoothed spectrum. for (int i = 0; i < 200; i++) { - freq0[i] = 0.0; - snr0[i] = 0.0; + freq0[i] = 0.0; + snr0[i] = 0.0; drift0[i] = 0.0; shift0[i] = 0; - sync0[i] = 0.0; + sync0[i] = 0.0; } int32_t npk = 0; for (int j = 1; j < 410; j++) { - if ((smspec[j] > smspec[j - 1]) && (smspec[j] > smspec[j + 1]) && (npk < 200)) { + if ((smspec[j] > smspec[j - 1]) && + (smspec[j] > smspec[j + 1]) && + (npk < 200)) { freq0[npk] = (j - 205) * (DF / 2.0); snr0[npk] = 10.0 * log10f(smspec[j]) - snr_scaling_factor; npk++; } } - /* Compute corrected fmin, fmax, accounting for dial frequency error - float dialfreq_error = 0.0; // dialfreq_error is in units of Hz - fmin += dialfreq_error; - fmax += dialfreq_error; - */ - // Don't waste time on signals outside of the range [fmin,fmax]. - i = 0; + int i = 0; for (int j = 0; j < npk; j++) { if (freq0[j] >= fmin && freq0[j] <= fmax) { freq0[i] = freq0[j]; @@ -782,7 +612,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // bubble sort on snr, bringing freq along for the ride float tmp; for (int pass = 1; pass <= npk - 1; pass++) { - for (k = 0; k < npk - pass; k++) { + for (int k = 0; k < npk - pass; k++) { if (snr0[k] < snr0[k + 1]) { tmp = snr0[k]; snr0[k] = snr0[k + 1]; @@ -815,10 +645,10 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, for (int idrift = -maxdrift; idrift <= maxdrift; idrift++) { // Drift search float ss = 0.0; float pow = 0.0; - for (k = 0; k < NSYM; k++) { // Sum over symbols + for (int k = 0; k < NSYM; k++) { // Sum over symbols int ifd = ifr + ((float)k - (float)NBITS) / (float)NBITS * ((float)idrift) / DF; int kindex = k0 + 2 * k; - if (kindex < nffts) { + if (kindex < blocks) { float p0 = sqrtf(ps[ifd - 3][kindex]); float p1 = sqrtf(ps[ifd - 1][kindex]); float p2 = sqrtf(ps[ifd + 1][kindex]); @@ -871,23 +701,20 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, shift1 = shift0[j]; sync1 = sync0[j]; - // Fine search for best sync lag (mode 0) - float fstep = 0.0; - int32_t lagmin = shift1 - 144; - int32_t lagmax = shift1 + 144; - int32_t lagstep = 8; + // Coarse-grid search for best sync lag (mode 0) + fstep = 0.0; ifmin = 0; ifmax = 0; - + lagmin = shift1 - 128; + lagmax = shift1 + 128; + lagstep = 8; if (options.quickmode) lagstep = 16; - sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, &shift1, lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 0); - // Fine search for frequency peak (mode 1) + // Coarse-grid search for frequency peak (mode 1) fstep = 0.1; - ifmin = 0; ifmin = -2; ifmax = 2; sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, &shift1, @@ -899,26 +726,24 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, worth_a_try = 0; } - int32_t idt = 0, ii = 0, jiggered_shift; - float y, sq, rms; - int32_t not_decoded = 1; - + int idt = 0, ii = 0; + int not_decoded = 1; while (worth_a_try && not_decoded && idt <= (128 / iifac)) { ii = (idt + 1) / 2; if (idt % 2 == 1) ii = -ii; ii = iifac * ii; - jiggered_shift = shift1 + ii; + int jiggered_shift = shift1 + ii; // Use mode 2 to get soft-decision symbols sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, &jiggered_shift, lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 2); - sq = 0.0; + float sq = 0.0; for (i = 0; i < NSYM; i++) { - y = (float)symbols[i] - 128.0; + float y = (float)symbols[i] - 128.0; sq += y * y; } - rms = sqrtf(sq / (float)NSYM); + float rms = sqrtf(sq / (float)NSYM); if ((sync1 > minsync2) && (rms > minrms)) { deinterleave(symbols); @@ -987,8 +812,8 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, // sort the result struct decoder_results temp; - for (j = 1; j <= uniques - 1; j++) { - for (k = 0; k < uniques - j; k++) { + for (int j = 1; j <= uniques - 1; j++) { + for (int k = 0; k < uniques - j; k++) { if (decodes[k].snr < decodes[k + 1].snr) { temp = decodes[k]; decodes[k] = decodes[k + 1]; @@ -1013,12 +838,13 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, if (options.usehashtable) { fhash = fopen("hashtable.txt", "w"); - for (i = 0; i < 32768; i++) { + for (int i = 0; i < 32768; i++) { if (strncmp(hashtab + i * 13, "\0", 1) != 0) { - fprintf(fhash, "%5d %s\n", i, hashtab + i * 13); + fprintf(fhash, "%5d %s %s\n", i, hashtab + i * 13, loctab + i * 5); } } fclose(fhash); } + return 0; } diff --git a/wsprd/wsprd.h b/wsprd/wsprd.h index ec3b7c5..0a44d89 100644 --- a/wsprd/wsprd.h +++ b/wsprd/wsprd.h @@ -66,44 +66,14 @@ struct decoder_results { uint32_t cycles; }; -// struct result { -// char date[7]; -// char time[5]; -// float sync; -// float snr; -// float dt; -// double freq; -// char message[23]; -// float drift; -// unsigned int cycles; -// int jitter; -// int blocksize; -// unsigned int metric; -// int nhardmin; -// int ipass; -// int decodetype; -// }; - void sync_and_demodulate(float *id, float *qd, long np, unsigned char *symbols, float *f1, int ifmin, int ifmax, float fstep, int *shift1, int lagmin, int lagmax, int lagstep, float *drift1, int symfac, float *sync, int mode); -void noncoherent_sequence_detection(float *id, float *qd, long np, - unsigned char *symbols, float *f1, int *shift1, - float *drift1, int symfac, int *nblocksize, int *bitmetric); void subtract_signal(float *id, float *qd, long np, float f0, int shift0, float drift0, unsigned char *channel_symbols); void subtract_signal2(float *id, float *qd, long np, float f0, int shift0, float drift0, unsigned char *channel_symbols); -unsigned int count_hard_errors(unsigned char *symbols, unsigned char *channel_symbols); int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, struct decoder_options options, struct decoder_results *decodes, int32_t *n_results); - - - - - - - - From 474c95df299a149481fcd4a7b97cb7cc2c132b0c Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 21:36:55 -0500 Subject: [PATCH 03/10] WIP chore: formatting --- wsprd/wsprd.c | 79 ++++++++++++++++++++++++++++----------------------- wsprd/wsprd.h | 2 +- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/wsprd/wsprd.c b/wsprd/wsprd.c index 1843a04..d4b05a9 100644 --- a/wsprd/wsprd.c +++ b/wsprd/wsprd.c @@ -401,45 +401,52 @@ void subtract_signal2(float *id, } -int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, - struct decoder_options options, struct decoder_results *decodes, - int32_t *n_results) { +int32_t wspr_decode(float *idat, + float *qdat, + int samples, + struct decoder_options options, + struct decoder_results *decodes, + int *n_results) { uint8_t symbols[NBITS * 2] = {0}; uint8_t decdata[(NBITS + 7) / 8] = {0}; int8_t message[12] = {0}; - float freq0[200], freq1 = 0.0; - float drift0[200], drift1 = 0.0; - float sync0[200], sync1 = 0.0; - float snr0[200]; - int32_t shift0[200], shift1 = 0; + /* Parameters used for performance-tuning */ + float minsync1 = 0.10; // First sync limit + float minsync2 = 0.12; // Second sync limit + int iifac = 3; // Step size in final DT peakup + int symfac = 50; // Soft-symbol normalizing factor + int maxdrift = 4; // Maximum (+/-) drift + float minrms = 52.0 * (symfac / 64.0); // Final test for plausible decoding + int delta = 60; // Fano threshold step + int maxcycles = 10000; // Fano timeout limit + float fmin = -110.0; + float fmax = 110.0; - uint32_t metric, cycles, maxnp; - int32_t worth_a_try; - int32_t uniques = 0; - - // Search tuning parameters + /* Search live parameters */ float fstep; int lagmin; int lagmax; int lagstep; int ifmin; int ifmax; - float fmin = -110.0; - float fmax = 110.0; - // Parameters used for performance-tuning: - uint32_t maxcycles = 10000; // Fano timeout limit - double minsync1 = 0.10; // First sync limit - double minsync2 = 0.12; // Second sync limit - int32_t iifac = 3; // Step size in final DT peakup - int32_t symfac = 50; // Soft-symbol normalizing factor - int32_t maxdrift = 4; // Maximum (+/-) drift - double minrms = 52.0 * (symfac / 64.0); // Final test for plausible decoding - int32_t delta = 60; // Fano threshold step + /* Decoder flags */ + int worth_a_try; + int uniques = 0; - // Results + /* CPU usage stats */ + uint32_t metric, cycles, maxnp; + + /* Candidates */ + float freq0[200], freq1 = 0.0; + float drift0[200], drift1 = 0.0; + float sync0[200], sync1 = 0.0; + float snr0[200]; + int shift0[200], shift1 = 0; + + /* Results */ float allfreqs[100] = {0}; char allcalls[100][13] = {0}; char callsign[13] = {0}; @@ -495,7 +502,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, } /* FFT output alloc */ - const int blocks = 4 * floor(npoints / 512) - 1; + const int blocks = 4 * floor(samples / 512) - 1; float ps[512][blocks]; memset(ps, 0.0, sizeof(float) * 512 * blocks); @@ -710,14 +717,14 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, lagstep = 8; if (options.quickmode) lagstep = 16; - sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, &shift1, + sync_and_demodulate(idat, qdat, samples, symbols, &freq1, ifmin, ifmax, fstep, &shift1, lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 0); // Coarse-grid search for frequency peak (mode 1) fstep = 0.1; ifmin = -2; ifmax = 2; - sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, &shift1, + sync_and_demodulate(idat, qdat, samples, symbols, &freq1, ifmin, ifmax, fstep, &shift1, lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 1); if (sync1 > minsync1) { @@ -735,7 +742,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, int jiggered_shift = shift1 + ii; // Use mode 2 to get soft-decision symbols - sync_and_demodulate(idat, qdat, npoints, symbols, &freq1, ifmin, ifmax, fstep, + sync_and_demodulate(idat, qdat, samples, symbols, &freq1, ifmin, ifmax, fstep, &jiggered_shift, lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 2); float sq = 0.0; @@ -772,7 +779,7 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, //if (get_wspr_channel_symbols(call_loc_pow, hashtab, channel_symbols)) { if (get_wspr_channel_symbols(call_loc_pow, hashtab, loctab, channel_symbols)) { - subtract_signal2(idat, qdat, npoints, freq1, shift1, drift1, channel_symbols); + subtract_signal2(idat, qdat, samples, freq1, shift1, drift1, channel_symbols); } else { break; } @@ -791,14 +798,14 @@ int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, uniques++; double dialfreq = (double)options.freq / 1e6; - double freq_print = dialfreq + (1500 + freq1) / 1e6; + double freq_print = dialfreq + (1500.0 + freq1) / 1e6; float dt_print = shift1 * DT - 2.0; - decodes[uniques - 1].sync = sync1; - decodes[uniques - 1].snr = snr0[j]; - decodes[uniques - 1].dt = dt_print; - decodes[uniques - 1].freq = freq_print; - decodes[uniques - 1].drift = drift1; + decodes[uniques - 1].sync = sync1; + decodes[uniques - 1].snr = snr0[j]; + decodes[uniques - 1].dt = dt_print; + decodes[uniques - 1].freq = freq_print; + decodes[uniques - 1].drift = drift1; decodes[uniques - 1].cycles = cycles; decodes[uniques - 1].jitter = ii; strcpy(decodes[uniques - 1].message, call_loc_pow); diff --git a/wsprd/wsprd.h b/wsprd/wsprd.h index 0a44d89..d51f3c1 100644 --- a/wsprd/wsprd.h +++ b/wsprd/wsprd.h @@ -74,6 +74,6 @@ void subtract_signal(float *id, float *qd, long np, float f0, int shift0, float drift0, unsigned char *channel_symbols); void subtract_signal2(float *id, float *qd, long np, float f0, int shift0, float drift0, unsigned char *channel_symbols); -int32_t wspr_decode(float *idat, float *qdat, uint32_t npoints, +int32_t wspr_decode(float *idat, float *qdat, int samples, struct decoder_options options, struct decoder_results *decodes, int32_t *n_results); From 92d3e34213be87dbd033e84e76966995d0359868 Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 21:58:33 -0500 Subject: [PATCH 04/10] WIP chore: wsprd lib update part3 --- wsprd/wsprd.c | 3 +- wsprd/wsprd.h | 93 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 61 insertions(+), 35 deletions(-) diff --git a/wsprd/wsprd.c b/wsprd/wsprd.c index d4b05a9..b512a51 100644 --- a/wsprd/wsprd.c +++ b/wsprd/wsprd.c @@ -401,7 +401,7 @@ void subtract_signal2(float *id, } -int32_t wspr_decode(float *idat, +int wspr_decode(float *idat, float *qdat, int samples, struct decoder_options options, @@ -440,6 +440,7 @@ int32_t wspr_decode(float *idat, uint32_t metric, cycles, maxnp; /* Candidates */ + struct cand candidates[200]; float freq0[200], freq1 = 0.0; float drift0[200], drift1 = 0.0; float sync0[200], sync1 = 0.0; diff --git a/wsprd/wsprd.h b/wsprd/wsprd.h index d51f3c1..fa004b4 100644 --- a/wsprd/wsprd.h +++ b/wsprd/wsprd.h @@ -35,45 +35,70 @@ /* Option & config of decoder (Shared with the wsprd code) */ struct decoder_options { - uint32_t freq; // Dial frequency - char rcall[13]; // Callsign of the RX station - char rloc[7]; // Locator of the RX station - uint32_t quickmode; // Decoder option & tweak - uint32_t usehashtable; // '' - uint32_t npasses; // '' - uint32_t subtraction; // '' + int freq; // Dial frequency + char rcall[13]; // Callsign of the RX station + char rloc[7]; // Locator of the RX station + int quickmode; // Decoder option & tweak + int usehashtable; // '' + int npasses; // '' + int subtraction; // '' }; struct cand { - float freq; - float snr; - int shift; - float drift; - float sync; + float freq; + float snr; + int shift; + float drift; + float sync; }; struct decoder_results { - double freq; - float sync; - float snr; - float dt; - float drift; - int32_t jitter; - char message[23]; - char call[13]; - char loc[7]; - char pwr[3]; - uint32_t cycles; + double freq; + float sync; + float snr; + float dt; + float drift; + int jitter; + char message[23]; + char call[13]; + char loc[7]; + char pwr[3]; + int cycles; }; -void sync_and_demodulate(float *id, float *qd, long np, - unsigned char *symbols, float *f1, int ifmin, int ifmax, float fstep, - int *shift1, int lagmin, int lagmax, int lagstep, - float *drift1, int symfac, float *sync, int mode); -void subtract_signal(float *id, float *qd, long np, - float f0, int shift0, float drift0, unsigned char *channel_symbols); -void subtract_signal2(float *id, float *qd, long np, - float f0, int shift0, float drift0, unsigned char *channel_symbols); -int32_t wspr_decode(float *idat, float *qdat, int samples, - struct decoder_options options, struct decoder_results *decodes, - int32_t *n_results); +void sync_and_demodulate(float *id, + float *qd, + long np, + unsigned char *symbols, + float *f1, + int ifmin, + int ifmax, + float fstep, + int *shift1, + int lagmin, + int lagmax, + int lagstep, + float *drift1, + int symfac, + float *sync, + int mode); +void subtract_signal(float *id, + float *qd, + long np, + float f0, + int shift0, + float drift0, + unsigned char *channel_symbols); +void subtract_signal2(float *id, + float *qd, + long np, + float f0, + int shift0, + float drift0, + unsigned char *channel_symbols); +int wspr_decode(float *idat, + float *qdat, + int samples, + struct decoder_options options, + struct decoder_results *decodes, + int *n_results); From 7dc970ee749003db059f78f847f2e62146609636 Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 22:52:54 -0500 Subject: [PATCH 05/10] WIP chore: wsprd lib update part4 --- wsprd/wsprd.c | 224 +++++++++++++++++++++++++------------------------- wsprd/wsprd.h | 15 ++-- 2 files changed, 118 insertions(+), 121 deletions(-) diff --git a/wsprd/wsprd.c b/wsprd/wsprd.c index b512a51..2a3fdd8 100644 --- a/wsprd/wsprd.c +++ b/wsprd/wsprd.c @@ -90,15 +90,15 @@ void sync_and_demodulate(float *id, float *qd, long np, unsigned char *symbols, - float *f1, + float *freq, int ifmin, int ifmax, float fstep, - int *shift1, + int *shift, int lagmin, int lagmax, int lagstep, - float *drift1, + float *drift, int symfac, float *sync, int mode) { @@ -126,22 +126,22 @@ void sync_and_demodulate(float *id, ifmax = 0; fstep = 0.0; } else if (mode == 1) { - lagmin = *shift1; - lagmax = *shift1; + lagmin = *shift; + lagmax = *shift; } else if (mode == 2) { - lagmin = *shift1; - lagmax = *shift1; + lagmin = *shift; + lagmax = *shift; ifmin = 0; ifmax = 0; } for (int ifreq = ifmin; ifreq <= ifmax; ifreq++) { - float f0 = *f1 + ifreq * fstep; + float f0 = *freq + ifreq * fstep; for (int lag = lagmin; lag <= lagmax; lag = lag + lagstep) { float ss = 0.0; float totp = 0.0; for (int i = 0; i < NSYM; i++) { - float fp = f0 + (*drift1 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; + float fp = f0 + (*drift / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; if (i == 0 || (fp != fplast)) { // only calculate sin/cos if necessary float dphi0 = TWOPIDT * (fp - DF15); float cdphi0 = cosf(dphi0); @@ -223,8 +223,8 @@ void sync_and_demodulate(float *id, if (mode <= 1) { // Send best params back to caller *sync = syncmax; - *shift1 = best_shift; - *f1 = fbest; + *shift = best_shift; + *freq = fbest; return; } @@ -252,14 +252,14 @@ void subtract_signal(float *id, float *qd, long np, float f0, - int shift0, - float drift0, + int shift, + float drift, unsigned char *channel_symbols) { float c0[NSPERSYM], s0[NSPERSYM]; for (int i = 0; i < NSYM; i++) { - float fp = f0 + ((float)drift0 / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; + float fp = f0 + ((float)drift / 2.0) * ((float)i - (float)NBITS) / (float)NBITS; float dphi = TWOPIDT * (fp + ((float)channel_symbols[i] - 1.5) * DF); float cdphi = cosf(dphi); @@ -277,7 +277,7 @@ void subtract_signal(float *id, float q0 = 0.0; for (int j = 0; j < NSPERSYM; j++) { - int k = shift0 + i * NSPERSYM + j; + int k = shift + i * NSPERSYM + j; if ((k > 0) & (k < np)) { i0 = i0 + id[k] * c0[j] + qd[k] * s0[j]; q0 = q0 - id[k] * s0[j] + qd[k] * c0[j]; @@ -289,7 +289,7 @@ void subtract_signal(float *id, q0 = q0 / (float)NSPERSYM; for (int j = 0; j < NSPERSYM; j++) { - int k = shift0 + i * NSPERSYM + j; + int k = shift + i * NSPERSYM + j; if ((k > 0) & (k < np)) { id[k] = id[k] - (i0 * c0[j] - q0 * s0[j]); qd[k] = qd[k] - (q0 * c0[j] + i0 * s0[j]); @@ -305,8 +305,8 @@ void subtract_signal2(float *id, float *qd, long np, float f0, - int shift0, - float drift0, + int shift, + float drift, unsigned char *channel_symbols) { float phi = 0.0; @@ -328,7 +328,7 @@ void subtract_signal2(float *id, for (int i = 0; i < NSYM; i++) { float cs = (float)channel_symbols[i]; - float dphi = TWOPIDT * (f0 + (drift0 / 2.0) * ((float)i - (float)NSYM / 2.0) / ((float)NSYM / 2.0) + (cs - 1.5) * DF); + float dphi = TWOPIDT * (f0 + (drift / 2.0) * ((float)i - (float)NSYM / 2.0) / ((float)NSYM / 2.0) + (cs - 1.5) * DF); for (int j = 0; j < NSPERSYM; j++) { int ii = NSPERSYM * i + j; @@ -357,11 +357,11 @@ void subtract_signal2(float *id, // s(t) * conjugate(r(t)) // beginning of first symbol in reference signal is at i=0 - // beginning of first symbol in received data is at shift0. + // beginning of first symbol in received data is at shift value. // filter transient lasts nfilt samples // leave nfilt zeros as a pad at the beginning of the unfiltered reference signal for (int i = 0; i < NSYM * NSPERSYM; i++) { - int k = shift0 + i; + int k = shift + i; if ((k > 0) && (k < np)) { ci[i + nfilt] = id[k] * refi[i] + qd[k] * refq[i]; cq[i + nfilt] = qd[k] * refi[i] - id[k] * refq[i]; @@ -381,7 +381,7 @@ void subtract_signal2(float *id, // subtract c(t)*r(t) here // (ci+j*cq)(refi+j*refq)=(ci*refi-cq*refq)+j(ci*refq+cq*refi) // beginning of first symbol in reference signal is at i=nfilt - // beginning of first symbol in received data is at shift0. + // beginning of first symbol in received data is at shift value. for (int i = 0; i < NSYM * NSPERSYM; i++) { if (i < nfilt / 2) { // take care of the end effect (LPF step response) here norm = partialsum[nfilt / 2 + i]; @@ -390,7 +390,7 @@ void subtract_signal2(float *id, } else { norm = 1.0; } - int k = shift0 + i; + int k = shift + i; int j = i + nfilt; if ((k > 0) && (k < np)) { id[k] = id[k] - (cfi[j] * refi[i] - cfq[j] * refq[i]) / norm; @@ -402,27 +402,23 @@ void subtract_signal2(float *id, int wspr_decode(float *idat, - float *qdat, - int samples, - struct decoder_options options, - struct decoder_results *decodes, - int *n_results) { - - uint8_t symbols[NBITS * 2] = {0}; - uint8_t decdata[(NBITS + 7) / 8] = {0}; - int8_t message[12] = {0}; + float *qdat, + int samples, + struct decoder_options options, + struct decoder_results *decodes, + int *n_results) { /* Parameters used for performance-tuning */ - float minsync1 = 0.10; // First sync limit - float minsync2 = 0.12; // Second sync limit - int iifac = 3; // Step size in final DT peakup - int symfac = 50; // Soft-symbol normalizing factor - int maxdrift = 4; // Maximum (+/-) drift - float minrms = 52.0 * (symfac / 64.0); // Final test for plausible decoding - int delta = 60; // Fano threshold step - int maxcycles = 10000; // Fano timeout limit - float fmin = -110.0; - float fmax = 110.0; + float minsync1 = 0.10; // First sync limit + float minsync2 = 0.12; // Second sync limit + int iifac = 3; // Step size in final DT peakup + int symfac = 50; // Soft-symbol normalizing factor + int maxdrift = 4; // Maximum (+/-) drift + float minrms = 52.0 * (symfac / 64.0); // Final test for plausible decoding + int delta = 60; // Fano threshold step + int maxcycles = 10000; // Fano timeout limit + float fmin = -110.0; + float fmax = 110.0; /* Search live parameters */ float fstep; @@ -439,22 +435,22 @@ int wspr_decode(float *idat, /* CPU usage stats */ uint32_t metric, cycles, maxnp; - /* Candidates */ + /* Candidates properties */ struct cand candidates[200]; - float freq0[200], freq1 = 0.0; - float drift0[200], drift1 = 0.0; - float sync0[200], sync1 = 0.0; - float snr0[200]; - int shift0[200], shift1 = 0; + + /* Decoded candidate */ + uint8_t symbols[NBITS * 2] = {0}; + uint8_t decdata[(NBITS + 7) / 8] = {0}; + int8_t message[12] = {0}; /* Results */ - float allfreqs[100] = {0}; - char allcalls[100][13] = {0}; char callsign[13] = {0}; char call_loc_pow[23] = {0}; char call[13] = {0}; char loc[7] = {0}; char pwr[3] = {0}; + float allfreqs[100] = {0}; + char allcalls[100][13] = {0}; /* Setup metric table */ int32_t mettab[2][256]; @@ -588,20 +584,22 @@ int wspr_decode(float *idat, // Find all local maxima in smoothed spectrum. for (int i = 0; i < 200; i++) { - freq0[i] = 0.0; - snr0[i] = 0.0; - drift0[i] = 0.0; - shift0[i] = 0; - sync0[i] = 0.0; + candidates[i].freq = 0.0; + candidates[i].snr = 0.0; + candidates[i].drift = 0.0; + candidates[i].shift = 0; + candidates[i].sync = 0.0; } - int32_t npk = 0; + int npk = 0; + unsigned char candidate; for (int j = 1; j < 410; j++) { - if ((smspec[j] > smspec[j - 1]) && - (smspec[j] > smspec[j + 1]) && - (npk < 200)) { - freq0[npk] = (j - 205) * (DF / 2.0); - snr0[npk] = 10.0 * log10f(smspec[j]) - snr_scaling_factor; + candidate = (smspec[j] > smspec[j - 1]) && + (smspec[j] > smspec[j + 1]) && + (npk < 200); + if (candidate) { + candidates[npk].freq = (j - 205) * (DF / 2.0); + candidates[npk].snr = 10.0 * log10f(smspec[j]) - snr_scaling_factor; npk++; } } @@ -609,25 +607,21 @@ int wspr_decode(float *idat, // Don't waste time on signals outside of the range [fmin,fmax]. int i = 0; for (int j = 0; j < npk; j++) { - if (freq0[j] >= fmin && freq0[j] <= fmax) { - freq0[i] = freq0[j]; - snr0[i] = snr0[j]; + if (candidates[j].freq >= fmin && candidates[j].freq <= fmax) { + candidates[i] = candidates[j]; i++; } } npk = i; // bubble sort on snr, bringing freq along for the ride - float tmp; + struct cand tmp; for (int pass = 1; pass <= npk - 1; pass++) { for (int k = 0; k < npk - pass; k++) { - if (snr0[k] < snr0[k + 1]) { - tmp = snr0[k]; - snr0[k] = snr0[k + 1]; - snr0[k + 1] = tmp; - tmp = freq0[k]; - freq0[k] = freq0[k + 1]; - freq0[k + 1] = tmp; + if (candidates[k].snr < candidates[k + 1].snr) { + tmp = candidates[k]; + candidates[k] = candidates[k + 1]; + candidates[k + 1] = tmp; } } } @@ -646,8 +640,8 @@ int wspr_decode(float *idat, signal vector. */ for (int j = 0; j < npk; j++) { // For each candidate... - float smax = -1e30; - int if0 = freq0[j] / (DF / 2.0) + NSPERSYM; + float sync, sync_max = -1e30; + int if0 = candidates[j].freq / (DF / 2.0) + NSPERSYM; for (int ifr = if0 - 1; ifr <= if0 + 1; ifr++) { // Freq search for (int k0 = -10; k0 < 22; k0++) { // Time search for (int idrift = -maxdrift; idrift <= maxdrift; idrift++) { // Drift search @@ -664,15 +658,15 @@ int wspr_decode(float *idat, ss = ss + (2 * pr3vector[k] - 1) * ((p1 + p3) - (p0 + p2)); pow = pow + p0 + p1 + p2 + p3; - sync1 = ss / pow; + sync = ss / pow; } } - if (sync1 > smax) { // Save coarse parameters - smax = sync1; - shift0[j] = 128 * (k0 + 1); - drift0[j] = idrift; - freq0[j] = (ifr - NSPERSYM) * (DF / 2.0); - sync0[j] = sync1; + if (sync > sync_max) { // Save coarse parameters + sync_max = sync; + candidates[j].shift = 128 * (k0 + 1); + candidates[j].drift = idrift; + candidates[j].freq = (ifr - NSPERSYM) * (DF / 2.0); + candidates[j].sync = sync; } } } @@ -697,38 +691,42 @@ int wspr_decode(float *idat, */ for (int j = 0; j < npk; j++) { - memset(symbols, 0, sizeof(char) * NBITS * 2); memset(callsign, 0, sizeof(char) * 13); memset(call_loc_pow, 0, sizeof(char) * 23); memset(call, 0, sizeof(char) * 13); memset(loc, 0, sizeof(char) * 7); memset(pwr, 0, sizeof(char) * 3); - freq1 = freq0[j]; - drift1 = drift0[j]; - shift1 = shift0[j]; - sync1 = sync0[j]; + float freq = candidates[j].freq; + float drift = candidates[j].drift; + float sync = candidates[j].sync; + int shift = candidates[j].shift; - // Coarse-grid search for best sync lag (mode 0) + // Search for best sync lag (mode 0) fstep = 0.0; ifmin = 0; ifmax = 0; - lagmin = shift1 - 128; - lagmax = shift1 + 128; + lagmin = shift - 128; + lagmax = shift + 128; lagstep = 8; if (options.quickmode) lagstep = 16; - sync_and_demodulate(idat, qdat, samples, symbols, &freq1, ifmin, ifmax, fstep, &shift1, - lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 0); + sync_and_demodulate(idat, qdat, samples, symbols, &freq, ifmin, ifmax, fstep, &shift, + lagmin, lagmax, lagstep, &drift, symfac, &sync, 0); - // Coarse-grid search for frequency peak (mode 1) + // Search for frequency peak (mode 1) fstep = 0.1; ifmin = -2; ifmax = 2; - sync_and_demodulate(idat, qdat, samples, symbols, &freq1, ifmin, ifmax, fstep, &shift1, - lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 1); + sync_and_demodulate(idat, qdat, samples, symbols, &freq, ifmin, ifmax, fstep, &shift, + lagmin, lagmax, lagstep, &drift, symfac, &sync, 1); - if (sync1 > minsync1) { + candidates[j].freq = freq; + candidates[j].shift = shift; + candidates[j].drift = drift; + candidates[j].sync = sync; + + if (sync > minsync1) { worth_a_try = 1; } else { worth_a_try = 0; @@ -740,12 +738,12 @@ int wspr_decode(float *idat, ii = (idt + 1) / 2; if (idt % 2 == 1) ii = -ii; ii = iifac * ii; - int jiggered_shift = shift1 + ii; + int jiggered_shift = shift + ii; // Use mode 2 to get soft-decision symbols - sync_and_demodulate(idat, qdat, samples, symbols, &freq1, ifmin, ifmax, fstep, - &jiggered_shift, lagmin, lagmax, lagstep, &drift1, symfac, - &sync1, 2); + sync_and_demodulate(idat, qdat, samples, symbols, &freq, ifmin, ifmax, fstep, + &jiggered_shift, lagmin, lagmax, lagstep, &drift, symfac, + &sync, 2); float sq = 0.0; for (i = 0; i < NSYM; i++) { float y = (float)symbols[i] - 128.0; @@ -753,13 +751,14 @@ int wspr_decode(float *idat, } float rms = sqrtf(sq / (float)NSYM); - if ((sync1 > minsync2) && (rms > minrms)) { + if ((sync > minsync2) && (rms > minrms)) { deinterleave(symbols); not_decoded = fano(&metric, &cycles, &maxnp, decdata, symbols, NBITS, mettab, delta, maxcycles); } idt++; - if (options.quickmode) break; + if (options.quickmode) + break; } if (worth_a_try && !not_decoded) { @@ -778,9 +777,8 @@ int wspr_decode(float *idat, if (options.subtraction && (ipass == 0) && !noprint) { unsigned char channel_symbols[NSYM]; - //if (get_wspr_channel_symbols(call_loc_pow, hashtab, channel_symbols)) { if (get_wspr_channel_symbols(call_loc_pow, hashtab, loctab, channel_symbols)) { - subtract_signal2(idat, qdat, samples, freq1, shift1, drift1, channel_symbols); + subtract_signal2(idat, qdat, samples, freq, shift, drift, channel_symbols); } else { break; } @@ -789,24 +787,23 @@ int wspr_decode(float *idat, // Remove dupes (same callsign and freq within 3 Hz) int32_t dupe = 0; for (i = 0; i < uniques; i++) { - if (!strcmp(callsign, allcalls[i]) && (fabs(freq1 - allfreqs[i]) < 3.0)) + if (!strcmp(callsign, allcalls[i]) && (fabs(freq - allfreqs[i]) < 3.0)) dupe = 1; } if (!dupe) { strcpy(allcalls[uniques], callsign); - allfreqs[uniques] = freq1; + allfreqs[uniques] = freq; uniques++; double dialfreq = (double)options.freq / 1e6; - double freq_print = dialfreq + (1500.0 + freq1) / 1e6; - float dt_print = shift1 * DT - 2.0; + double freq_print = dialfreq + (1500.0 + freq) / 1e6; - decodes[uniques - 1].sync = sync1; - decodes[uniques - 1].snr = snr0[j]; - decodes[uniques - 1].dt = dt_print; + decodes[uniques - 1].sync = candidates[j].sync; + decodes[uniques - 1].snr = candidates[j].snr; + decodes[uniques - 1].dt = shift * DT - 2.0; decodes[uniques - 1].freq = freq_print; - decodes[uniques - 1].drift = drift1; + decodes[uniques - 1].drift = drift; decodes[uniques - 1].cycles = cycles; decodes[uniques - 1].jitter = ii; strcpy(decodes[uniques - 1].message, call_loc_pow); @@ -818,20 +815,19 @@ int wspr_decode(float *idat, } } - // sort the result + /* Sort the result */ struct decoder_results temp; for (int j = 1; j <= uniques - 1; j++) { for (int k = 0; k < uniques - j; k++) { if (decodes[k].snr < decodes[k + 1].snr) { temp = decodes[k]; decodes[k] = decodes[k + 1]; - ; decodes[k + 1] = temp; } } } - // Return number of spots to the calling fct + /* Return number of spots to the calling fct */ *n_results = uniques; fftwf_free(fftin); diff --git a/wsprd/wsprd.h b/wsprd/wsprd.h index fa004b4..088c470 100644 --- a/wsprd/wsprd.h +++ b/wsprd/wsprd.h @@ -70,15 +70,15 @@ void sync_and_demodulate(float *id, float *qd, long np, unsigned char *symbols, - float *f1, + float *freq, int ifmin, int ifmax, float fstep, - int *shift1, + int *shift, int lagmin, int lagmax, int lagstep, - float *drift1, + float *drift, int symfac, float *sync, int mode); @@ -86,15 +86,15 @@ void subtract_signal(float *id, float *qd, long np, float f0, - int shift0, - float drift0, + int shift, + float drift, unsigned char *channel_symbols); void subtract_signal2(float *id, float *qd, long np, float f0, - int shift0, - float drift0, + int shift, + float drift, unsigned char *channel_symbols); int wspr_decode(float *idat, float *qdat, @@ -102,3 +102,4 @@ int wspr_decode(float *idat, struct decoder_options options, struct decoder_results *decodes, int *n_results); + From df6e87068b0e6ce4ccc74d3591643bf6050b19cd Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 22:58:27 -0500 Subject: [PATCH 06/10] chore: wsprd lib update --- Makefile | 4 ++-- wsprd/wsprd_utils.c | 2 +- wsprd/wsprsim_utils.c | 23 ++++++++++++----------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 2672352..14b689b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC = clang -CFLAGS = -O3 -std=gnu17 -Wall -LIBS = -lusb-1.0 -lrtlsdr -lpthread -lfftw3f -lcurl -lm -Wall +CFLAGS = -O3 -std=gnu17 +LIBS = -lusb-1.0 -lrtlsdr -lpthread -lfftw3f -lcurl -lm # Note # gcc is a bit faster that clang on this app diff --git a/wsprd/wsprd_utils.c b/wsprd/wsprd_utils.c index 96e54fa..12f8d4b 100644 --- a/wsprd/wsprd_utils.c +++ b/wsprd/wsprd_utils.c @@ -297,7 +297,7 @@ int unpk_(signed char *message, char *hashtab, char *loctab, char *call_loc_pow, strncat(call_loc_pow, cdbm, 2); strncat(call_loc_pow, "\0", 1); int nu = ndbm % 10; - if (nu == 0 || nu == 3 || nu == 7 || nu == 10) { // make sure power is OK + if (nu == 0 || nu == 3 || nu == 7) { // make sure power is OK ihash = nhash(callsign, strlen(callsign), (uint32_t)146); strcpy(hashtab + ihash * 13, callsign); } else diff --git a/wsprd/wsprsim_utils.c b/wsprd/wsprsim_utils.c index 7845cc7..b64118f 100644 --- a/wsprd/wsprsim_utils.c +++ b/wsprd/wsprsim_utils.c @@ -164,16 +164,17 @@ int get_wspr_channel_symbols(char *rawmessage, char *hashtab, char *loctab, unsi int m = 0, ntype = 0; long unsigned int n = 0; int i, j, ihash; - unsigned char pr3[162] = - {1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, - 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, - 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, - 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, - 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, - 0, 0}; + unsigned char pr3vector[162] = { + 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, + 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, + 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, + 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0 }; + int nu[10] = {0, -1, 1, 0, -1, 2, 1, 0, -1, 1}; char *callsign, *grid, *powstr; char grid4[5], message[23]; @@ -297,7 +298,7 @@ int get_wspr_channel_symbols(char *rawmessage, char *hashtab, char *loctab, unsi interleave(channelbits); for (i = 0; i < 162; i++) { - symbols[i] = 2 * channelbits[i] + pr3[i]; + symbols[i] = 2 * channelbits[i] + pr3vector[i]; } free(check_call_loc_pow); free(check_callsign); From 73f4e8c411f8be3045e0cfbd69c154632dc8076e Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 23:15:27 -0500 Subject: [PATCH 07/10] chore: version format update for wsprnet --- rtlsdr_wsprd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtlsdr_wsprd.c b/rtlsdr_wsprd.c index bec6a5c..e2ede42 100644 --- a/rtlsdr_wsprd.c +++ b/rtlsdr_wsprd.c @@ -324,7 +324,7 @@ void postSpots(uint32_t n_results) { // "Table 'wsprnet_db.activity' doesn't exist" reported on web site... // Anyone has doc about this? if (n_results == 0) { - snprintf(url, sizeof(url) - 1, "http://wsprnet.org/post?function=wsprstat&rcall=%s&rgrid=%s&rqrg=%.6f&tpct=%.2f&tqrg=%.6f&dbm=%d&version=rtlsdr-wsprd_v0.4.2&mode=2", + snprintf(url, sizeof(url) - 1, "http://wsprnet.org/post?function=wsprstat&rcall=%s&rgrid=%s&rqrg=%.6f&tpct=%.2f&tqrg=%.6f&dbm=%d&version=rtlsdr-050&mode=2", dec_options.rcall, dec_options.rloc, rx_options.realfreq / 1e6, @@ -347,7 +347,7 @@ void postSpots(uint32_t n_results) { } for (uint32_t i = 0; i < n_results; i++) { - snprintf(url, sizeof(url) - 1, "http://wsprnet.org/post?function=wspr&rcall=%s&rgrid=%s&rqrg=%.6f&date=%02d%02d%02d&time=%02d%02d&sig=%.0f&dt=%.1f&tqrg=%.6f&tcall=%s&tgrid=%s&dbm=%s&version=rtlsdr-wsprd_v0.4.2&mode=2", + snprintf(url, sizeof(url) - 1, "http://wsprnet.org/post?function=wspr&rcall=%s&rgrid=%s&rqrg=%.6f&date=%02d%02d%02d&time=%02d%02d&sig=%.0f&dt=%.1f&tqrg=%.6f&tcall=%s&tgrid=%s&dbm=%s&version=rtlsdr-050&mode=2", dec_options.rcall, dec_options.rloc, dec_results[i].freq, @@ -961,7 +961,7 @@ int main(int argc, char **argv) { struct tm *gtm = gmtime(&rawtime); /* Print used parameter */ - printf("\nStarting rtlsdr-wsprd (%04d-%02d-%02d, %02d:%02dz) -- Version 0.4.2\n", + printf("\nStarting rtlsdr-wsprd (%04d-%02d-%02d, %02d:%02dz) -- Version 0.5.0\n", gtm->tm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday, gtm->tm_hour, gtm->tm_min); printf(" Callsign : %s\n", dec_options.rcall); printf(" Locator : %s\n", dec_options.rloc); From f2ce421e87470d12970058ee0f86b45a5c90efd7 Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 23:17:35 -0500 Subject: [PATCH 08/10] fix: implicit direct sampling for HF bands --- rtlsdr_wsprd.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/rtlsdr_wsprd.c b/rtlsdr_wsprd.c index e2ede42..328152c 100644 --- a/rtlsdr_wsprd.c +++ b/rtlsdr_wsprd.c @@ -721,28 +721,53 @@ int main(int argc, char **argv) { case 'f': // Frequency if (!strcasecmp(optarg, "LF")) { rx_options.dialfreq = 136000; + // Implicit direct sampling for HF bands & lower + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "MF")) { rx_options.dialfreq = 474200; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "160m")) { rx_options.dialfreq = 1836600; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "80m")) { rx_options.dialfreq = 3592600; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "60m")) { rx_options.dialfreq = 5287200; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "40m")) { rx_options.dialfreq = 7038600; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "30m")) { rx_options.dialfreq = 10138700; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "20m")) { rx_options.dialfreq = 14095600; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "17m")) { rx_options.dialfreq = 18104600; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "15m")) { rx_options.dialfreq = 21094600; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "12m")) { rx_options.dialfreq = 24924600; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "10m")) { rx_options.dialfreq = 28124600; + if (!rx_options.directsampling) + rx_options.directsampling = 2; } else if (!strcasecmp(optarg, "6m")) { rx_options.dialfreq = 50293000; } else if (!strcasecmp(optarg, "4m")) { From 6b7521102fc4fde78cf78524672f9d02f27a2ba6 Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 23:20:07 -0500 Subject: [PATCH 09/10] chore: EXIT_SUCCESS / EXIT_FAILURE --- rtlsdr_wsprd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rtlsdr_wsprd.c b/rtlsdr_wsprd.c index 328152c..1bc60c7 100644 --- a/rtlsdr_wsprd.c +++ b/rtlsdr_wsprd.c @@ -847,18 +847,18 @@ int main(int argc, char **argv) { if (rx_options.selftest == true) { if (decoderSelfTest()) { fprintf(stdout, "Self-test SUCCESS!\n"); - exit(0); + return EXIT_SUCCESS; } else { fprintf(stderr, "Self-test FAILED!\n"); - exit(1); + return EXIT_FAILURE; } } if (rx_options.readfile == true) { fprintf(stdout, "Reading IQ file: %s\n", rx_options.filename); decodeRecordedFile(rx_options.filename); - exit(0); + return EXIT_SUCCESS; } if (rx_options.writefile == true) { @@ -868,19 +868,19 @@ int main(int argc, char **argv) { if (rx_options.dialfreq == 0) { fprintf(stderr, "Please specify a dial frequency.\n"); fprintf(stderr, " --help for usage...\n"); - exit(1); + return EXIT_FAILURE; } if (dec_options.rcall[0] == 0) { fprintf(stderr, "Please specify your callsign.\n"); fprintf(stderr, " --help for usage...\n"); - exit(1); + return EXIT_FAILURE; } if (dec_options.rloc[0] == 0) { fprintf(stderr, "Please specify your locator.\n"); fprintf(stderr, " --help for usage...\n"); - exit(1); + return EXIT_FAILURE; } /* Calcule shift offset */ From 15913219f268001616f7c87df3f959caf0b14b5f Mon Sep 17 00:00:00 2001 From: Guenael Date: Wed, 22 Dec 2021 23:22:19 -0500 Subject: [PATCH 10/10] fix: always true condition fixed --- wsprd/wsprd_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsprd/wsprd_utils.c b/wsprd/wsprd_utils.c index 12f8d4b..9a63009 100644 --- a/wsprd/wsprd_utils.c +++ b/wsprd/wsprd_utils.c @@ -311,7 +311,7 @@ int unpk_(signed char *message, char *hashtab, char *loctab, char *call_loc_pow, strncat(grid6, callsign + len - 1, 1); strncat(grid6, callsign, len - 1); int nu = ndbm % 10; - if ((nu != 0 && nu != 3 && nu != 7 && nu != 10) || + if ((nu != 0 && nu != 3 && nu != 7) || !isalpha(grid6[0]) || !isalpha(grid6[1]) || !isdigit(grid6[2]) || !isdigit(grid6[3])) { // not testing 4'th and 5'th chars because of this case: JO33 40