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