| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2023-11-19 05:24:06 +01:00
										 |  |  | // Copyright (C) 2023 Edouard Griffiths, F4EXB <f4exb06@gmail.com>               //
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This is the code from ft8mon: https://github.com/rtmrtmrtmrtm/ft8mon          //
 | 
					
						
							|  |  |  | // reformatted and adapted to Qt and SDRangel context                            //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify          //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by          //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                  //
 | 
					
						
							|  |  |  | // (at your option) any later version.                                           //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,               //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2024-03-28 15:15:48 +01:00
										 |  |  | #include <regex>
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-28 15:15:48 +01:00
										 |  |  | #include "packing.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-12 20:54:42 +01:00
										 |  |  | #include "unpack0.h"
 | 
					
						
							| 
									
										
										
										
											2024-03-28 15:15:48 +01:00
										 |  |  | #include "pack0.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | #include "util.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace FT8 { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | int Packing::ihashcall(std::string rawcall, int m) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     std::string call = trim(rawcall); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     const char *chars = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     while (call.size() < 11) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         call += " "; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     unsigned long long x = 0; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     for (int i = 0; i < 11; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int c = call[i]; | 
					
						
							|  |  |  |         const char *p = strchr(chars, c); | 
					
						
							| 
									
										
										
										
											2023-01-24 04:05:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (p) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             int j = p - chars; | 
					
						
							|  |  |  |             x = 38 * x + j; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     x = x * 47055833459LL; | 
					
						
							|  |  |  |     x = x >> (64 - m); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // turn 28 bits of packed call into the call
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | std::string Packing::unpackcall(int x) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     char tmp[64]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const char *c1 = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 
					
						
							|  |  |  |     const char *c2 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 
					
						
							|  |  |  |     const char *c3 = "0123456789"; | 
					
						
							|  |  |  |     const char *c4 = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (x == 0) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         return "DE"; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (x == 1) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         return "QRZ"; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (x == 2) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         return "CQ"; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     if (x <= 1002) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         sprintf(tmp, "CQ %d", x - 3); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |         return std::string(tmp); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     if (x <= 532443) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         x -= 1003; | 
					
						
							|  |  |  |         int ci1 = x / (27 * 27 * 27); | 
					
						
							|  |  |  |         x %= 27 * 27 * 27; | 
					
						
							|  |  |  |         int ci2 = x / (27 * 27); | 
					
						
							|  |  |  |         x %= 27 * 27; | 
					
						
							|  |  |  |         int ci3 = x / 27; | 
					
						
							|  |  |  |         x %= 27; | 
					
						
							|  |  |  |         int ci4 = x; | 
					
						
							|  |  |  |         sprintf(tmp, "CQ %c%c%c%c", c4[ci1], c4[ci2], c4[ci3], c4[ci4]); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |         return std::string(tmp); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (x < NTOKENS) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         return "<TOKEN>"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     x -= NTOKENS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (x < MAX22) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // 22-bit hash...
 | 
					
						
							|  |  |  |         std::string s; | 
					
						
							|  |  |  |         hashes_mu.lock(); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (hashes22.count(x) > 0) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |             s = hashes22[x]; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |             s = "<...22>"; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         hashes_mu.unlock(); | 
					
						
							|  |  |  |         return s; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     x -= MAX22; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     char a[7]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     a[5] = c4[x % 27]; | 
					
						
							|  |  |  |     x = x / 27; | 
					
						
							|  |  |  |     a[4] = c4[x % 27]; | 
					
						
							|  |  |  |     x = x / 27; | 
					
						
							|  |  |  |     a[3] = c4[x % 27]; | 
					
						
							|  |  |  |     x = x / 27; | 
					
						
							|  |  |  |     a[2] = c3[x % 10]; | 
					
						
							|  |  |  |     x = x / 10; | 
					
						
							|  |  |  |     a[1] = c2[x % 36]; | 
					
						
							|  |  |  |     x = x / 36; | 
					
						
							|  |  |  |     a[0] = c1[x]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     a[6] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     return std::string(a); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // unpack a 15-bit grid square &c.
 | 
					
						
							|  |  |  | // 77-bit version, from inspection of packjt77.f90.
 | 
					
						
							|  |  |  | // ir is the bit after the two 28+1-bit callee/caller.
 | 
					
						
							| 
									
										
										
										
											2023-01-28 22:45:07 +01:00
										 |  |  | std::string Packing::unpackgrid15(int ng, int ir) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (ng < NGBASE) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // maidenhead grid system:
 | 
					
						
							|  |  |  |         //   latitude from south pole to north pole.
 | 
					
						
							|  |  |  |         //   longitude eastward from anti-meridian.
 | 
					
						
							|  |  |  |         //   first: 20 degrees longitude.
 | 
					
						
							|  |  |  |         //   second: 10 degrees latitude.
 | 
					
						
							|  |  |  |         //   third: 2 degrees longitude.
 | 
					
						
							|  |  |  |         //   fourth: 1 degree latitude.
 | 
					
						
							|  |  |  |         // so there are 18*18*10*10 possibilities.
 | 
					
						
							|  |  |  |         int x1 = ng / (18 * 10 * 10); | 
					
						
							|  |  |  |         ng %= 18 * 10 * 10; | 
					
						
							|  |  |  |         int x2 = ng / (10 * 10); | 
					
						
							|  |  |  |         ng %= 10 * 10; | 
					
						
							|  |  |  |         int x3 = ng / 10; | 
					
						
							|  |  |  |         ng %= 10; | 
					
						
							|  |  |  |         int x4 = ng; | 
					
						
							|  |  |  |         char tmp[5]; | 
					
						
							|  |  |  |         tmp[0] = 'A' + x1; | 
					
						
							|  |  |  |         tmp[1] = 'A' + x2; | 
					
						
							|  |  |  |         tmp[2] = '0' + x3; | 
					
						
							|  |  |  |         tmp[3] = '0' + x4; | 
					
						
							|  |  |  |         tmp[4] = '\0'; | 
					
						
							|  |  |  |         return tmp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ng -= NGBASE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (ng == 1) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         return "   "; // ???
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (ng == 2) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         return "RRR "; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (ng == 3) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         return "RR73"; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (ng == 4) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         return "73  "; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int db = ng - 35; | 
					
						
							|  |  |  |     char tmp[16]; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (db >= 0) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         sprintf(tmp, "%s+%02d", ir ? "R" : "", db); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         sprintf(tmp, "%s-%02d", ir ? "R" : "", 0 - db); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return std::string(tmp); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 22:45:07 +01:00
										 |  |  | std::string Packing::unpackgrid25(int ng) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int x1 = ng / (18 * 10 * 10 * 25 * 25); | 
					
						
							|  |  |  |     ng %= (18 * 10 * 10 * 25 * 25); | 
					
						
							|  |  |  |     int x2 = ng / (10 * 10 * 25 * 25); | 
					
						
							|  |  |  |     ng %= (10 * 10 * 25 * 25); | 
					
						
							|  |  |  |     int x3 = ng / (10 * 25 * 25); | 
					
						
							|  |  |  |     ng %= (10 * 25 * 25); | 
					
						
							|  |  |  |     int x4 = ng / (25 * 25); | 
					
						
							|  |  |  |     ng %= (25 * 25); | 
					
						
							|  |  |  |     int x5 = ng / (25); | 
					
						
							|  |  |  |     ng %= (25); | 
					
						
							|  |  |  |     int x6 = ng; | 
					
						
							|  |  |  |     char tmp[7]; | 
					
						
							|  |  |  |     tmp[0] = 'A' + x1; | 
					
						
							|  |  |  |     tmp[1] = 'A' + x2; | 
					
						
							|  |  |  |     tmp[2] = '0' + x3; | 
					
						
							|  |  |  |     tmp[3] = '0' + x4; | 
					
						
							|  |  |  |     tmp[4] = 'A' + x5; | 
					
						
							|  |  |  |     tmp[5] = 'A' + x6; | 
					
						
							|  |  |  |     tmp[6] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return std::string(tmp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | void Packing::remember_call(std::string call) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     hashes_mu.lock(); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     if (call.size() >= 3 && call[0] != '<') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         hashes22[ihashcall(call, 22)] = call; | 
					
						
							|  |  |  |         hashes12[ihashcall(call, 12)] = call; | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  |         hashes10[ihashcall(call, 10)] = call; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     hashes_mu.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // i3 == 4
 | 
					
						
							|  |  |  | // a call that doesn't fit in 28 bits.
 | 
					
						
							|  |  |  | // 12 bits: hash of a previous call
 | 
					
						
							|  |  |  | // 58 bits: 11 characters
 | 
					
						
							|  |  |  | // 1 bit: swap
 | 
					
						
							|  |  |  | // 2 bits: 1 RRR, 2 RR73, 3 73
 | 
					
						
							|  |  |  | // 1 bit: 1 means CQ
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | std::string Packing::unpack_4(int a77[], std::string& call1str, std::string& call2str, std::string& locstr) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     (void) locstr; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     // 38 possible characters:
 | 
					
						
							|  |  |  |     const char *chars = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/"; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     long long n58 = un64(a77, 12, 58); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     char call[16]; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     for (int i = 0; i < 11; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         call[10 - i] = chars[n58 % 38]; | 
					
						
							|  |  |  |         n58 = n58 / 38; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     call[11] = '\0'; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     std::string callstr(call); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     remember_call(callstr); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (un64(a77, 73, 1) == 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         call1str = std::string("CQ ") + callstr; | 
					
						
							|  |  |  |         return call1str; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int x12 = un64(a77, 0, 12); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     // 12-bit hash
 | 
					
						
							|  |  |  |     hashes_mu.lock(); | 
					
						
							|  |  |  |     std::string ocall; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (hashes12.count(x12) > 0) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         ocall = hashes12[x12]; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         ocall = "<...12>"; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     hashes_mu.unlock(); | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int swap = un64(a77, 70, 1); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     std::string msg; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     if (swap) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-29 23:20:58 +01:00
										 |  |  |         msg = call1str + " " + ocall; | 
					
						
							|  |  |  |         call1str = trim(call); | 
					
						
							|  |  |  |         call2str = trim(ocall); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         msg = std::string(ocall) + " " + call; | 
					
						
							| 
									
										
										
										
											2023-01-29 23:20:58 +01:00
										 |  |  |         call1str = trim(ocall); | 
					
						
							|  |  |  |         call2str = trim(call); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int suffix = un64(a77, 71, 2); | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (suffix == 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         locstr = " RRR"; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     } else if (suffix == 2) { | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |         locstr = " RR73"; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     } else if (suffix == 3) { | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |         locstr = " 73"; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     msg += locstr; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     return msg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // i3=1
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | std::string Packing::unpack_1(int a77[], std::string& call1str, std::string& call2str, std::string& locstr) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     // type 1:
 | 
					
						
							|  |  |  |     // 28 call1
 | 
					
						
							|  |  |  |     // 1 P/R
 | 
					
						
							|  |  |  |     // 28 call2
 | 
					
						
							|  |  |  |     // 1 P/R
 | 
					
						
							|  |  |  |     // 1 ???
 | 
					
						
							|  |  |  |     // 15 grid
 | 
					
						
							|  |  |  |     // 3 type
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int i = 0; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int call1 = un64(a77, i, 28); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 28; | 
					
						
							|  |  |  |     int rover1 = a77[i]; | 
					
						
							|  |  |  |     i += 1; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int call2 = un64(a77, i, 28); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 28; | 
					
						
							|  |  |  |     int rover2 = a77[i]; | 
					
						
							|  |  |  |     i += 1; | 
					
						
							|  |  |  |     int ir = a77[i]; | 
					
						
							|  |  |  |     i += 1; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int grid = un64(a77, i, 15); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 15; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int i3 = un64(a77, i, 3); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 3; | 
					
						
							| 
									
										
										
										
											2023-01-24 04:05:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!((i3 == 1 || i3 == 2) && i == 77)) { | 
					
						
							|  |  |  |         return std::string(""); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     call1str = trim(unpackcall(call1)); | 
					
						
							|  |  |  |     call2str = trim(unpackcall(call2)); | 
					
						
							| 
									
										
										
										
											2023-01-28 22:45:07 +01:00
										 |  |  |     locstr = unpackgrid15(grid, ir); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     remember_call(call1str); | 
					
						
							|  |  |  |     remember_call(call2str); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     const std::string pr = (i3 == 1 ? "/R" : "/P"); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     return call1str + (rover1 ? pr : "") + " " + call2str + (rover2 ? pr : "") + " " + locstr; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 22:45:07 +01:00
										 |  |  | std::string Packing::unpack_5(int a77[], std::string& call1str, std::string& call2str, std::string& locstr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int x12 = un64(a77, 0, 12); | 
					
						
							|  |  |  |     // 12-bit hash
 | 
					
						
							|  |  |  |     hashes_mu.lock(); | 
					
						
							|  |  |  |     std::string ocall; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (hashes12.count(x12) > 0) { | 
					
						
							|  |  |  |         ocall = hashes12[x12]; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ocall = "<...12>"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     call1str = std::string(ocall); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int x22 = un64(a77, 12, 22); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (hashes22.count(x22) > 0) { | 
					
						
							|  |  |  |         ocall = hashes12[x22]; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ocall = "<...22>"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-29 19:27:45 +01:00
										 |  |  |     hashes_mu.unlock(); | 
					
						
							| 
									
										
										
										
											2023-01-28 22:45:07 +01:00
										 |  |  |     call2str = std::string(ocall); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // mext bit is alway for R
 | 
					
						
							|  |  |  |     int i = 12+ 22 +1; | 
					
						
							|  |  |  |     // r3
 | 
					
						
							|  |  |  |     int rst = un64(a77, i, 3); | 
					
						
							|  |  |  |     rst = 52 + 10 * rst; | 
					
						
							|  |  |  |     i += 3; | 
					
						
							|  |  |  |     int qsonb = un64(a77, i, 11); | 
					
						
							|  |  |  |     char report[16]; | 
					
						
							|  |  |  |     sprintf(report, "%d%04d", rst, qsonb); | 
					
						
							|  |  |  |     i += 11; | 
					
						
							|  |  |  |     // g25
 | 
					
						
							|  |  |  |     int ng = un64(a77, i, 25); | 
					
						
							|  |  |  |     locstr = unpackgrid25(ng); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::string msg; | 
					
						
							|  |  |  |     msg = call1str + " " + call2str + " " + std::string(report) + " " + locstr; | 
					
						
							|  |  |  |     call1str += " " + std::string(report); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return msg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | // free text
 | 
					
						
							|  |  |  | // 71 bits, 13 characters, each one of 42 choices.
 | 
					
						
							|  |  |  | // reversed.
 | 
					
						
							|  |  |  | // details from wsjt-x's packjt77.f90
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | std::string Packing::unpack_0_0(int a77[], std::string& call1str, std::string& call2str, std::string& locstr) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  |     // bit fields: f71
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     (void) call2str; | 
					
						
							|  |  |  |     (void) locstr; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     // the 42 possible characters.
 | 
					
						
							|  |  |  |     const char *cc = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     boost::multiprecision::int128_t x = un128(a77, 0, 71); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     std::string msg = "0123456789123"; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     for (int i = 0; i < 13; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |         msg[13 - 1 - i] = cc[(int) (x % 42)]; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         x = x / 42; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     call1str = msg; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     return msg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  | std::string Packing::unpack_0_1(int a77[], std::string& call1str, std::string& call2str, std::string& locstr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // bit fields: c28 c28 h10 r5
 | 
					
						
							|  |  |  |     int i = 0; | 
					
						
							|  |  |  |     int call1 = un64(a77, i, 28); // c28
 | 
					
						
							|  |  |  |     i += 28; | 
					
						
							|  |  |  |     int call2 = un64(a77, i, 28); // c28
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     call1str = trim(unpackcall(call1)) + ";" + trim(unpackcall(call2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i += 28; | 
					
						
							|  |  |  |     int x10 = un64(a77, i, 10); | 
					
						
							|  |  |  |     // 10-bit hash
 | 
					
						
							|  |  |  |     hashes_mu.lock(); | 
					
						
							|  |  |  |     std::string ocall; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (hashes10.count(x10) > 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         call2str = hashes10[x10]; | 
					
						
							|  |  |  |         ocall = "<" + call2str + ">"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         call2str = "<...10>"; | 
					
						
							|  |  |  |         ocall = call2str; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     hashes_mu.unlock(); | 
					
						
							|  |  |  |     i += 10; | 
					
						
							|  |  |  |     int i5 = un64(a77, i, 5); // decode r5
 | 
					
						
							|  |  |  |     int r = 2*i5 - 30; | 
					
						
							|  |  |  |     char tmp[32]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (r >= 0) { | 
					
						
							|  |  |  |         sprintf(tmp, "+%02d", r); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         sprintf(tmp, "-%02d", -r); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     locstr = std::string(tmp); | 
					
						
							|  |  |  |     std::string msg; | 
					
						
							|  |  |  |     msg = trim(unpackcall(call1)) + " RR73;" + trim(unpackcall(call2)) + " " + ocall; | 
					
						
							|  |  |  |     return msg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 22:45:07 +01:00
										 |  |  | std::string Packing::unpack_0_5(int a77[], std::string& call1str, std::string& call2str, std::string& locstr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) call2str; | 
					
						
							|  |  |  |     (void) locstr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const char *cc = "0123456789ABCDEF"; | 
					
						
							|  |  |  |     std::string msg = "123456789ABCDEF012"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // first digit is on 3 bits
 | 
					
						
							|  |  |  |     int d0 = un64(a77, 0, 3); | 
					
						
							|  |  |  |     msg[17] = cc[d0]; | 
					
						
							|  |  |  |     // 17 hexadecimal digits = 17*4 = 68 bits
 | 
					
						
							|  |  |  |     boost::multiprecision::int128_t x = un128(a77, 3, 68); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < 17; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         msg[17 - 1 - i] = cc[(int) (x % 4)]; | 
					
						
							|  |  |  |         x = x / 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     call1str = msg; | 
					
						
							|  |  |  |     return msg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | // ARRL RTTY Round-Up states/provinces
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | const char *Packing::ru_states[] = { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", | 
					
						
							|  |  |  |     "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", | 
					
						
							|  |  |  |     "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", | 
					
						
							|  |  |  |     "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", | 
					
						
							|  |  |  |     "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY", | 
					
						
							|  |  |  |     "NB", "NS", "QC", "ON", "MB", "SK", "AB", "BC", "NWT", "NF", | 
					
						
							|  |  |  |     "LB", "NU", "YT", "PEI", "DC"}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // i3=3
 | 
					
						
							|  |  |  | // 3     TU; W9XYZ K1ABC R 579 MA           1 28 28 1 3 13   74   ARRL RTTY Roundup
 | 
					
						
							|  |  |  | //  1 TU
 | 
					
						
							|  |  |  | // 28 call1
 | 
					
						
							|  |  |  | // 28 call2
 | 
					
						
							|  |  |  | //  1 R
 | 
					
						
							|  |  |  | //  3 RST 529 to 599
 | 
					
						
							|  |  |  | // 13 state/province/serialnumber
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | std::string Packing::unpack_3(int a77[], std::string& call1str, std::string& call2str, std::string& locstr) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     (void) locstr; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     int i = 0; | 
					
						
							|  |  |  |     int tu = a77[i]; | 
					
						
							|  |  |  |     i += 1; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int call1 = un64(a77, i, 28); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 28; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int call2 = un64(a77, i, 28); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 28; | 
					
						
							|  |  |  |     int r = a77[i]; | 
					
						
							|  |  |  |     i += 1; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int rst = un64(a77, i, 3); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 3; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int serial = un64(a77, i, 13); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 13; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     call1str = trim(unpackcall(call1)); | 
					
						
							|  |  |  |     call2str = trim(unpackcall(call2)); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     rst = 529 + 10 * rst; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int statei = serial - 8001; | 
					
						
							|  |  |  |     std::string serialstr; | 
					
						
							|  |  |  |     int nstates = sizeof(ru_states) / sizeof(ru_states[0]); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     if (serial > 8000 && statei < nstates) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         serialstr = ru_states[statei]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         char tmp[32]; | 
					
						
							|  |  |  |         sprintf(tmp, "%04d", serial); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |         serialstr = std::string(tmp); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::string msg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     if (tu) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         msg += "TU; "; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     msg += call1str + " " + call2str + " "; | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     if (r) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         msg += "R "; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         char tmp[16]; | 
					
						
							|  |  |  |         sprintf(tmp, "%d ", rst); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |         msg += std::string(tmp); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     msg += serialstr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     remember_call(call1str); | 
					
						
							|  |  |  |     remember_call(call2str); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return msg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ARRL Field Day sections
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | const char *Packing::sections[] = { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     "AB ", "AK ", "AL ", "AR ", "AZ ", "BC ", "CO ", "CT ", "DE ", "EB ", | 
					
						
							|  |  |  |     "EMA", "ENY", "EPA", "EWA", "GA ", "GTA", "IA ", "ID ", "IL ", "IN ", | 
					
						
							|  |  |  |     "KS ", "KY ", "LA ", "LAX", "MAR", "MB ", "MDC", "ME ", "MI ", "MN ", | 
					
						
							|  |  |  |     "MO ", "MS ", "MT ", "NC ", "ND ", "NE ", "NFL", "NH ", "NL ", "NLI", | 
					
						
							|  |  |  |     "NM ", "NNJ", "NNY", "NT ", "NTX", "NV ", "OH ", "OK ", "ONE", "ONN", | 
					
						
							|  |  |  |     "ONS", "OR ", "ORG", "PAC", "PR ", "QC ", "RI ", "SB ", "SC ", "SCV", | 
					
						
							|  |  |  |     "SD ", "SDG", "SF ", "SFL", "SJV", "SK ", "SNJ", "STX", "SV ", "TN ", | 
					
						
							|  |  |  |     "UT ", "VA ", "VI ", "VT ", "WCF", "WI ", "WMA", "WNY", "WPA", "WTX", | 
					
						
							|  |  |  |     "WV ", "WWA", "WY ", "DX "}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // i3 = 0, n3 = 3 or 4: ARRL Field Day
 | 
					
						
							|  |  |  | // 0.3   WA9XYZ KA1ABC R 16A EMA            28 28 1 4 3 7    71   ARRL Field Day
 | 
					
						
							|  |  |  | // 0.4   WA9XYZ KA1ABC R 32A EMA            28 28 1 4 3 7    71   ARRL Field Day
 | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  | std::string Packing::unpack_0_3(int a77[], int n3, std::string& call1str, std::string& call2str, std::string& locstr) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     (void) locstr; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     int i = 0; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int call1 = un64(a77, i, 28); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 28; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int call2 = un64(a77, i, 28); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 28; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int R = un64(a77, i, 1); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 1; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int n_transmitters = un64(a77, i, 4); | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (n3 == 4) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         n_transmitters += 16; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 4; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int clss = un64(a77, i, 3); // class
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 3; | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int section = un64(a77, i, 7); // ARRL section
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     i += 7; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::string msg; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     call1str = trim(unpackcall(call1)); | 
					
						
							|  |  |  |     msg += call1str; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     msg += " "; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     call2str = trim(unpackcall(call2)); | 
					
						
							|  |  |  |     msg += call2str; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     msg += " "; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (R) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         msg += "R "; | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         char tmp[16]; | 
					
						
							|  |  |  |         sprintf(tmp, "%d%c ", n_transmitters + 1, clss + 'A'); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |         msg += std::string(tmp); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (section - 1 >= 0 && section - 1 < (int)(sizeof(sections) / sizeof(sections[0]))) { | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |         msg += sections[section - 1]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return msg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // unpack an FT8 message.
 | 
					
						
							|  |  |  | // a77 is 91 bits -- 77 plus the 14-bit CRC.
 | 
					
						
							|  |  |  | // CRC and LDPC have already been checked.
 | 
					
						
							|  |  |  | // details from wsjt-x's packjt77.f90 and 77bit.txt.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  | std::string Packing::unpack(int a77[], std::string& call1, std::string& call2, std::string& loc, std::string& type) | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-11 04:49:16 +01:00
										 |  |  |     int i3 = un64(a77, 74, 3); | 
					
						
							|  |  |  |     int n3 = un64(a77, 71, 3); | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  |     char tmp[64]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (i3 == 0) { | 
					
						
							|  |  |  |         sprintf(tmp, "%d.%d", i3, n3); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         sprintf(tmp, "%d", i3); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     type = std::string(tmp); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (i3 == 0 && n3 == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // free text
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |         return unpack_0_0(a77, call1, call2, loc); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  |     if (i3 == 0 && n3 == 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // DXpedition
 | 
					
						
							|  |  |  |         return unpack_0_1(a77, call1, call2, loc); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     if (i3 == 0 && (n3 == 3 || n3 == 4)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // ARRL Field Day
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |         return unpack_0_3(a77, n3, call1, call2, loc); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 22:45:07 +01:00
										 |  |  |     if (i3 == 0 && n3 == 5) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // telemetry
 | 
					
						
							|  |  |  |         return unpack_0_5(a77, call1, call2, loc); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     if (i3 == 1 || i3 == 2) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  |         // ordinary message or EU VHF
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |         return unpack_1(a77, call1, call2, loc); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (i3 == 3) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // RTTY Round-Up
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |         return unpack_3(a77, call1, call2, loc); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (i3 == 4) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  |         // call that doesn't fit in 28 bits (non standard call)
 | 
					
						
							| 
									
										
										
										
											2023-01-08 23:15:31 +01:00
										 |  |  |         return unpack_4(a77, call1, call2, loc); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 22:45:07 +01:00
										 |  |  |     if (i3 == 5) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // EU VHF with 6 digits locator
 | 
					
						
							|  |  |  |         return unpack_5(a77, call1, call2, loc); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-28 11:39:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     call1 = "UNK"; | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  |     sprintf(tmp, "UNK i3=%d n3=%d", i3, n3); | 
					
						
							| 
									
										
										
										
											2023-01-19 23:51:43 +01:00
										 |  |  |     return std::string(tmp); | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-28 15:15:48 +01:00
										 |  |  | bool Packing::packcall_std(int& c28, const std::string& callstr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     c28 = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (callstr.size() == 2) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (callstr == "DE") { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (callstr == "CQ") | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             c28 = 2; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (callstr == "QRZ") | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         c28 = 1; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (callstr.rfind("CQ ", 0) == 0) // special CQ
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         std::regex cq_regex_num("CQ (\\d\\d\\d)"); | 
					
						
							|  |  |  |         std::regex cq_regex_alpha("CQ ([A-Z]+)"); | 
					
						
							|  |  |  |         std::smatch cq_match; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (std::regex_match(callstr, cq_match, cq_regex_num)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             std::string cq_num_arg = cq_match[1].str(); | 
					
						
							|  |  |  |             int cq_num = stoi(cq_num_arg); | 
					
						
							|  |  |  |             c28 = 3 + cq_num; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (std::regex_match(callstr, cq_match, cq_regex_alpha)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             std::string cq_alpha_arg = cq_match[1].str(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (cq_alpha_arg.size() > 4) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             int arg_value = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (auto c : cq_alpha_arg) { | 
					
						
							|  |  |  |                 arg_value *= int(c) - int('A') + 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (cq_alpha_arg.size() == 1) { | 
					
						
							|  |  |  |                 c28 = 1003 + arg_value; | 
					
						
							|  |  |  |             } else if (cq_alpha_arg.size() == 2) { | 
					
						
							|  |  |  |                 c28 = 1030 + arg_value; | 
					
						
							|  |  |  |             } else if (cq_alpha_arg.size() == 3) { | 
					
						
							|  |  |  |                 c28 = 1759 + arg_value; | 
					
						
							|  |  |  |             } else if (cq_alpha_arg.size() == 4) { | 
					
						
							|  |  |  |                 c28 = 21442 + arg_value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((callstr.size() < 3) || (callstr.size() > 6)) { // standard callsigns are 3 to 6 characters
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::string call_prefix; | 
					
						
							|  |  |  |     int call_num; | 
					
						
							|  |  |  |     std::string call_suffix; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (isdigit(callstr.at(0))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         std::regex call_regex("(\\d[A-Z])(\\d)([A-Z]{1,3})"); | 
					
						
							|  |  |  |         std::smatch call_match; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (std::regex_match(callstr, call_match, call_regex)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             call_prefix = call_match[1].str(); | 
					
						
							|  |  |  |             call_num = stoi(call_match[2].str()); | 
					
						
							|  |  |  |             call_suffix = call_match[3].str(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         std::regex call_regex("([A-Z0-9]{1,2})(\\d)([A-Z]{1,3})"); | 
					
						
							|  |  |  |         std::smatch call_match; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (std::regex_match(callstr, call_match, call_regex)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             call_prefix = call_match[1].str(); | 
					
						
							|  |  |  |             call_num = stoi(call_match[2].str()); | 
					
						
							|  |  |  |             call_suffix = call_match[3].str(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (isdigit(call_prefix.at(0))) { // In this case the first character cannot be a digit
 | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // qDebug("Packing::packcall_std: %s %d %s", call_prefix.c_str(), call_num, call_suffix.c_str());
 | 
					
						
							|  |  |  |     int i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0; | 
					
						
							|  |  |  |     std::string alnums = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 
					
						
							|  |  |  |     std::string alphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (call_prefix.size() == 2) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         i1 = alnums.find(call_prefix.at(0)) + 1; | 
					
						
							|  |  |  |         i2 = alnums.find(call_prefix.at(1)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         i2 = alnums.find(call_prefix.at(0)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i3 = call_num; | 
					
						
							|  |  |  |     i4 = alphas.find(call_suffix.at(0)) + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (call_suffix.size() > 1) { | 
					
						
							|  |  |  |         i5 = alphas.find(call_suffix.at(1)) + 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (call_suffix.size() > 2) { | 
					
						
							|  |  |  |         i6 = alphas.find(call_suffix.at(2)) + 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     c28 = 2063592 + (1<<22) + 36*10*27*27*27*i1 + 10*27*27*27*i2 + 27*27*27*i3 + 27*27*i4 + 27*i5 + i6; | 
					
						
							|  |  |  |     // qDebug("Packing::packcall c28: %d, i1: %d, i2: %d, i3: %d, i4: %d, i5: %d, i6: %d", c28, i1, i2, i3, i4, i5, i6);
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Packing::packgrid(int& g15, const std::string& locstr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static const int MAXGRID4 = 32400; | 
					
						
							|  |  |  |     std::regex loc_regex("[A-R][A-R][0-9][0-9]"); | 
					
						
							|  |  |  |     std::smatch loc_match; | 
					
						
							|  |  |  |     g15 = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (locstr.size() == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         g15 = MAXGRID4 + 1; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (locstr == "RRR") | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         g15 = MAXGRID4 + 2; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (locstr == "RR73") | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         g15 = MAXGRID4 + 3; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (locstr == "73") | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         g15 = MAXGRID4 + 4; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (std::regex_match(locstr, loc_match, loc_regex)) // Maidenhead 4 char locator
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int i1 = int(locstr.at(0)) - int('A'); | 
					
						
							|  |  |  |         int i2 = int(locstr.at(1)) - int('A'); | 
					
						
							|  |  |  |         int i3 = int(locstr.at(2)) - int('0'); | 
					
						
							|  |  |  |         int i4 = int(locstr.at(3)) - int('0'); | 
					
						
							|  |  |  |         g15 = i1*18*10*10 + i2*10*10 + i3*10 + i4; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::regex rpt_regex("([+-])(\\d)(\\d)"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (std::regex_match(locstr, loc_match, rpt_regex)) // Report -30 to +99
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int i1 = int(locstr.at(1)) - int('0'); | 
					
						
							|  |  |  |         int i2 = int(locstr.at(2)) - int('0'); | 
					
						
							|  |  |  |         int s = (locstr.at(0) == '-') ? -1 : 1; | 
					
						
							|  |  |  |         g15 = MAXGRID4 + 35 + s*(i1*10 + i2); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Packing::packfree(int a77[], const std::string& msg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     std::string s = msg; | 
					
						
							|  |  |  |     s.append(13, ' '); | 
					
						
							|  |  |  |     s = s.substr(0, 13); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::string a = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"; | 
					
						
							|  |  |  |     boost::multiprecision::int128_t b = 1, x = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i=12; i>=0; i--) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int ai = a.find(s.at(i)); | 
					
						
							|  |  |  |         ai = (ai < 0) ? 0 : ai; // map unknown characters to blanks
 | 
					
						
							|  |  |  |         x += ai * b; | 
					
						
							|  |  |  |         b *= 42; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pa128(a77, 0, 71, x); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-05 01:03:24 +02:00
										 |  |  | void Packing::pack1(int a77[], int c28_1, int c28_2, int g15, int reply) | 
					
						
							| 
									
										
										
										
											2024-03-28 22:12:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     pa64(a77, 0, 28, c28_1); | 
					
						
							|  |  |  |     pa64(a77, 28+1, 28, c28_2); | 
					
						
							| 
									
										
										
										
											2024-04-05 01:03:24 +02:00
										 |  |  |     a77[28+1+28+1] = reply; | 
					
						
							| 
									
										
										
										
											2024-03-28 22:12:27 +01:00
										 |  |  |     pa64(a77, 28+1+28+2, 15, g15); | 
					
						
							|  |  |  |     pa64(a77, 28+1+28+2+15, 3, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 19:03:29 +01:00
										 |  |  | } // namespace FT8
 |