Use standard FT8 packing for standard FT8 messages, but apply a directed header for those messages that _can_ be directed

This commit is contained in:
Jordan Sherer 2018-07-15 15:43:29 -04:00
parent 2832572741
commit 3260bb7b89
4 changed files with 99 additions and 16 deletions

View File

@ -164,7 +164,7 @@ namespace
{
Radio::Frequency constexpr default_frequency {14074000};
QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
QRegExp message_input_alphabet {"[- A-Za-z0-9+./?\\n:]*"};
QRegExp message_input_alphabet {"[- A-Za-z0-9+./?\\n:@&]*"};
// grid exact match excluding RR73
QRegularExpression grid_regexp {"\\A(?![Rr]{2}73)[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}){0,1}\\z"};
@ -5434,13 +5434,27 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
QString mycall = m_config.my_callsign();
foreach(QString line, text.split(QRegExp("[\\r\\n]"), QString::SkipEmptyParts)){
while(line.size() > 0){
QString frame;
bool useStd = false;
bool isFree = false;
QString stdFrame = parseFT8Message(line, &isFree);
int n = 0;
QString frame = Varicode::packDirectedMessage(line, mycall, &n);
if(n > 0){
frames.append(frame);
line = line.mid(n).trimmed();
QString dirFrame = Varicode::packDirectedMessage(line, mycall, &n);
// if this parses to a standard FT8 free text message
// but it can be parsed as a directed message, then we
// should send the directed version
if(isFree && n > 0){
useStd = false;
frame = dirFrame;
} else {
frame = parseFT8Message(line);
useStd = true;
frame = stdFrame;
}
if(useStd){
if(frame.isEmpty()){
break;
}
@ -5454,15 +5468,25 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
}
line = line.mid(frame.length()).trimmed();
} else {
frames.append(frame);
line = line.mid(n).trimmed();
}
}
}
#if 0
qDebug() << "parsed frames:";
foreach(auto frame, frames){
qDebug() << "->" << frame;
}
#endif
return frames;
}
QString MainWindow::parseFT8Message(QString input){
QString MainWindow::parseFT8Message(QString input, bool *isFree){
char message[29];
char msgsent[29];
char volatile ft8msgbits[75 + 12];
@ -5479,6 +5503,28 @@ QString MainWindow::parseFT8Message(QString input){
const_cast<int *> (itone), 22, 6, 22);
msgsent[22]=0;
// decode the msg bits into 6-bit bytes so we can check to see if its a free text message or not...
// see extractmessage1764.f90 for the original implementation. we could technically add a boolean output
// from the fortran code, but this avoids having to modify that so we can easily apply updates to the
// signal functions in the future without incurring too much cognitive overhead of merge conflicts.
char msgbytes[12];
for(int ibyte = 1; ibyte <= 12; ibyte++){
int itmp = 0;
for(int ibit = 1; ibit <= 6; ibit++){
itmp = (itmp << 1) + (1 & (ft8msgbits[((ibyte-1) * 6 + ibit)-1]));
}
msgbytes[ibyte-1] = itmp;
}
int a = msgbytes[9];
int b = msgbytes[10];
int c = msgbytes[11];
int d = ((a & 15) << 12) + (b << 6) + c;
if(isFree){
*isFree = (d >= 32768);
}
return QString::fromLatin1(msgsent).trimmed();
}
@ -6801,17 +6847,26 @@ void MainWindow::on_queryButton_pressed(){
// TODO: jsherer - this should be extracted
connect(snrAction, &QAction::triggered, this, [this](){
QString selectedCall;
auto items = ui->tableWidgetCalls->selectedItems();
if(!items.isEmpty()){
selectedCall = items.first()->text();
QString selectedCall = callsignSelected();
if(selectedCall.isEmpty()){
return;
}
addMessageText(QString("%1:%2?").arg(m_config.my_callsign(), selectedCall));
addMessageText(QString("%1?").arg(selectedCall));
});
auto qthAction = menu->addAction("@ - What is your QTH?");
connect(qthAction, &QAction::triggered, this, [this](){
QString selectedCall = callsignSelected();
if(selectedCall.isEmpty()){
return;
}
addMessageText(QString("%1@").arg(selectedCall));
});
menu->addAction("$ - What stations are you hearing?")->setEnabled(false);
menu->addAction("@ - What is your QTH?")->setEnabled(false);
menu->addAction("&& - What is your message?")->setEnabled(false);
menu->addAction("| - Relay the following message")->setEnabled(false);
@ -8041,7 +8096,7 @@ void MainWindow::displayActivity(bool force){
qDebug() << "processing command" << d.from << d.to << d.command << d.freq;
// we're only processing queries at this point
if(d.command != "?"){
if(d.command != "?" && d.command != "@"){
continue;
}
@ -8056,7 +8111,12 @@ void MainWindow::displayActivity(bool force){
}
// construct reply
auto reply = QString("%1 %2 %3").arg(d.from).arg(m_config.my_callsign()).arg(d.snr);
auto reply = QString("%1 %2 %3").arg(d.from).arg(m_config.my_callsign());
if(d.command == "?"){
reply = reply.arg(d.snr);
} else if(d.command == "@"){
reply = reply.arg(m_config.my_grid());
}
addMessageText(reply);
// use the last frequency

View File

@ -253,7 +253,7 @@ private slots:
void on_extFreeTextMsg_currentTextChanged (QString const&);
void on_extFreeTextMsgEdit_currentTextChanged (QString const&);
QStringList buildFT8MessageFrames(QString const& text);
QString parseFT8Message(QString input);
QString parseFT8Message(QString input, bool *isFree);
bool prepareNextMessageFrame();
bool isFreqOffsetFree(int f, int bw);
int findFreeFreqOffset(int fmin, int fmax, int bw);

View File

@ -198,6 +198,16 @@ QString Varicode::huffDecode(QVector<bool> const& bitvec){
return out;
}
// convert char* array of 0 bytes and 1 bytes to bool vector
QVector<bool> Varicode::bytesToBits(char *bitvec, int n){
QVector<bool> bits;
for(int i = 0; i < n; i++){
bits.append(bitvec[i] == 0x01);
}
return bits;
}
// convert string of 0s and 1s to bool vector
QVector<bool> Varicode::strToBits(QString const& bitvec){
QVector<bool> bits;
foreach(auto ch, bitvec){
@ -239,6 +249,17 @@ quint64 Varicode::bitsToInt(QVector<bool> const value){
return v;
}
quint64 Varicode::bitsToInt(QVector<bool>::ConstIterator start, int n){
quint64 v = 0;
for(int i = 0; i < n; i++){
int bit = (int)(*start);
v = (v << 1) + (int)(bit);
start++;
}
return v;
}
quint8 Varicode::unpack5bits(QString const& value){
return alphabet.indexOf(value.at(0));
}

View File

@ -24,11 +24,13 @@ public:
static QVector<bool> huffFlatten(QList<QVector<bool>> &list);
static QString huffDecode(QVector<bool> const& bitvec);
static QVector<bool> bytesToBits(char * bitvec, int n);
static QVector<bool> strToBits(QString const& bitvec);
static QString bitsToStr(QVector<bool> const& bitvec);
static QVector<bool> intToBits(quint64 value, int expected=0);
static quint64 bitsToInt(QVector<bool> const value);
static quint64 bitsToInt(QVector<bool>::ConstIterator start, int n);
static quint8 unpack5bits(QString const& value);
static QString pack5bits(quint8 packed);