Finally a good command parsing technique yeilds loads more usable data.

Dark mode is in too!
merge-requests/1/merge
Elliott Liggett 2018-06-22 16:31:52 -07:00 zatwierdzone przez Elliott Liggett
rodzic 24c8ec5a09
commit 1fd6ce5310
49 zmienionych plików z 1566 dodań i 81 usunięć

Wyświetl plik

@ -18,6 +18,10 @@ commHandler::commHandler()
setupComm(); // basic parameters
openPort();
qDebug() << "Serial buffer size: " << port->readBufferSize();
//port->setReadBufferSize(1024); // manually. 256 never saw any return from the radio. why...
//qDebug() << "Serial buffer size: " << port->readBufferSize();
connect(port, SIGNAL(readyRead()), this, SLOT(receiveDataIn()));
}
@ -60,10 +64,57 @@ void commHandler::receiveDataIn()
// connected to comm port data signal
// inPortData.append(port->readAll());
// OLD: inPortData = port->readAll();
// new code:
port->startTransaction();
inPortData = port->readAll();
if(inPortData.startsWith("\xFE\xFE"))
{
if(inPortData.endsWith("\xFD"))
{
// good!
port->commitTransaction();
emit haveDataFromPort(inPortData);
// PRoblem: We often get several chunks together this way
// if we can split and individually send them that would be better.
// could emit several at each FE....FD segment.
// should probbly make the buffer smaller to reduce this
if(rolledBack)
{
qDebug() << "Rolled back and was successfull. Length: " << inPortData.length();
//printHex(inPortData, false, true);
rolledBack = false;
}
} else {
// did not receive the entire thing so roll back:
qDebug() << "Rolling back transaction. End not detected. Lenth: " << inPortData.length();
//printHex(inPortData, false, true);
port->rollbackTransaction();
rolledBack = true;
}
} else {
port->commitTransaction();
qDebug() << "Warning: received data with invalid start. Dropping data.";
qDebug() << "THIS SHOULD ONLY HAPPEN ONCE!!";
// THIS SHOULD ONLY HAPPEN ONCE!
//qDebug() << "Data start: 0x" << (char)inPortData[00] << (char)inPortData[01]; // danger
// unrecoverable. We did not receive the start and must
// have missed it earlier because we did not roll back to
// preserve the beginning.
//printHex(inPortData, false, true);
}
// Here is where we can be smart about this:
// port->startTransaction(); port->rollbackTransaction();
// port->commitTransaction();
// qDebug() << "Data: " << inPortData;
emit haveDataFromPort(inPortData);
// OLD: emit haveDataFromPort(inPortData);
}
void commHandler::openPort()
@ -100,3 +151,37 @@ void commHandler::debugThis()
emit haveDataFromPort(inPortData);
}
void commHandler::printHex(const QByteArray &pdata, bool printVert, bool printHoriz)
{
qDebug() << "---- Begin hex dump -----:";
QString sdata("DATA: ");
QString index("INDEX: ");
QStringList strings;
for(int i=0; i < pdata.length(); i++)
{
strings << QString("[%1]: %2").arg(i,8,10,QChar('0')).arg((unsigned char)pdata[i], 2, 16, QChar('0'));
sdata.append(QString("%1 ").arg((unsigned char)pdata[i], 2, 16, QChar('0')) );
index.append(QString("%1 ").arg(i, 2, 10, QChar('0')));
}
if(printVert)
{
for(int i=0; i < strings.length(); i++)
{
//sdata = QString(strings.at(i));
qDebug() << strings.at(i);
}
}
if(printHoriz)
{
qDebug() << index;
qDebug() << sdata;
}
qDebug() << "----- End hex dump -----";
}

Wyświetl plik

@ -50,10 +50,13 @@ private:
QSerialPort *port;
qint32 baudrate;
unsigned char stopbits;
bool rolledBack;
bool isConnected; // port opened
mutable QMutex mutex;
void printHex(const QByteArray &pdata, bool printVert, bool printHoriz);
};
#endif // COMMHANDLER_H

Wyświetl plik

@ -7,6 +7,8 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//a.setStyle( "Fusion" );
wfmain w;
w.show();

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 220 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 172 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 228 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 187 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 147 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 160 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 150 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 166 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 492 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 491 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 252 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 493 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 249 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 464 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 464 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 240 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 598 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 598 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 586 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 165 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 166 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 166 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 166 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 940 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 972 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 846 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 728 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 760 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 646 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 160 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 160 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 129 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 224 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 182 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 239 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 195 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 578 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 158 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 159 B

Wyświetl plik

@ -0,0 +1,46 @@
<RCC>
<qresource prefix="qss_icons">
<file>rc/up_arrow_disabled.png</file>
<file>rc/Hmovetoolbar.png</file>
<file>rc/stylesheet-branch-end.png</file>
<file>rc/branch_closed-on.png</file>
<file>rc/stylesheet-vline.png</file>
<file>rc/branch_closed.png</file>
<file>rc/branch_open-on.png</file>
<file>rc/transparent.png</file>
<file>rc/right_arrow_disabled.png</file>
<file>rc/sizegrip.png</file>
<file>rc/close.png</file>
<file>rc/close-hover.png</file>
<file>rc/close-pressed.png</file>
<file>rc/down_arrow.png</file>
<file>rc/Vmovetoolbar.png</file>
<file>rc/left_arrow.png</file>
<file>rc/stylesheet-branch-more.png</file>
<file>rc/up_arrow.png</file>
<file>rc/right_arrow.png</file>
<file>rc/left_arrow_disabled.png</file>
<file>rc/Hsepartoolbar.png</file>
<file>rc/branch_open.png</file>
<file>rc/Vsepartoolbar.png</file>
<file>rc/down_arrow_disabled.png</file>
<file>rc/undock.png</file>
<file>rc/checkbox_checked_disabled.png</file>
<file>rc/checkbox_checked_focus.png</file>
<file>rc/checkbox_checked.png</file>
<file>rc/checkbox_indeterminate.png</file>
<file>rc/checkbox_indeterminate_focus.png</file>
<file>rc/checkbox_unchecked_disabled.png</file>
<file>rc/checkbox_unchecked_focus.png</file>
<file>rc/checkbox_unchecked.png</file>
<file>rc/radio_checked_disabled.png</file>
<file>rc/radio_checked_focus.png</file>
<file>rc/radio_checked.png</file>
<file>rc/radio_unchecked_disabled.png</file>
<file>rc/radio_unchecked_focus.png</file>
<file>rc/radio_unchecked.png</file>
</qresource>
<qresource prefix="qdarkstyle">
<file>style.qss</file>
</qresource>
</RCC>

1235
qdarkstyle/style.qss 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -243,91 +243,126 @@ void rigCommander::handleNewData(const QByteArray &data)
parseData(data);
}
void rigCommander::parseData(QByteArray data)
void rigCommander::parseData(QByteArray dataInput)
{
// TODO: Clean this up.
// It finally works very nicely, needs to be streamlined.
//
// Data echo'd back from the rig start with this:
// fe fe 94 e0 ...... fd
int index = 0;
volatile int count = 0; // debug purposes
// Data from the rig that is not an echo start with this:
// fe fe e0 94 ...... fd (for example, a reply to a query)
// Data from the rig that was not asked for is sent to controller 0x00:
// fe fe 00 94 ...... fd (for example, user rotates the tune control or changes the mode)
//qDebug() << "Data received: ";
//printHex(data, false, true);
if(data.length() < 4)
// use this:
QList <QByteArray> dataList = dataInput.split('\xFD');
QByteArray data;
// qDebug() << "data list has this many elements: " << dataList.size();
if (dataList.last().isEmpty())
{
if(data.length())
{
qDebug() << "Data length too short: " << data.length() << " bytes. Data:";
printHex(data, false, true);
}
return;
dataList.removeLast(); // if the original ended in FD, then there is a blank entry at the end.
}
if(!data.startsWith("\xFE\xFE"))
// Only thing is, each frame is missing '\xFD' at the end. So append! Keeps the frames intact.
for(index = 0; index < dataList.count(); index++)
{
qDebug() << "Warning: Invalid data received, did not start with FE FE.";
// find 94 e0 and shift over,
// or look inside for a second FE FE
// Often a local echo will miss a few bytes at the beginning.
if(data.startsWith('\xFE'))
data = dataList[index];
data.append('\xFD'); // because we expect it to be there.
// foreach(listitem)
// listitem.append('\xFD');
// continue parsing...
count++;
// Data echo'd back from the rig start with this:
// fe fe 94 e0 ...... fd
// Data from the rig that is not an echo start with this:
// fe fe e0 94 ...... fd (for example, a reply to a query)
// Data from the rig that was not asked for is sent to controller 0x00:
// fe fe 00 94 ...... fd (for example, user rotates the tune control or changes the mode)
//qDebug() << "Data received: ";
//printHex(data, false, true);
if(data.length() < 4)
{
data.prepend('\xFE');
qDebug() << "Warning: Working with prepended data stream.";
parseData(payloadIn);
return;
} else {
qDebug() << "Error: Could not reconstruct corrupted data: ";
printHex(data, false, true);
// data.right(data.length() - data.find('\xFE\xFE'));
// if found do not return and keep going.
return;
if(data.length())
{
// Finally this almost never happens
qDebug() << "Data length too short: " << data.length() << " bytes. Data:";
printHex(data, false, true);
}
// no
//return;
// maybe:
// continue;
}
if(!data.startsWith("\xFE\xFE"))
{
qDebug() << "Warning: Invalid data received, did not start with FE FE.";
// find 94 e0 and shift over,
// or look inside for a second FE FE
// Often a local echo will miss a few bytes at the beginning.
if(data.startsWith('\xFE'))
{
data.prepend('\xFE');
qDebug() << "Warning: Working with prepended data stream.";
parseData(payloadIn);
return;
} else {
qDebug() << "Error: Could not reconstruct corrupted data: ";
printHex(data, false, true);
// data.right(data.length() - data.find('\xFE\xFE'));
// if found do not return and keep going.
return;
}
}
if((unsigned char)data[02] == civAddr)
{
// data is or begins with an echoback from what we sent
// find the first 'fd' and cut it. Then continue.
//payloadIn = data.right(data.length() - data.indexOf('\xfd')-1);
// qDebug() << "[FOUND] Trimmed off echo:";
//printHex(payloadIn, false, true);
//parseData(payloadIn);
//return;
}
switch(data[02])
{
// case civAddr: // can't have a variable here :-(
// // data is or begins with an echoback from what we sent
// // find the first 'fd' and cut it. Then continue.
// payloadIn = data.right(data.length() - data.indexOf('\xfd')-1);
// //qDebug() << "Trimmed off echo:";
// //printHex(payloadIn, false, true);
// parseData(payloadIn);
// break;
case '\xE0':
// data is a reply to some query we sent
// extract the payload out and parse.
// payload = getpayload(data); // or something
// parse (payload); // recursive ok?
payloadIn = data.right(data.length() - 4);
parseCommand();
break;
case '\x00':
// data send initiated by the rig due to user control
// extract the payload out and parse.
payloadIn = data.right(data.length() - 4);
parseCommand();
break;
default:
// could be for other equipment on the CIV network.
// just drop for now.
break;
}
}
if((unsigned char)data[02] == civAddr)
/*
if(dataList.length() > 1)
{
// data is or begins with an echoback from what we sent
// find the first 'fd' and cut it. Then continue.
payloadIn = data.right(data.length() - data.indexOf('\xfd')-1);
//qDebug() << "Trimmed off echo:";
//printHex(payloadIn, false, true);
parseData(payloadIn);
return;
}
switch(data[02])
{
// case civAddr: // can't have a variable here :-(
// // data is or begins with an echoback from what we sent
// // find the first 'fd' and cut it. Then continue.
// payloadIn = data.right(data.length() - data.indexOf('\xfd')-1);
// //qDebug() << "Trimmed off echo:";
// //printHex(payloadIn, false, true);
// parseData(payloadIn);
// break;
case '\xE0':
// data is a reply to some query we sent
// extract the payload out and parse.
// payload = getpayload(data); // or something
// parse (payload); // recursive ok?
payloadIn = data.right(data.length() - 4);
parseCommand();
break;
case '\x00':
// data send initiated by the rig due to user control
// extract the payload out and parse.
payloadIn = data.right(data.length() - 4);
parseCommand();
break;
default:
// could be for other equipment on the CIV network.
// just drop for now.
break;
qDebug() << "Recovered " << count << " frames from single data with size" << dataList.count();
}
*/
}
void rigCommander::parseCommand()
@ -373,6 +408,8 @@ void rigCommander::parseCommand()
printHex(payloadIn, false, true);
break;
}
// is any payload left?
}
void rigCommander::parseSpectrum()

Wyświetl plik

@ -126,9 +126,78 @@ wfmain::~wfmain()
delete ui;
}
void wfmain::setDarkTheme(bool dark)
void wfmain::on_useDarkThemeChk_clicked(bool checked)
{
//theParent->setStyle();
setAppTheme(checked);
setPlotTheme(wf, checked);
setPlotTheme(plot, checked);
}
void wfmain::setAppTheme(bool isDark)
{
if(isDark)
{
QFile f(":qdarkstyle/style.qss");
if (!f.exists())
{
printf("Unable to set stylesheet, file not found\n");
}
else
{
f.open(QFile::ReadOnly | QFile::Text);
QTextStream ts(&f);
qApp->setStyleSheet(ts.readAll());
}
} else {
qApp->setStyleSheet("");
}
}
void wfmain::setPlotTheme(QCustomPlot *plot, bool isDark)
{
if(isDark)
{
plot->setBackground(QColor(0,0,0,255));
plot->xAxis->grid()->setPen(QColor(75,75,75,255));
plot->yAxis->grid()->setPen(QColor(75,75,75,255));
plot->legend->setTextColor(QColor(255,255,255,255));
plot->legend->setBorderPen(QColor(255,255,255,255));
plot->legend->setBrush(QColor(0,0,0,200));
plot->xAxis->setTickLabelColor(Qt::white);
plot->xAxis->setLabelColor(Qt::white);
plot->yAxis->setTickLabelColor(Qt::white);
plot->yAxis->setLabelColor(Qt::white);
plot->xAxis->setBasePen(QPen(Qt::white));
plot->xAxis->setTickPen(QPen(Qt::white));
plot->yAxis->setBasePen(QPen(Qt::white));
plot->yAxis->setTickPen(QPen(Qt::white));
plot->graph(0)->setPen(QPen(Qt::lightGray)); // magenta, yellow, green, lightGray
} else {
plot->setBackground(QColor(255,255,255,255));
plot->xAxis->grid()->setPen(QColor(200,200,200,255));
plot->yAxis->grid()->setPen(QColor(200,200,200,255));
plot->legend->setTextColor(QColor(0,0,0,255));
plot->legend->setBorderPen(QColor(0,0,0,255));
plot->legend->setBrush(QColor(255,255,255,200));
plot->xAxis->setTickLabelColor(Qt::black);
plot->xAxis->setLabelColor(Qt::black);
plot->yAxis->setTickLabelColor(Qt::black);
plot->yAxis->setLabelColor(Qt::black);
plot->xAxis->setBasePen(QPen(Qt::black));
plot->xAxis->setTickPen(QPen(Qt::black));
plot->yAxis->setBasePen(QPen(Qt::black));
plot->yAxis->setTickPen(QPen(Qt::black));
plot->graph(0)->setPen(QPen(Qt::blue));
}
}
void wfmain::runDelayedCommand()
@ -170,7 +239,7 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e
//qDebug() << "Spectrum data received at UI! Length: " << specLen;
if(specLen != 475)
{
//qDebug () << "Unusual spectrum: length: " << specLen;
qDebug () << "Unusual spectrum: length: " << specLen;
if(specLen > 475)
{
specLen = 475;
@ -508,3 +577,5 @@ void wfmain::on_modeSelectCombo_currentIndexChanged(int index)
}
}
}

Wyświetl plik

@ -94,13 +94,16 @@ private slots:
void on_modeSelectCombo_currentIndexChanged(int index);
void on_useDarkThemeChk_clicked(bool checked);
private:
Ui::wfmain *ui;
QCustomPlot *plot; // line plot
QCustomPlot *wf; // waterfall image
QCPItemTracer * tracer; // marker of current frequency
//commHandler *comm;
void setDarkTheme(bool dark);
void setAppTheme(bool isDark);
void setPlotTheme(QCustomPlot *plot, bool isDark);
QWidget * theParent;
rigCommander * rig;

Wyświetl plik

@ -18,7 +18,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>3</number>
</property>
<widget class="QWidget" name="mainTab">
<attribute name="title">
@ -910,7 +910,7 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<widget class="QCheckBox" name="useDarkThemeChk">
<property name="text">
<string>Use Dark Theme</string>
</property>

Wyświetl plik

@ -20,6 +20,9 @@ QMAKE_CXXFLAGS += -march=native
DEFINES += QT_DEPRECATED_WARNINGS
DEFINES += QCUSTOMPLOT_COMPILE_LIBRARY
RESOURCES += qdarkstyle/style.qrc
#CONFIG(debug, release|debug) {
# win32:QCPLIB = qcustomplotd1
# else: QCPLIB = qcustomplotd