Refactored callsign packing to use 21 bits instead of 22, reducing our dependence on Prefix/Suffix flags added to our frame type enum
This commit is contained in:
		
							parent
							
								
									e316554b68
								
							
						
					
					
						commit
						479d647456
					
				| @ -1263,6 +1263,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, | |||||||
|   qDebug() << packed << Varicode::unpackBeaconMessage(packed, &isCQ) << isCQ; |   qDebug() << packed << Varicode::unpackBeaconMessage(packed, &isCQ) << isCQ; | ||||||
| 
 | 
 | ||||||
|   m_valid = false; |   m_valid = false; | ||||||
|  | 
 | ||||||
|  |   bool isPrefix = false; | ||||||
|  |   qDebug() << Varicode::packCallsignPrefixSuffix("VE3", true) << Varicode::unpackCallsignPrefixSuffix(Varicode::packCallsignPrefixSuffix("VE3", true), &isPrefix) << isPrefix; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|   // this must be the last statement of constructor
 |   // this must be the last statement of constructor
 | ||||||
| @ -8990,7 +8993,11 @@ void MainWindow::processCommandActivity() { | |||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 auto d = m_callActivity[call]; |                 auto d = m_callActivity[call]; | ||||||
|                 lines.append(QString("%1 SNR %2").arg(d.call).arg(Varicode::formatSNR(d.snr))); | 
 | ||||||
|  | 
 | ||||||
|  |                 //lines.append(QString("%1 SNR %2").arg(d.call).arg(Varicode::formatSNR(d.snr)));
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|                 i++; |                 i++; | ||||||
|             } |             } | ||||||
|             reply = lines.join('\n'); |             reply = lines.join('\n'); | ||||||
|  | |||||||
							
								
								
									
										117
									
								
								varicode.cpp
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								varicode.cpp
									
									
									
									
									
								
							| @ -28,12 +28,12 @@ | |||||||
| #include "varicode.h" | #include "varicode.h" | ||||||
| 
 | 
 | ||||||
| const int nalphabet = 41; | const int nalphabet = 41; | ||||||
| QString alphabet = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"}; | QString alphabet = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"}; // alphabet to encode _into_ for FT8 freetext transmission
 | ||||||
| QString grid_pattern = {R"((?<grid>[A-R]{2}[0-9]{2})+)"}; | QString grid_pattern = {R"((?<grid>[A-R]{2}[0-9]{2})+)"}; | ||||||
| QString orig_compound_callsign_pattern = {R"((?<callsign>(\d|[A-Z])+\/?((\d|[A-Z]){2,})(\/(\d|[A-Z])+)?(\/(\d|[A-Z])+)?))"}; | QString orig_compound_callsign_pattern = {R"((?<callsign>(\d|[A-Z])+\/?((\d|[A-Z]){2,})(\/(\d|[A-Z])+)?(\/(\d|[A-Z])+)?))"}; | ||||||
| QString compound_callsign_pattern = {R"((?<callsign>\b(?<prefix>[A-Z0-9]{1,4}\/)?(?<base>([0-9A-Z])?([0-9A-Z])([0-9])([A-Z])?([A-Z])?([A-Z])?)(?<suffix>\/[A-Z0-9]{1,4})?)\b)"}; | QString compound_callsign_pattern = {R"((?<callsign>\b(?<prefix>[A-Z0-9]{1,4}\/)?(?<base>([0-9A-Z])?([0-9A-Z])([0-9])([A-Z])?([A-Z])?([A-Z])?)(?<suffix>\/[A-Z0-9]{1,4})?)\b)"}; | ||||||
| QString pack_callsign_pattern = {R"(([0-9A-Z ])([0-9A-Z])([0-9])([A-Z ])([A-Z ])([A-Z ]))"}; | QString pack_callsign_pattern = {R"(([0-9A-Z ])([0-9A-Z])([0-9])([A-Z ])([A-Z ])([A-Z ]))"}; | ||||||
| QString callsign_alphabet = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ "}; | QString alphanumeric = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ "}; // callsign and grid alphabet
 | ||||||
| 
 | 
 | ||||||
| QMap<QString, int> directed_cmds = { | QMap<QString, int> directed_cmds = { | ||||||
|     // any changes here need to be made also in the directed regular xpression for parsing
 |     // any changes here need to be made also in the directed regular xpression for parsing
 | ||||||
| @ -299,6 +299,8 @@ QChar ESC = '\\';   // Escape char | |||||||
| QChar EOT = '\x04'; // EOT char
 | QChar EOT = '\x04'; // EOT char
 | ||||||
| 
 | 
 | ||||||
| quint32 nbasecall = 37 * 36 * 10 * 27 * 27 * 27; | quint32 nbasecall = 37 * 36 * 10 * 27 * 27 * 27; | ||||||
|  | quint16 nbasegrid = 180 * 180; | ||||||
|  | quint16 nmaxgrid  = (1<<15)-1; | ||||||
| 
 | 
 | ||||||
| QMap<QString, quint32> basecalls = { | QMap<QString, quint32> basecalls = { | ||||||
|     { "<....>",  nbasecall + 1 }, // incomplete callsign
 |     { "<....>",  nbasecall + 1 }, // incomplete callsign
 | ||||||
| @ -730,28 +732,49 @@ QString Varicode::pack64bits(quint64 packed){ | |||||||
| //     //
 | //     //
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // pack a 4-digit alpha-numeric callsign prefix/suffix into a 22 bit value
 | // pack a 4-digit alpha-numeric + space into a 22 bit value
 | ||||||
| quint32 Varicode::packCallsignPrefixSuffix(QString const& value){ | // 21 bits for the data + 1 bit for a flag indicator
 | ||||||
|     quint8 mask6 = (1<<6)-1; | // giving us a total of 5.5 bits per character
 | ||||||
| 
 | quint32 Varicode::packAlphaNumeric22(QString const& value, bool isFlag){ | ||||||
|     QString prefix = QString(value).replace(QRegExp("[^A-Z0-9]"), ""); |     QString word = QString(value).replace(QRegExp("[^A-Z0-9]"), ""); | ||||||
|     if(prefix.length() < 4){ |     if(word.length() < 4){ | ||||||
|         prefix = prefix + QString(".").repeated(4-prefix.length()); |         word = word + QString(" ").repeated(4-word.length()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // [16][6] = 22 bits
 |     quint32 a = 37 * 37 * 37 * alphanumeric.indexOf(word.at(0)); | ||||||
|     auto left = prefix.left(3); |     quint32 b = 37 * 37 * alphanumeric.indexOf(word.at(1)); | ||||||
|     auto right = prefix.right(1); // guaranteed to be in our alphabet...
 |     quint32 c = 37 * alphanumeric.indexOf(word.at(2)); | ||||||
|  |     quint32 d = alphanumeric.indexOf(word.at(3)); | ||||||
| 
 | 
 | ||||||
|     return ((quint32)Varicode::unpack16bits(left) << 6) | (Varicode::unpack6bits(right) & mask6); |     quint32 packed = a + b + c + d; | ||||||
|  |     packed = (packed << 1) + (int)isFlag; | ||||||
|  | 
 | ||||||
|  |     return packed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| QString Varicode::unpackCallsignPrefixSuffix(quint32 packed){ | QString Varicode::unpackAlphaNumeric22(quint32 packed, bool *isFlag){ | ||||||
|     quint32 mask22 = ((1<<16)-1) << 6; |     QChar word[4]; | ||||||
|     quint32 mask6 = ((1<<6)-1); | 
 | ||||||
|     quint16 a = (packed & mask22) >> 6; |     if(isFlag) *isFlag = packed & 1; | ||||||
|     quint16 b = packed & mask6 ; |     packed = packed >> 1; | ||||||
|     return QString(Varicode::pack16bits(a) + Varicode::pack6bits(b)).replace(".", ""); | 
 | ||||||
|  |     quint32 tmp = packed % 37; | ||||||
|  |     word[3] = alphanumeric.at(tmp); | ||||||
|  |     packed = packed / 37; | ||||||
|  | 
 | ||||||
|  |     tmp = packed % 37; | ||||||
|  |     word[2] = alphanumeric.at(tmp); | ||||||
|  |     packed = packed / 37; | ||||||
|  | 
 | ||||||
|  |     tmp = packed % 37; | ||||||
|  |     word[1] = alphanumeric.at(tmp); | ||||||
|  |     packed = packed / 37; | ||||||
|  | 
 | ||||||
|  |     tmp = packed % 37; | ||||||
|  |     word[0] = alphanumeric.at(tmp); | ||||||
|  |     packed = packed / 37; | ||||||
|  | 
 | ||||||
|  |     return QString(word, 4); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // pack a callsign into a 28-bit value
 | // pack a callsign into a 28-bit value
 | ||||||
| @ -815,12 +838,12 @@ quint32 Varicode::packCallsign(QString const& value){ | |||||||
|         return packed; |         return packed; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     packed = callsign_alphabet.indexOf(matched.at(0)); |     packed = alphanumeric.indexOf(matched.at(0)); | ||||||
|     packed = 36*packed + callsign_alphabet.indexOf(matched.at(1)); |     packed = 36*packed + alphanumeric.indexOf(matched.at(1)); | ||||||
|     packed = 10*packed + callsign_alphabet.indexOf(matched.at(2)); |     packed = 10*packed + alphanumeric.indexOf(matched.at(2)); | ||||||
|     packed = 27*packed + callsign_alphabet.indexOf(matched.at(3)) - 10; |     packed = 27*packed + alphanumeric.indexOf(matched.at(3)) - 10; | ||||||
|     packed = 27*packed + callsign_alphabet.indexOf(matched.at(4)) - 10; |     packed = 27*packed + alphanumeric.indexOf(matched.at(4)) - 10; | ||||||
|     packed = 27*packed + callsign_alphabet.indexOf(matched.at(5)) - 10; |     packed = 27*packed + alphanumeric.indexOf(matched.at(5)) - 10; | ||||||
| 
 | 
 | ||||||
|     return packed; |     return packed; | ||||||
| } | } | ||||||
| @ -834,27 +857,27 @@ QString Varicode::unpackCallsign(quint32 value){ | |||||||
| 
 | 
 | ||||||
|     QChar word[6]; |     QChar word[6]; | ||||||
|     quint32 tmp = value % 27 + 10; |     quint32 tmp = value % 27 + 10; | ||||||
|     word[5] = callsign_alphabet.at(tmp); |     word[5] = alphanumeric.at(tmp); | ||||||
|     value = value/27; |     value = value/27; | ||||||
| 
 | 
 | ||||||
|     tmp = value % 27 + 10; |     tmp = value % 27 + 10; | ||||||
|     word[4] = callsign_alphabet.at(tmp); |     word[4] = alphanumeric.at(tmp); | ||||||
|     value = value/27; |     value = value/27; | ||||||
| 
 | 
 | ||||||
|     tmp = value % 27 + 10; |     tmp = value % 27 + 10; | ||||||
|     word[3] = callsign_alphabet.at(tmp); |     word[3] = alphanumeric.at(tmp); | ||||||
|     value = value/27; |     value = value/27; | ||||||
| 
 | 
 | ||||||
|     tmp = value % 10; |     tmp = value % 10; | ||||||
|     word[2] = callsign_alphabet.at(tmp); |     word[2] = alphanumeric.at(tmp); | ||||||
|     value = value/10; |     value = value/10; | ||||||
| 
 | 
 | ||||||
|     tmp = value % 36; |     tmp = value % 36; | ||||||
|     word[1] = callsign_alphabet.at(tmp); |     word[1] = alphanumeric.at(tmp); | ||||||
|     value = value/36; |     value = value/36; | ||||||
| 
 | 
 | ||||||
|     tmp = value; |     tmp = value; | ||||||
|     word[0] = callsign_alphabet.at(tmp); |     word[0] = alphanumeric.at(tmp); | ||||||
| 
 | 
 | ||||||
|     QString callsign(word, 6); |     QString callsign(word, 6); | ||||||
|     if(callsign.startsWith("3D0")){ |     if(callsign.startsWith("3D0")){ | ||||||
| @ -1011,7 +1034,7 @@ QString Varicode::packBeaconMessage(QString const &text, const QString &callsign | |||||||
|         fix = parsedCall.captured("suffix"); |         fix = parsedCall.captured("suffix"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     quint16 packed_extra = 180*180 + 1; // maximum grid + 1 (which will display an empty string)
 |     quint16 packed_extra = nmaxgrid; // which will display an empty string
 | ||||||
|     if(extra.length() == 4 && QRegularExpression(grid_pattern).match(extra).hasMatch()){ |     if(extra.length() == 4 && QRegularExpression(grid_pattern).match(extra).hasMatch()){ | ||||||
|         packed_extra = Varicode::packGrid(extra); |         packed_extra = Varicode::packGrid(extra); | ||||||
|     } |     } | ||||||
| @ -1045,15 +1068,9 @@ QStringList Varicode::unpackBeaconMessage(const QString &text, bool *isBeacon, b | |||||||
| QString Varicode::packCompoundFrame(const QString &baseCallsign, const QString &fix, bool isPrefix,  bool isBeacon, quint16 num){ | QString Varicode::packCompoundFrame(const QString &baseCallsign, const QString &fix, bool isPrefix,  bool isBeacon, quint16 num){ | ||||||
|     QString frame; |     QString frame; | ||||||
| 
 | 
 | ||||||
|     quint8 packed_flag = 0; |     quint8 packed_flag = isBeacon ? FrameBeacon : FrameCompound; | ||||||
|     if(isBeacon){ |  | ||||||
|         packed_flag = isPrefix ? FrameBeaconPrefix : FrameBeaconSuffix; |  | ||||||
|     } else { |  | ||||||
|         packed_flag = isPrefix ? FrameCompoundPrefix : FrameCompoundSuffix; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     quint32 packed_base = Varicode::packCallsign(baseCallsign); |     quint32 packed_base = Varicode::packCallsign(baseCallsign); | ||||||
|     quint32 packed_fix = Varicode::packCallsignPrefixSuffix(fix); |     quint32 packed_fix = Varicode::packAlphaNumeric22(fix, isPrefix); | ||||||
| 
 | 
 | ||||||
|     if(packed_base == 0 || packed_fix == 0){ |     if(packed_base == 0 || packed_fix == 0){ | ||||||
|         return frame; |         return frame; | ||||||
| @ -1087,35 +1104,33 @@ QStringList Varicode::unpackCompoundFrame(const QString &text, bool *isBeacon, q | |||||||
|     auto bits = Varicode::bitsToStr(Varicode::intToBits(Varicode::unpack64bits(text.left(12)), 64)); |     auto bits = Varicode::bitsToStr(Varicode::intToBits(Varicode::unpack64bits(text.left(12)), 64)); | ||||||
|     quint8 packed_5 = Varicode::unpack5bits(text.right(1)); |     quint8 packed_5 = Varicode::unpack5bits(text.right(1)); | ||||||
| 
 | 
 | ||||||
|     bool is_prefix = false; |  | ||||||
|     bool is_suffix = false; |  | ||||||
|     quint8 packed_flag = Varicode::bitsToInt(Varicode::strToBits(bits.left(3))); |     quint8 packed_flag = Varicode::bitsToInt(Varicode::strToBits(bits.left(3))); | ||||||
|     if(packed_flag == FrameBeaconPrefix || packed_flag == FrameCompoundPrefix){ |     if(packed_flag != FrameBeacon && packed_flag != FrameCompound){ | ||||||
|         is_prefix = true; |  | ||||||
|     } else if (packed_flag == FrameBeaconSuffix || packed_flag == FrameCompoundSuffix){ |  | ||||||
|         is_suffix = true; |  | ||||||
|     } else { |  | ||||||
|         return unpacked; |         return unpacked; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     quint32 packed_base = Varicode::bitsToInt(Varicode::strToBits(bits.mid(3, 28))); |     quint32 packed_base = Varicode::bitsToInt(Varicode::strToBits(bits.mid(3, 28))); | ||||||
|     quint32 packed_fix = Varicode::bitsToInt(Varicode::strToBits(bits.mid(31, 22))); |     quint32 packed_fix = Varicode::bitsToInt(Varicode::strToBits(bits.mid(31, 22))); | ||||||
|     quint16 packed_11 = Varicode::bitsToInt(Varicode::strToBits(bits.mid(53, 11))); |     quint16 packed_11 = Varicode::bitsToInt(Varicode::strToBits(bits.mid(53, 11))); | ||||||
| 
 | 
 | ||||||
|     QString base = Varicode::unpackCallsign(packed_base).trimmed(); |     QString base = Varicode::unpackCallsign(packed_base).trimmed(); | ||||||
|     QString fix = Varicode::unpackCallsignPrefixSuffix(packed_fix); | 
 | ||||||
|  |     bool isPrefix = false; | ||||||
|  |     QString fix = Varicode::unpackAlphaNumeric22(packed_fix, &isPrefix).trimmed(); | ||||||
|  | 
 | ||||||
|     quint16 num = (packed_11 << 5) | packed_5; |     quint16 num = (packed_11 << 5) | packed_5; | ||||||
| 
 | 
 | ||||||
|     if(pNum) *pNum = num; |     if(pNum) *pNum = num; | ||||||
|     if(isBeacon) *isBeacon = packed_flag == FrameBeaconPrefix || packed_flag == FrameBeaconSuffix; |     if(isBeacon) *isBeacon = packed_flag == FrameBeacon; | ||||||
| 
 | 
 | ||||||
|     if(is_prefix){ |     if(isPrefix){ | ||||||
|         unpacked.append(fix); |         unpacked.append(fix); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     unpacked.append(base); |     unpacked.append(base); | ||||||
| 
 | 
 | ||||||
|     if(is_suffix){ |     if(!isPrefix){ | ||||||
|         unpacked.append(fix); |         unpacked.append(fix); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								varicode.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								varicode.h
									
									
									
									
									
								
							| @ -27,14 +27,14 @@ public: | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     enum FrameType { |     enum FrameType { | ||||||
|         FrameBeaconPrefix     = 0, // [000]
 |         FrameBeacon           = 0, // [000]
 | ||||||
|         FrameBeaconSuffix     = 1, // [001]
 |         FrameCompound         = 1, // [001]
 | ||||||
|         FrameCompoundPrefix   = 2, // [010]
 |         FrameDirectedPositive = 2, // [010]
 | ||||||
|         FrameCompoundSuffix   = 3, // [011]
 |         FrameDirectedNegative = 3, // [011]
 | ||||||
|         FrameDirectedPositive = 4, // [100]
 |         FrameDataUnpadded     = 4, // [100]
 | ||||||
|         FrameDirectedNegative = 5, // [101]
 |         FrameDataPadded       = 5, // [101]
 | ||||||
|         FrameDataUnpadded     = 6, // [110]
 |         FrameReservedA        = 6, // [110]
 | ||||||
|         FrameDataPadded       = 7, // [111]
 |         FrameReservedB        = 7, // [111]
 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     //Varicode();
 |     //Varicode();
 | ||||||
| @ -83,8 +83,8 @@ public: | |||||||
|     static quint64 unpack64bits(QString const& value); |     static quint64 unpack64bits(QString const& value); | ||||||
|     static QString pack64bits(quint64 packed); |     static QString pack64bits(quint64 packed); | ||||||
| 
 | 
 | ||||||
|     static quint32 packCallsignPrefixSuffix(QString const& value); |     static quint32 packAlphaNumeric22(QString const& value, bool isFlag); | ||||||
|     static QString unpackCallsignPrefixSuffix(quint32 packed); |     static QString unpackAlphaNumeric22(quint32 packed, bool *isFlag); | ||||||
| 
 | 
 | ||||||
|     static quint32 packCallsign(QString const& value); |     static quint32 packCallsign(QString const& value); | ||||||
|     static QString unpackCallsign(quint32 value); |     static QString unpackCallsign(quint32 value); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jordan Sherer
						Jordan Sherer