Add memory format specifier to Rig Creator

rigcreator
Phil Taylor 2023-05-03 13:38:06 +01:00
rodzic b6e2729683
commit e6f20ee45f
10 zmienionych plików z 355 dodań i 68 usunięć

Wyświetl plik

@ -40,30 +40,104 @@ memories::memories(rigCapabilities rigCaps, QWidget *parent) :
"Filter" << "Data" << "Duplex" << "Tone Mode" << "DSQL" << "Tone" << "TSQL" << "DTCS" <<"DTCS Pol" << "DV Sql" << "Offset" << "UR" << "R1" << "R2";
ui->table->setHorizontalHeaderLabels(headers);
ui->groupLabel->hide();
ui->group->hide();
ui->vfoMode->hide();
ui->memoryMode->hide();
if (rigCaps.memGroups < 2) {
ui->table->hideColumn(columnDuplex);
ui->table->hideColumn(columnDSQL);
ui->table->hideColumn(columnDTCS);
ui->table->hideColumn(columnOffset);
ui->table->hideColumn(columnUR);
ui->table->hideColumn(columnR1);
ui->table->hideColumn(columnR2);
}
if (rigCaps.memGroups < 2) {
ui->groupLabel->hide();
ui->group->hide();
ui->vfoMode->hide();
ui->memoryMode->hide();
} else
// Hide all columns except recall
for (int i=1;i<ui->table->columnCount();i++)
{
ui->groupLabel->show();
ui->group->show();
ui->vfoMode->show();
ui->memoryMode->show();
ui->table->hideColumn(i);
}
foreach (auto parse, rigCaps.memParser) {
switch (parse.spec)
{
case 'a':
ui->groupLabel->show();
ui->group->show();
ui->vfoMode->show();
ui->memoryMode->show();
break;
case 'b':
ui->table->showColumn(columnNum);
break;
case 'c':
ui->table->showColumn(columnMemory);
break;
case 'd':
ui->table->showColumn(columnFrequency);
break;
case 'e':
ui->table->showColumn(columnMode);
break;
case 'f':
ui->table->showColumn(columnFilter);
break;
case 'g':
ui->table->showColumn(columnData);
break;
case 'h':
ui->table->showColumn(columnDuplex);
ui->table->showColumn(columnToneMode);
break;
case 'i':
ui->table->showColumn(columnData);
ui->table->showColumn(columnToneMode);
break;
case 'j':
ui->table->showColumn(columnDSQL);
break;
case 'k':
ui->table->showColumn(columnTone);
break;
case 'l':
ui->table->showColumn(columnTSQL);
break;
case 'm':
ui->table->showColumn(columnDTCSPolarity);
break;
case 'n':
ui->table->showColumn(columnDTCS);
break;
case 'o':
ui->table->showColumn(columnDVSquelch);
break;
case 'p':
ui->table->showColumn(columnOffset);
break;
case 'q':
ui->table->showColumn(columnUR);
break;
case 'r':
ui->table->showColumn(columnR1);
break;
case 's':
ui->table->showColumn(columnR2);
break;
case 't':
ui->table->showColumn(columnName);
break;
case 'u':
break;
case 'v':
break;
case 'w':
break;
case 'x':
break;
case 'y':
break;
case 'z':
break;
default:
break;
}
}
ui->group->blockSignals(true);
for (int i=1;i<=rigCaps.memGroups;i++) {
@ -111,9 +185,9 @@ memories::memories(rigCapabilities rigCaps, QWidget *parent) :
ui->table->setItemDelegateForColumn(columnNum, numEditor);
if (rigCaps.memGroups>1)
nameEditor = new tableEditor(QRegularExpression("[0-9A-Za-z\/\ ]{0,16}$"),ui->table);
nameEditor = new tableEditor(QRegularExpression("[0-9A-Za-z\\/\\ ]{0,16}$"),ui->table);
else
nameEditor = new tableEditor(QRegularExpression("[0-9A-Za-z\/\ ]{0,10}$"),ui->table);
nameEditor = new tableEditor(QRegularExpression("[0-9A-Za-z\\/\\ ]{0,10}$"),ui->table);
ui->table->setItemDelegateForColumn(columnName, nameEditor);
@ -163,13 +237,13 @@ memories::memories(rigCapabilities rigCaps, QWidget *parent) :
dvsqlEditor = new tableEditor(QRegularExpression("[0-9]{0,2}"),ui->table);
ui->table->setItemDelegateForColumn(columnDVSquelch, dvsqlEditor);
urEditor = new tableEditor(QRegularExpression("[0-9A-Z\/\ ]{0,8}$"),ui->table);
urEditor = new tableEditor(QRegularExpression("[0-9A-Z\\/\\ ]{0,8}$"),ui->table);
ui->table->setItemDelegateForColumn(columnUR, urEditor);
r1Editor = new tableEditor(QRegularExpression("[0-9A-Z\/\ ]{0,8}$"),ui->table);
r1Editor = new tableEditor(QRegularExpression("[0-9A-Z\\/\\ ]{0,8}$"),ui->table);
ui->table->setItemDelegateForColumn(columnR1, r1Editor);
r2Editor = new tableEditor(QRegularExpression("[0-9A-Z\/\ ]{0,8}$"),ui->table);
r2Editor = new tableEditor(QRegularExpression("[0-9A-Z\\/\\ ]{0,8}$"),ui->table);
ui->table->setItemDelegateForColumn(columnR2, r2Editor);
connect(ui->table,SIGNAL(rowAdded(int)),this,SLOT(rowAdded(int)));

Wyświetl plik

@ -97,6 +97,7 @@ private:
Ui::memories *ui;
bool extended = false;
enum columns {
columnRecall=0,
columnNum,

Wyświetl plik

@ -1388,47 +1388,89 @@ void rigCommander::setMemory(memoryType mem)
QByteArray payload;
char nul = 0x0;
if (getCommand(funcMemoryContents,payload))
if (getCommand(funcMemoryContents,payload,mem.channel))
{
// Parse the memory entry into a memoryType.
// Format is different for radios with memory groups
qInfo() << "Mem" << mem.channel <<"Offset" <<mem.duplexOffset.Hz;
if (rigCaps.memGroups > 1) {
payload.append(mem.group);
}
payload.append(bcdEncodeInt(mem.channel));
payload.append(mem.memory);
payload.append(makeFreqPayload(mem.frequency));
payload.append(mem.mode);
payload.append(mem.filter);
if (rigCaps.memGroups > 1) {
payload.append(mem.datamode);
payload.append((mem.duplex << 4) | mem.tonemode);
payload.append(mem.dsql << 4);
}
else {
payload.append((mem.datamode << 4 & 0xf0) | (mem.tonemode & 0x0f));
}
payload.append(nul);
payload.append(bcdEncodeInt(mem.tone));
payload.append(nul);
payload.append(bcdEncodeInt(mem.tsql));
if (rigCaps.memGroups > 1) {
payload.append(mem.dtcsp);
payload.append(bcdEncodeInt(mem.dtcs));
payload.append(mem.dvsql);
payload.append(makeFreqPayload(mem.duplexOffset).mid(1,3));
payload.append(QByteArray(mem.UR).leftJustified(8,' '));
payload.append(QByteArray(mem.R1).leftJustified(8,' '));
payload.append(QByteArray(mem.R2).leftJustified(8,' '));
payload.append(QByteArray(mem.name).leftJustified(16,' '));
} else {
payload.append(QByteArray(mem.name).leftJustified(10,' '));
// Format is different for all radios!
foreach (auto parse, rigCaps.memParser) {
switch (parse.spec)
{
case 'a':
payload.append(mem.group);
break;
case 'b':
payload.append(bcdEncodeInt(mem.channel));
break;
case 'c':
payload.append(mem.memory);
break;
case 'd':
payload.append(makeFreqPayload(mem.frequency));
break;
case 'e':
payload.append(mem.mode);
break;
case 'f':
payload.append(mem.filter);
break;
case 'g': // single datamode
payload.append(mem.datamode);
break;
case 'h': // combined duplex and tonemode
payload.append((mem.duplex << 4) | mem.tonemode);
break;
case 'i': // combined datamode and tonemode
payload.append((mem.datamode << 4 & 0xf0) | (mem.tonemode & 0x0f));
break;
case 'j':
payload.append(mem.dsql << 4);
break;
case 'k':
payload.append(nul);
payload.append(bcdEncodeInt(mem.tone));
break;
case 'l':
payload.append(nul);
payload.append(bcdEncodeInt(mem.tsql));
break;
case 'm':
payload.append(mem.dtcsp);
break;
case 'n':
payload.append(bcdEncodeInt(mem.dtcs));
break;
case 'o':
payload.append(mem.dvsql);
break;
case 'p':
payload.append(makeFreqPayload(mem.duplexOffset).mid(1,3));
break;
case 'q':
payload.append(QByteArray(mem.UR).leftJustified(parse.len,' '));
break;
case 'r':
payload.append(QByteArray(mem.R1).leftJustified(parse.len,' '));
break;
case 's':
payload.append(QByteArray(mem.R2).leftJustified(parse.len,' '));
break;
case 't':
payload.append(QByteArray(mem.name).leftJustified(parse.len,' '));
break;
case 'u':
break;
case 'v':
break;
case 'w':
break;
case 'x':
break;
case 'y':
break;
case 'z':
break;
default:
break;
}
}
prepDataAndSend(payload);
}
@ -1830,9 +1872,99 @@ void rigCommander::parseCommand()
break;
case funcMemoryContents:
{
// Parse the memory entry into a memoryType:
memoryType mem;
mem.frequency.Hz=0;
mem.duplexOffset.Hz=0;
int offset = 1;
/*
// 16 is fixed 0x0;
// 19 is fixed 0x0;
*/
foreach (auto parse, rigCaps.memParser) {
QByteArray data = payloadIn.mid(offset+parse.pos,parse.len);
switch (parse.spec)
{
case 'a':
mem.group = bcdHexToUChar(data[0]);
break;
case 'b':
mem.channel = bcdHexToUInt(data[0],data[1]);
break;
case 'c':
mem.memory = data[0];
break;
case 'd':
mem.frequency = parseRawFrequency(data);
break;
case 'e':
mem.mode=(mode_kind)bcdHexToUChar(data[0]);
break;
case 'f':
mem.filter=data[0];
break;
case 'g': // single datamode
mem.datamode=data[0];
break;
case 'h': // combined duplex and tonemode
mem.duplex=duplexMode(data[0] >> 4 & 0x0f);
mem.tonemode=data[0] & 0x0f;
case 'i': // combined datamode and tonemode
mem.datamode=(data[0] >> 4 & 0x0f);
mem.tonemode=data[0] & 0x0f;
break;
case 'j':
mem.dsql = (data[0] >> 4 & 0x0f);
break;
case 'k':
mem.tone = bcdHexToUInt(data[1],data[2]); // First byte is not used
break;
case 'l':
mem.tsql = bcdHexToUInt(data[1],data[2]); // First byte is not used
break;
case 'm':
mem.dtcsp = data[0];
break;
case 'n':
mem.dtcs = bcdHexToUInt(data[0],data[1]);
break;
case 'o':
mem.dvsql = bcdHexToUChar(data[0]);
break;
case 'p':
mem.duplexOffset = parseRawFrequency(data);
break;
case 'q':
memcpy(mem.UR,data,sizeof(mem.UR));
break;
case 'r':
memcpy(mem.R1,data,sizeof(mem.R1));
break;
case 's':
memcpy(mem.R2,data,sizeof(mem.R2));
break;
case 't':
memcpy(mem.name,data,sizeof(mem.name));
break;
case 'u':
break;
case 'v':
break;
case 'w':
break;
case 'x':
break;
case 'y':
break;
case 'z':
break;
default:
break;
}
}
/*
if (rigCaps.memGroups > 1)
{
mem.group = bcdHexToUChar(payloadIn[2]);
@ -1869,6 +2001,7 @@ void rigCommander::parseCommand()
mem.tsql = bcdHexToUInt(payloadIn[17],payloadIn[18]);
memcpy(mem.name,payloadIn.mid(19,10),sizeof(mem.name));
}
*/
emit haveMemory(mem);
}
case funcMemoryClear:
@ -4262,6 +4395,7 @@ void rigCommander::determineRigCaps()
rigCaps.antennas.clear();
rigCaps.filters.clear();
rigCaps.steps.clear();
rigCaps.memParser.clear();
// modelID should already be set!
while (!rigList.contains(rigCaps.modelID))
@ -4304,6 +4438,7 @@ void rigCommander::determineRigCaps()
rigCaps.memGroups = settings->value("MemGroups",0).toUInt();
rigCaps.memories = settings->value("Memories",0).toUInt();
rigCaps.memFormat = settings->value("MemFormat","").toString();
// Temporary QList to hold the function string lookup // I would still like to find a better way of doing this!
QHash<QString, funcs> funcsLookup;
@ -4464,6 +4599,22 @@ void rigCommander::determineRigCaps()
settings->endGroup();
delete settings;
// Setup memory format.
static QRegularExpression memFmtEx("%(?<flags>[-+#0])?(?<pos>\\d+|\\*)?(?:\\.(?<width>\\d+|\\*))?(?<spec>[abcdefghijklmnopqrstuvwxyz])");
QRegularExpressionMatchIterator i = memFmtEx.globalMatch(rigCaps.memFormat);
while (i.hasNext()) {
QRegularExpressionMatch qmatch = i.next();
if (qmatch.hasCaptured("spec") && qmatch.hasCaptured("pos") && qmatch.hasCaptured("width")) {
rigCaps.memParser.append(memParserFormat(qmatch.captured("spec").at(0).toLatin1(),qmatch.captured("pos").toInt(),qmatch.captured("width").toInt()));
qInfo() << QString("Captured: %0 pos: %1 len: %2").arg(rigCaps.memParser.at(rigCaps.memParser.size()-1).spec).
arg(rigCaps.memParser.at(rigCaps.memParser.size()-1).pos).
arg(rigCaps.memParser.at(rigCaps.memParser.size()-1).len);
}
}
/*
switch(model){
case model7300:
@ -5739,6 +5890,25 @@ freqt rigCommander::parseFrequency(QByteArray data, unsigned char lastPosition)
}
freqt rigCommander::parseRawFrequency(QByteArray data)
{
// Allow raw frequency data to be parsed with no bells and whistles (for memory use)
freqt freqs;
freqs.MHzDouble = 0;
freqs.VFO=selVFO_t::activeVFO;
freqs.Hz = 0;
for (int i=0;i<data.size()*2;i=i+2)
{
freqs.Hz += (data[i/2] & 0x0f) * pow10[i];
freqs.Hz += ((data[i/2] & 0xf0) >> 4) * (pow10[i+1]);
}
freqs.MHzDouble = (double)(freqs.Hz / 1000000.0);
return freqs;
}
void rigCommander::parseMode()
{
unsigned char filter=0;

Wyświetl plik

@ -4,6 +4,7 @@
#include <QObject>
#include <QMutexLocker>
#include <QSettings>
#include <QRegularExpression>
#include <QDebug>
#include "wfviewtypes.h"
@ -415,6 +416,7 @@ private:
QByteArray bcdEncodeInt(unsigned int);
void parseFrequency();
freqt parseFrequency(QByteArray data, unsigned char lastPosition); // supply index where Mhz is found
freqt parseRawFrequency(QByteArray data); // supply index where Mhz is found
freqt parseFrequencyRptOffset(QByteArray data);
QByteArray makeFreqPayloadRptOffset(freqt freq);
QByteArray makeFreqPayload(double frequency);
@ -516,6 +518,10 @@ private:
quint8 guid[GUIDLEN] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
QHash<unsigned char,QString> rigList;
quint64 pow10[12] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000
};
#ifdef DEBUG_PARSE
quint64 averageParseTime=0;
int numParseSamples = 0;

Wyświetl plik

@ -109,6 +109,7 @@ void rigCreator::loadRigFile(QString file)
ui->memGroups->setText(settings->value("MemGroups","0").toString());
ui->memories->setText(settings->value("Memories","0").toString());
ui->memoryFormat->setText(settings->value("MemFormat","").toString());
ui->commands->setRowCount(0);
int numCommands = settings->beginReadArray("Commands");
@ -343,6 +344,7 @@ void rigCreator::saveRigFile(QString file)
settings->setValue("MemGroups",ui->memGroups->text().toInt());
settings->setValue("Memories",ui->memories->text().toInt());
settings->setValue("MemFormat",ui->memoryFormat->text());
//settings->remove("Commands");

Wyświetl plik

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>978</width>
<height>551</height>
<height>593</height>
</rect>
</property>
<property name="sizePolicy">
@ -1043,8 +1043,8 @@
<rect>
<x>10</x>
<y>31</y>
<width>101</width>
<height>51</height>
<width>108</width>
<height>52</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
@ -1079,6 +1079,28 @@
</layout>
</widget>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget_2">
<property name="geometry">
<rect>
<x>10</x>
<y>550</y>
<width>951</width>
<height>31</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Memory Format</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="memoryFormat"/>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>

Wyświetl plik

@ -219,6 +219,8 @@ struct rigCapabilities {
quint32 baudRate;
quint16 memGroups;
quint16 memories;
QString memFormat;
QVector<memParserFormat> memParser;
};

Wyświetl plik

@ -17,6 +17,7 @@ HasTransmit=true
HasFDComms=true
MemGroups=3
Memories=107
MemFormat=%1.1a %2.2b %4.1c %5.5d %10.1e %11.1f %12.1g %13.1h %14.1j %15.3k %18.3l %21.1m %22.2n %24.1o %24.4p %28.8q %36.8r %44.8s %52.16t
Commands\1\Type=ACC1 Mod Level
Commands\1\String=\\x1a\\x05\\x01\\x12
Commands\1\Min=0

Wyświetl plik

@ -17,6 +17,7 @@ HasTransmit=true
HasFDComms=false
MemGroups=1
Memories=101
MemFormat=%1.2b %3.1c %4.5d %9.1e %10.1f %11.1i %12.3k %15.3l %18.10t
Commands\1\Type=ACC1 Mod Level
Commands\1\String=\\x1A\\x05\\x00\\x88
Commands\1\Min=0

Wyświetl plik

@ -317,7 +317,7 @@ struct memoryType{
quint16 tsql=670;
quint8 dsql=0;
int dtcs=0;
bool dtcsp=false;
quint8 dtcsp=0;
quint8 dvsql=0;
freqt duplexOffset;
char UR[9];
@ -326,6 +326,14 @@ struct memoryType{
char name[17]; // 1 more than the absolute max
};
struct memParserFormat{
memParserFormat(char spec, int pos, int len) : spec(spec), pos(pos), len(len) {};
char spec;
int pos;
int len;
};
enum audioType {qtAudio,portAudio,rtAudio};
enum codecType { LPCM, PCMU, OPUS };