diff --git a/decodedtext.cpp b/decodedtext.cpp index 65cc343..6e183bf 100644 --- a/decodedtext.cpp +++ b/decodedtext.cpp @@ -221,19 +221,14 @@ bool DecodedText::tryUnpackData(){ return false; } - if((bits_ & Varicode::JS8CallData) != Varicode::JS8CallData){ - return false; - } - - quint8 type = Varicode::FrameUnknown; - QString data = Varicode::unpackDataMessage(m, &type); + QString data = Varicode::unpackDataMessage(m); if(data.isEmpty()){ return false; } message_ = data; - frameType_ = type; + frameType_ = Varicode::FrameData; return true; } diff --git a/mainwindow.cpp b/mainwindow.cpp index d4859ab..d8ce39e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -3887,8 +3887,8 @@ void MainWindow::readFromStdout() //readFromStdout if(!m_bandActivity.contains(offset)){ QList offsets = { - offset - 60, offset - 61, offset - 62, offset - 63, offset - 64, offset - 65, offset - 66, offset - 67, offset - 68, offset - 69, - offset + 60, offset + 61, offset + 62, offset + 63, offset + 64, offset + 65, offset + 66, offset + 67, offset + 68, offset + 69, + // offset - 60, offset - 61, offset - 62, offset - 63, offset - 64, offset - 65, offset - 66, offset - 67, offset - 68, offset - 69, + // offset + 60, offset + 61, offset + 62, offset + 63, offset + 64, offset + 65, offset + 66, offset + 67, offset + 68, offset + 69, offset - 1, offset - 2, offset - 3, offset - 4, offset - 5, offset - 6, offset - 7, offset - 8, offset - 9, offset - 10, offset + 1, offset + 2, offset + 3, offset + 4, offset + 5, offset + 6, offset + 7, offset + 8, offset + 9, offset + 10 }; @@ -4200,8 +4200,8 @@ bool MainWindow::hasExistingMessageBuffer(int offset, bool drift, int *pPrevOffs } QList offsets = { - offset - 60, offset - 61, offset - 62, offset - 63, offset - 64, offset - 65, offset - 66, offset - 67, offset - 68, offset - 69, - offset + 60, offset + 61, offset + 62, offset + 63, offset + 64, offset + 65, offset + 66, offset + 67, offset + 68, offset + 69, + //offset - 60, offset - 61, offset - 62, offset - 63, offset - 64, offset - 65, offset - 66, offset - 67, offset - 68, offset - 69, + //offset + 60, offset + 61, offset + 62, offset + 63, offset + 64, offset + 65, offset + 66, offset + 67, offset + 68, offset + 69, offset - 1, offset - 2, offset - 3, offset - 4, offset - 5, offset - 6, offset - 7, offset - 8, offset - 9, offset - 10, offset + 1, offset + 2, offset + 3, offset + 4, offset + 5, offset + 6, offset + 7, offset + 8, offset + 9, offset + 10 }; @@ -4517,12 +4517,12 @@ void MainWindow::guiUpdate() foxcom_.nfreq=ui->TxFreqSpinBox->value(); if(m_config.split_mode()) foxcom_.nfreq = foxcom_.nfreq - m_XIT; //Fox Tx freq strncpy(&foxcom_.cmsg[0][0], QString::fromStdString(message).toLatin1(), 12); - foxcom_.i3bit[0] = m_i3bit; + foxcom_.i3bit[0] = m_i3bit | Varicode::JS8CallExtended; int i = 1; while(!m_txFrameQueue.isEmpty() && foxcom_.nslots < TEST_FOX_WAVE_GEN_SLOTS){ auto pair = m_txFrameQueue.dequeue(); strncpy(&foxcom_.cmsg[i][0], pair.first.toLatin1(), 12); - foxcom_.i3bit[i] = pair.second; + foxcom_.i3bit[i] = pair.second | Varicode::JS8CallExtended; foxcom_.nslots += 1; //m_currentMessage.append(pair.first); @@ -9022,7 +9022,7 @@ void MainWindow::processCompoundActivity() { bits == Varicode::JS8Call || ((bits & Varicode::JS8CallFirst) == Varicode::JS8CallFirst) || ((bits & Varicode::JS8CallLast) == Varicode::JS8CallLast) || - ((bits & Varicode::JS8CallData) == Varicode::JS8CallData) + ((bits & Varicode::JS8CallExtended) == Varicode::JS8CallExtended) ); if (!validBits) { qDebug() << "-> buffer.cmd bits is invalid...skip"; diff --git a/varicode.cpp b/varicode.cpp index 67ffe78..44905f5 100644 --- a/varicode.cpp +++ b/varicode.cpp @@ -1183,7 +1183,9 @@ QString Varicode::packHeartbeatMessage(QString const &text, const QString &calls cqNumber = cqs.key(type, 0); } - frame = packCompoundFrame(callsign, FrameHeartbeat, packed_extra, cqNumber); + quint8 cqNumber = cqs.key(type, 0); + + frame = packCompoundFrame(callsign, Varicode::FrameHeartbeat, packed_extra, cqNumber); if(frame.isEmpty()){ if(n) *n = 0; return frame; @@ -1194,12 +1196,12 @@ QString Varicode::packHeartbeatMessage(QString const &text, const QString &calls } QStringList Varicode::unpackHeartbeatMessage(const QString &text, quint8 *pType, bool * isAlt, quint8 * pBits3){ - quint8 type = FrameHeartbeat; + quint8 type = Varicode::FrameHeartbeat; quint16 num = nmaxgrid; quint8 bits3 = 0; QStringList unpacked = unpackCompoundFrame(text, &type, &num, &bits3); - if(unpacked.isEmpty() || type != FrameHeartbeat){ + if(unpacked.isEmpty() || type != Varicode::FrameHeartbeat){ return QStringList{}; } @@ -1239,7 +1241,7 @@ QString Varicode::packCompoundMessage(QString const &text, int *n){ return frame; } - quint8 type = FrameCompound; + quint8 type = Varicode::FrameCompound; quint16 extra = nmaxgrid; qDebug() << "try pack cmd" << cmd << directed_cmds.contains(cmd) << Varicode::isCommandAllowed(cmd); @@ -1249,7 +1251,7 @@ QString Varicode::packCompoundMessage(QString const &text, int *n){ qint8 inum = Varicode::packNum(num, nullptr); extra = nusergrid + Varicode::packCmd(directed_cmds[cmd], inum, &packedNum); - type = FrameCompoundDirected; + type = Varicode::FrameCompoundDirected; } else if(!grid.isEmpty()){ extra = Varicode::packGrid(grid); } @@ -1261,12 +1263,12 @@ QString Varicode::packCompoundMessage(QString const &text, int *n){ } QStringList Varicode::unpackCompoundMessage(const QString &text, quint8 *pType, quint8 *pBits3){ - quint8 type = FrameCompound; + quint8 type = Varicode::FrameCompound; quint16 extra = nmaxgrid; quint8 bits3 = 0; QStringList unpacked = unpackCompoundFrame(text, &type, &extra, &bits3); - if(unpacked.isEmpty() || (type != FrameCompound && type != FrameCompoundDirected)){ + if(unpacked.isEmpty() || (type != Varicode::FrameCompound && type != Varicode::FrameCompoundDirected)){ return QStringList {}; } @@ -1294,7 +1296,7 @@ QString Varicode::packCompoundFrame(const QString &callsign, quint8 type, quint1 QString frame; // needs to be a compound type... - if(type == FrameDataCompressed || type == FrameDataUncompressed || type == FrameDirected){ + if(type == Varicode::FrameData || type == Varicode::FrameDirected){ return frame; } @@ -1338,7 +1340,7 @@ QStringList Varicode::unpackCompoundFrame(const QString &text, quint8 *pType, qu quint8 packed_flag = Varicode::bitsToInt(bits.mid(0, 3)); // needs to be a ping type... - if(packed_flag == FrameDataCompressed || packed_flag == FrameDataUncompressed || packed_flag == FrameDirected){ + if(packed_flag == Varicode::FrameData || packed_flag == Varicode::FrameDirected){ return unpacked; } @@ -1439,7 +1441,7 @@ QString Varicode::packDirectedMessage(const QString &text, const QString &mycall cmdOut = cmd.trimmed(); packed_cmd = directed_cmds[cmdOut]; } - quint8 packed_flag = FrameDirected; + quint8 packed_flag = Varicode::FrameDirected; quint8 packed_extra = inum; // [3][28][28][5],[2][6] = 72 @@ -1467,7 +1469,7 @@ QStringList Varicode::unpackDirectedMessage(const QString &text, quint8 *pType){ auto bits = Varicode::intToBits(Varicode::unpack72bits(text, &extra), 64); quint8 packed_flag = Varicode::bitsToInt(bits.mid(0, 3)); - if(packed_flag != FrameDirected){ + if(packed_flag != Varicode::FrameDirected){ return unpacked; } @@ -1500,8 +1502,12 @@ QString packHuffMessage(const QString &input, int *n){ QString frame; - // [1][71] = 72 - QVector frameBits = {false}; + // [1][1][70] = 72 + // The first bit is a flag that indicates this is a data frame, technically encoded as [100] + // but, since none of the other frame types start with a 1, we can drop the two zeros and use + // them for encoding the first two bits of the actuall data sent. boom! + // The second bit is a flag that indicates this is not compressed frame (huffman coding) + QVector frameBits = {true, false}; int i = 0; @@ -1554,8 +1560,12 @@ QString packCompressedMessage(const QString &input, int *n){ QString frame; - // [1][71] = 72 - QVector frameBits = {true}; + // [1][1][70] = 72 + // The first bit is a flag that indicates this is a data frame, technically encoded as [100] + // but, since none of the other frame types start with a 1, we can drop the two zeros and use + // them for encoding the first two bits of the actuall data sent. boom! + // The second bit is a flag that indicates this is a compressed frame (dense coding) + QVector frameBits = {true, true}; int i = 0; foreach(auto pair, JSC::compress(input)){ @@ -1593,24 +1603,25 @@ QString packCompressedMessage(const QString &input, int *n){ } QString Varicode::packDataMessage(const QString &input, int *n){ - QString huffFrame; - int huffChars = 0; - huffFrame = packHuffMessage(input, &huffChars); + QString huffFrame; + int huffChars = 0; + huffFrame = packHuffMessage(input, &huffChars); - QString compressedFrame; - int compressedChars = 0; - compressedFrame = packCompressedMessage(input, &compressedChars); + QString compressedFrame; + int compressedChars = 0; + compressedFrame = packCompressedMessage(input, &compressedChars); - if(huffChars > compressedChars){ - if(n) *n = huffChars; - return huffFrame; - } else { - if(n) *n = compressedChars; - return compressedFrame; - } + if(huffChars > compressedChars){ + if(n) *n = huffChars; + return huffFrame; + } else { + if(n) *n = compressedChars; + return compressedFrame; + } } -QString Varicode::unpackDataMessage(const QString &text, quint8 *pType){ + +QString Varicode::unpackDataMessage(const QString &text){ QString unpacked; if(text.length() < 12 || text.contains(" ")){ @@ -1621,18 +1632,24 @@ QString Varicode::unpackDataMessage(const QString &text, quint8 *pType){ quint64 value = Varicode::unpack72bits(text, &rem); auto bits = Varicode::intToBits(value, 64) + Varicode::intToBits(rem, 8); + bool isData = bits.at(0); + if(!isData){ + return unpacked; + } + + bits = bits.mid(1); + bool compressed = bits.at(0); int n = bits.lastIndexOf(0); bits = bits.mid(1, n-1); if(compressed){ + // partial word (s,c)-dense coding with code tables unpacked = JSC::decompress(bits); - if(pType) *pType = Varicode::FrameDataCompressed; } else { // huff decode the bits (without escapes) unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits); - if(pType) *pType = Varicode::FrameDataUncompressed; } return unpacked; @@ -1852,7 +1869,7 @@ QList> Varicode::buildMessageFrames( } if(useDat){ - frames.append({ frame, Varicode::JS8CallData }); + frames.append({ frame, Varicode::JS8Call }); line = line.mid(m); } } diff --git a/varicode.h b/varicode.h index cb9020c..e75375e 100644 --- a/varicode.h +++ b/varicode.h @@ -21,22 +21,28 @@ public: JS8Call = 0, // [000] <- any other frame of the message JS8CallFirst = 1, // [001] <- the first frame of a message JS8CallLast = 2, // [010] <- the last frame of a message - JS8CallData = 4, // [100] <- raw data frame (no frame type header) + JS8CallExtended = 4, // [100] <- raw data frame (no frame type header) }; + /* + + 000 = heartbeat + 001 = compound + 010 = compound directed + 011 = directed + 1XX = data, with X bits dropped + */ enum FrameType { FrameUnknown = 255, // [11111111] <- only used as a sentinel FrameHeartbeat = 0, // [000] FrameCompound = 1, // [001] FrameCompoundDirected = 2, // [010] FrameDirected = 3, // [011] - FrameReservedA = 4, // [100] <- Reserved for future use, likely an extension of one of these formats. - FrameDataUncompressed = 5, // [101] - FrameDataCompressed = 6, // [110] - FrameReservedB = 7, // [111] <- Reserved for future use, likely binary data / other formats. + FrameData = 4, // [1XX] // but this only encodes the msb bit 1 and drops the two zeros + FrameDataCompressed = 6, // [11X] // but this only encodes the first 2 msb bits and drops the lsb }; - static const quint8 FrameTypeMax = 7; + static const quint8 FrameTypeMax = 6; static QString frameTypeString(quint8 type) { const char* FrameTypeStrings[] = { @@ -44,10 +50,9 @@ public: "FrameCompound", "FrameCompoundDirected", "FrameDirected", - "FrameReservedA", - "FrameDataUncompressed", + "FrameData", + "FrameUnknown", // 5 "FrameDataCompressed", - "FrameReservedB" }; if(type > FrameTypeMax){ @@ -148,7 +153,7 @@ public: static QStringList unpackDirectedMessage(QString const& text, quint8 *pType); static QString packDataMessage(QString const& text, int *n); - static QString unpackDataMessage(QString const& text, quint8 *pType); + static QString unpackDataMessage(QString const& text); static QList> buildMessageFrames( QString const& mycall,