Split beacon packing from compound packing
This commit is contained in:
parent
eb7882e253
commit
e649a375cf
@ -17,22 +17,19 @@ namespace
|
||||
|
||||
DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString const& my_grid)
|
||||
: string_ {the_string.left (the_string.indexOf (QChar::Nbsp))} // discard appended info
|
||||
, padding_ {string_.indexOf (" ") > 4 ? 2 : 0} // allow for
|
||||
// seconds
|
||||
, padding_ {string_.indexOf (" ") > 4 ? 2 : 0} // allow for seconds
|
||||
, contest_mode_ {contest_mode}
|
||||
, message_ {string_.mid (column_qsoText + padding_).trimmed ()}
|
||||
, is_standard_ {false}
|
||||
{
|
||||
if (message_.length() >= 1)
|
||||
{
|
||||
if(message_.length() >= 1) {
|
||||
message_ = message_.left (21).remove (QRegularExpression {"[<>]"});
|
||||
int i1 = message_.indexOf ('\r');
|
||||
if (i1 > 0)
|
||||
{
|
||||
if (i1 > 0) {
|
||||
message_ = message_.left (i1 - 1);
|
||||
}
|
||||
if (message_.contains (QRegularExpression {"^(CQ|QRZ)\\s"}))
|
||||
{
|
||||
|
||||
if (message_.contains (QRegularExpression {"^(CQ|QRZ)\\s"})) {
|
||||
// TODO this magic position 16 is guaranteed to be after the
|
||||
// last space in a decoded CQ or QRZ message but before any
|
||||
// appended DXCC entity name or worked before information
|
||||
@ -42,16 +39,14 @@ DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString
|
||||
// remove DXCC entity and worked B4 status. TODO need a better way to do this
|
||||
message_ = message_.left (eom_pos + 1);
|
||||
}
|
||||
|
||||
// stdmsg is a fortran routine that packs the text, unpacks it
|
||||
// and compares the result
|
||||
auto message_c_string = message_.toLocal8Bit ();
|
||||
message_c_string += QByteArray {22 - message_c_string.size (), ' '};
|
||||
auto grid_c_string = my_grid.toLocal8Bit ();
|
||||
grid_c_string += QByteArray {6 - grid_c_string.size (), ' '};
|
||||
is_standard_ = stdmsg_ (message_c_string.constData ()
|
||||
, contest_mode_
|
||||
, grid_c_string.constData ()
|
||||
, 22, 6);
|
||||
is_standard_ = stdmsg_ (message_c_string.constData (), contest_mode_, grid_c_string.constData (), 22, 6);
|
||||
|
||||
// We're only going to unpack standard messages for CQs && beacons...
|
||||
// TODO: jsherer - this is a hack for now...
|
||||
@ -81,6 +76,11 @@ bool DecodedText::tryUnpack(){
|
||||
unpacked = tryUnpackBeacon();
|
||||
}
|
||||
|
||||
if(!unpacked){
|
||||
unpacked = tryUnpackCompound();
|
||||
}
|
||||
|
||||
|
||||
if(!unpacked){
|
||||
unpacked = tryUnpackDirected();
|
||||
}
|
||||
@ -128,6 +128,40 @@ bool DecodedText::tryUnpackBeacon(){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodedText::tryUnpackCompound(){
|
||||
auto m = message().trimmed();
|
||||
// directed calls will always be 12+ chars and contain no spaces.
|
||||
if(m.length() < 12 || m.contains(' ')){
|
||||
return false;
|
||||
}
|
||||
|
||||
auto parts = Varicode::unpackCompoundMessage(m);
|
||||
if(parts.isEmpty() || parts.length() < 2){
|
||||
return false;
|
||||
}
|
||||
|
||||
isBeacon_ = false;
|
||||
|
||||
extra_ = parts.at(2);
|
||||
|
||||
QStringList cmp;
|
||||
if(!parts.at(0).isEmpty()){
|
||||
cmp.append(parts.at(0));
|
||||
}
|
||||
if(!parts.at(1).isEmpty()){
|
||||
cmp.append(parts.at(1));
|
||||
}
|
||||
compound_ = cmp.join("/");
|
||||
|
||||
if(extra_.isEmpty()){
|
||||
message_ = QString("<%1> ").arg(compound_);
|
||||
} else {
|
||||
message_ = QString("<%1 %2> ").arg(compound_).arg(extra_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodedText::tryUnpackDirected(){
|
||||
QString m = message().trimmed();
|
||||
|
||||
|
@ -35,11 +35,12 @@ public:
|
||||
|
||||
bool tryUnpack();
|
||||
bool tryUnpackBeacon();
|
||||
bool tryUnpackCompound();
|
||||
bool tryUnpackDirected();
|
||||
bool tryUnpackData();
|
||||
|
||||
QString compoundCall() const { return compound_; }
|
||||
bool isCompoundMessage() const { return !compound_.isEmpty(); }
|
||||
bool isCompound() const { return !compound_.isEmpty(); }
|
||||
|
||||
QString extra() const { return extra_; }
|
||||
bool isBeacon() const { return isBeacon_; }
|
||||
|
@ -3365,7 +3365,7 @@ void MainWindow::readFromStdout() //readFromStdout
|
||||
ActivityDetail d;
|
||||
d.isLowConfidence = decodedtext.isLowConfidence();
|
||||
d.isFree = !decodedtext.isStandardMessage();
|
||||
d.isCompound = decodedtext.isCompoundMessage();
|
||||
d.isCompound = decodedtext.isCompound();
|
||||
d.isDirected = decodedtext.isDirectedMessage();
|
||||
d.bits = decodedtext.bits();
|
||||
d.freq = offset;
|
||||
@ -3376,7 +3376,7 @@ void MainWindow::readFromStdout() //readFromStdout
|
||||
m_rxActivityQueue.append(d);
|
||||
|
||||
// if we have a data frame, and a message buffer has been established, buffer it...
|
||||
if(m_messageBuffer.contains(d.freq/10*10) && !decodedtext.isCompoundMessage() && !decodedtext.isDirectedMessage()){
|
||||
if(m_messageBuffer.contains(d.freq/10*10) && !decodedtext.isCompound() && !decodedtext.isDirectedMessage()){
|
||||
qDebug() << "buffering data" << (d.freq/10*10) << d.text;
|
||||
m_messageBuffer[d.freq/10*10].msgs.append(d);
|
||||
}
|
||||
@ -3391,7 +3391,7 @@ void MainWindow::readFromStdout() //readFromStdout
|
||||
// Process compound callsign commands (put them in cache)"
|
||||
#if 1
|
||||
bool shouldProcessCompound = true;
|
||||
if(shouldProcessCompound && decodedtext.isCompoundMessage()){
|
||||
if(shouldProcessCompound && decodedtext.isCompound()){
|
||||
CallDetail cd;
|
||||
cd.call = decodedtext.compoundCall();
|
||||
cd.grid = decodedtext.extra(); // compound calls via beacons may contain grid...
|
||||
@ -5903,6 +5903,7 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
|
||||
|
||||
bool useStd = false;
|
||||
bool useBcn = false;
|
||||
bool useCmp = false;
|
||||
bool useDir = false;
|
||||
bool useDat = false;
|
||||
bool isFree = false;
|
||||
@ -5911,6 +5912,9 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
|
||||
int l = 0;
|
||||
QString bcnFrame = Varicode::packBeaconMessage(line, mycall, &l);
|
||||
|
||||
int o = 0;
|
||||
QString cmpFrame = Varicode::packCompoundMessage(line, &o);
|
||||
|
||||
int n = 0;
|
||||
QString dirCmd;
|
||||
QString dirTo;
|
||||
@ -5932,6 +5936,11 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
|
||||
hasDirected = false;
|
||||
frame = bcnFrame;
|
||||
}
|
||||
else if(isFree && !hasDirected && !hasData && o > 0){
|
||||
useCmp = true;
|
||||
hasDirected = false;
|
||||
frame = cmpFrame;
|
||||
}
|
||||
else if(isFree && !hasDirected && !hasData && n > 0){
|
||||
useDir = true;
|
||||
hasDirected = true;
|
||||
@ -5970,26 +5979,29 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
|
||||
line = line.mid(l);
|
||||
}
|
||||
|
||||
if(useCmp){
|
||||
frames.append(frame);
|
||||
line = line.mid(o);
|
||||
}
|
||||
|
||||
if(useDir){
|
||||
// from compound callsign
|
||||
if(compound){
|
||||
QString compoundMessage = QString("DE %1").arg(mygrid);
|
||||
QString beaconFrame = Varicode::packBeaconMessage(compoundMessage, mycall, nullptr);
|
||||
if(!beaconFrame.isEmpty()){
|
||||
frames.append(beaconFrame);
|
||||
QString compoundMessage = QString("<%1 %2>").arg(mycall).arg(mygrid);
|
||||
QString compoundFrame = Varicode::packCompoundMessage(compoundMessage, nullptr);
|
||||
if(!compoundFrame.isEmpty()){
|
||||
frames.append(compoundFrame);
|
||||
}
|
||||
}
|
||||
|
||||
frames.append(frame);
|
||||
|
||||
// to compound callsign
|
||||
if(!dirTo.isEmpty()){
|
||||
if(dirTo.contains("/")){
|
||||
QString compoundMessage = QString("CALL");
|
||||
QString beaconFrame = Varicode::packBeaconMessage(compoundMessage, dirTo, nullptr);
|
||||
if(!beaconFrame.isEmpty()){
|
||||
frames.append(beaconFrame);
|
||||
}
|
||||
if(!dirTo.isEmpty() && dirTo.contains("/")){
|
||||
QString compoundMessage = QString("<%1>").arg(dirTo);
|
||||
QString compoundFrame = Varicode::packCompoundMessage(compoundMessage, nullptr);
|
||||
if(!compoundFrame.isEmpty()){
|
||||
frames.append(compoundFrame);
|
||||
}
|
||||
}
|
||||
|
||||
|
82
varicode.cpp
82
varicode.cpp
@ -74,6 +74,10 @@ QRegularExpression directed_re("^"
|
||||
"(?<num>\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?"
|
||||
);
|
||||
|
||||
QRegularExpression beacon_re(R"(^ALLCALL\s(?<type>CQ|BCN)(?:\s(?<grid>[A-Z]{2}[0-9]{2}))?\b)");
|
||||
|
||||
QRegularExpression compound_re(R"(^[<](?<callsign>[A-Z0-9/]+)(?:\s(?<grid>[A-Z]{2}[0-9]{2}))?[>])");
|
||||
|
||||
QMap<QString, QString> hufftable = {
|
||||
// char code weight
|
||||
// 3 bits
|
||||
@ -985,10 +989,12 @@ bool Varicode::isCommandBuffered(const QString &cmd){
|
||||
return directed_cmds.contains(cmd) && buffered_cmds.contains(directed_cmds[cmd]);
|
||||
}
|
||||
|
||||
// ALLCALL CQ EM73
|
||||
// ALLCALL BCN EM73
|
||||
QString Varicode::packBeaconMessage(QString const &text, const QString &callsign, int *n){
|
||||
QString frame;
|
||||
|
||||
auto parsedText = QRegularExpression(R"(^ALLCALL\s(?<type>CQ|BCN)(?:\s(?<grid>[A-Z]{2}[0-9]{2}))?\b)").match(text);
|
||||
auto parsedText = beacon_re.match(text);
|
||||
if(!parsedText.hasMatch()){
|
||||
if(n) *n = 0;
|
||||
return frame;
|
||||
@ -1043,12 +1049,12 @@ QString Varicode::packBeaconMessage(QString const &text, const QString &callsign
|
||||
}
|
||||
|
||||
QStringList Varicode::unpackBeaconMessage(const QString &text, bool * isAlt){
|
||||
quint8 type = 0;
|
||||
quint16 num = 0;
|
||||
quint8 type = FrameBeacon;
|
||||
quint16 num = nmaxgrid;
|
||||
|
||||
QStringList unpacked = unpackCompoundFrame(text, &type, &num);
|
||||
if(unpacked.isEmpty()){
|
||||
return unpacked;
|
||||
if(unpacked.isEmpty() || type != FrameBeacon){
|
||||
return QStringList{};
|
||||
}
|
||||
|
||||
unpacked.append(Varicode::unpackGrid(num & ((1<<15)-1)));
|
||||
@ -1058,6 +1064,62 @@ QStringList Varicode::unpackBeaconMessage(const QString &text, bool * isAlt){
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
|
||||
// KN4CRD/XXXX EM73
|
||||
// XXXX/KN4CRD EM73
|
||||
// KN4CRD/P
|
||||
QString Varicode::packCompoundMessage(QString const &text, int *n){
|
||||
QString frame;
|
||||
|
||||
auto parsedText = compound_re.match(text);
|
||||
if(!parsedText.hasMatch()){
|
||||
if(n) *n = 0;
|
||||
return frame;
|
||||
}
|
||||
|
||||
auto callsign = parsedText.captured("callsign");
|
||||
auto grid = parsedText.captured("grid");
|
||||
|
||||
auto parsedCall = QRegularExpression(compound_callsign_pattern).match(callsign);
|
||||
if(!parsedCall.hasMatch()){
|
||||
if(n) *n = 0;
|
||||
return frame;
|
||||
}
|
||||
|
||||
auto base = parsedCall.captured("base");
|
||||
|
||||
bool isPrefix = false;
|
||||
auto fix = parsedCall.captured("prefix");
|
||||
if(!fix.isEmpty()){
|
||||
isPrefix = true;
|
||||
}
|
||||
|
||||
if(!isPrefix){
|
||||
fix = parsedCall.captured("suffix");
|
||||
}
|
||||
|
||||
quint16 extra = Varicode::packGrid(grid);
|
||||
|
||||
frame = Varicode::packCompoundFrame(base, fix, isPrefix, FrameCompound, extra);
|
||||
|
||||
if(n) *n = parsedText.captured(0).length();
|
||||
return frame;
|
||||
}
|
||||
|
||||
QStringList Varicode::unpackCompoundMessage(const QString &text){
|
||||
quint8 type = FrameCompound;
|
||||
quint16 num = nmaxgrid;
|
||||
|
||||
QStringList unpacked = unpackCompoundFrame(text, &type, &num);
|
||||
if(unpacked.isEmpty() || type != FrameCompound){
|
||||
return QStringList {};
|
||||
}
|
||||
|
||||
unpacked.append(Varicode::unpackGrid(num & ((1<<15)-1)));
|
||||
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
QString Varicode::packCompoundFrame(const QString &baseCallsign, const QString &fix, bool isPrefix, quint8 type, quint16 num){
|
||||
QString frame;
|
||||
|
||||
@ -1081,12 +1143,6 @@ QString Varicode::packCompoundFrame(const QString &baseCallsign, const QString &
|
||||
quint8 packed_5 = num & mask5;
|
||||
|
||||
// [3][28][22][11],[5] = 69
|
||||
/*
|
||||
if(extra.isEmpty()){
|
||||
if(n) *n = 0;
|
||||
return frame;
|
||||
}
|
||||
*/
|
||||
auto bits = (
|
||||
Varicode::intToBits(packed_flag, 3) +
|
||||
Varicode::intToBits(packed_base, 28) +
|
||||
@ -1142,6 +1198,10 @@ QStringList Varicode::unpackCompoundFrame(const QString &text, quint8 *pType, qu
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
// J1Y ACK
|
||||
// J1Y?
|
||||
// KN4CRD: J1Y$
|
||||
// KN4CRD: J1Y! HELLO WORLD
|
||||
QString Varicode::packDirectedMessage(const QString &text, const QString &callsign, QString *pTo, QString * pCmd, int *n){
|
||||
QString frame;
|
||||
|
||||
|
@ -98,6 +98,9 @@ public:
|
||||
static QString packBeaconMessage(QString const &text, QString const&callsign, int *n);
|
||||
static QStringList unpackBeaconMessage(const QString &text, bool *isAlt);
|
||||
|
||||
static QString packCompoundMessage(QString const &text, int *n);
|
||||
static QStringList unpackCompoundMessage(const QString &text);
|
||||
|
||||
static QString packCompoundFrame(const QString &baseCallsign, const QString &fix, bool isPrefix, quint8 type, quint16 num);
|
||||
static QStringList unpackCompoundFrame(const QString &text, quint8 *pType, quint16 *pNum);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user