Merge pull request #166 from collin80/WIP
Merge WIP changes into Master
@@ -1,12 +1,12 @@
|
|||||||
# SavvyCAN
|
# SavvyCAN
|
||||||
Qt based cross platform canbus tool
|
Qt based cross platform canbus tool
|
||||||
(C) 2015-2017 EVTV and Collin Kidder
|
(C) 2015-2018 EVTV and Collin Kidder
|
||||||
|
|
||||||
A Qt5 based cross platform tool which can be used to load, save, and capture canbus frames.
|
A Qt5 based cross platform tool which can be used to load, save, and capture canbus frames.
|
||||||
This tool is designed to help with visualization, reverse engineering, debugging, and
|
This tool is designed to help with visualization, reverse engineering, debugging, and
|
||||||
capturing of canbus frames.
|
capturing of canbus frames.
|
||||||
|
|
||||||
Really requires at a resolution of at least 1024x768. Fully multi-monitor capable.
|
Really requires at a resolution of at least 1024x768. Fully multi-monitor capable. Works on 4K monitors as well.
|
||||||
|
|
||||||
You are highly recommended to use the
|
You are highly recommended to use the
|
||||||
[CANDue board from EVTV](http://store.evtv.me/proddetail.php?prod=ArduinoDueCANBUS&cat=23).
|
[CANDue board from EVTV](http://store.evtv.me/proddetail.php?prod=ArduinoDueCANBUS&cat=23).
|
||||||
@@ -14,8 +14,8 @@ You are highly recommended to use the
|
|||||||
The CANDue board must be running the GVRET firmware which can also be found
|
The CANDue board must be running the GVRET firmware which can also be found
|
||||||
within the collin80 repos.
|
within the collin80 repos.
|
||||||
|
|
||||||
It is now possible to use any SocketCAN compatible device
|
It is now possible to use any QT SerialBus driver (socketcan, Vector, PeakCAN, TinyCAN).
|
||||||
under LINUX. There may, however, be some loss of some functionality as
|
There may, however, be some loss of some functionality as
|
||||||
some functions of SavvyCAN are designed for use directly with the
|
some functions of SavvyCAN are designed for use directly with the
|
||||||
EVTVDue and CANDue 2.0 boards.
|
EVTVDue and CANDue 2.0 boards.
|
||||||
|
|
||||||
@@ -46,7 +46,8 @@ http://www.qcustomplot.com/
|
|||||||
However, this source code is integrated into the source for SavvyCAN and one isn't required
|
However, this source code is integrated into the source for SavvyCAN and one isn't required
|
||||||
to download it separately.
|
to download it separately.
|
||||||
|
|
||||||
This project requires 5.8.0 or higher because of a dependency on QSerialBus.
|
This project requires 5.8.0 or higher because of a dependency on QSerialBus. However, you will get
|
||||||
|
even more SerialBus goodness if you use QT 5.11 or 5.12
|
||||||
|
|
||||||
## Instructions for compiling:
|
## Instructions for compiling:
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ SOURCES += main.cpp\
|
|||||||
jsedit.cpp \
|
jsedit.cpp \
|
||||||
frameplaybackobject.cpp \
|
frameplaybackobject.cpp \
|
||||||
helpwindow.cpp \
|
helpwindow.cpp \
|
||||||
blfhandler.cpp
|
blfhandler.cpp \
|
||||||
|
re/sniffer/SnifferDelegate.cpp
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
can_structs.h \
|
can_structs.h \
|
||||||
@@ -121,7 +122,8 @@ HEADERS += mainwindow.h \
|
|||||||
jsedit.h \
|
jsedit.h \
|
||||||
frameplaybackobject.h \
|
frameplaybackobject.h \
|
||||||
helpwindow.h \
|
helpwindow.h \
|
||||||
blfhandler.h
|
blfhandler.h \
|
||||||
|
re/sniffer/SnifferDelegate.h
|
||||||
|
|
||||||
FORMS += ui/candatagrid.ui \
|
FORMS += ui/candatagrid.ui \
|
||||||
ui/connectionwindow.ui \
|
ui/connectionwindow.ui \
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<QHelpCollectionProject version="1.0">
|
<QHelpCollectionProject version="1.0">
|
||||||
<assistant>
|
<assistant>
|
||||||
<title>SavvyCAN 181 documentation</title>
|
<title>SavvyCAN 189 documentation</title>
|
||||||
<homePage>qthelp://org.sphinx.savvycan.181/doc/index.html</homePage>
|
<homePage>qthelp://org.sphinx.savvycan.189/doc/index.html</homePage>
|
||||||
<startPage>qthelp://org.sphinx.savvycan.181/doc/index.html</startPage>
|
<startPage>qthelp://org.sphinx.savvycan.189/doc/index.html</startPage>
|
||||||
</assistant>
|
</assistant>
|
||||||
<docFiles>
|
<docFiles>
|
||||||
<generate>
|
<generate>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<QtHelpProject version="1.0">
|
<QtHelpProject version="1.0">
|
||||||
<namespace>org.sphinx.savvycan.181</namespace>
|
<namespace>org.sphinx.savvycan.189</namespace>
|
||||||
<virtualFolder>doc</virtualFolder>
|
<virtualFolder>doc</virtualFolder>
|
||||||
<customFilter name="SavvyCAN 181">
|
<customFilter name="SavvyCAN 189">
|
||||||
<filterAttribute>SavvyCAN</filterAttribute>
|
<filterAttribute>SavvyCAN</filterAttribute>
|
||||||
<filterAttribute>181</filterAttribute>
|
<filterAttribute>189</filterAttribute>
|
||||||
</customFilter>
|
</customFilter>
|
||||||
<filterSection>
|
<filterSection>
|
||||||
<filterAttribute>SavvyCAN</filterAttribute>
|
<filterAttribute>SavvyCAN</filterAttribute>
|
||||||
<filterAttribute>181</filterAttribute>
|
<filterAttribute>189</filterAttribute>
|
||||||
<toc>
|
<toc>
|
||||||
<section title="SavvyCAN 181 documentation" ref="index.html">
|
<section title="SavvyCAN 189 documentation" ref="index.html">
|
||||||
<section title="Main / Start Up Screen" ref="mainscreen.html"/>
|
<section title="Main / Start Up Screen" ref="mainscreen.html"/>
|
||||||
<section title="The Main Frame List" ref="mainscreen.html#the-main-frame-list"/>
|
<section title="The Main Frame List" ref="mainscreen.html#the-main-frame-list"/>
|
||||||
<section title="The Bottom Statusbar" ref="mainscreen.html#the-bottom-statusbar"/>
|
<section title="The Bottom Statusbar" ref="mainscreen.html#the-bottom-statusbar"/>
|
||||||
@@ -58,6 +58,11 @@
|
|||||||
<section title="Sniffer Window" ref="sniffer.html"/>
|
<section title="Sniffer Window" ref="sniffer.html"/>
|
||||||
<section title="Using the Sniffer Window" ref="sniffer.html#using-the-sniffer-window"/>
|
<section title="Using the Sniffer Window" ref="sniffer.html#using-the-sniffer-window"/>
|
||||||
<section title="Notching and Unnotching" ref="sniffer.html#notching-and-unnotching"/>
|
<section title="Notching and Unnotching" ref="sniffer.html#notching-and-unnotching"/>
|
||||||
|
<section title="Advanced Options" ref="sniffer.html#advanced-options"/>
|
||||||
|
<section title="Never Expire IDs" ref="sniffer.html#never-expire-ids"/>
|
||||||
|
<section title="Mute notched bits" ref="sniffer.html#mute-notched-bits"/>
|
||||||
|
<section title="Fade inactive bytes" ref="sniffer.html#fade-inactive-bytes"/>
|
||||||
|
<section title="View Bits" ref="sniffer.html#view-bits"/>
|
||||||
<section title="Frame Details Window" ref="framedetails.html"/>
|
<section title="Frame Details Window" ref="framedetails.html"/>
|
||||||
<section title="The Purpose of Frame Details Window" ref="framedetails.html#the-purpose-of-frame-details-window"/>
|
<section title="The Purpose of Frame Details Window" ref="framedetails.html#the-purpose-of-frame-details-window"/>
|
||||||
<section title="File Comparison Window" ref="filecomparison.html"/>
|
<section title="File Comparison Window" ref="filecomparison.html"/>
|
||||||
@@ -101,63 +106,65 @@
|
|||||||
|
|
||||||
</keywords>
|
</keywords>
|
||||||
<files>
|
<files>
|
||||||
<file>flowview.html</file>
|
|
||||||
<file>dbc_manager.html</file>
|
|
||||||
<file>graphwindow.html</file>
|
|
||||||
<file>framedetails.html</file>
|
|
||||||
<file>rangestate.html</file>
|
|
||||||
<file>filecomparison.html</file>
|
|
||||||
<file>connectionwindow.html</file>
|
|
||||||
<file>fuzzingwindow.html</file>
|
|
||||||
<file>mainscreen.html</file>
|
|
||||||
<file>signaleditor.html</file>
|
|
||||||
<file>uds_scanner.html</file>
|
|
||||||
<file>customsender.html</file>
|
|
||||||
<file>graphsetup.html</file>
|
|
||||||
<file>playbackwindow.html</file>
|
|
||||||
<file>index.html</file>
|
|
||||||
<file>scriptingwindow.html</file>
|
|
||||||
<file>bisector.html</file>
|
<file>bisector.html</file>
|
||||||
<file>firmwareuploader.html</file>
|
<file>connectionwindow.html</file>
|
||||||
<file>genindex.html</file>
|
<file>customsender.html</file>
|
||||||
<file>sniffer.html</file>
|
|
||||||
<file>isotp_decoder.html</file>
|
|
||||||
<file>preferences.html</file>
|
|
||||||
<file>dbc_editor.html</file>
|
<file>dbc_editor.html</file>
|
||||||
<file>_static/file.png</file>
|
<file>dbc_manager.html</file>
|
||||||
<file>_static/down.png</file>
|
<file>filecomparison.html</file>
|
||||||
|
<file>firmwareuploader.html</file>
|
||||||
|
<file>flowview.html</file>
|
||||||
|
<file>framedetails.html</file>
|
||||||
|
<file>fuzzingwindow.html</file>
|
||||||
|
<file>genindex.html</file>
|
||||||
|
<file>graphsetup.html</file>
|
||||||
|
<file>graphwindow.html</file>
|
||||||
|
<file>index.html</file>
|
||||||
|
<file>isotp_decoder.html</file>
|
||||||
|
<file>mainscreen.html</file>
|
||||||
|
<file>playbackwindow.html</file>
|
||||||
|
<file>preferences.html</file>
|
||||||
|
<file>rangestate.html</file>
|
||||||
|
<file>scriptingwindow.html</file>
|
||||||
|
<file>search.html</file>
|
||||||
|
<file>signaleditor.html</file>
|
||||||
|
<file>sniffer.html</file>
|
||||||
|
<file>uds_scanner.html</file>
|
||||||
<file>_static/ajax-loader.gif</file>
|
<file>_static/ajax-loader.gif</file>
|
||||||
<file>_static/comment-close.png</file>
|
<file>_static/alabaster.css</file>
|
||||||
<file>_static/minus.png</file>
|
|
||||||
<file>_static/comment-bright.png</file>
|
|
||||||
<file>_static/up-pressed.png</file>
|
|
||||||
<file>_static/pygments.css</file>
|
|
||||||
<file>_static/plus.png</file>
|
|
||||||
<file>_static/nonav.css</file>
|
|
||||||
<file>_static/basic.css</file>
|
<file>_static/basic.css</file>
|
||||||
<file>_static/down-pressed.png</file>
|
<file>_static/comment-bright.png</file>
|
||||||
<file>_static/up.png</file>
|
<file>_static/comment-close.png</file>
|
||||||
<file>_static/comment.png</file>
|
<file>_static/comment.png</file>
|
||||||
<file>_images/SignalEditor.png</file>
|
<file>_static/down-pressed.png</file>
|
||||||
<file>_images/FrameInfoWindow.png</file>
|
<file>_static/down.png</file>
|
||||||
<file>_images/DBCEditor.png</file>
|
<file>_static/file.png</file>
|
||||||
<file>_images/UDS_Scanner.png</file>
|
<file>_static/minus.png</file>
|
||||||
<file>_images/Sniffer.png</file>
|
<file>_static/nonav.css</file>
|
||||||
|
<file>_static/plus.png</file>
|
||||||
|
<file>_static/pygments.css</file>
|
||||||
|
<file>_static/up-pressed.png</file>
|
||||||
|
<file>_static/up.png</file>
|
||||||
<file>_images/Bisector.png</file>
|
<file>_images/Bisector.png</file>
|
||||||
<file>_images/FuzzingWindow.png</file>
|
|
||||||
<file>_images/GraphingView.png</file>
|
|
||||||
<file>_images/ScriptingWindow.png</file>
|
|
||||||
<file>_images/DBCManager.png</file>
|
|
||||||
<file>_images/GraphSetup.png</file>
|
|
||||||
<file>_images/RangeState.png</file>
|
|
||||||
<file>_images/Preferences.png</file>
|
|
||||||
<file>_images/ConnectionWindow.png</file>
|
<file>_images/ConnectionWindow.png</file>
|
||||||
|
<file>_images/CustomSender.png</file>
|
||||||
|
<file>_images/DBCEditor.png</file>
|
||||||
|
<file>_images/DBCManager.png</file>
|
||||||
<file>_images/FileComparator.png</file>
|
<file>_images/FileComparator.png</file>
|
||||||
|
<file>_images/FlowView.png</file>
|
||||||
|
<file>_images/FrameInfoWindow.png</file>
|
||||||
|
<file>_images/FuzzingWindow.png</file>
|
||||||
|
<file>_images/GraphSetup.png</file>
|
||||||
|
<file>_images/GraphingView.png</file>
|
||||||
<file>_images/ISOTPDecoder.png</file>
|
<file>_images/ISOTPDecoder.png</file>
|
||||||
<file>_images/MainScreen.png</file>
|
<file>_images/MainScreen.png</file>
|
||||||
<file>_images/FlowView.png</file>
|
|
||||||
<file>_images/CustomSender.png</file>
|
|
||||||
<file>_images/Playback.png</file>
|
<file>_images/Playback.png</file>
|
||||||
|
<file>_images/Preferences.png</file>
|
||||||
|
<file>_images/RangeState.png</file>
|
||||||
|
<file>_images/ScriptingWindow.png</file>
|
||||||
|
<file>_images/SignalEditor.png</file>
|
||||||
|
<file>_images/Sniffer.png</file>
|
||||||
|
<file>_images/UDS_Scanner.png</file>
|
||||||
</files>
|
</files>
|
||||||
</filterSection>
|
</filterSection>
|
||||||
</QtHelpProject>
|
</QtHelpProject>
|
||||||
@@ -160,6 +160,7 @@ void CANFrameModel::setOverwriteMode(bool mode)
|
|||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
overwriteDups = mode;
|
overwriteDups = mode;
|
||||||
|
recalcOverwrite();
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,26 +192,20 @@ void CANFrameModel::recalcOverwrite()
|
|||||||
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
for (int i = 1; i < frames.count(); i++)
|
|
||||||
{
|
|
||||||
found = false;
|
|
||||||
for (int j = 0; j <= lastUnique; j++)
|
|
||||||
{
|
|
||||||
if (frames[i].ID == frames[j].ID)
|
|
||||||
{
|
|
||||||
frames.replace(j, frames[i]);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
lastUnique++;
|
|
||||||
frames.replace(lastUnique, frames[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (frames.count() > lastUnique) frames.removeLast();
|
//Look at the current list of frames and turn it into just a list of unique IDs
|
||||||
|
QHash<int, CANFrame> overWriteFrames;
|
||||||
|
foreach(CANFrame frame, frames)
|
||||||
|
{
|
||||||
|
if (!overWriteFrames.contains(frame.ID))
|
||||||
|
{
|
||||||
|
overWriteFrames.insert(frame.ID, frame);
|
||||||
|
}
|
||||||
|
else overWriteFrames[frame.ID] = frame;
|
||||||
|
}
|
||||||
|
//Then replace the old list of frames with just the unique list
|
||||||
|
frames.clear();
|
||||||
|
frames.append(overWriteFrames.values().toVector());
|
||||||
|
|
||||||
filteredFrames.clear();
|
filteredFrames.clear();
|
||||||
filteredFrames.reserve(preallocSize);
|
filteredFrames.reserve(preallocSize);
|
||||||
@@ -255,6 +250,11 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
|
|||||||
return QColor(Qt::white);
|
return QColor(Qt::white);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (role == Qt::TextAlignmentRole)
|
||||||
|
{
|
||||||
|
return Qt::AlignLeft;
|
||||||
|
}
|
||||||
|
|
||||||
if (role == Qt::TextColorRole)
|
if (role == Qt::TextColorRole)
|
||||||
{
|
{
|
||||||
if (dbcHandler != NULL && interpretFrames)
|
if (dbcHandler != NULL && interpretFrames)
|
||||||
@@ -300,7 +300,8 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
|
|||||||
for (int i = 0; i < dLen; i++)
|
for (int i = 0; i < dLen; i++)
|
||||||
{
|
{
|
||||||
quint8 byt = thisFrame.data[i];
|
quint8 byt = thisFrame.data[i];
|
||||||
if (byt < 0x20) byt = 0x2E; //A dot
|
//0x20 through 0x7E are printable characters. Outside of that range they aren't. So use dots instead
|
||||||
|
if (byt < 0x20) byt = 0x2E; //dot character
|
||||||
if (byt > 0x7E) byt = 0x2E;
|
if (byt > 0x7E) byt = 0x2E;
|
||||||
tempString.append(QString::fromUtf8((char *)&byt, 1));
|
tempString.append(QString::fromUtf8((char *)&byt, 1));
|
||||||
}
|
}
|
||||||
@@ -326,7 +327,7 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
|
|||||||
DBC_MESSAGE *msg = dbcHandler->findMessage(thisFrame);
|
DBC_MESSAGE *msg = dbcHandler->findMessage(thisFrame);
|
||||||
if (msg != NULL)
|
if (msg != NULL)
|
||||||
{
|
{
|
||||||
tempString.append("\n");
|
tempString.append(" <Interpreted>\n");
|
||||||
tempString.append(msg->name + "\n" + msg->comment + "\n");
|
tempString.append(msg->name + "\n" + msg->comment + "\n");
|
||||||
for (int j = 0; j < msg->sigHandler->getCount(); j++)
|
for (int j = 0; j < msg->sigHandler->getCount(); j++)
|
||||||
{
|
{
|
||||||
@@ -410,7 +411,7 @@ void CANFrameModel::addFrame(const CANFrame& frame, bool autoRefresh = false)
|
|||||||
frames.append(tempFrame);
|
frames.append(tempFrame);
|
||||||
if (filters[tempFrame.ID])
|
if (filters[tempFrame.ID])
|
||||||
{
|
{
|
||||||
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + 1);
|
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count(), filteredFrames.count());
|
||||||
filteredFrames.append(tempFrame);
|
filteredFrames.append(tempFrame);
|
||||||
if (autoRefresh) endInsertRows();
|
if (autoRefresh) endInsertRows();
|
||||||
}
|
}
|
||||||
@@ -432,7 +433,7 @@ void CANFrameModel::addFrame(const CANFrame& frame, bool autoRefresh = false)
|
|||||||
frames.append(tempFrame);
|
frames.append(tempFrame);
|
||||||
if (filters[tempFrame.ID])
|
if (filters[tempFrame.ID])
|
||||||
{
|
{
|
||||||
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + 1);
|
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count(), filteredFrames.count());
|
||||||
filteredFrames.append(tempFrame);
|
filteredFrames.append(tempFrame);
|
||||||
if (autoRefresh) endInsertRows();
|
if (autoRefresh) endInsertRows();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef CONFIG
|
#ifndef CONFIG
|
||||||
#define CONFIG
|
#define CONFIG
|
||||||
|
|
||||||
#define VERSION 187
|
#define VERSION 190
|
||||||
|
|
||||||
//try to keep this in sync.
|
//try to keep this in sync.
|
||||||
//SavvyCAN will complain if you connect a GVRET board with a revision
|
//SavvyCAN will complain if you connect a GVRET board with a revision
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace CANCon {
|
|||||||
{
|
{
|
||||||
GVRET_SERIAL,
|
GVRET_SERIAL,
|
||||||
KVASER,
|
KVASER,
|
||||||
SOCKETCAN,
|
SERIALBUS,
|
||||||
REMOTE,
|
REMOTE,
|
||||||
NONE
|
NONE
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
using namespace CANCon;
|
using namespace CANCon;
|
||||||
|
|
||||||
CANConnection* CanConFactory::create(type pType, QString pPortName)
|
CANConnection* CanConFactory::create(type pType, QString pPortName, QString pDriverName)
|
||||||
{
|
{
|
||||||
switch(pType) {
|
switch(pType) {
|
||||||
case SOCKETCAN:
|
case SERIALBUS:
|
||||||
return new SerialBusConnection(pPortName);
|
return new SerialBusConnection(pPortName, pDriverName);
|
||||||
case GVRET_SERIAL:
|
case GVRET_SERIAL:
|
||||||
return new GVRetSerial(pPortName, false);
|
return new GVRetSerial(pPortName, false);
|
||||||
case REMOTE:
|
case REMOTE:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
class CanConFactory
|
class CanConFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static CANConnection* create(CANCon::type, QString pPortName);
|
static CANConnection* create(CANCon::type, QString pPortName, QString pDriverName);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CANCONFACTORY_H
|
#endif // CANCONFACTORY_H
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "canconnection.h"
|
#include "canconnection.h"
|
||||||
|
|
||||||
CANConnection::CANConnection(QString pPort,
|
CANConnection::CANConnection(QString pPort,
|
||||||
|
QString pDriver,
|
||||||
CANCon::type pType,
|
CANCon::type pType,
|
||||||
int pNumBuses,
|
int pNumBuses,
|
||||||
int pQueueLen,
|
int pQueueLen,
|
||||||
@@ -10,6 +11,7 @@ CANConnection::CANConnection(QString pPort,
|
|||||||
mQueue(),
|
mQueue(),
|
||||||
mNumBuses(pNumBuses),
|
mNumBuses(pNumBuses),
|
||||||
mPort(pPort),
|
mPort(pPort),
|
||||||
|
mDriver(pDriver),
|
||||||
mType(pType),
|
mType(pType),
|
||||||
mIsCapSuspended(false),
|
mIsCapSuspended(false),
|
||||||
mStatus(CANCon::NOT_CONNECTED),
|
mStatus(CANCon::NOT_CONNECTED),
|
||||||
@@ -227,6 +229,10 @@ QString CANConnection::getPort() {
|
|||||||
return mPort;
|
return mPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CANConnection::getDriver()
|
||||||
|
{
|
||||||
|
return mDriver;
|
||||||
|
}
|
||||||
|
|
||||||
LFQueue<CANFrame>& CANConnection::getQueue() {
|
LFQueue<CANFrame>& CANConnection::getQueue() {
|
||||||
return mQueue;
|
return mQueue;
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* @brief CANConnection constructor
|
* @brief CANConnection constructor
|
||||||
* @param pPort: string containing port name
|
* @param pPort: string containing port name
|
||||||
|
* @param pDriver: string containing driver name - Really only used for SerialBus connections
|
||||||
* @param pType: the type of connection @ref CANCon::type
|
* @param pType: the type of connection @ref CANCon::type
|
||||||
* @param pNumBuses: the number of buses the device has
|
* @param pNumBuses: the number of buses the device has
|
||||||
* @param pQueueLen: the length of the lock free queue to use
|
* @param pQueueLen: the length of the lock free queue to use
|
||||||
* @param pUseThread: if set to true, object will be execute in a dedicated thread
|
* @param pUseThread: if set to true, object will be execute in a dedicated thread
|
||||||
*/
|
*/
|
||||||
CANConnection(QString pPort,
|
CANConnection(QString pPort,
|
||||||
|
QString pDriver,
|
||||||
CANCon::type pType,
|
CANCon::type pType,
|
||||||
int pNumBuses,
|
int pNumBuses,
|
||||||
int pQueueLen,
|
int pQueueLen,
|
||||||
@@ -50,6 +52,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
QString getPort();
|
QString getPort();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getDriver
|
||||||
|
* @return returns the name of the driver used for this device
|
||||||
|
*/
|
||||||
|
QString getDriver();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getQueue
|
* @brief getQueue
|
||||||
* @return the lock free queue of the device
|
* @return the lock free queue of the device
|
||||||
@@ -294,6 +303,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
LFQueue<CANFrame> mQueue;
|
LFQueue<CANFrame> mQueue;
|
||||||
const QString mPort;
|
const QString mPort;
|
||||||
|
const QString mDriver;
|
||||||
const CANCon::type mType;
|
const CANCon::type mType;
|
||||||
bool mIsCapSuspended;
|
bool mIsCapSuspended;
|
||||||
QAtomicInt mStatus;
|
QAtomicInt mStatus;
|
||||||
|
|||||||
@@ -87,10 +87,11 @@ Qt::ItemFlags CANConnectionModel::flags(const QModelIndex &index) const
|
|||||||
CANConnection *conn_p = getAtIdx(index.row(), busId);
|
CANConnection *conn_p = getAtIdx(index.row(), busId);
|
||||||
if (!conn_p) return Qt::ItemFlag::NoItemFlags;
|
if (!conn_p) return Qt::ItemFlag::NoItemFlags;
|
||||||
|
|
||||||
//you can't set speed, single wire, or listen only on socketcan devices so
|
//socketcan is limited for what you can set but the other serialbus
|
||||||
//detect if we're using GVRET where you can and turn that functionality on
|
//devices should be able to set the stuff. For now let anyone try
|
||||||
bool editParams = false;
|
//and the underlying drivers can do with them as they will
|
||||||
if (conn_p->getType() == CANCon::GVRET_SERIAL) editParams = true;
|
bool editParams = true;
|
||||||
|
//if (conn_p->getType() == CANCon::GVRET_SERIAL) editParams = true;
|
||||||
|
|
||||||
switch (Column(index.column()))
|
switch (Column(index.column()))
|
||||||
{
|
{
|
||||||
@@ -152,7 +153,7 @@ QVariant CANConnectionModel::data(const QModelIndex &index, int role) const
|
|||||||
bool ret;
|
bool ret;
|
||||||
if (!conn_p) return QVariant();
|
if (!conn_p) return QVariant();
|
||||||
ret = conn_p->getBusSettings(busId, bus);
|
ret = conn_p->getBusSettings(busId, bus);
|
||||||
bool isSocketCAN = (conn_p->getType() == CANCon::SOCKETCAN) ? true: false;
|
bool isSocketCAN = (conn_p->getType() == CANCon::SERIALBUS) ? true: false;
|
||||||
|
|
||||||
//qDebug() << "ConnP: " << conn_p << " ret " << ret;
|
//qDebug() << "ConnP: " << conn_p << " ret " << ret;
|
||||||
|
|
||||||
@@ -167,7 +168,7 @@ QVariant CANConnectionModel::data(const QModelIndex &index, int role) const
|
|||||||
if (conn_p)
|
if (conn_p)
|
||||||
switch (conn_p->getType()) {
|
switch (conn_p->getType()) {
|
||||||
case CANCon::KVASER: return "KVASER";
|
case CANCon::KVASER: return "KVASER";
|
||||||
case CANCon::SOCKETCAN: return "SocketCAN";
|
case CANCon::SERIALBUS: return "SerialBus";
|
||||||
case CANCon::GVRET_SERIAL: return "GVRET";
|
case CANCon::GVRET_SERIAL: return "GVRET";
|
||||||
default: {}
|
default: {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,16 +44,13 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) :
|
|||||||
/* load connection configuration */
|
/* load connection configuration */
|
||||||
loadConnections();
|
loadConnections();
|
||||||
|
|
||||||
ui->rbSocketCAN->setEnabled(isSocketCanAvailable());
|
ui->rbSocketCAN->setEnabled(isSerialBusAvailable());
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
ui->rbKvaser->setEnabled(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
connect(ui->btnOK, &QAbstractButton::clicked, this, &ConnectionWindow::handleOKButton);
|
connect(ui->btnOK, &QAbstractButton::clicked, this, &ConnectionWindow::handleOKButton);
|
||||||
connect(ui->rbGVRET, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
connect(ui->rbGVRET, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||||
connect(ui->rbKvaser, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
|
||||||
connect(ui->rbSocketCAN, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
connect(ui->rbSocketCAN, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||||
connect(ui->rbRemote, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
connect(ui->rbRemote, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||||
|
connect(ui->cbDeviceType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ConnectionWindow::handleDeviceTypeChanged);
|
||||||
connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &ConnectionWindow::currentRowChanged);
|
connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &ConnectionWindow::currentRowChanged);
|
||||||
connect(ui->btnActivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleEnableAll);
|
connect(ui->btnActivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleEnableAll);
|
||||||
connect(ui->btnDeactivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleDisableAll);
|
connect(ui->btnDeactivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleDisableAll);
|
||||||
@@ -63,6 +60,9 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) :
|
|||||||
connect(ui->btnSendHex, &QPushButton::clicked, this, &ConnectionWindow::handleSendHex);
|
connect(ui->btnSendHex, &QPushButton::clicked, this, &ConnectionWindow::handleSendHex);
|
||||||
connect(ui->btnSendText, &QPushButton::clicked, this, &ConnectionWindow::handleSendText);
|
connect(ui->btnSendText, &QPushButton::clicked, this, &ConnectionWindow::handleSendText);
|
||||||
connect(ui->ckEnableConsole, &QCheckBox::toggled, this, &ConnectionWindow::consoleEnableChanged);
|
connect(ui->ckEnableConsole, &QCheckBox::toggled, this, &ConnectionWindow::consoleEnableChanged);
|
||||||
|
|
||||||
|
ui->lblDeviceType->setHidden(true);
|
||||||
|
ui->cbDeviceType->setHidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionWindow::~ConnectionWindow()
|
ConnectionWindow::~ConnectionWindow()
|
||||||
@@ -118,7 +118,7 @@ bool ConnectionWindow::eventFilter(QObject *obj, QEvent *event)
|
|||||||
// standard event processing
|
// standard event processing
|
||||||
return QObject::eventFilter(obj, event);
|
return QObject::eventFilter(obj, event);
|
||||||
}
|
}
|
||||||
return false;
|
//return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::readSettings()
|
void ConnectionWindow::readSettings()
|
||||||
@@ -200,7 +200,7 @@ void ConnectionWindow::consoleEnableChanged(bool checked) {
|
|||||||
connect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
connect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
||||||
}
|
}
|
||||||
else { //turn it off
|
else { //turn it off
|
||||||
disconnect(conn_p, SIGNAL(debugOutput(QString)), 0, 0);
|
disconnect(conn_p, SIGNAL(debugOutput(QString)), nullptr, nullptr);
|
||||||
disconnect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
disconnect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,11 +226,18 @@ void ConnectionWindow::handleDisableAll()
|
|||||||
void ConnectionWindow::handleConnTypeChanged()
|
void ConnectionWindow::handleConnTypeChanged()
|
||||||
{
|
{
|
||||||
if (ui->rbGVRET->isChecked()) selectSerial();
|
if (ui->rbGVRET->isChecked()) selectSerial();
|
||||||
if (ui->rbKvaser->isChecked()) selectKvaser();
|
|
||||||
if (ui->rbSocketCAN->isChecked()) selectSocketCan();
|
if (ui->rbSocketCAN->isChecked()) selectSocketCan();
|
||||||
if (ui->rbRemote->isChecked()) selectRemote();
|
if (ui->rbRemote->isChecked()) selectRemote();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConnectionWindow::handleDeviceTypeChanged()
|
||||||
|
{
|
||||||
|
ui->cbPort->clear();
|
||||||
|
canDevices = QCanBus::instance()->availableDevices(ui->cbDeviceType->currentText());
|
||||||
|
|
||||||
|
for (int i = 0; i < canDevices.count(); i++)
|
||||||
|
ui->cbPort->addItem(canDevices[i].name());
|
||||||
|
}
|
||||||
|
|
||||||
/* status */
|
/* status */
|
||||||
void ConnectionWindow::connectionStatus(CANConStatus pStatus)
|
void ConnectionWindow::connectionStatus(CANConStatus pStatus)
|
||||||
@@ -244,12 +251,12 @@ void ConnectionWindow::connectionStatus(CANConStatus pStatus)
|
|||||||
|
|
||||||
void ConnectionWindow::handleOKButton()
|
void ConnectionWindow::handleOKButton()
|
||||||
{
|
{
|
||||||
CANConnection* conn_p = NULL;
|
CANConnection* conn_p = nullptr;
|
||||||
|
|
||||||
if( ! CANConManager::getInstance()->getByName(getPortName()) )
|
if( ! CANConManager::getInstance()->getByName(getPortName()) )
|
||||||
{
|
{
|
||||||
/* create connection */
|
/* create connection */
|
||||||
conn_p = create(getConnectionType(), getPortName());
|
conn_p = create(getConnectionType(), getPortName(), getDriverName());
|
||||||
if(!conn_p)
|
if(!conn_p)
|
||||||
return;
|
return;
|
||||||
/* add connection to model */
|
/* add connection to model */
|
||||||
@@ -281,7 +288,7 @@ return;
|
|||||||
ui->btnOK->setText(tr("Create New Connection"));
|
ui->btnOK->setText(tr("Create New Connection"));
|
||||||
ui->rbGVRET->setChecked(true);
|
ui->rbGVRET->setChecked(true);
|
||||||
setSpeed(0);
|
setSpeed(0);
|
||||||
setPortName(CANCon::GVRET_SERIAL, "");
|
setPortName(CANCon::GVRET_SERIAL, "", "");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -300,7 +307,7 @@ return;
|
|||||||
|
|
||||||
ui->btnOK->setText(tr("Update Connection Settings"));
|
ui->btnOK->setText(tr("Update Connection Settings"));
|
||||||
setSpeed(bus.getSpeed());
|
setSpeed(bus.getSpeed());
|
||||||
setPortName(conn_p->getType(), conn_p->getPort());
|
setPortName(conn_p->getType(), conn_p->getPort(), conn_p->getDriver());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,6 +340,8 @@ void ConnectionWindow::selectSerial()
|
|||||||
ui->lPort->setText("Port:");
|
ui->lPort->setText("Port:");
|
||||||
/* set combobox page visible */
|
/* set combobox page visible */
|
||||||
ui->stPort->setCurrentWidget(ui->cbPage);
|
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||||
|
ui->lblDeviceType->setHidden(true);
|
||||||
|
ui->cbDeviceType->setHidden(true);
|
||||||
|
|
||||||
ui->cbPort->clear();
|
ui->cbPort->clear();
|
||||||
ports = QSerialPortInfo::availablePorts();
|
ports = QSerialPortInfo::availablePorts();
|
||||||
@@ -341,41 +350,42 @@ void ConnectionWindow::selectSerial()
|
|||||||
ui->cbPort->addItem(ports[i].portName());
|
ui->cbPort->addItem(ports[i].portName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::selectKvaser()
|
|
||||||
{
|
|
||||||
ui->lPort->setText("Port:");
|
|
||||||
/* set combobox page visible */
|
|
||||||
ui->stPort->setCurrentWidget(ui->cbPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionWindow::selectSocketCan()
|
void ConnectionWindow::selectSocketCan()
|
||||||
{
|
{
|
||||||
ui->lPort->setText("Port:");
|
ui->lPort->setText("Port:");
|
||||||
/* set edit text page visible */
|
/* set edit text page visible */
|
||||||
ui->stPort->setCurrentWidget(ui->etPage);
|
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||||
|
ui->lblDeviceType->setHidden(false);
|
||||||
|
ui->cbDeviceType->setHidden(false);
|
||||||
|
|
||||||
|
ui->cbDeviceType->clear();
|
||||||
|
QStringList plugins;
|
||||||
|
plugins = QCanBus::instance()->plugins();
|
||||||
|
for (int i = 0; i < plugins.count(); i++)
|
||||||
|
ui->cbDeviceType->addItem(plugins[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::selectRemote()
|
void ConnectionWindow::selectRemote()
|
||||||
{
|
{
|
||||||
ui->lPort->setText("IP Address:");
|
ui->lPort->setText("IP Address:");
|
||||||
ui->stPort->setCurrentWidget(ui->etPage);
|
ui->stPort->setCurrentWidget(ui->etPage);
|
||||||
|
ui->lblDeviceType->setHidden(true);
|
||||||
|
ui->cbDeviceType->setHidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::setSpeed(int speed0)
|
void ConnectionWindow::setSpeed(int speed0)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(speed0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName)
|
void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName, QString pDriver)
|
||||||
{
|
{
|
||||||
switch(pType)
|
switch(pType)
|
||||||
{
|
{
|
||||||
case CANCon::GVRET_SERIAL:
|
case CANCon::GVRET_SERIAL:
|
||||||
ui->rbGVRET->setChecked(true);
|
ui->rbGVRET->setChecked(true);
|
||||||
break;
|
break;
|
||||||
case CANCon::KVASER:
|
case CANCon::SERIALBUS:
|
||||||
ui->rbKvaser->setChecked(true);
|
|
||||||
break;
|
|
||||||
case CANCon::SOCKETCAN:
|
|
||||||
ui->rbSocketCAN->setChecked(true);
|
ui->rbSocketCAN->setChecked(true);
|
||||||
//you can't configure any of the below three with socketcan so dim them out
|
//you can't configure any of the below three with socketcan so dim them out
|
||||||
break;
|
break;
|
||||||
@@ -394,7 +404,16 @@ void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName)
|
|||||||
ui->cbPort->setCurrentIndex(idx);
|
ui->cbPort->setCurrentIndex(idx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CANCon::SOCKETCAN:
|
case CANCon::SERIALBUS:
|
||||||
|
{
|
||||||
|
int idx = ui->cbDeviceType->findText(pDriver);
|
||||||
|
if (idx < 0) idx = 0;
|
||||||
|
ui->cbDeviceType->setCurrentIndex(idx);
|
||||||
|
idx = ui->cbPort->findText(pPortName);
|
||||||
|
if( idx < 0 ) idx = 0;
|
||||||
|
ui->cbPort->setCurrentIndex(idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CANCon::REMOTE:
|
case CANCon::REMOTE:
|
||||||
{
|
{
|
||||||
ui->lePort->setText(pPortName);
|
ui->lePort->setText(pPortName);
|
||||||
@@ -415,9 +434,8 @@ QString ConnectionWindow::getPortName()
|
|||||||
{
|
{
|
||||||
switch( getConnectionType() ) {
|
switch( getConnectionType() ) {
|
||||||
case CANCon::GVRET_SERIAL:
|
case CANCon::GVRET_SERIAL:
|
||||||
case CANCon::KVASER:
|
case CANCon::SERIALBUS:
|
||||||
return ui->cbPort->currentText();
|
return ui->cbPort->currentText();
|
||||||
case CANCon::SOCKETCAN:
|
|
||||||
case CANCon::REMOTE:
|
case CANCon::REMOTE:
|
||||||
return ui->lePort->text();
|
return ui->lePort->text();
|
||||||
default:
|
default:
|
||||||
@@ -427,11 +445,20 @@ QString ConnectionWindow::getPortName()
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ConnectionWindow::getDriverName()
|
||||||
|
{
|
||||||
|
if (getConnectionType() == CANCon::SERIALBUS)
|
||||||
|
{
|
||||||
|
return ui->cbDeviceType->currentText();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
CANCon::type ConnectionWindow::getConnectionType()
|
CANCon::type ConnectionWindow::getConnectionType()
|
||||||
{
|
{
|
||||||
if (ui->rbGVRET->isChecked()) return CANCon::GVRET_SERIAL;
|
if (ui->rbGVRET->isChecked()) return CANCon::GVRET_SERIAL;
|
||||||
if (ui->rbKvaser->isChecked()) return CANCon::KVASER;
|
if (ui->rbSocketCAN->isChecked()) return CANCon::SERIALBUS;
|
||||||
if (ui->rbSocketCAN->isChecked()) return CANCon::SOCKETCAN;
|
|
||||||
if (ui->rbRemote->isChecked()) return CANCon::REMOTE;
|
if (ui->rbRemote->isChecked()) return CANCon::REMOTE;
|
||||||
qDebug() << "getConnectionType: error";
|
qDebug() << "getConnectionType: error";
|
||||||
return CANCon::NONE;
|
return CANCon::NONE;
|
||||||
@@ -440,6 +467,7 @@ CANCon::type ConnectionWindow::getConnectionType()
|
|||||||
|
|
||||||
void ConnectionWindow::setSWMode(bool mode)
|
void ConnectionWindow::setSWMode(bool mode)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConnectionWindow::getSWMode()
|
bool ConnectionWindow::getSWMode()
|
||||||
@@ -475,21 +503,19 @@ void ConnectionWindow::handleRevert()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ConnectionWindow::isSocketCanAvailable()
|
bool ConnectionWindow::isSerialBusAvailable()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_LINUX
|
if (QCanBus::instance()->plugins().count() > 0) return true;
|
||||||
if (QCanBus::instance()->plugins().contains(QStringLiteral("socketcan"))) return true;
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CANConnection* ConnectionWindow::create(CANCon::type pTye, QString pPortName)
|
CANConnection* ConnectionWindow::create(CANCon::type pTye, QString pPortName, QString pDriver)
|
||||||
{
|
{
|
||||||
CANConnection* conn_p;
|
CANConnection* conn_p;
|
||||||
|
|
||||||
/* create connection */
|
/* create connection */
|
||||||
conn_p = CanConFactory::create(pTye, pPortName);
|
conn_p = CanConFactory::create(pTye, pPortName, pDriver);
|
||||||
if(conn_p)
|
if(conn_p)
|
||||||
{
|
{
|
||||||
/* connect signal */
|
/* connect signal */
|
||||||
@@ -512,11 +538,15 @@ void ConnectionWindow::loadConnections()
|
|||||||
|
|
||||||
/* fill connection list */
|
/* fill connection list */
|
||||||
QVector<QString> portNames = settings.value("connections/portNames").value<QVector<QString>>();
|
QVector<QString> portNames = settings.value("connections/portNames").value<QVector<QString>>();
|
||||||
|
QVector<QString> driverNames = settings.value("connections/driverNames").value<QVector<QString>>();
|
||||||
QVector<int> devTypes = settings.value("connections/types").value<QVector<int>>();
|
QVector<int> devTypes = settings.value("connections/types").value<QVector<int>>();
|
||||||
|
|
||||||
|
//don't load the connections if the three setting arrays above aren't all the same size.
|
||||||
|
if (portNames.count() != driverNames.count() || devTypes.count() != driverNames.count()) return;
|
||||||
|
|
||||||
for(int i = 0 ; i < portNames.count() ; i++)
|
for(int i = 0 ; i < portNames.count() ; i++)
|
||||||
{
|
{
|
||||||
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i]);
|
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i], driverNames[i]);
|
||||||
/* add connection to model */
|
/* add connection to model */
|
||||||
connModel->add(conn_p);
|
connModel->add(conn_p);
|
||||||
}
|
}
|
||||||
@@ -533,14 +563,17 @@ void ConnectionWindow::saveConnections()
|
|||||||
QSettings settings;
|
QSettings settings;
|
||||||
QVector<QString> portNames;
|
QVector<QString> portNames;
|
||||||
QVector<int> devTypes;
|
QVector<int> devTypes;
|
||||||
|
QVector<QString> driverNames;
|
||||||
|
|
||||||
/* save connections */
|
/* save connections */
|
||||||
foreach(CANConnection* conn_p, conns)
|
foreach(CANConnection* conn_p, conns)
|
||||||
{
|
{
|
||||||
portNames.append(conn_p->getPort());
|
portNames.append(conn_p->getPort());
|
||||||
devTypes.append(conn_p->getType());
|
devTypes.append(conn_p->getType());
|
||||||
|
driverNames.append(conn_p->getDriver());
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.setValue("connections/portNames", QVariant::fromValue(portNames));
|
settings.setValue("connections/portNames", QVariant::fromValue(portNames));
|
||||||
settings.setValue("connections/types", QVariant::fromValue(devTypes));
|
settings.setValue("connections/types", QVariant::fromValue(devTypes));
|
||||||
|
settings.setValue("connections/driverNames", QVariant::fromValue(driverNames));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QItemSelection>
|
#include <QItemSelection>
|
||||||
|
#include <QCanBusDeviceInfo>
|
||||||
#include "canconnectionmodel.h"
|
#include "canconnectionmodel.h"
|
||||||
#include "connections/canconnection.h"
|
#include "connections/canconnection.h"
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ public slots:
|
|||||||
private slots:
|
private slots:
|
||||||
void handleOKButton();
|
void handleOKButton();
|
||||||
void handleConnTypeChanged();
|
void handleConnTypeChanged();
|
||||||
|
void handleDeviceTypeChanged();
|
||||||
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
void consoleEnableChanged(bool checked);
|
void consoleEnableChanged(bool checked);
|
||||||
void handleRemoveConn();
|
void handleRemoveConn();
|
||||||
@@ -63,6 +65,7 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
Ui::ConnectionWindow *ui;
|
Ui::ConnectionWindow *ui;
|
||||||
QList<QSerialPortInfo> ports;
|
QList<QSerialPortInfo> ports;
|
||||||
|
QList<QCanBusDeviceInfo> canDevices;
|
||||||
QSettings *settings;
|
QSettings *settings;
|
||||||
CANConnectionModel *connModel;
|
CANConnectionModel *connModel;
|
||||||
|
|
||||||
@@ -70,13 +73,14 @@ private:
|
|||||||
void selectKvaser();
|
void selectKvaser();
|
||||||
void selectSocketCan();
|
void selectSocketCan();
|
||||||
void selectRemote();
|
void selectRemote();
|
||||||
bool isSocketCanAvailable();
|
bool isSerialBusAvailable();
|
||||||
int getSpeed();
|
int getSpeed();
|
||||||
QString getPortName();
|
QString getPortName();
|
||||||
void setPortName(CANCon::type pType, QString pPortName);
|
QString getDriverName();
|
||||||
|
void setPortName(CANCon::type pType, QString pPortName, QString pDriver);
|
||||||
|
|
||||||
void setActiveAll(bool pActive);
|
void setActiveAll(bool pActive);
|
||||||
CANConnection* create(CANCon::type pTye, QString pPortName);
|
CANConnection* create(CANCon::type pTye, QString pPortName, QString pDriver);
|
||||||
void loadConnections();
|
void loadConnections();
|
||||||
void saveConnections();
|
void saveConnections();
|
||||||
void showEvent(QShowEvent *);
|
void showEvent(QShowEvent *);
|
||||||
|
|||||||
@@ -9,19 +9,20 @@
|
|||||||
#include "gvretserial.h"
|
#include "gvretserial.h"
|
||||||
|
|
||||||
GVRetSerial::GVRetSerial(QString portName, bool useTcp) :
|
GVRetSerial::GVRetSerial(QString portName, bool useTcp) :
|
||||||
CANConnection(portName, CANCon::GVRET_SERIAL, 3, 4000, true),
|
CANConnection(portName, "gvret", CANCon::GVRET_SERIAL, 3, 4000, true),
|
||||||
useTcp(useTcp),
|
useTcp(useTcp),
|
||||||
mTimer(this) /*NB: set this as parent of timer to manage it from working thread */
|
mTimer(this) /*NB: set this as parent of timer to manage it from working thread */
|
||||||
{
|
{
|
||||||
qDebug() << "GVRetSerial()";
|
sendDebug("GVRetSerial()");
|
||||||
debugOutput("GVRetSerial()");
|
|
||||||
|
|
||||||
serial = NULL;
|
serial = NULL;
|
||||||
tcpClient = NULL;
|
tcpClient = NULL;
|
||||||
|
udpClient = NULL;
|
||||||
rx_state = IDLE;
|
rx_state = IDLE;
|
||||||
rx_step = 0;
|
rx_step = 0;
|
||||||
gotValidated = true;
|
validationCounter = 10; //how many times we can miss validation before we die
|
||||||
isAutoRestart = false;
|
isAutoRestart = false;
|
||||||
|
espSerialMode = true;
|
||||||
|
|
||||||
timeBasis = 0;
|
timeBasis = 0;
|
||||||
lastSystemTimeBasis = 0;
|
lastSystemTimeBasis = 0;
|
||||||
@@ -34,27 +35,38 @@ GVRetSerial::GVRetSerial(QString portName, bool useTcp) :
|
|||||||
GVRetSerial::~GVRetSerial()
|
GVRetSerial::~GVRetSerial()
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
qDebug() << "~GVRetSerial()";
|
sendDebug("~GVRetSerial()");
|
||||||
debugOutput("~GVRetSerial()");
|
}
|
||||||
|
|
||||||
|
void GVRetSerial::sendDebug(const QString debugText)
|
||||||
|
{
|
||||||
|
qDebug() << debugText;
|
||||||
|
debugOutput(debugText);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GVRetSerial::sendToSerial(const QByteArray &bytes)
|
void GVRetSerial::sendToSerial(const QByteArray &bytes)
|
||||||
{
|
{
|
||||||
if (serial == NULL && tcpClient == NULL)
|
if (serial == NULL && tcpClient == NULL && udpClient == NULL)
|
||||||
{
|
{
|
||||||
debugOutput("Attempt to write to serial port when it has not been initialized!");
|
sendDebug("Attempt to write to serial port when it has not been initialized!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serial && !serial->isOpen())
|
if (serial && !serial->isOpen())
|
||||||
{
|
{
|
||||||
debugOutput("Attempt to write to serial port when it is not open!");
|
sendDebug("Attempt to write to serial port when it is not open!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcpClient && !tcpClient->isOpen())
|
if (tcpClient && !tcpClient->isOpen())
|
||||||
{
|
{
|
||||||
debugOutput("Attempt to write to TCP/IP port when it is not open!");
|
sendDebug("Attempt to write to TCP/IP port when it is not open!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (udpClient && !udpClient->isOpen())
|
||||||
|
{
|
||||||
|
sendDebug("Attempt to write to UDP Socket when it is not open!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,10 +76,11 @@ void GVRetSerial::sendToSerial(const QByteArray &bytes)
|
|||||||
byt = (unsigned char)byt;
|
byt = (unsigned char)byt;
|
||||||
buildDebug = buildDebug % QString::number(byt, 16) % " ";
|
buildDebug = buildDebug % QString::number(byt, 16) % " ";
|
||||||
}
|
}
|
||||||
debugOutput(buildDebug);
|
sendDebug(buildDebug);
|
||||||
|
|
||||||
if (serial) serial->write(bytes);
|
if (serial) serial->write(bytes);
|
||||||
if (tcpClient) tcpClient->write(bytes);
|
if (tcpClient) tcpClient->write(bytes);
|
||||||
|
if (udpClient) udpClient->write(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GVRetSerial::piStarted()
|
void GVRetSerial::piStarted()
|
||||||
@@ -176,8 +189,7 @@ void GVRetSerial::piSetBusSettings(int pBusIdx, CANBus bus)
|
|||||||
if (pBusIdx < 2) {
|
if (pBusIdx < 2) {
|
||||||
/* update baud rates */
|
/* update baud rates */
|
||||||
QByteArray buffer;
|
QByteArray buffer;
|
||||||
qDebug() << "Got signal to update bauds. 1: " << (can0Baud & 0xFFFFFFF) <<" 2: " << (can1Baud & 0xFFFFFFF);
|
sendDebug("Got signal to update bauds. 1: " + QString::number((can0Baud & 0xFFFFFFF)) + " 2: " + QString::number((can1Baud & 0xFFFFFFF)));
|
||||||
debugOutput("Got signal to update bauds. 1: " + QString::number((can0Baud & 0xFFFFFFF)) + " 2: " + QString::number((can1Baud & 0xFFFFFFF)));
|
|
||||||
buffer[0] = (char)0xF1; //start of a command over serial
|
buffer[0] = (char)0xF1; //start of a command over serial
|
||||||
buffer[1] = 5; //setup canbus
|
buffer[1] = 5; //setup canbus
|
||||||
buffer[2] = (unsigned char)(can0Baud & 0xFF); //four bytes of ID LSB first
|
buffer[2] = (unsigned char)(can0Baud & 0xFF); //four bytes of ID LSB first
|
||||||
@@ -195,8 +207,7 @@ void GVRetSerial::piSetBusSettings(int pBusIdx, CANBus bus)
|
|||||||
{
|
{
|
||||||
/* update baud rates */
|
/* update baud rates */
|
||||||
QByteArray buffer;
|
QByteArray buffer;
|
||||||
qDebug() << "Got signal to update extended bus speeds SWCAN: " << swcanBaud <<" LIN1: " << lin1Baud << " LIN2: " << lin2Baud;
|
sendDebug("Got signal to update extended bus speeds SWCAN: " + QString::number(swcanBaud) + " LIN1: " + QString::number(lin1Baud) + " LIN2: " + QString::number(lin2Baud));
|
||||||
debugOutput("Got signal to update extended bus speeds SWCAN: " + QString::number(swcanBaud) + " LIN1: " + QString::number(lin1Baud) + " LIN2: " + QString::number(lin2Baud));
|
|
||||||
buffer[0] = (char)0xF1; //start of a command over serial
|
buffer[0] = (char)0xF1; //start of a command over serial
|
||||||
buffer[1] = 14; //setup extended buses
|
buffer[1] = 14; //setup extended buses
|
||||||
buffer[2] = (unsigned char)(swcanBaud & 0xFF); //four bytes of ID LSB first
|
buffer[2] = (unsigned char)(swcanBaud & 0xFF); //four bytes of ID LSB first
|
||||||
@@ -227,8 +238,10 @@ bool GVRetSerial::piSendFrame(const CANFrame& frame)
|
|||||||
|
|
||||||
framesRapid++;
|
framesRapid++;
|
||||||
|
|
||||||
if (serial == NULL) return false;
|
if (serial == NULL && tcpClient == NULL && udpClient == NULL) return false;
|
||||||
if (!serial->isOpen()) return false;
|
if (serial && !serial->isOpen()) return false;
|
||||||
|
if (tcpClient && !tcpClient->isOpen()) return false;
|
||||||
|
if (udpClient && !udpClient->isOpen()) return false;
|
||||||
//if (!isConnected) return false;
|
//if (!isConnected) return false;
|
||||||
|
|
||||||
// Doesn't make sense to send an error frame
|
// Doesn't make sense to send an error frame
|
||||||
@@ -283,55 +296,84 @@ void GVRetSerial::connectDevice()
|
|||||||
disconnectDevice();
|
disconnectDevice();
|
||||||
if(tcpClient)
|
if(tcpClient)
|
||||||
disconnectDevice();
|
disconnectDevice();
|
||||||
|
if (udpClient)
|
||||||
|
disconnectDevice();
|
||||||
|
|
||||||
/* open new device */
|
/* open new device */
|
||||||
|
|
||||||
// this does the wrong thing if the serial port has a '.' in the name
|
|
||||||
// if (getPort().contains('.')) //TCP/IP mode then since it looks like an IP address
|
|
||||||
if (useTcp)
|
if (useTcp)
|
||||||
{
|
{
|
||||||
qDebug() << "TCP Connection to a GVRET device";
|
// /*
|
||||||
|
sendDebug("TCP Connection to a GVRET device");
|
||||||
tcpClient = new QTcpSocket();
|
tcpClient = new QTcpSocket();
|
||||||
tcpClient->connectToHost(getPort(), 23);
|
tcpClient->connectToHost(getPort(), 23);
|
||||||
connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
||||||
connect(tcpClient, SIGNAL(connected()), this, SLOT(tcpConnected()));
|
connect(tcpClient, SIGNAL(connected()), this, SLOT(deviceConnected()));
|
||||||
|
sendDebug("Created TCP Socket");
|
||||||
|
// */
|
||||||
|
/*
|
||||||
|
qDebug() << "UDP Connection to a GVRET device";
|
||||||
|
udpClient = new QUdpSocket();
|
||||||
|
udpClient->connectToHost(getPort(), 17222);
|
||||||
|
connect(udpClient, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
||||||
|
//connect(udpClient, SIGNAL(connected()), this, SLOT(tcpConnected()));
|
||||||
|
debugOutput("Created UDP Socket");
|
||||||
|
tcpConnected();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qDebug() << "Serial connection to a GVRET device";
|
sendDebug("Serial connection to a GVRET device");
|
||||||
serial = new QSerialPort(QSerialPortInfo(getPort()));
|
serial = new QSerialPort(QSerialPortInfo(getPort()));
|
||||||
if(!serial) {
|
if(!serial) {
|
||||||
qDebug() << "can't open serial port " << getPort();
|
sendDebug("can't open serial port " + getPort());
|
||||||
debugOutput("can't open serial port " + getPort());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debugOutput("Created Serial Port Object");
|
sendDebug("Created Serial Port Object");
|
||||||
|
|
||||||
/* configure */
|
|
||||||
serial->setDataBits(serial->Data8);
|
|
||||||
serial->setFlowControl(serial->HardwareControl); //this is important though
|
|
||||||
//serial->setFlowControl(serial->NoFlowControl);
|
|
||||||
serial->setBaudRate(1000000);
|
|
||||||
if (!serial->open(QIODevice::ReadWrite))
|
|
||||||
{
|
|
||||||
qDebug() << serial->errorString();
|
|
||||||
}
|
|
||||||
//serial->setDataTerminalReady(false); //you do need to set these or the fan gets dirty
|
|
||||||
//serial->setRequestToSend(false);
|
|
||||||
serial->setDataTerminalReady(true); //you do need to set these or the fan gets dirty
|
|
||||||
serial->setRequestToSend(true);
|
|
||||||
|
|
||||||
debugOutput("Opened Serial Port");
|
|
||||||
/* connect reading event */
|
/* connect reading event */
|
||||||
connect(serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
connect(serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
||||||
connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(serialError(QSerialPort::SerialPortError)));
|
connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(serialError(QSerialPort::SerialPortError)));
|
||||||
}
|
|
||||||
|
|
||||||
if (serial) tcpConnected(); //well, not a proper function name I guess...
|
/* configure */
|
||||||
}
|
serial->setBaudRate(1000000); //most GVRET devices ignore baud, ESP32 needs it set explicitly to the proper value
|
||||||
|
serial->setDataBits(serial->Data8);
|
||||||
|
|
||||||
void GVRetSerial::tcpConnected()
|
if (espSerialMode)
|
||||||
{
|
{
|
||||||
qDebug() << "Connected to GVRET Device!";
|
sendDebug("Trying ESP32 Serial Mode");
|
||||||
|
serial->setFlowControl(serial->NoFlowControl);
|
||||||
|
if (!serial->open(QIODevice::ReadWrite))
|
||||||
|
{
|
||||||
|
//sendDebug("Error returned during port opening: " + serial->errorString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serial->setDataTerminalReady(false); //ESP32 uses these for bootloader selection and reset so turn them off
|
||||||
|
serial->setRequestToSend(false);
|
||||||
|
QTimer::singleShot(3000, this, SLOT(deviceConnected())); //give ESP32 some time as it could have rebooted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendDebug("Trying Standard Serial Mode");
|
||||||
|
serial->setFlowControl(serial->HardwareControl); //Most GVRET style devices use hardware flow control
|
||||||
|
if (!serial->open(QIODevice::ReadWrite))
|
||||||
|
{
|
||||||
|
//sendDebug("Error returned during port opening: " + serial->errorString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//serial->setDataTerminalReady(true); //Seemingly these two lines used to be needed
|
||||||
|
//serial->setRequestToSend(true); //But, really both ends should automatically handle these
|
||||||
|
deviceConnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GVRetSerial::deviceConnected()
|
||||||
|
{
|
||||||
|
sendDebug("Connecting to GVRET Device!");
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
output.append((unsigned char)0xE7); //this puts the device into binary comm mode
|
output.append((unsigned char)0xE7); //this puts the device into binary comm mode
|
||||||
output.append((unsigned char)0xE7);
|
output.append((unsigned char)0xE7);
|
||||||
@@ -367,14 +409,8 @@ void GVRetSerial::tcpConnected()
|
|||||||
|
|
||||||
sendToSerial(output);
|
sendToSerial(output);
|
||||||
|
|
||||||
/* start timer */
|
|
||||||
connect(&mTimer, SIGNAL(timeout()), this, SLOT(handleTick()));
|
|
||||||
mTimer.setInterval(250); //tick four times per second
|
|
||||||
mTimer.setSingleShot(false); //keep ticking
|
|
||||||
mTimer.start();
|
|
||||||
|
|
||||||
if(doValidation) {
|
if(doValidation) {
|
||||||
QTimer::singleShot(1000, this, SLOT(connectionTimeout()));
|
QTimer::singleShot(5000, this, SLOT(connectionTimeout()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setStatus(CANCon::CONNECTED);
|
setStatus(CANCon::CONNECTED);
|
||||||
@@ -390,7 +426,7 @@ void GVRetSerial::disconnectDevice() {
|
|||||||
{
|
{
|
||||||
if (serial->isOpen())
|
if (serial->isOpen())
|
||||||
{
|
{
|
||||||
serial->clear();
|
//serial->clear();
|
||||||
serial->close();
|
serial->close();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -408,6 +444,17 @@ void GVRetSerial::disconnectDevice() {
|
|||||||
delete tcpClient;
|
delete tcpClient;
|
||||||
tcpClient = NULL;
|
tcpClient = NULL;
|
||||||
}
|
}
|
||||||
|
if (udpClient != NULL)
|
||||||
|
{
|
||||||
|
if (udpClient->isOpen())
|
||||||
|
{
|
||||||
|
udpClient->close();
|
||||||
|
}
|
||||||
|
udpClient->disconnect();
|
||||||
|
delete udpClient;
|
||||||
|
udpClient = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
setStatus(CANCon::NOT_CONNECTED);
|
setStatus(CANCon::NOT_CONNECTED);
|
||||||
CANConStatus stats;
|
CANConStatus stats;
|
||||||
stats.conStatus = getStatus();
|
stats.conStatus = getStatus();
|
||||||
@@ -426,14 +473,17 @@ void GVRetSerial::serialError(QSerialPort::SerialPortError err)
|
|||||||
case QSerialPort::DeviceNotFoundError:
|
case QSerialPort::DeviceNotFoundError:
|
||||||
errMessage = "Device not found error on serial";
|
errMessage = "Device not found error on serial";
|
||||||
killConnection = true;
|
killConnection = true;
|
||||||
|
piStop();
|
||||||
break;
|
break;
|
||||||
case QSerialPort::PermissionError:
|
case QSerialPort::PermissionError:
|
||||||
errMessage = "Permission error on serial port";
|
errMessage = "Permission error on serial port";
|
||||||
killConnection = true;
|
killConnection = true;
|
||||||
|
piStop();
|
||||||
break;
|
break;
|
||||||
case QSerialPort::OpenError:
|
case QSerialPort::OpenError:
|
||||||
errMessage = "Open error on serial port";
|
errMessage = "Open error on serial port";
|
||||||
killConnection = true;
|
killConnection = true;
|
||||||
|
piStop();
|
||||||
break;
|
break;
|
||||||
case QSerialPort::ParityError:
|
case QSerialPort::ParityError:
|
||||||
errMessage = "Parity error on serial port";
|
errMessage = "Parity error on serial port";
|
||||||
@@ -446,13 +496,16 @@ void GVRetSerial::serialError(QSerialPort::SerialPortError err)
|
|||||||
break;
|
break;
|
||||||
case QSerialPort::WriteError:
|
case QSerialPort::WriteError:
|
||||||
errMessage = "Write error on serial port";
|
errMessage = "Write error on serial port";
|
||||||
|
piStop();
|
||||||
break;
|
break;
|
||||||
case QSerialPort::ReadError:
|
case QSerialPort::ReadError:
|
||||||
errMessage = "Read error on serial port";
|
errMessage = "Read error on serial port";
|
||||||
|
piStop();
|
||||||
break;
|
break;
|
||||||
case QSerialPort::ResourceError:
|
case QSerialPort::ResourceError:
|
||||||
errMessage = "Serial port seems to have disappeared.";
|
errMessage = "Serial port seems to have disappeared.";
|
||||||
killConnection = true;
|
killConnection = true;
|
||||||
|
piStop();
|
||||||
break;
|
break;
|
||||||
case QSerialPort::UnsupportedOperationError:
|
case QSerialPort::UnsupportedOperationError:
|
||||||
errMessage = "Unsupported operation on serial port";
|
errMessage = "Unsupported operation on serial port";
|
||||||
@@ -461,23 +514,28 @@ void GVRetSerial::serialError(QSerialPort::SerialPortError err)
|
|||||||
case QSerialPort::UnknownError:
|
case QSerialPort::UnknownError:
|
||||||
errMessage = "Beats me what happened to the serial port.";
|
errMessage = "Beats me what happened to the serial port.";
|
||||||
killConnection = true;
|
killConnection = true;
|
||||||
|
piStop();
|
||||||
break;
|
break;
|
||||||
case QSerialPort::TimeoutError:
|
case QSerialPort::TimeoutError:
|
||||||
errMessage = "Timeout error on serial port";
|
errMessage = "Timeout error on serial port";
|
||||||
killConnection = true;
|
killConnection = true;
|
||||||
break;
|
break;
|
||||||
case QSerialPort::NotOpenError:
|
case QSerialPort::NotOpenError:
|
||||||
errMessage = "The serial port isn't open dummy";
|
errMessage = "The serial port isn't open";
|
||||||
killConnection = true;
|
killConnection = true;
|
||||||
|
piStop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
if (serial)
|
||||||
|
{
|
||||||
serial->clearError();
|
serial->clearError();
|
||||||
serial->flush();
|
serial->flush();
|
||||||
serial->close();
|
serial->close();
|
||||||
|
}*/
|
||||||
if (errMessage.length() > 1)
|
if (errMessage.length() > 1)
|
||||||
{
|
{
|
||||||
qDebug() << errMessage;
|
sendDebug(errMessage);
|
||||||
debugOutput(errMessage);
|
|
||||||
}
|
}
|
||||||
if (killConnection)
|
if (killConnection)
|
||||||
{
|
{
|
||||||
@@ -490,13 +548,23 @@ void GVRetSerial::serialError(QSerialPort::SerialPortError err)
|
|||||||
void GVRetSerial::connectionTimeout()
|
void GVRetSerial::connectionTimeout()
|
||||||
{
|
{
|
||||||
//one second after trying to connect are we actually connected?
|
//one second after trying to connect are we actually connected?
|
||||||
//if (CANCon::NOT_CONNECTED==getStatus()) //no?
|
if (CANCon::NOT_CONNECTED==getStatus()) //no?
|
||||||
if (!gotValidated)
|
|
||||||
{
|
{
|
||||||
//then emit the the failure signal and see if anyone cares
|
//then emit the the failure signal and see if anyone cares
|
||||||
qDebug() << "Failed to connect to GVRET at that com port";
|
sendDebug("Failed to connect to GVRET at that com port");
|
||||||
|
|
||||||
|
//toggle the serial mode and try again
|
||||||
|
espSerialMode = !espSerialMode;
|
||||||
disconnectDevice();
|
disconnectDevice();
|
||||||
|
connectDevice();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* start timer */
|
||||||
|
connect(&mTimer, SIGNAL(timeout()), this, SLOT(handleTick()));
|
||||||
|
mTimer.setInterval(250); //tick four times per second
|
||||||
|
mTimer.setSingleShot(false); //keep ticking
|
||||||
|
mTimer.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,9 +577,9 @@ void GVRetSerial::readSerialData()
|
|||||||
|
|
||||||
if (serial) data = serial->readAll();
|
if (serial) data = serial->readAll();
|
||||||
if (tcpClient) data = tcpClient->readAll();
|
if (tcpClient) data = tcpClient->readAll();
|
||||||
|
if (udpClient) data = udpClient->readAll();
|
||||||
|
|
||||||
debugOutput("Got data from serial. Len = " % QString::number(data.length()));
|
sendDebug("Got data from serial. Len = " % QString::number(data.length()));
|
||||||
//qDebug() << (tr("Got data from serial. Len = %0").arg(data.length()));
|
|
||||||
for (int i = 0; i < data.length(); i++)
|
for (int i = 0; i < data.length(); i++)
|
||||||
{
|
{
|
||||||
c = data.at(i);
|
c = data.at(i);
|
||||||
@@ -571,7 +639,7 @@ void GVRetSerial::procRXChar(unsigned char c)
|
|||||||
rx_step = 0;
|
rx_step = 0;
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
gotValidated = true;
|
validationCounter = 10;
|
||||||
//qDebug() << "Got validated";
|
//qDebug() << "Got validated";
|
||||||
rx_state = IDLE;
|
rx_state = IDLE;
|
||||||
break;
|
break;
|
||||||
@@ -932,12 +1000,14 @@ void GVRetSerial::handleTick()
|
|||||||
|
|
||||||
if( CANCon::CONNECTED == getStatus() )
|
if( CANCon::CONNECTED == getStatus() )
|
||||||
{
|
{
|
||||||
if (!gotValidated && doValidation)
|
if (doValidation) validationCounter--;
|
||||||
|
//qDebug() << validationCounter;
|
||||||
|
if (validationCounter == 0 && doValidation)
|
||||||
{
|
{
|
||||||
if (serial == NULL && tcpClient == NULL) return;
|
if (serial == NULL && tcpClient == NULL) return;
|
||||||
if ( (serial && serial->isOpen()) || (tcpClient && tcpClient->isOpen())) //if it's still false we have a problem...
|
if ( (serial && serial->isOpen()) || (tcpClient && tcpClient->isOpen()) || (udpClient && udpClient->isOpen())) //if it's still false we have a problem...
|
||||||
{
|
{
|
||||||
qDebug() << "Comm validation failed. ";
|
sendDebug("Comm validation failed.");
|
||||||
|
|
||||||
setStatus(CANCon::NOT_CONNECTED);
|
setStatus(CANCon::NOT_CONNECTED);
|
||||||
//emit status(getStatus());
|
//emit status(getStatus());
|
||||||
@@ -952,6 +1022,7 @@ void GVRetSerial::handleTick()
|
|||||||
}
|
}
|
||||||
if (doValidation && serial && serial->isOpen()) sendCommValidation();
|
if (doValidation && serial && serial->isOpen()) sendCommValidation();
|
||||||
if (doValidation && tcpClient && tcpClient->isOpen()) sendCommValidation();
|
if (doValidation && tcpClient && tcpClient->isOpen()) sendCommValidation();
|
||||||
|
if (doValidation && udpClient && udpClient->isOpen()) sendCommValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -959,7 +1030,6 @@ void GVRetSerial::sendCommValidation()
|
|||||||
{
|
{
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
|
|
||||||
gotValidated = false;
|
|
||||||
output.append((unsigned char)0xF1); //another command to the GVRET
|
output.append((unsigned char)0xF1); //another command to the GVRET
|
||||||
output.append((unsigned char)0x09); //request a reply to get validation
|
output.append((unsigned char)0x09); //request a reply to get validation
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
|
#include <QUdpSocket>
|
||||||
|
|
||||||
/*************/
|
/*************/
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -64,7 +65,7 @@ private slots:
|
|||||||
void connectionTimeout();
|
void connectionTimeout();
|
||||||
void readSerialData();
|
void readSerialData();
|
||||||
void serialError(QSerialPort::SerialPortError err);
|
void serialError(QSerialPort::SerialPortError err);
|
||||||
void tcpConnected();
|
void deviceConnected();
|
||||||
void handleTick();
|
void handleTick();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -73,18 +74,21 @@ private:
|
|||||||
void sendCommValidation();
|
void sendCommValidation();
|
||||||
void rebuildLocalTimeBasis();
|
void rebuildLocalTimeBasis();
|
||||||
void sendToSerial(const QByteArray &bytes);
|
void sendToSerial(const QByteArray &bytes);
|
||||||
|
void sendDebug(const QString debugText);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QTimer mTimer;
|
QTimer mTimer;
|
||||||
QThread mThread;
|
QThread mThread;
|
||||||
|
|
||||||
bool doValidation;
|
bool doValidation;
|
||||||
bool gotValidated;
|
int validationCounter;
|
||||||
bool isAutoRestart;
|
bool isAutoRestart;
|
||||||
bool continuousTimeSync;
|
bool continuousTimeSync;
|
||||||
bool useTcp;
|
bool useTcp;
|
||||||
|
bool espSerialMode; //special serial mode for ESP32 based boards - no flow control and much slower serial baud speed
|
||||||
QSerialPort *serial;
|
QSerialPort *serial;
|
||||||
QTcpSocket *tcpClient;
|
QTcpSocket *tcpClient;
|
||||||
|
QUdpSocket *udpClient;
|
||||||
int framesRapid;
|
int framesRapid;
|
||||||
STATE rx_state;
|
STATE rx_state;
|
||||||
uint32_t rx_step;
|
uint32_t rx_step;
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
/**** class definition ****/
|
/**** class definition ****/
|
||||||
/***********************************/
|
/***********************************/
|
||||||
|
|
||||||
SerialBusConnection::SerialBusConnection(QString portName) :
|
SerialBusConnection::SerialBusConnection(QString portName, QString driverName) :
|
||||||
CANConnection(portName, CANCon::SOCKETCAN, 1, 4000, true),
|
CANConnection(portName, driverName, CANCon::SERIALBUS, 1, 4000, true),
|
||||||
mTimer(this) /*NB: set connection as parent of timer to manage it from working thread */
|
mTimer(this) /*NB: set connection as parent of timer to manage it from working thread */
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,22 @@ SerialBusConnection::~SerialBusConnection()
|
|||||||
|
|
||||||
void SerialBusConnection::piStarted()
|
void SerialBusConnection::piStarted()
|
||||||
{
|
{
|
||||||
|
qDebug() << "piStarted()";
|
||||||
|
/* create device */
|
||||||
|
QString errorString;
|
||||||
|
qDebug() << "Creating device instance";
|
||||||
|
mDev_p = QCanBus::instance()->createDevice(getDriver(), getPort(), &errorString);
|
||||||
|
if (!mDev_p) {
|
||||||
|
disconnectDevice();
|
||||||
|
qDebug() << "Error: createDevice(" << getType() << getDriver() << getPort() << "):" << errorString;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* connect slots */
|
||||||
|
connect(mDev_p, &QCanBusDevice::errorOccurred, this, &SerialBusConnection::errorReceived);
|
||||||
|
connect(mDev_p, &QCanBusDevice::framesWritten, this, &SerialBusConnection::framesWritten);
|
||||||
|
connect(mDev_p, &QCanBusDevice::framesReceived, this, &SerialBusConnection::framesReceived);
|
||||||
|
|
||||||
connect(&mTimer, SIGNAL(timeout()), this, SLOT(testConnection()));
|
connect(&mTimer, SIGNAL(timeout()), this, SLOT(testConnection()));
|
||||||
mTimer.setInterval(1000);
|
mTimer.setInterval(1000);
|
||||||
mTimer.setSingleShot(false); //keep ticking
|
mTimer.setSingleShot(false); //keep ticking
|
||||||
@@ -47,6 +63,7 @@ void SerialBusConnection::piSuspend(bool pSuspend)
|
|||||||
|
|
||||||
|
|
||||||
void SerialBusConnection::piStop() {
|
void SerialBusConnection::piStop() {
|
||||||
|
qDebug() << "piStop()";
|
||||||
mTimer.stop();
|
mTimer.stop();
|
||||||
disconnectDevice();
|
disconnectDevice();
|
||||||
}
|
}
|
||||||
@@ -65,6 +82,8 @@ void SerialBusConnection::piSetBusSettings(int pBusIdx, CANBus bus)
|
|||||||
if(0 != pBusIdx)
|
if(0 != pBusIdx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!mDev_p) return;
|
||||||
|
|
||||||
/* disconnect device if we have one connected */
|
/* disconnect device if we have one connected */
|
||||||
disconnectDevice();
|
disconnectDevice();
|
||||||
|
|
||||||
@@ -75,20 +94,6 @@ void SerialBusConnection::piSetBusSettings(int pBusIdx, CANBus bus)
|
|||||||
if(!bus.active)
|
if(!bus.active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* create device */
|
|
||||||
QString errorString;
|
|
||||||
mDev_p = QCanBus::instance()->createDevice("socketcan", getPort(), &errorString);
|
|
||||||
if (!mDev_p) {
|
|
||||||
disconnectDevice();
|
|
||||||
qDebug() << "Error: createDevice(" << getType() << getPort() << "):" << errorString;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* connect slots */
|
|
||||||
connect(mDev_p, &QCanBusDevice::errorOccurred, this, &SerialBusConnection::errorReceived);
|
|
||||||
connect(mDev_p, &QCanBusDevice::framesWritten, this, &SerialBusConnection::framesWritten);
|
|
||||||
connect(mDev_p, &QCanBusDevice::framesReceived, this, &SerialBusConnection::framesReceived);
|
|
||||||
|
|
||||||
/* set configuration */
|
/* set configuration */
|
||||||
/*if (p.useConfigurationEnabled) {
|
/*if (p.useConfigurationEnabled) {
|
||||||
foreach (const SettingsDialog::ConfigurationItem &item, p.configurations)
|
foreach (const SettingsDialog::ConfigurationItem &item, p.configurations)
|
||||||
@@ -96,7 +101,8 @@ void SerialBusConnection::piSetBusSettings(int pBusIdx, CANBus bus)
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
//You cannot set the speed of a socketcan interface, it has to be set with console commands.
|
//You cannot set the speed of a socketcan interface, it has to be set with console commands.
|
||||||
//mDev_p->setConfigurationParameter(QCanBusDevice::BitRateKey, bus.speed);
|
//But, you can probabaly set the speed of many of the other serialbus devices so go ahead and try
|
||||||
|
mDev_p->setConfigurationParameter(QCanBusDevice::BitRateKey, bus.speed);
|
||||||
|
|
||||||
/* connect device */
|
/* connect device */
|
||||||
if (!mDev_p->connectDevice()) {
|
if (!mDev_p->connectDevice()) {
|
||||||
@@ -115,8 +121,8 @@ bool SerialBusConnection::piSendFrame(const CANFrame& pFrame)
|
|||||||
|
|
||||||
/* fill frame */
|
/* fill frame */
|
||||||
QCanBusFrame frame;
|
QCanBusFrame frame;
|
||||||
frame.setFrameId(pFrame.ID);
|
|
||||||
frame.setExtendedFrameFormat(pFrame.extended);
|
frame.setExtendedFrameFormat(pFrame.extended);
|
||||||
|
frame.setFrameId(pFrame.ID);
|
||||||
if (pFrame.remote) {
|
if (pFrame.remote) {
|
||||||
frame.setFrameType(QCanBusFrame::FrameType::RemoteRequestFrame);
|
frame.setFrameType(QCanBusFrame::FrameType::RemoteRequestFrame);
|
||||||
} else {
|
} else {
|
||||||
@@ -137,8 +143,6 @@ bool SerialBusConnection::piSendFrame(const CANFrame& pFrame)
|
|||||||
void SerialBusConnection::disconnectDevice() {
|
void SerialBusConnection::disconnectDevice() {
|
||||||
if(mDev_p) {
|
if(mDev_p) {
|
||||||
mDev_p->disconnectDevice();
|
mDev_p->disconnectDevice();
|
||||||
delete mDev_p;
|
|
||||||
mDev_p = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,13 +259,12 @@ void SerialBusConnection::framesReceived()
|
|||||||
|
|
||||||
|
|
||||||
void SerialBusConnection::testConnection() {
|
void SerialBusConnection::testConnection() {
|
||||||
QCanBusDevice* dev_p = QCanBus::instance()->createDevice("socketcan", getPort());
|
|
||||||
CANConStatus stats;
|
CANConStatus stats;
|
||||||
|
|
||||||
switch(getStatus())
|
switch(getStatus())
|
||||||
{
|
{
|
||||||
case CANCon::CONNECTED:
|
case CANCon::CONNECTED:
|
||||||
if (!dev_p || !dev_p->connectDevice()) {
|
if (!mDev_p || mDev_p->state() == QCanBusDevice::UnconnectedState) {
|
||||||
/* we have lost connectivity */
|
/* we have lost connectivity */
|
||||||
disconnectDevice();
|
disconnectDevice();
|
||||||
|
|
||||||
@@ -269,11 +272,11 @@ void SerialBusConnection::testConnection() {
|
|||||||
stats.conStatus = getStatus();
|
stats.conStatus = getStatus();
|
||||||
stats.numHardwareBuses = mNumBuses;
|
stats.numHardwareBuses = mNumBuses;
|
||||||
emit status(stats);
|
emit status(stats);
|
||||||
|
piStop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CANCon::NOT_CONNECTED:
|
case CANCon::NOT_CONNECTED:
|
||||||
if (dev_p && dev_p->connectDevice()) {
|
if (mDev_p && mDev_p->state() == QCanBusDevice::UnconnectedState) {
|
||||||
if(!mDev_p) {
|
|
||||||
/* try to reconnect */
|
/* try to reconnect */
|
||||||
CANBus bus;
|
CANBus bus;
|
||||||
if(getBusConfig(0, bus))
|
if(getBusConfig(0, bus))
|
||||||
@@ -281,9 +284,6 @@ void SerialBusConnection::testConnection() {
|
|||||||
bus.setEnabled(true);
|
bus.setEnabled(true);
|
||||||
setBusSettings(0, bus);
|
setBusSettings(0, bus);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* disconnect test instance */
|
|
||||||
dev_p->disconnectDevice();
|
|
||||||
|
|
||||||
setStatus(CANCon::CONNECTED);
|
setStatus(CANCon::CONNECTED);
|
||||||
stats.conStatus = getStatus();
|
stats.conStatus = getStatus();
|
||||||
@@ -293,7 +293,4 @@ void SerialBusConnection::testConnection() {
|
|||||||
break;
|
break;
|
||||||
default: {}
|
default: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dev_p)
|
|
||||||
delete dev_p;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class SerialBusConnection : public CANConnection
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SerialBusConnection(QString portName);
|
SerialBusConnection(QString portName, QString driverName);
|
||||||
virtual ~SerialBusConnection();
|
virtual ~SerialBusConnection();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -8,21 +8,22 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
#include "connections/canconmanager.h"
|
||||||
|
|
||||||
DBCHandler* DBCHandler::instance = NULL;
|
DBCHandler* DBCHandler::instance = nullptr;
|
||||||
|
|
||||||
DBC_SIGNAL* DBCSignalHandler::findSignalByIdx(int idx)
|
DBC_SIGNAL* DBCSignalHandler::findSignalByIdx(int idx)
|
||||||
{
|
{
|
||||||
if (sigs.count() == 0) return NULL;
|
if (sigs.count() == 0) return nullptr;
|
||||||
if (idx < 0) return NULL;
|
if (idx < 0) return nullptr;
|
||||||
if (idx >= sigs.count()) return NULL;
|
if (idx >= sigs.count()) return nullptr;
|
||||||
|
|
||||||
return &sigs[idx];
|
return &sigs[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
DBC_SIGNAL* DBCSignalHandler::findSignalByName(QString name)
|
DBC_SIGNAL* DBCSignalHandler::findSignalByName(QString name)
|
||||||
{
|
{
|
||||||
if (sigs.count() == 0) return NULL;
|
if (sigs.count() == 0) return nullptr;
|
||||||
for (int i = 0; i < sigs.count(); i++)
|
for (int i = 0; i < sigs.count(); i++)
|
||||||
{
|
{
|
||||||
if (sigs[i].name.compare(name, Qt::CaseInsensitive) == 0)
|
if (sigs[i].name.compare(name, Qt::CaseInsensitive) == 0)
|
||||||
@@ -30,7 +31,7 @@ DBC_SIGNAL* DBCSignalHandler::findSignalByName(QString name)
|
|||||||
return &sigs[i];
|
return &sigs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DBCSignalHandler::addSignal(DBC_SIGNAL &sig)
|
bool DBCSignalHandler::addSignal(DBC_SIGNAL &sig)
|
||||||
@@ -82,7 +83,7 @@ int DBCSignalHandler::getCount()
|
|||||||
|
|
||||||
DBC_MESSAGE* DBCMessageHandler::findMsgByID(uint32_t id)
|
DBC_MESSAGE* DBCMessageHandler::findMsgByID(uint32_t id)
|
||||||
{
|
{
|
||||||
if (messages.count() == 0) return NULL;
|
if (messages.count() == 0) return nullptr;
|
||||||
for (int i = 0; i < messages.count(); i++)
|
for (int i = 0; i < messages.count(); i++)
|
||||||
{
|
{
|
||||||
if (isJ1939Handler)
|
if (isJ1939Handler)
|
||||||
@@ -115,20 +116,20 @@ DBC_MESSAGE* DBCMessageHandler::findMsgByID(uint32_t id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBC_MESSAGE* DBCMessageHandler::findMsgByIdx(int idx)
|
DBC_MESSAGE* DBCMessageHandler::findMsgByIdx(int idx)
|
||||||
{
|
{
|
||||||
if (messages.count() == 0) return NULL;
|
if (messages.count() == 0) return nullptr;
|
||||||
if (idx < 0) return NULL;
|
if (idx < 0) return nullptr;
|
||||||
if (idx >= messages.count()) return NULL;
|
if (idx >= messages.count()) return nullptr;
|
||||||
return &messages[idx];
|
return &messages[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
DBC_MESSAGE* DBCMessageHandler::findMsgByName(QString name)
|
DBC_MESSAGE* DBCMessageHandler::findMsgByName(QString name)
|
||||||
{
|
{
|
||||||
if (messages.count() == 0) return NULL;
|
if (messages.count() == 0) return nullptr;
|
||||||
for (int i = 0; i < messages.count(); i++)
|
for (int i = 0; i < messages.count(); i++)
|
||||||
{
|
{
|
||||||
if (messages[i].name.compare(name, Qt::CaseInsensitive) == 0)
|
if (messages[i].name.compare(name, Qt::CaseInsensitive) == 0)
|
||||||
@@ -136,7 +137,7 @@ DBC_MESSAGE* DBCMessageHandler::findMsgByName(QString name)
|
|||||||
return &messages[i];
|
return &messages[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DBCMessageHandler::addMessage(DBC_MESSAGE &msg)
|
bool DBCMessageHandler::addMessage(DBC_MESSAGE &msg)
|
||||||
@@ -251,14 +252,14 @@ DBCFile& DBCFile::operator=(const DBCFile& cpy)
|
|||||||
|
|
||||||
DBC_NODE* DBCFile::findNodeByIdx(int idx)
|
DBC_NODE* DBCFile::findNodeByIdx(int idx)
|
||||||
{
|
{
|
||||||
if (idx < 0) return NULL;
|
if (idx < 0) return nullptr;
|
||||||
if (idx >= dbc_nodes.count()) return NULL;
|
if (idx >= dbc_nodes.count()) return nullptr;
|
||||||
return &dbc_nodes[idx];
|
return &dbc_nodes[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
DBC_NODE* DBCFile::findNodeByName(QString name)
|
DBC_NODE* DBCFile::findNodeByName(QString name)
|
||||||
{
|
{
|
||||||
if (dbc_nodes.length() == 0) return NULL;
|
if (dbc_nodes.length() == 0) return nullptr;
|
||||||
for (int i = 0; i < dbc_nodes.length(); i++)
|
for (int i = 0; i < dbc_nodes.length(); i++)
|
||||||
{
|
{
|
||||||
if (dbc_nodes[i].name.compare(name, Qt::CaseInsensitive) == 0)
|
if (dbc_nodes[i].name.compare(name, Qt::CaseInsensitive) == 0)
|
||||||
@@ -266,7 +267,7 @@ DBC_NODE* DBCFile::findNodeByName(QString name)
|
|||||||
return &dbc_nodes[i];
|
return &dbc_nodes[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DBCFile::getFullFilename()
|
QString DBCFile::getFullFilename()
|
||||||
@@ -291,14 +292,15 @@ int DBCFile::getAssocBus()
|
|||||||
|
|
||||||
void DBCFile::setAssocBus(int bus)
|
void DBCFile::setAssocBus(int bus)
|
||||||
{
|
{
|
||||||
|
int numBuses = CANConManager::getInstance()->getNumBuses();
|
||||||
if (bus < -1) return;
|
if (bus < -1) return;
|
||||||
if (bus > 1) return;
|
if (bus >= numBuses) return;
|
||||||
assocBuses = bus;
|
assocBuses = bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBC_ATTRIBUTE *DBCFile::findAttributeByName(QString name)
|
DBC_ATTRIBUTE *DBCFile::findAttributeByName(QString name)
|
||||||
{
|
{
|
||||||
if (dbc_attributes.length() == 0) return NULL;
|
if (dbc_attributes.length() == 0) return nullptr;
|
||||||
for (int i = 0; i < dbc_attributes.length(); i++)
|
for (int i = 0; i < dbc_attributes.length(); i++)
|
||||||
{
|
{
|
||||||
if (dbc_attributes[i].name.compare(name, Qt::CaseInsensitive) == 0)
|
if (dbc_attributes[i].name.compare(name, Qt::CaseInsensitive) == 0)
|
||||||
@@ -306,13 +308,13 @@ DBC_ATTRIBUTE *DBCFile::findAttributeByName(QString name)
|
|||||||
return &dbc_attributes[i];
|
return &dbc_attributes[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBC_ATTRIBUTE *DBCFile::findAttributeByIdx(int idx)
|
DBC_ATTRIBUTE *DBCFile::findAttributeByIdx(int idx)
|
||||||
{
|
{
|
||||||
if (idx < 0) return NULL;
|
if (idx < 0) return nullptr;
|
||||||
if (idx >= dbc_attributes.count()) return NULL;
|
if (idx >= dbc_attributes.count()) return nullptr;
|
||||||
return &dbc_attributes[idx];
|
return &dbc_attributes[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,8 +347,9 @@ DBC_MESSAGE* DBCFile::parseMessageLine(QString line)
|
|||||||
DBC_MESSAGE msg;
|
DBC_MESSAGE msg;
|
||||||
msg.ID = match.captured(1).toULong() & 0x7FFFFFFFul; //the ID is always stored in decimal format
|
msg.ID = match.captured(1).toULong() & 0x7FFFFFFFul; //the ID is always stored in decimal format
|
||||||
msg.name = match.captured(2);
|
msg.name = match.captured(2);
|
||||||
msg.len = match.captured(3).toInt();
|
msg.len = match.captured(3).toUInt();
|
||||||
msg.sender = findNodeByName(match.captured(4));
|
msg.sender = findNodeByName(match.captured(4));
|
||||||
|
if (!msg.sender) msg.sender = findNodeByIdx(0);
|
||||||
messageHandler->addMessage(msg);
|
messageHandler->addMessage(msg);
|
||||||
msgPtr = messageHandler->findMsgByID(msg.ID);
|
msgPtr = messageHandler->findMsgByID(msg.ID);
|
||||||
}
|
}
|
||||||
@@ -453,6 +456,9 @@ DBC_SIGNAL* DBCFile::parseSignalLine(QString line, DBC_MESSAGE *msg)
|
|||||||
sig.receiver = findNodeByName(tmp);
|
sig.receiver = findNodeByName(tmp);
|
||||||
}
|
}
|
||||||
else sig.receiver = findNodeByName(match.captured(11 + offset));
|
else sig.receiver = findNodeByName(match.captured(11 + offset));
|
||||||
|
|
||||||
|
if (!sig.receiver) sig.receiver = findNodeByIdx(0); //apply default if there was no match
|
||||||
|
|
||||||
sig.parentMessage = msg;
|
sig.parentMessage = msg;
|
||||||
msg->sigHandler->addSignal(sig);
|
msg->sigHandler->addSignal(sig);
|
||||||
if (isMultiplexor) msg->multiplexorSignal = msg->sigHandler->findSignalByName(sig.name);
|
if (isMultiplexor) msg->multiplexorSignal = msg->sigHandler->findSignalByName(sig.name);
|
||||||
@@ -476,11 +482,11 @@ bool DBCFile::parseValueLine(QString line)
|
|||||||
if (match.hasMatch())
|
if (match.hasMatch())
|
||||||
{
|
{
|
||||||
//qDebug() << "Data was: " << match.captured(3);
|
//qDebug() << "Data was: " << match.captured(3);
|
||||||
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toInt());
|
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toUInt());
|
||||||
if (msg != NULL)
|
if (msg != nullptr)
|
||||||
{
|
{
|
||||||
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(match.captured(2));
|
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(match.captured(2));
|
||||||
if (sig != NULL)
|
if (sig != nullptr)
|
||||||
{
|
{
|
||||||
QString tokenString = match.captured(3);
|
QString tokenString = match.captured(3);
|
||||||
DBC_VAL_ENUM_ENTRY val;
|
DBC_VAL_ENUM_ENTRY val;
|
||||||
@@ -525,7 +531,7 @@ bool DBCFile::parseAttributeLine(QString line)
|
|||||||
if (foundAttr)
|
if (foundAttr)
|
||||||
{
|
{
|
||||||
qDebug() << "That attribute does exist";
|
qDebug() << "That attribute does exist";
|
||||||
DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toInt());
|
DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toUInt());
|
||||||
if (foundMsg)
|
if (foundMsg)
|
||||||
{
|
{
|
||||||
qDebug() << "It references a valid, registered message";
|
qDebug() << "It references a valid, registered message";
|
||||||
@@ -557,7 +563,7 @@ bool DBCFile::parseAttributeLine(QString line)
|
|||||||
if (foundAttr)
|
if (foundAttr)
|
||||||
{
|
{
|
||||||
qDebug() << "That attribute does exist";
|
qDebug() << "That attribute does exist";
|
||||||
DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toInt());
|
DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toUInt());
|
||||||
if (foundMsg)
|
if (foundMsg)
|
||||||
{
|
{
|
||||||
qDebug() << "It references a valid, registered message";
|
qDebug() << "It references a valid, registered message";
|
||||||
@@ -662,7 +668,7 @@ void DBCFile::loadFile(QString fileName)
|
|||||||
QString line, rawLine;
|
QString line, rawLine;
|
||||||
QRegularExpression regex;
|
QRegularExpression regex;
|
||||||
QRegularExpressionMatch match;
|
QRegularExpressionMatch match;
|
||||||
DBC_MESSAGE *currentMessage = NULL;
|
DBC_MESSAGE *currentMessage = nullptr;
|
||||||
DBC_ATTRIBUTE attr;
|
DBC_ATTRIBUTE attr;
|
||||||
int numSigFaults = 0, numMsgFaults = 0;
|
int numSigFaults = 0, numMsgFaults = 0;
|
||||||
|
|
||||||
@@ -746,11 +752,11 @@ void DBCFile::loadFile(QString fileName)
|
|||||||
if (match.hasMatch())
|
if (match.hasMatch())
|
||||||
{
|
{
|
||||||
//qDebug() << "Comment was: " << match.captured(3);
|
//qDebug() << "Comment was: " << match.captured(3);
|
||||||
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toInt());
|
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toUInt());
|
||||||
if (msg != NULL)
|
if (msg != nullptr)
|
||||||
{
|
{
|
||||||
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(match.captured(2));
|
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(match.captured(2));
|
||||||
if (sig != NULL)
|
if (sig != nullptr)
|
||||||
{
|
{
|
||||||
sig->comment = match.captured(3);
|
sig->comment = match.captured(3);
|
||||||
}
|
}
|
||||||
@@ -767,8 +773,8 @@ void DBCFile::loadFile(QString fileName)
|
|||||||
if (match.hasMatch())
|
if (match.hasMatch())
|
||||||
{
|
{
|
||||||
//qDebug() << "Comment was: " << match.captured(2);
|
//qDebug() << "Comment was: " << match.captured(2);
|
||||||
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toInt());
|
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toUInt());
|
||||||
if (msg != NULL)
|
if (msg != nullptr)
|
||||||
{
|
{
|
||||||
msg->comment = match.captured(2);
|
msg->comment = match.captured(2);
|
||||||
}
|
}
|
||||||
@@ -785,7 +791,7 @@ void DBCFile::loadFile(QString fileName)
|
|||||||
{
|
{
|
||||||
//qDebug() << "Comment was: " << match.captured(2);
|
//qDebug() << "Comment was: " << match.captured(2);
|
||||||
DBC_NODE *node = findNodeByName(match.captured(1));
|
DBC_NODE *node = findNodeByName(match.captured(1));
|
||||||
if (node != NULL)
|
if (node != nullptr)
|
||||||
{
|
{
|
||||||
node->comment = match.captured(2);
|
node->comment = match.captured(2);
|
||||||
}
|
}
|
||||||
@@ -1036,6 +1042,9 @@ bool DBCFile::parseAttribute(QString inpString, DBC_ATTRIBUTE &attr)
|
|||||||
|
|
||||||
void DBCFile::saveFile(QString fileName)
|
void DBCFile::saveFile(QString fileName)
|
||||||
{
|
{
|
||||||
|
int nodeNumber = 1;
|
||||||
|
int msgNumber = 1;
|
||||||
|
int sigNumber = 1;
|
||||||
QFile *outFile = new QFile(fileName);
|
QFile *outFile = new QFile(fileName);
|
||||||
QString nodesOutput, msgOutput, commentsOutput, valuesOutput;
|
QString nodesOutput, msgOutput, commentsOutput, valuesOutput;
|
||||||
QString defaultsOutput, attrValOutput;
|
QString defaultsOutput, attrValOutput;
|
||||||
@@ -1089,6 +1098,11 @@ void DBCFile::saveFile(QString fileName)
|
|||||||
DBC_NODE node = dbc_nodes[x];
|
DBC_NODE node = dbc_nodes[x];
|
||||||
if (node.name.compare("Vector__XXX", Qt::CaseInsensitive) != 0)
|
if (node.name.compare("Vector__XXX", Qt::CaseInsensitive) != 0)
|
||||||
{
|
{
|
||||||
|
if (node.name.length() < 1) //detect an empty string and fill it out with something
|
||||||
|
{
|
||||||
|
node.name = "NODE" + QString::number(nodeNumber);
|
||||||
|
nodeNumber++;
|
||||||
|
}
|
||||||
nodesOutput.append(node.name + " ");
|
nodesOutput.append(node.name + " ");
|
||||||
if (node.comment.length() > 0)
|
if (node.comment.length() > 0)
|
||||||
{
|
{
|
||||||
@@ -1119,6 +1133,12 @@ void DBCFile::saveFile(QString fileName)
|
|||||||
{
|
{
|
||||||
DBC_MESSAGE *msg = messageHandler->findMsgByIdx(x);
|
DBC_MESSAGE *msg = messageHandler->findMsgByIdx(x);
|
||||||
|
|
||||||
|
if (msg->name.length() < 1) //detect an empty string and fill it out with something
|
||||||
|
{
|
||||||
|
msg->name = "MSG" + QString::number(msgNumber);
|
||||||
|
msgNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
msgOutput.append("BO_ " + QString::number(msg->ID) + " " + msg->name + ": " + QString::number(msg->len) +
|
msgOutput.append("BO_ " + QString::number(msg->ID) + " " + msg->name + ": " + QString::number(msg->len) +
|
||||||
" " + msg->sender->name + "\n");
|
" " + msg->sender->name + "\n");
|
||||||
if (msg->comment.length() > 0)
|
if (msg->comment.length() > 0)
|
||||||
@@ -1146,6 +1166,13 @@ void DBCFile::saveFile(QString fileName)
|
|||||||
for (int s = 0; s < msg->sigHandler->getCount(); s++)
|
for (int s = 0; s < msg->sigHandler->getCount(); s++)
|
||||||
{
|
{
|
||||||
DBC_SIGNAL *sig = msg->sigHandler->findSignalByIdx(s);
|
DBC_SIGNAL *sig = msg->sigHandler->findSignalByIdx(s);
|
||||||
|
|
||||||
|
if (sig->name.length() < 1) //detect an empty string and fill it out with something
|
||||||
|
{
|
||||||
|
sig->name = "SIG" + QString::number(sigNumber);
|
||||||
|
sigNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
msgOutput.append(" SG_ " + sig->name);
|
msgOutput.append(" SG_ " + sig->name);
|
||||||
|
|
||||||
if (sig->isMultiplexor) msgOutput.append(" M");
|
if (sig->isMultiplexor) msgOutput.append(" M");
|
||||||
@@ -1399,7 +1426,7 @@ DBCFile* DBCHandler::loadDBCFile(int idx)
|
|||||||
return &loadedFiles.last();
|
return &loadedFiles.last();
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBCHandler::removeDBCFile(int idx)
|
void DBCHandler::removeDBCFile(int idx)
|
||||||
@@ -1439,10 +1466,10 @@ DBC_MESSAGE* DBCHandler::findMessage(const CANFrame &frame)
|
|||||||
if (loadedFiles[i].getAssocBus() == -1 || frame.bus == (unsigned int)loadedFiles[i].getAssocBus())
|
if (loadedFiles[i].getAssocBus() == -1 || frame.bus == (unsigned int)loadedFiles[i].getAssocBus())
|
||||||
{
|
{
|
||||||
DBC_MESSAGE* msg = loadedFiles[i].messageHandler->findMsgByID(frame.ID);
|
DBC_MESSAGE* msg = loadedFiles[i].messageHandler->findMsgByID(frame.ID);
|
||||||
if (msg != NULL) return msg;
|
if (msg != nullptr) return msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DBCHandler::getFileCount()
|
int DBCHandler::getFileCount()
|
||||||
@@ -1452,15 +1479,15 @@ int DBCHandler::getFileCount()
|
|||||||
|
|
||||||
DBCFile* DBCHandler::getFileByIdx(int idx)
|
DBCFile* DBCHandler::getFileByIdx(int idx)
|
||||||
{
|
{
|
||||||
if (loadedFiles.count() == 0) return NULL;
|
if (loadedFiles.count() == 0) return nullptr;
|
||||||
if (idx < 0) return NULL;
|
if (idx < 0) return nullptr;
|
||||||
if (idx >= loadedFiles.count()) return NULL;
|
if (idx >= loadedFiles.count()) return nullptr;
|
||||||
return &loadedFiles[idx];
|
return &loadedFiles[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
DBCFile* DBCHandler::getFileByName(QString name)
|
DBCFile* DBCHandler::getFileByName(QString name)
|
||||||
{
|
{
|
||||||
if (loadedFiles.count() == 0) return NULL;
|
if (loadedFiles.count() == 0) return nullptr;
|
||||||
for (int i = 0; i < loadedFiles.count(); i++)
|
for (int i = 0; i < loadedFiles.count(); i++)
|
||||||
{
|
{
|
||||||
if (loadedFiles[i].getFilename().compare(name, Qt::CaseInsensitive) == 0)
|
if (loadedFiles[i].getFilename().compare(name, Qt::CaseInsensitive) == 0)
|
||||||
@@ -1468,7 +1495,7 @@ DBCFile* DBCHandler::getFileByName(QString name)
|
|||||||
return &loadedFiles[i];
|
return &loadedFiles[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBCHandler::DBCHandler()
|
DBCHandler::DBCHandler()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "ui_dbcloadsavewindow.h"
|
#include "ui_dbcloadsavewindow.h"
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include "helpwindow.h"
|
#include "helpwindow.h"
|
||||||
|
#include "connections/canconmanager.h"
|
||||||
|
|
||||||
DBCLoadSaveWindow::DBCLoadSaveWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
DBCLoadSaveWindow::DBCLoadSaveWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
@@ -34,6 +35,7 @@ DBCLoadSaveWindow::DBCLoadSaveWindow(const QVector<CANFrame> *frames, QWidget *p
|
|||||||
connect(ui->tableFiles, &QTableWidget::cellDoubleClicked, this, &DBCLoadSaveWindow::cellDoubleClicked);
|
connect(ui->tableFiles, &QTableWidget::cellDoubleClicked, this, &DBCLoadSaveWindow::cellDoubleClicked);
|
||||||
|
|
||||||
editorWindow = new DBCMainEditor(frames);
|
editorWindow = new DBCMainEditor(frames);
|
||||||
|
currentlyEditingFile = nullptr;
|
||||||
|
|
||||||
installEventFilter(this);
|
installEventFilter(this);
|
||||||
}
|
}
|
||||||
@@ -108,11 +110,26 @@ void DBCLoadSaveWindow::saveFile()
|
|||||||
|
|
||||||
void DBCLoadSaveWindow::removeFile()
|
void DBCLoadSaveWindow::removeFile()
|
||||||
{
|
{
|
||||||
|
bool bContinue = true;
|
||||||
int idx = ui->tableFiles->currentRow();
|
int idx = ui->tableFiles->currentRow();
|
||||||
if (idx < 0) return;
|
if (idx < 0) return;
|
||||||
|
|
||||||
|
if (currentlyEditingFile == dbcHandler->getFileByIdx(idx))
|
||||||
|
{
|
||||||
|
bContinue = false;
|
||||||
|
QMessageBox::StandardButton confirmDialog;
|
||||||
|
confirmDialog = QMessageBox::question(this, "Confirm Deletion", "This DBC is currently open for editing.\nMake sure you've saved any changes!\nAre you sure you want to remove this DBC?",
|
||||||
|
QMessageBox::Yes|QMessageBox::No);
|
||||||
|
if (confirmDialog == QMessageBox::Yes) bContinue = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bContinue)
|
||||||
|
{
|
||||||
|
editorWindow->close();
|
||||||
dbcHandler->removeDBCFile(idx);
|
dbcHandler->removeDBCFile(idx);
|
||||||
ui->tableFiles->removeRow(idx);
|
ui->tableFiles->removeRow(idx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DBCLoadSaveWindow::moveUp()
|
void DBCLoadSaveWindow::moveUp()
|
||||||
{
|
{
|
||||||
@@ -146,7 +163,8 @@ void DBCLoadSaveWindow::cellChanged(int row, int col)
|
|||||||
{
|
{
|
||||||
DBCFile *file = dbcHandler->getFileByIdx(row);
|
DBCFile *file = dbcHandler->getFileByIdx(row);
|
||||||
int bus = ui->tableFiles->item(row, col)->text().toInt();
|
int bus = ui->tableFiles->item(row, col)->text().toInt();
|
||||||
if (bus > -2 && bus < 2)
|
int numBuses = CANConManager::getInstance()->getNumBuses();
|
||||||
|
if (bus > -2 && bus < numBuses)
|
||||||
{
|
{
|
||||||
file->setAssocBus(bus);
|
file->setAssocBus(bus);
|
||||||
}
|
}
|
||||||
@@ -185,6 +203,7 @@ void DBCLoadSaveWindow::cellChanged(int row, int col)
|
|||||||
void DBCLoadSaveWindow::cellDoubleClicked(int row, int col)
|
void DBCLoadSaveWindow::cellDoubleClicked(int row, int col)
|
||||||
{
|
{
|
||||||
Q_UNUSED(col)
|
Q_UNUSED(col)
|
||||||
|
currentlyEditingFile = dbcHandler->getFileByIdx(row);
|
||||||
editorWindow->setFileIdx(row);
|
editorWindow->setFileIdx(row);
|
||||||
editorWindow->show();
|
editorWindow->show();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
Ui::DBCLoadSaveWindow *ui;
|
Ui::DBCLoadSaveWindow *ui;
|
||||||
DBCHandler *dbcHandler;
|
DBCHandler *dbcHandler;
|
||||||
|
DBCFile *currentlyEditingFile;
|
||||||
const QVector<CANFrame> *referenceFrames;
|
const QVector<CANFrame> *referenceFrames;
|
||||||
DBCMainEditor *editorWindow;
|
DBCMainEditor *editorWindow;
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ void DBCMainEditor::closeEvent(QCloseEvent *event)
|
|||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
writeSettings();
|
writeSettings();
|
||||||
|
sigEditor->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBCMainEditor::readSettings()
|
void DBCMainEditor::readSettings()
|
||||||
@@ -283,6 +284,9 @@ void DBCMainEditor::onCellChangedMessage(int row,int col)
|
|||||||
newMsg.name = "";
|
newMsg.name = "";
|
||||||
newMsg.sender = node;
|
newMsg.sender = node;
|
||||||
newMsg.len = 0;
|
newMsg.len = 0;
|
||||||
|
newMsg.fgColor = ui->MessagesTable->item(row, 4)->backgroundColor();
|
||||||
|
newMsg.bgColor = ui->MessagesTable->item(row, 5)->backgroundColor();
|
||||||
|
|
||||||
for (int i = 0; i < referenceFrames->length(); i++)
|
for (int i = 0; i < referenceFrames->length(); i++)
|
||||||
{
|
{
|
||||||
if ((uint) referenceFrames->at(i).ID == msgID)
|
if ((uint) referenceFrames->at(i).ID == msgID)
|
||||||
@@ -547,7 +551,7 @@ void DBCMainEditor::insertBlankRow()
|
|||||||
{
|
{
|
||||||
QTableWidgetItem *item = new QTableWidgetItem("");
|
QTableWidgetItem *item = new QTableWidgetItem("");
|
||||||
if (i == 4) item->setBackgroundColor(QApplication::palette().color(QPalette::WindowText)); //foreground color
|
if (i == 4) item->setBackgroundColor(QApplication::palette().color(QPalette::WindowText)); //foreground color
|
||||||
//if (i == 5) item->setBackgroundColor(ui->MessagesTable->palette().color(ui->MessagesTable->backgroundRole())); //background color
|
if (i == 5) item->setBackgroundColor(QApplication::palette().color(QPalette::Base));
|
||||||
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
||||||
ui->MessagesTable->setItem(rowIdx, i, item);
|
ui->MessagesTable->setItem(rowIdx, i, item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,8 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
|||||||
[=]()
|
[=]()
|
||||||
{
|
{
|
||||||
if (currentSignal == NULL) return;
|
if (currentSignal == NULL) return;
|
||||||
currentSignal->name = ui->txtName->text().simplified().replace(' ', '_');
|
QString tempNameStr = ui->txtName->text().simplified().replace(' ', '_');
|
||||||
|
if (tempNameStr.length() > 0) currentSignal->name = tempNameStr;
|
||||||
//need to update the list too.
|
//need to update the list too.
|
||||||
ui->signalsList->currentItem()->setText(currentSignal->name);
|
ui->signalsList->currentItem()->setText(currentSignal->name);
|
||||||
});
|
});
|
||||||
@@ -256,7 +257,7 @@ void DBCSignalEditor::readSettings()
|
|||||||
QSettings settings;
|
QSettings settings;
|
||||||
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||||
{
|
{
|
||||||
resize(settings.value("DBCSignalEditor/WindowSize", QSize(800, 572)).toSize());
|
resize(settings.value("DBCSignalEditor/WindowSize", QSize(1000, 600)).toSize());
|
||||||
move(settings.value("DBCSignalEditor/WindowPos", QPoint(100, 100)).toPoint());
|
move(settings.value("DBCSignalEditor/WindowPos", QPoint(100, 100)).toPoint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -371,8 +372,8 @@ void DBCSignalEditor::deleteCurrentSignal()
|
|||||||
{
|
{
|
||||||
int currIdx = ui->signalsList->currentRow();
|
int currIdx = ui->signalsList->currentRow();
|
||||||
|
|
||||||
if(currIdx==ui->signalsList->count()-1)
|
//if(currIdx==ui->signalsList->count()-1)
|
||||||
return;
|
//return;
|
||||||
|
|
||||||
if (currIdx > -1)
|
if (currIdx > -1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
make qthelp
|
make qthelp
|
||||||
~/Qt/5.9.1/gcc_64/bin/qcollectiongenerator build/qthelp/SavvyCAN.qhcp
|
~/Qt/5.12.1/gcc_64/bin/qcollectiongenerator build/qthelp/SavvyCAN.qhcp
|
||||||
~/Qt/5.9.1/gcc_64/bin/assistant -collectionFile build/qthelp/SavvyCAN.qhc
|
~/Qt/5.12.1/gcc_64/bin/assistant -collectionFile build/qthelp/SavvyCAN.qhc
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'SavvyCAN'
|
project = u'SavvyCAN'
|
||||||
copyright = u'2017, EVTV'
|
copyright = u'2018, EVTV'
|
||||||
author = u'Collin Kidder'
|
author = u'Collin Kidder'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
@@ -55,9 +55,9 @@ author = u'Collin Kidder'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '181'
|
version = '189'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '181'
|
release = '189'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|||||||
@@ -5,32 +5,60 @@ Connection Window
|
|||||||
|
|
||||||
.. image:: ./images/ConnectionWindow.png
|
.. image:: ./images/ConnectionWindow.png
|
||||||
|
|
||||||
The connection window is used to add, remove, and modify connections. At the moment it is possible to use any SocketCAN compatible device (in LINUX) and any GVRET compatible device in any of the supported operating systems.
|
The connection window is used to add, remove, and modify connections. At the moment it is possible
|
||||||
At this time GVRET compatible devices are: EVTVDue, EVTV CANDue (1.3/2/2.1/2.2), Teensy 3.1-3.6, Macchina M2.
|
to use any QT SerialBus compatible device and any GVRET compatible device in any of the supported
|
||||||
|
operating systems. SerialBus supports socketcan on linux, passthrough on Linux and Windows 32
|
||||||
|
bit, and Vector, PeakCAN, and TinyCAN on supported OS's.
|
||||||
|
|
||||||
|
At this time GVRET compatible devices are: EVTVDue, EVTV CANDue (1.3/2/2.1/2.2),
|
||||||
|
Teensy 3.1-3.6, Macchina M2, EVTV ESP32 Due.
|
||||||
|
|
||||||
|
|
||||||
Connecting To A Dongle
|
Connecting To A Dongle
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
SavvyCAN is able to connect to GVRET compatible devices to capture new traffic. These devices will present as serial ports on the connected PC.
|
SavvyCAN is able to connect to GVRET compatible devices to capture new traffic. These
|
||||||
To connect to a dongle select the proper serial port and click "Create New Connection". If a valid device is found on that serial port the first
|
devices will present as serial ports on the connected PC.
|
||||||
statusbar section will update and the currently set canbus speeds will show in the table at the left of the window. These speeds can then
|
To connect to a dongle select the proper serial port and click "Create New Connection".
|
||||||
be changed by clicking on the speed (or otherwise selecting the cell in the table) and typing in a new value. Leaving the cell will update the speed to the new value. GVRET devices also support
|
If a valid device is found on that serial port the first statusbar section will update
|
||||||
setting "listen only" on each bus. This mode causes the device to not acknowledge any traffic or try to modify the bus at all. It is as it says, a mode where you can only listen to whatever traffic
|
and the currently set canbus speeds will show in the table at the left of the window.
|
||||||
is found on the bus. Some older GVRET devices supported a mode where you could change the second bus between single wire CAN and normal CAN. This is deprecated. However, newer GVRET devices have
|
These speeds can then be changed by clicking on the speed (or otherwise selecting the cell
|
||||||
dedicated single wire CAN buses and the relevant bus will show the checkbox.
|
in the table) and typing in a new value. Leaving the cell will update the speed to the new
|
||||||
|
value. GVRET devices also support setting "listen only" on each bus. This mode causes the
|
||||||
|
device to not acknowledge any traffic or try to modify the bus at all. It is as it says,
|
||||||
|
a mode where you can only listen to whatever traffic is found on the bus. Some older GVRET
|
||||||
|
devices supported a mode where you could change the second bus between single wire CAN
|
||||||
|
and normal CAN. This is deprecated. However, newer GVRET devices have dedicated single
|
||||||
|
wire CAN buses and the relevant bus will show the checkbox.
|
||||||
|
|
||||||
SavvyCAN can also connect to SocketCAN devices in LINUX. Select "SocketCAN" as the connection type and then type in the device name. This should be just the same as you would provide to the can-utils
|
SavvyCAN can also connect to a wide variety of CAN hardware through the built-in QT
|
||||||
programs. That is, do not enter /dev/can0 but rather can0. Then push "Create New Connection" and you should see the new connection in the table on the left of the window. Note that SocketCAN devices don't
|
SerialBus drivers. These drivers vary by operating system but support socketcan on LINUX
|
||||||
support changing the baud rate within a program. You must do this when you set up the connection via console commands. This is outside the scope of this documentation. Consult the SocketCAN documentation
|
and Vector tools on both LINUX and Windows. When you select "QT SerialBus Devices" you will
|
||||||
for details on configuring such devices.
|
get a list of device types supported. Select a device type and for most devices you should see
|
||||||
|
the Port list fill out with all registered and valid ports for that driver. Socketcan devices, for
|
||||||
|
instance, are automatically detected now. Then push "Create New Connection" and you should
|
||||||
|
see the new connection in the table on the left of the window. Note that SocketCAN devices
|
||||||
|
don't support changing the baud rate within a program. You must do this when you set up
|
||||||
|
the connection via console commands. This is outside the scope of this documentation.
|
||||||
|
Consult the SocketCAN documentation for details on configuring such devices.
|
||||||
|
|
||||||
|
The last connection option is "Remote Host." If you select this option then Port will change
|
||||||
|
to a textbox. Enter the IP address of the remote (but still local to your LAN) IP address. Currently
|
||||||
|
this works with EVTV ESP32 boards and M2 boards.
|
||||||
|
|
||||||
Debugging Connection Problems
|
Debugging Connection Problems
|
||||||
==============================
|
==============================
|
||||||
GVRET devices present as serial ports and have significant configuration options. However, the ability to configure so many things and the ability to compile the firmware yourself both come as a
|
GVRET devices present as serial ports and have significant configuration options.
|
||||||
double edged sword. They present many opportunities for things to go wrong. Because of this there is a debugging console present on the connection window. Click a bus in the table then click "Enable Console"
|
However, the ability to configure so many things and the ability to compile the firmware
|
||||||
to cause it to start logging serial traffic. From this console you can see what is going on. It shows what SavvyCAN is sending and what it is getting back. It has extended status messages that might help to narrow down
|
yourself both come as a double edged sword. They present many opportunities for things
|
||||||
what is going wrong. Additionally, if you're feeling adventurous you can send traffic to the serial device from the Send line. "Send Hex" accepts a set of hex values separated by spaces. "Send Text" will send the raw
|
to go wrong. Because of this there is a debugging console present on the connection window.
|
||||||
text you type on the line. GVRET traffic is ordinarily binary so "Send Text" won't work very well for that. But, there is also a text console possible on GVRET devices. If you connect to them with a serial program you can
|
Click a bus in the table then click "Enable Console" to cause it to start logging serial
|
||||||
configure things via a text console. Type ? and follow it up with some form of line ending (Cr, Lf, CrLf, any will work).
|
traffic. From this console you can see what is going on. It shows what SavvyCAN is sending
|
||||||
|
and what it is getting back. It has extended status messages that might help to narrow down
|
||||||
|
what is going wrong. Additionally, if you're feeling adventurous you can send traffic to
|
||||||
|
the serial device from the Send line. "Send Hex" accepts a set of hex values separated
|
||||||
|
by spaces. "Send Text" will send the raw text you type on the line. GVRET traffic is
|
||||||
|
ordinarily binary so "Send Text" won't work very well for that. But, there is also a
|
||||||
|
text console possible on GVRET devices. If you connect to them with a serial program you can
|
||||||
|
configure things via a text console. Type ? and follow it up with some form of line
|
||||||
|
ending (Cr, Lf, CrLf, any will work).
|
||||||
|
|||||||
@@ -8,4 +8,12 @@ Frame Details Window
|
|||||||
The Purpose of Frame Details Window
|
The Purpose of Frame Details Window
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
This window is used to get detailed statistics about frames. It provides information about a given frame ID across all frames with that ID. You can get such information as the number of frames, the number of data bytes that frame ID has, the average interval between frames with that ID, and the minimum and maximum interval. Also listed are detailed statistics for each data byte in that frame. Each byte has listed which bits changed, the range of values found, and a histogram both graphically (at the bottom of the window) and textually. The textual representation shows the number of times a specific value occurred. Also listed at the bottom is a histogram of each bit and how many times it was set. The graph is a histogram of all the bits and the number of times each bit was set. This can be used to quickly visually see where data has changed. All information can be saved to a text file for later analysis.
|
This window is used to get detailed statistics about frames.
|
||||||
|
|
||||||
|
It provides information about a given frame ID across all frames with that ID. You can get such information as the number of frames, the number of data bytes that frame ID has, the average interval between frames with that ID, and the minimum and maximum interval.
|
||||||
|
|
||||||
|
Also listed are detailed statistics for each data byte in that frame. Each byte has listed which bits changed, the range of values found, and a histogram both graphically (at the righthand side of the window) and textually. The textual representation shows the number of times a specific value occurred.
|
||||||
|
|
||||||
|
The top right graph is a histogram of all the bits and the number of times each bit was set. This can be used to quickly visually see where data has changed.
|
||||||
|
|
||||||
|
The bottom right graph is of each individual byte as its value varies over time. All textual information can be saved to a text file for later analysis.
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 135 KiB |
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
Welcome to SavvyCAN V181 documentation!
|
Welcome to SavvyCAN V189 documentation!
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
Contents:
|
Contents:
|
||||||
|
|||||||
@@ -8,11 +8,64 @@ Sniffer Window
|
|||||||
Using the Sniffer Window
|
Using the Sniffer Window
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
This window is essentially a graphical version of the linux can_utils. The general idea here is to display a list of frames such that you only see frames that are actively updating. If a given ID has not been seen in 4 seconds the ID portion will turn RED and then disappear from the list. In this way only frames that are updating are in the list. They are ordered by last update time. Bytes that have deincremented will be red and bytes that have incremented will be green. You can use the "Filters" area to mask away some IDs so that they never show up. This can help to declutter the list.
|
This window is essentially a turbo charged graphical version of the linux
|
||||||
|
can_utils program "cansniffer". The general idea here is to display a list
|
||||||
|
of frames such that you only see frames that are actively updating. If a given
|
||||||
|
ID has not been seen in 5 seconds the ID portion will turn RED and then disappear
|
||||||
|
from the list. In this way only frames that are updating are in the list. They are
|
||||||
|
ordered by ID. Bytes that have deincremented will be red and bytes that have incremented
|
||||||
|
will be green. You can use the "Filters" area to mask away some IDs so that they never
|
||||||
|
show up. This can help to declutter the list.
|
||||||
|
|
||||||
|
This window updates with a 200ms interval.
|
||||||
|
|
||||||
Notching and Unnotching
|
Notching and Unnotching
|
||||||
========================
|
========================
|
||||||
|
|
||||||
Honestly, I don't know. It seems that notching means to store the current value of the data bytes for each frame and then use that notch data for the comparison for increment / deincrement to color the bytes. Unnotching would then be clearing that out so that it uses the previous value from the last time the frame ID was seen. But, don't quote me on that. This should be figured out definitively and corrected.
|
While the window is running it keeps a running list each 200ms cycle of all the bits that
|
||||||
|
changed in that timespan. Each 200ms this list is backed up and reset. If you push the
|
||||||
|
notch button the system will remember all the bits that were set in the last 200ms window
|
||||||
|
and will not color the output if those bits are toggled in the future. They will thus somewhat
|
||||||
|
be ignored except that you can visually still see them updating. If you click the Notch
|
||||||
|
button repeatedly it will add any new changed bits to the old changed bits. In this way you
|
||||||
|
can build up a set of bits to ignore. Un-notching causes all notched (ignored) bits to be
|
||||||
|
reset and thus all changes will be colored once again.
|
||||||
|
|
||||||
|
Advanced Options
|
||||||
|
==================
|
||||||
|
|
||||||
|
All of the above was valid if you do not check any of the four checkboxes. With the checkboxes
|
||||||
|
unchecked this window is very close to cansniffer on the command line. But, what fun is that?
|
||||||
|
These checkboxes modify the way the window works in a variety of ways.
|
||||||
|
|
||||||
|
Never Expire IDs
|
||||||
|
==================
|
||||||
|
|
||||||
|
This checkbox will do exactly what it says on the tin. Instead of frame ID's expiring after
|
||||||
|
5 seconds of inactivity they will stick around forever. This can be useful so that the ID you
|
||||||
|
are watching doesn't jump up and down as IDs expire and potentially come back later on or new IDs
|
||||||
|
are seen. With no expiration you will get a more consistent view of the IDs. You are still free
|
||||||
|
to filter away IDs you are not interested in.
|
||||||
|
|
||||||
|
Mute notched bits
|
||||||
|
===================
|
||||||
|
|
||||||
|
This checkbox might sound a bit strange. With this checked any bytes that you have notched will
|
||||||
|
ignore any notched bits and not even change the display to update if only notched bits were changed.
|
||||||
|
This completely hides all notched data. The view of the frames will then NOT perfectly or correctly
|
||||||
|
represent the actual most up to date data for each ID. So, use this option with caution. But, it
|
||||||
|
is handy when you are looking for a needle in a haystack and you don't want things changing if you've
|
||||||
|
already told the program to notch them away.
|
||||||
|
|
||||||
|
Fade inactive bytes
|
||||||
|
====================
|
||||||
|
|
||||||
|
This can be used with mute or without but has a similar purpose. When this is checked any bytes
|
||||||
|
that haven't updated recently will begin to fade away to white. They never quite get all the way
|
||||||
|
to disappearing but will fade to be very light. In this way only data which is actively changing will
|
||||||
|
be very visible. This drastically aids in helping you to ignore any bytes that are not changing.
|
||||||
|
|
||||||
|
View Bits
|
||||||
|
==========
|
||||||
|
|
||||||
|
This option changes the view very starkly. This is the view shown in the picture associated with this topic. When View Bits is selected the display will change to show each bit within the bytes as separate blocks that each can separately be black when set and unchanged, white when unset and unchanged, red when freshly unset, and green when freshly set. This allows for a very fine grained view. Fade inactive, and never expire still work as usual. This mode might be a bit "busy" and lowers the number of IDs you can see at once. But, the choice is yours. You give up some density in exchange for verbosity.
|
||||||
|
|||||||
@@ -555,9 +555,9 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
|||||||
thisFrame.isReceived = true;
|
thisFrame.isReceived = true;
|
||||||
thisFrame.bus = 0;
|
thisFrame.bus = 0;
|
||||||
if (line.at(28) == ' ') {
|
if (line.at(28) == ' ') {
|
||||||
thisFrame.extended = true;
|
|
||||||
} else {
|
|
||||||
thisFrame.extended = false;
|
thisFrame.extended = false;
|
||||||
|
} else {
|
||||||
|
thisFrame.extended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.at(41) == 'R') {
|
if (line.at(41) == 'R') {
|
||||||
@@ -657,6 +657,8 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
|
|||||||
if (line.length() > 2)
|
if (line.length() > 2)
|
||||||
{
|
{
|
||||||
QList<QByteArray> tokens = line.simplified().split(' ');
|
QList<QByteArray> tokens = line.simplified().split(' ');
|
||||||
|
if (tokens.length() > 4)
|
||||||
|
{
|
||||||
thisFrame.timestamp = (uint32_t)(tokens[0].toFloat() * 1000000.0);
|
thisFrame.timestamp = (uint32_t)(tokens[0].toFloat() * 1000000.0);
|
||||||
thisFrame.ID = tokens[2].toUInt(NULL, 16);
|
thisFrame.ID = tokens[2].toUInt(NULL, 16);
|
||||||
thisFrame.len = tokens[5].toUInt();
|
thisFrame.len = tokens[5].toUInt();
|
||||||
@@ -676,6 +678,7 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
|
|||||||
foundErrors = true;
|
foundErrors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
frames->append(thisFrame);
|
frames->append(thisFrame);
|
||||||
}
|
}
|
||||||
//else foundErrors = true;
|
//else foundErrors = true;
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ FramePlaybackObject::FramePlaybackObject()
|
|||||||
playbackActive = false;
|
playbackActive = false;
|
||||||
playbackForward = true;
|
playbackForward = true;
|
||||||
useOrigTiming = false;
|
useOrigTiming = false;
|
||||||
whichBusSend = -1;
|
whichBusSend = 0;
|
||||||
|
currentSeqItem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramePlaybackObject::~FramePlaybackObject()
|
FramePlaybackObject::~FramePlaybackObject()
|
||||||
@@ -25,6 +26,12 @@ FramePlaybackObject::~FramePlaybackObject()
|
|||||||
quint64 FramePlaybackObject::updatePosition(bool forward)
|
quint64 FramePlaybackObject::updatePosition(bool forward)
|
||||||
{
|
{
|
||||||
//qDebug() << "updatePosition";
|
//qDebug() << "updatePosition";
|
||||||
|
if (!currentSeqItem) {
|
||||||
|
playbackTimer->stop(); //pushing this button halts automatic playback
|
||||||
|
playbackActive = false;
|
||||||
|
currentPosition = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (forward)
|
if (forward)
|
||||||
{
|
{
|
||||||
if (currentPosition < (currentSeqItem->data.count() - 1)) currentPosition++; //still in same file so keep going
|
if (currentPosition < (currentSeqItem->data.count() - 1)) currentPosition++; //still in same file so keep going
|
||||||
@@ -231,6 +238,7 @@ void FramePlaybackObject::stepPlaybackForward()
|
|||||||
playbackActive = false;
|
playbackActive = false;
|
||||||
updatePosition(true);
|
updatePosition(true);
|
||||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||||
|
emit statusUpdate(currentPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackObject::stepPlaybackBackward()
|
void FramePlaybackObject::stepPlaybackBackward()
|
||||||
@@ -248,6 +256,7 @@ void FramePlaybackObject::stepPlaybackBackward()
|
|||||||
|
|
||||||
updatePosition(false);
|
updatePosition(false);
|
||||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||||
|
emit statusUpdate(currentPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackObject::stopPlayback()
|
void FramePlaybackObject::stopPlayback()
|
||||||
@@ -262,6 +271,7 @@ void FramePlaybackObject::stopPlayback()
|
|||||||
playbackTimer->stop(); //pushing this button halts automatic playback
|
playbackTimer->stop(); //pushing this button halts automatic playback
|
||||||
playbackActive = false;
|
playbackActive = false;
|
||||||
currentPosition = 0;
|
currentPosition = 0;
|
||||||
|
emit statusUpdate(currentPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackObject::pausePlayback()
|
void FramePlaybackObject::pausePlayback()
|
||||||
@@ -275,6 +285,7 @@ void FramePlaybackObject::pausePlayback()
|
|||||||
|
|
||||||
playbackActive = false;
|
playbackActive = false;
|
||||||
playbackTimer->stop();
|
playbackTimer->stop();
|
||||||
|
emit statusUpdate(currentPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackObject::setSequenceObject(SequenceItem *item)
|
void FramePlaybackObject::setSequenceObject(SequenceItem *item)
|
||||||
@@ -289,6 +300,7 @@ void FramePlaybackObject::setUseOriginalTiming(bool state)
|
|||||||
|
|
||||||
void FramePlaybackObject::setSendingBus(int bus)
|
void FramePlaybackObject::setSendingBus(int bus)
|
||||||
{
|
{
|
||||||
|
qDebug() << "Setting sending bus to " << bus;
|
||||||
whichBusSend = bus;
|
whichBusSend = bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -296,9 +296,14 @@ void FramePlaybackWindow::calculateWhichBus()
|
|||||||
{
|
{
|
||||||
int idx = ui->comboCANBus->currentIndex();
|
int idx = ui->comboCANBus->currentIndex();
|
||||||
int maxIdx = ui->comboCANBus->count() - 1;
|
int maxIdx = ui->comboCANBus->count() - 1;
|
||||||
|
if (maxIdx == 0) maxIdx = 2;
|
||||||
int out = idx;
|
int out = idx;
|
||||||
|
|
||||||
|
qDebug() << idx << "***" << maxIdx;
|
||||||
|
|
||||||
if (idx == (maxIdx - 1) ) out = -1;
|
if (idx == (maxIdx - 1) ) out = -1;
|
||||||
if (idx == maxIdx) out = -2;
|
if (idx == maxIdx) out = -2;
|
||||||
|
if (idx < 0) out = 0;
|
||||||
|
|
||||||
playbackObject.setSendingBus(out);
|
playbackObject.setSendingBus(out);
|
||||||
}
|
}
|
||||||
@@ -534,6 +539,7 @@ void FramePlaybackWindow::btnReverseClick()
|
|||||||
forward = false;
|
forward = false;
|
||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
playbackObject.startPlaybackBackward();
|
playbackObject.startPlaybackBackward();
|
||||||
|
updateFrameLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::btnStopClick()
|
void FramePlaybackWindow::btnStopClick()
|
||||||
@@ -554,7 +560,6 @@ void FramePlaybackWindow::btnStopClick()
|
|||||||
ui->tblSequence->setCurrentCell(0, 0);
|
ui->tblSequence->setCurrentCell(0, 0);
|
||||||
refreshIDList();
|
refreshIDList();
|
||||||
}
|
}
|
||||||
updateFrameLabel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::btnPlayClick()
|
void FramePlaybackWindow::btnPlayClick()
|
||||||
|
|||||||
@@ -820,6 +820,8 @@ void FrameSenderWindow::processCellChange(int line, int col)
|
|||||||
|
|
||||||
sendingData[line].count = 0;
|
sendingData[line].count = 0;
|
||||||
|
|
||||||
|
int numBuses = CANConManager::getInstance()->getNumBuses();
|
||||||
|
|
||||||
switch (col)
|
switch (col)
|
||||||
{
|
{
|
||||||
case 0: //Enable check box
|
case 0: //Enable check box
|
||||||
@@ -832,8 +834,8 @@ void FrameSenderWindow::processCellChange(int line, int col)
|
|||||||
break;
|
break;
|
||||||
case 1: //Bus designation
|
case 1: //Bus designation
|
||||||
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 1)->text());
|
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 1)->text());
|
||||||
if (tempVal < 0) tempVal = 0;
|
if (tempVal < -1) tempVal = -1;
|
||||||
if (tempVal > 1) tempVal = 1;
|
if (tempVal >= numBuses) tempVal = numBuses - 1;
|
||||||
sendingData[line].bus = tempVal;
|
sendingData[line].bus = tempVal;
|
||||||
qDebug() << "Setting bus to " << tempVal;
|
qDebug() << "Setting bus to " << tempVal;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ HelpWindow* HelpWindow::getRef()
|
|||||||
void HelpWindow::showHelp(QString help)
|
void HelpWindow::showHelp(QString help)
|
||||||
{
|
{
|
||||||
if (m_helpEngine) {
|
if (m_helpEngine) {
|
||||||
QString url = "qthelp://org.sphinx.savvycan.181/doc/" + help;
|
QString url = "qthelp://org.sphinx.savvycan.189/doc/" + help;
|
||||||
qDebug() << "Searching for " << url;
|
qDebug() << "Searching for " << url;
|
||||||
QByteArray helpData = m_helpEngine->fileData(QUrl(url));
|
QByteArray helpData = m_helpEngine->fileData(QUrl(url));
|
||||||
qDebug() << "Help file size: " << helpData.length();
|
qDebug() << "Help file size: " << helpData.length();
|
||||||
|
|||||||
@@ -55,31 +55,34 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
|
|
||||||
readSettings();
|
readSettings();
|
||||||
|
|
||||||
|
QHeaderView *verticalHeader = ui->canFramesView->verticalHeader();
|
||||||
|
verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
|
||||||
|
verticalHeader->setDefaultSectionSize(10);
|
||||||
QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader();
|
QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader();
|
||||||
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
|
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
|
||||||
connect(HorzHdr, SIGNAL(sectionClicked(int)), this, SLOT(headerClicked(int)));
|
connect(HorzHdr, SIGNAL(sectionClicked(int)), this, SLOT(headerClicked(int)));
|
||||||
|
|
||||||
graphingWindow = NULL;
|
graphingWindow = nullptr;
|
||||||
frameInfoWindow = NULL;
|
frameInfoWindow = nullptr;
|
||||||
playbackWindow = NULL;
|
playbackWindow = nullptr;
|
||||||
flowViewWindow = NULL;
|
flowViewWindow = nullptr;
|
||||||
frameSenderWindow = NULL;
|
frameSenderWindow = nullptr;
|
||||||
dbcMainEditor = NULL;
|
dbcMainEditor = nullptr;
|
||||||
comparatorWindow = NULL;
|
comparatorWindow = nullptr;
|
||||||
settingsDialog = NULL;
|
settingsDialog = nullptr;
|
||||||
firmwareUploaderWindow = NULL;
|
firmwareUploaderWindow = nullptr;
|
||||||
discreteStateWindow = NULL;
|
discreteStateWindow = nullptr;
|
||||||
connectionWindow = NULL;
|
connectionWindow = nullptr;
|
||||||
scriptingWindow = NULL;
|
scriptingWindow = nullptr;
|
||||||
rangeWindow = NULL;
|
rangeWindow = nullptr;
|
||||||
dbcFileWindow = NULL;
|
dbcFileWindow = nullptr;
|
||||||
fuzzingWindow = NULL;
|
fuzzingWindow = nullptr;
|
||||||
udsScanWindow = NULL;
|
udsScanWindow = nullptr;
|
||||||
motorctrlConfigWindow = NULL;
|
motorctrlConfigWindow = nullptr;
|
||||||
isoWindow = NULL;
|
isoWindow = nullptr;
|
||||||
snifferWindow = NULL;
|
snifferWindow = nullptr;
|
||||||
bisectWindow = NULL;
|
bisectWindow = nullptr;
|
||||||
signalViewerWindow = NULL;
|
signalViewerWindow = nullptr;
|
||||||
dbcHandler = DBCHandler::getReference();
|
dbcHandler = DBCHandler::getReference();
|
||||||
bDirty = false;
|
bDirty = false;
|
||||||
inhibitFilterUpdate = false;
|
inhibitFilterUpdate = false;
|
||||||
@@ -160,6 +163,10 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
temp.bus = 0;
|
temp.bus = 0;
|
||||||
temp.ID = 0x100;
|
temp.ID = 0x100;
|
||||||
temp.len = 0;
|
temp.len = 0;
|
||||||
|
temp.extended = false;
|
||||||
|
temp.isReceived = true;
|
||||||
|
temp.remote = false;
|
||||||
|
temp.timestamp = 100000000;
|
||||||
model->addFrame(temp, true);
|
model->addFrame(temp, true);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
tickGUIUpdate(); //force a GUI refresh so that the row exists to measure
|
tickGUIUpdate(); //force a GUI refresh so that the row exists to measure
|
||||||
@@ -180,7 +187,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
ui->actionFirmware_Update->setVisible(false);
|
ui->actionFirmware_Update->setVisible(false);
|
||||||
ui->actionMotorControlConfig->setVisible(false);
|
ui->actionMotorControlConfig->setVisible(false);
|
||||||
ui->actionSignal_Viewer->setVisible(false);
|
ui->actionSignal_Viewer->setVisible(false);
|
||||||
//ui->actionSingle_Multi_State_2->setVisible(false);
|
ui->actionSingle_Multi_State_2->setVisible(false);
|
||||||
|
|
||||||
installEventFilter(this);
|
installEventFilter(this);
|
||||||
}
|
}
|
||||||
@@ -293,7 +300,7 @@ void MainWindow::readSettings()
|
|||||||
ui->canFramesView->setColumnWidth(5, settings.value("Main/BusColumn", 40).toUInt()); //bus
|
ui->canFramesView->setColumnWidth(5, settings.value("Main/BusColumn", 40).toUInt()); //bus
|
||||||
ui->canFramesView->setColumnWidth(6, settings.value("Main/LengthColumn", 40).toUInt()); //length
|
ui->canFramesView->setColumnWidth(6, settings.value("Main/LengthColumn", 40).toUInt()); //length
|
||||||
ui->canFramesView->setColumnWidth(7, settings.value("Main/AsciiColumn", 50).toUInt()); //ascii
|
ui->canFramesView->setColumnWidth(7, settings.value("Main/AsciiColumn", 50).toUInt()); //ascii
|
||||||
ui->canFramesView->setColumnWidth(8, settings.value("Main/DataColumn", 225).toUInt()); //data
|
//ui->canFramesView->setColumnWidth(8, settings.value("Main/DataColumn", 225).toUInt()); //data
|
||||||
}
|
}
|
||||||
if (settings.value("Main/AutoScroll", false).toBool())
|
if (settings.value("Main/AutoScroll", false).toBool())
|
||||||
{
|
{
|
||||||
@@ -338,7 +345,7 @@ void MainWindow::writeSettings()
|
|||||||
settings.setValue("Main/BusColumn", ui->canFramesView->columnWidth(5));
|
settings.setValue("Main/BusColumn", ui->canFramesView->columnWidth(5));
|
||||||
settings.setValue("Main/LengthColumn", ui->canFramesView->columnWidth(6));
|
settings.setValue("Main/LengthColumn", ui->canFramesView->columnWidth(6));
|
||||||
settings.setValue("Main/AsciiColumn", ui->canFramesView->columnWidth(7));
|
settings.setValue("Main/AsciiColumn", ui->canFramesView->columnWidth(7));
|
||||||
settings.setValue("Main/DataColumn", ui->canFramesView->columnWidth(8));
|
//settings.setValue("Main/DataColumn", ui->canFramesView->columnWidth(8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,12 +394,23 @@ void MainWindow::gridDoubleClicked(QModelIndex idx)
|
|||||||
void MainWindow::interpretToggled(bool state)
|
void MainWindow::interpretToggled(bool state)
|
||||||
{
|
{
|
||||||
model->setInterpetMode(state);
|
model->setInterpetMode(state);
|
||||||
|
//ui->canFramesView->resizeRowsToContents(); //a VERY costly operation!
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::overwriteToggled(bool state)
|
void MainWindow::overwriteToggled(bool state)
|
||||||
|
{
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
QMessageBox::StandardButton confirmDialog;
|
||||||
|
confirmDialog = QMessageBox::question(this, "Danger Will Robinson", "Enabling Overwrite mode will\ndelete your captured frames\nand replace them with one\nframe per ID.\n\nAre you ready to do that?",
|
||||||
|
QMessageBox::Yes|QMessageBox::No);
|
||||||
|
if (confirmDialog == QMessageBox::Yes)
|
||||||
{
|
{
|
||||||
model->setOverwriteMode(state);
|
model->setOverwriteMode(state);
|
||||||
}
|
}
|
||||||
|
else ui->cbOverwrite->setCheckState(Qt::Unchecked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::updateFilterList()
|
void MainWindow::updateFilterList()
|
||||||
{
|
{
|
||||||
@@ -466,7 +484,7 @@ void MainWindow::tickGUIUpdate()
|
|||||||
framesPerSec = 0;
|
framesPerSec = 0;
|
||||||
|
|
||||||
ui->lbNumFrames->setText(QString::number(model->rowCount()));
|
ui->lbNumFrames->setText(QString::number(model->rowCount()));
|
||||||
if (allowCapture && ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom();
|
if (rxFrames > 0 && /*allowCapture && */ ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom();
|
||||||
ui->lbFPS->setText(QString::number(framesPerSec));
|
ui->lbFPS->setText(QString::number(framesPerSec));
|
||||||
if (rxFrames > 0)
|
if (rxFrames > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
#include "helpwindow.h"
|
#include "helpwindow.h"
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
|
const QColor FrameInfoWindow::byteGraphColors[8] = {Qt::blue, Qt::green, Qt::black, Qt::red, //0 1 2 3
|
||||||
|
Qt::gray, Qt::yellow, Qt::cyan, Qt::darkMagenta}; //4 5 6 7
|
||||||
|
QPen FrameInfoWindow::bytePens[8];
|
||||||
|
|
||||||
FrameInfoWindow::FrameInfoWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
FrameInfoWindow::FrameInfoWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::FrameInfoWindow)
|
ui(new Ui::FrameInfoWindow)
|
||||||
@@ -32,19 +36,40 @@ FrameInfoWindow::FrameInfoWindow(const QVector<CANFrame> *frames, QWidget *paren
|
|||||||
|
|
||||||
ui->graphHistogram->legend->setVisible(false);
|
ui->graphHistogram->legend->setVisible(false);
|
||||||
|
|
||||||
|
ui->graphBytes->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
|
||||||
|
QCP::iSelectLegend | QCP::iSelectPlottables);
|
||||||
|
|
||||||
|
ui->graphBytes->xAxis->setRange(0, 63);
|
||||||
|
ui->graphBytes->yAxis->setRange(0, 265);
|
||||||
|
ui->graphBytes->axisRect()->setupFullAxesBox();
|
||||||
|
|
||||||
|
ui->graphBytes->xAxis->setLabel("Time");
|
||||||
|
ui->graphBytes->yAxis->setLabel("Value");
|
||||||
|
|
||||||
|
ui->graphBytes->legend->setVisible(false);
|
||||||
|
|
||||||
if (useOpenGL)
|
if (useOpenGL)
|
||||||
{
|
{
|
||||||
ui->graphHistogram->setAntialiasedElements(QCP::aeAll);
|
ui->graphHistogram->setAntialiasedElements(QCP::aeAll);
|
||||||
//ui->graphingView->setNoAntialiasingOnDrag(true);
|
|
||||||
ui->graphHistogram->setOpenGl(true);
|
ui->graphHistogram->setOpenGl(true);
|
||||||
|
ui->graphBytes->setAntialiasedElements(QCP::aeAll);
|
||||||
|
ui->graphBytes->setOpenGl(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ui->graphHistogram->setOpenGl(false);
|
ui->graphHistogram->setOpenGl(false);
|
||||||
ui->graphHistogram->setAntialiasedElements(QCP::aeNone);
|
ui->graphHistogram->setAntialiasedElements(QCP::aeNone);
|
||||||
|
ui->graphBytes->setOpenGl(false);
|
||||||
|
ui->graphBytes->setAntialiasedElements(QCP::aeNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
installEventFilter(this);
|
installEventFilter(this);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
bytePens[i].setColor(byteGraphColors[i]);
|
||||||
|
bytePens[i].setWidth(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameInfoWindow::showEvent(QShowEvent* event)
|
void FrameInfoWindow::showEvent(QShowEvent* event)
|
||||||
@@ -94,7 +119,7 @@ void FrameInfoWindow::readSettings()
|
|||||||
QSettings settings;
|
QSettings settings;
|
||||||
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||||
{
|
{
|
||||||
resize(settings.value("FrameInfo/WindowSize", QSize(794, 494)).toSize());
|
resize(settings.value("FrameInfo/WindowSize", QSize(794, 694)).toSize());
|
||||||
move(settings.value("FrameInfo/WindowPos", QPoint(50, 50)).toPoint());
|
move(settings.value("FrameInfo/WindowPos", QPoint(50, 50)).toPoint());
|
||||||
}
|
}
|
||||||
useOpenGL = settings.value("Main/UseOpenGL", false).toBool();
|
useOpenGL = settings.value("Main/UseOpenGL", false).toBool();
|
||||||
@@ -188,7 +213,8 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
int maxData[8];
|
int maxData[8];
|
||||||
int dataHistogram[256][8];
|
int dataHistogram[256][8];
|
||||||
int bitfieldHistogram[64];
|
int bitfieldHistogram[64];
|
||||||
QVector<double> graphX, graphY;
|
QVector<double> histGraphX, histGraphY;
|
||||||
|
QVector<double> byteGraphX, byteGraphY[8];
|
||||||
double maxY = -1000.0;
|
double maxY = -1000.0;
|
||||||
uint8_t changedBits[8];
|
uint8_t changedBits[8];
|
||||||
uint8_t referenceBits[8];
|
uint8_t referenceBits[8];
|
||||||
@@ -248,7 +274,7 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
baseNode->addChild(tempItem);
|
baseNode->addChild(tempItem);
|
||||||
|
|
||||||
tempItem = new QTreeWidgetItem();
|
tempItem = new QTreeWidgetItem();
|
||||||
tempItem->setText(0, tr("PGN: ") + Utility::formatNumber(jid.pgn));
|
tempItem->setText(0, tr("PGN: ") + Utility::formatNumber(jid.pgn) + "(" + QString::number(jid.pgn) + ")");
|
||||||
baseNode->addChild(tempItem);
|
baseNode->addChild(tempItem);
|
||||||
|
|
||||||
tempItem = new QTreeWidgetItem();
|
tempItem = new QTreeWidgetItem();
|
||||||
@@ -287,6 +313,12 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
//then find all data points
|
//then find all data points
|
||||||
for (int j = 0; j < frameCache.count(); j++)
|
for (int j = 0; j < frameCache.count(); j++)
|
||||||
{
|
{
|
||||||
|
byteGraphX.append(j);
|
||||||
|
for (int bytcnt = 0; bytcnt < frameCache[j].len; bytcnt++)
|
||||||
|
{
|
||||||
|
byteGraphY[bytcnt].append(frameCache[j].data[bytcnt]);
|
||||||
|
}
|
||||||
|
|
||||||
if (j != 0)
|
if (j != 0)
|
||||||
{
|
{
|
||||||
thisInterval = (frameCache[j].timestamp - frameCache[j-1].timestamp);
|
thisInterval = (frameCache[j].timestamp - frameCache[j-1].timestamp);
|
||||||
@@ -381,16 +413,17 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
+ QString::number(c % 8) + ") :" + QString::number(bitfieldHistogram[c]));
|
+ QString::number(c % 8) + ") :" + QString::number(bitfieldHistogram[c]));
|
||||||
|
|
||||||
dataBase->addChild(tempItem);
|
dataBase->addChild(tempItem);
|
||||||
graphX.append(c);
|
histGraphX.append(c);
|
||||||
graphY.append(bitfieldHistogram[c]);
|
histGraphY.append(bitfieldHistogram[c]);
|
||||||
if (bitfieldHistogram[c] > maxY) maxY = bitfieldHistogram[c];
|
if (bitfieldHistogram[c] > maxY) maxY = bitfieldHistogram[c];
|
||||||
}
|
}
|
||||||
baseNode->addChild(dataBase);
|
baseNode->addChild(dataBase);
|
||||||
|
|
||||||
ui->treeDetails->insertTopLevelItem(0, baseNode);
|
ui->treeDetails->insertTopLevelItem(0, baseNode);
|
||||||
|
|
||||||
ui->graphHistogram->clearGraphs();
|
ui->graphHistogram->clearGraphs();
|
||||||
ui->graphHistogram->addGraph();
|
ui->graphHistogram->addGraph();
|
||||||
ui->graphHistogram->graph()->setData(graphX, graphY);
|
ui->graphHistogram->graph()->setData(histGraphX, histGraphY);
|
||||||
ui->graphHistogram->graph()->setLineStyle(QCPGraph::lsStepLeft); //connect points with lines
|
ui->graphHistogram->graph()->setLineStyle(QCPGraph::lsStepLeft); //connect points with lines
|
||||||
QBrush graphBrush;
|
QBrush graphBrush;
|
||||||
graphBrush.setColor(Qt::red);
|
graphBrush.setColor(Qt::red);
|
||||||
@@ -400,6 +433,16 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
ui->graphHistogram->yAxis->setRange(0, maxY * 1.02);
|
ui->graphHistogram->yAxis->setRange(0, maxY * 1.02);
|
||||||
ui->graphHistogram->axisRect()->setupFullAxesBox();
|
ui->graphHistogram->axisRect()->setupFullAxesBox();
|
||||||
ui->graphHistogram->replot();
|
ui->graphHistogram->replot();
|
||||||
|
|
||||||
|
ui->graphBytes->clearGraphs();
|
||||||
|
for (int graphs = 0; graphs < 8; graphs++)
|
||||||
|
{
|
||||||
|
ui->graphBytes->addGraph();
|
||||||
|
ui->graphBytes->graph()->setData(byteGraphX, byteGraphY[graphs]);
|
||||||
|
ui->graphBytes->graph()->setPen(bytePens[graphs]);
|
||||||
|
}
|
||||||
|
ui->graphBytes->xAxis->setRange(0, byteGraphX.count());
|
||||||
|
ui->graphBytes->replot();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ private:
|
|||||||
QList<CANFrame> frameCache;
|
QList<CANFrame> frameCache;
|
||||||
const QVector<CANFrame> *modelFrames;
|
const QVector<CANFrame> *modelFrames;
|
||||||
bool useOpenGL;
|
bool useOpenGL;
|
||||||
|
static const QColor byteGraphColors[8];
|
||||||
|
static QPen bytePens[8];
|
||||||
|
|
||||||
void refreshIDList();
|
void refreshIDList();
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
|
|||||||
@@ -696,7 +696,7 @@ void GraphingWindow::saveSpreadsheet()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
QList<GraphParams>::iterator iter;
|
QList<GraphParams>::iterator iter;
|
||||||
double xMin = 1000000000, xMax=-1000000000;
|
double xMin = 10000000000000, xMax=-10000000000000;
|
||||||
int maxCount = 0;
|
int maxCount = 0;
|
||||||
int numGraphs = 0;
|
int numGraphs = 0;
|
||||||
for (iter = graphParams.begin(); iter != graphParams.end(); ++iter)
|
for (iter = graphParams.begin(); iter != graphParams.end(); ++iter)
|
||||||
@@ -732,6 +732,7 @@ void GraphingWindow::saveSpreadsheet()
|
|||||||
for (int j = 1; j < (maxCount - 1); j++)
|
for (int j = 1; j < (maxCount - 1); j++)
|
||||||
{
|
{
|
||||||
currentX = xMin + (j * sliceSize);
|
currentX = xMin + (j * sliceSize);
|
||||||
|
qDebug() << "X: " << currentX;
|
||||||
outFile->write(QString::number(currentX).toUtf8());
|
outFile->write(QString::number(currentX).toUtf8());
|
||||||
for (int k = 0; k < graphParams.count(); k++)
|
for (int k = 0; k < graphParams.count(); k++)
|
||||||
{
|
{
|
||||||
@@ -764,9 +765,10 @@ void GraphingWindow::saveSpreadsheet()
|
|||||||
double span = graphParams[k].x[indices[k] + 1] - graphParams[k].x[indices[k]];
|
double span = graphParams[k].x[indices[k] + 1] - graphParams[k].x[indices[k]];
|
||||||
double progress = (currentX - graphParams[k].x[indices[k]]) / span;
|
double progress = (currentX - graphParams[k].x[indices[k]]) / span;
|
||||||
value = Utility::Lerp(graphParams[k].y[indices[k]], graphParams[k].y[indices[k] + 1], progress);
|
value = Utility::Lerp(graphParams[k].y[indices[k]], graphParams[k].y[indices[k] + 1], progress);
|
||||||
|
qDebug() << "Span: " << span << " Prog: " << progress << " Value: " << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentX >= graphParams[k].x[indices[k] + 1]) indices[k]++;
|
if (currentX >= graphParams[k].x[indices[k]]) indices[k]++;
|
||||||
|
|
||||||
outFile->putChar(',');
|
outFile->putChar(',');
|
||||||
outFile->write(QString::number(value).toUtf8());
|
outFile->write(QString::number(value).toUtf8());
|
||||||
@@ -845,7 +847,7 @@ void GraphingWindow::loadDefinitions()
|
|||||||
QStringList filters;
|
QStringList filters;
|
||||||
filters.append(QString(tr("Graph definition (*.gdf)")));
|
filters.append(QString(tr("Graph definition (*.gdf)")));
|
||||||
|
|
||||||
if (dbcHandler == NULL) return;
|
if (dbcHandler == nullptr) return;
|
||||||
if (dbcHandler->getFileCount() == 0) dbcHandler->createBlankFile();
|
if (dbcHandler->getFileCount() == 0) dbcHandler->createBlankFile();
|
||||||
|
|
||||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
@@ -871,10 +873,13 @@ void GraphingWindow::loadDefinitions()
|
|||||||
|
|
||||||
if (tokens[0] == "X") //newest format based around signals
|
if (tokens[0] == "X") //newest format based around signals
|
||||||
{
|
{
|
||||||
gp.ID = tokens[1].toInt(NULL, 16);
|
gp.ID = tokens[1].toUInt(nullptr, 16);
|
||||||
gp.mask = tokens[2].toULongLong(NULL, 16);
|
gp.mask = tokens[2].toULongLong(nullptr, 16);
|
||||||
gp.startBit = tokens[3].toInt();
|
gp.startBit = tokens[3].toInt();
|
||||||
if (gp.startBit < 0) gp.intelFormat = false;
|
if (gp.startBit < 0) {
|
||||||
|
gp.intelFormat = false;
|
||||||
|
gp.startBit *= -1;
|
||||||
|
}
|
||||||
else gp.intelFormat = true;
|
else gp.intelFormat = true;
|
||||||
gp.numBits = tokens[4].toInt();
|
gp.numBits = tokens[4].toInt();
|
||||||
if (tokens[5] == "Y") gp.isSigned = true;
|
if (tokens[5] == "Y") gp.isSigned = true;
|
||||||
@@ -894,18 +899,18 @@ void GraphingWindow::loadDefinitions()
|
|||||||
}
|
}
|
||||||
else //one of the two older formats then
|
else //one of the two older formats then
|
||||||
{
|
{
|
||||||
gp.ID = tokens[0].toInt(NULL, 16);
|
gp.ID = tokens[0].toUInt(nullptr, 16);
|
||||||
if (tokens[1] == "S") //old signal based graph definition
|
if (tokens[1] == "S") //old signal based graph definition
|
||||||
{
|
{
|
||||||
//tokens[2] is the signal name. Need to use the message ID and this name to look it up
|
//tokens[2] is the signal name. Need to use the message ID and this name to look it up
|
||||||
DBC_MESSAGE *msg = dbcHandler->getFileByIdx(0)->messageHandler->findMsgByID(gp.ID);
|
DBC_MESSAGE *msg = dbcHandler->getFileByIdx(0)->messageHandler->findMsgByID(gp.ID);
|
||||||
if (msg != NULL)
|
if (msg != nullptr)
|
||||||
{
|
{
|
||||||
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(tokens[2]);
|
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(tokens[2]);
|
||||||
if (sig)
|
if (sig)
|
||||||
{
|
{
|
||||||
gp.mask = 0xFFFFFFFF;
|
gp.mask = 0xFFFFFFFF;
|
||||||
gp.bias = sig->bias;
|
gp.bias = (float)sig->bias;
|
||||||
gp.color.setRed(tokens[3].toInt());
|
gp.color.setRed(tokens[3].toInt());
|
||||||
gp.color.setGreen(tokens[4].toInt());
|
gp.color.setGreen(tokens[4].toInt());
|
||||||
gp.color.setBlue(tokens[5].toInt());
|
gp.color.setBlue(tokens[5].toInt());
|
||||||
@@ -914,7 +919,7 @@ void GraphingWindow::loadDefinitions()
|
|||||||
if (sig->valType == SIGNED_INT) gp.isSigned = true;
|
if (sig->valType == SIGNED_INT) gp.isSigned = true;
|
||||||
else gp.isSigned = false;
|
else gp.isSigned = false;
|
||||||
gp.numBits = sig->signalSize;
|
gp.numBits = sig->signalSize;
|
||||||
gp.scale = sig->factor;
|
gp.scale = (float)sig->factor;
|
||||||
gp.startBit = sig->startBit;
|
gp.startBit = sig->startBit;
|
||||||
gp.stride = 1;
|
gp.stride = 1;
|
||||||
createGraph(gp, true);
|
createGraph(gp, true);
|
||||||
@@ -926,7 +931,7 @@ void GraphingWindow::loadDefinitions()
|
|||||||
//hard part - this all changed drastically
|
//hard part - this all changed drastically
|
||||||
//the difference between intel and motorola format is whether
|
//the difference between intel and motorola format is whether
|
||||||
//start is larger than end byte or not.
|
//start is larger than end byte or not.
|
||||||
uint64_t oldMask = tokens[1].toULongLong(NULL, 16);
|
uint64_t oldMask = tokens[1].toULongLong(nullptr, 16);
|
||||||
int oldStart = tokens[2].toInt();
|
int oldStart = tokens[2].toInt();
|
||||||
int oldEnd = tokens[3].toInt();
|
int oldEnd = tokens[3].toInt();
|
||||||
|
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ void ISOTP_InterpreterWindow::updatedFrames(int numFrames)
|
|||||||
|
|
||||||
void ISOTP_InterpreterWindow::headerClicked(int logicalIndex)
|
void ISOTP_InterpreterWindow::headerClicked(int logicalIndex)
|
||||||
{
|
{
|
||||||
|
ui->tableIsoFrames->setSortingEnabled(false);
|
||||||
ui->tableIsoFrames->sortByColumn(logicalIndex);
|
ui->tableIsoFrames->sortByColumn(logicalIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,9 +262,13 @@ void ISOTP_InterpreterWindow::newISOMessage(ISOTP_MESSAGE msg)
|
|||||||
messages.append(msg);
|
messages.append(msg);
|
||||||
|
|
||||||
rowNum = ui->tableIsoFrames->rowCount();
|
rowNum = ui->tableIsoFrames->rowCount();
|
||||||
|
|
||||||
ui->tableIsoFrames->insertRow(rowNum);
|
ui->tableIsoFrames->insertRow(rowNum);
|
||||||
|
|
||||||
ui->tableIsoFrames->setItem(rowNum, 0, new QTableWidgetItem(Utility::formatTimestamp(msg.timestamp)));
|
QTableWidgetItem *item = new QTableWidgetItem;
|
||||||
|
item->setData(Qt::EditRole, Utility::formatTimestamp(msg.timestamp));
|
||||||
|
//ui->tableIsoFrames->setItem(rowNum, 0, (double)msg.timestamp, Utility::formatTimestamp(msg.timestamp)));
|
||||||
|
ui->tableIsoFrames->setItem(rowNum, 0, item);
|
||||||
ui->tableIsoFrames->setItem(rowNum, 1, new QTableWidgetItem(QString::number(msg.ID, 16)));
|
ui->tableIsoFrames->setItem(rowNum, 1, new QTableWidgetItem(QString::number(msg.ID, 16)));
|
||||||
ui->tableIsoFrames->setItem(rowNum, 2, new QTableWidgetItem(QString::number(msg.bus)));
|
ui->tableIsoFrames->setItem(rowNum, 2, new QTableWidgetItem(QString::number(msg.bus)));
|
||||||
if (msg.isReceived) ui->tableIsoFrames->setItem(rowNum, 3, new QTableWidgetItem("Rx"));
|
if (msg.isReceived) ui->tableIsoFrames->setItem(rowNum, 3, new QTableWidgetItem("Rx"));
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
#include "SnifferDelegate.h"
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "utility.h"
|
||||||
|
#include "re/sniffer/snifferitem.h"
|
||||||
|
|
||||||
|
SnifferDelegate::SnifferDelegate(QWidget *parent) : QItemDelegate(parent)
|
||||||
|
{
|
||||||
|
blackBrush = QBrush(Qt::black);
|
||||||
|
whiteBrush = QBrush(Qt::white);
|
||||||
|
redBrush = QBrush(Qt::red);
|
||||||
|
greenBrush = QBrush(Qt::green);
|
||||||
|
grayBrush = QBrush(QColor(230,230,230));
|
||||||
|
mainFont.setPointSize(10);
|
||||||
|
mainFontInfo = new QFontInfo(mainFont);
|
||||||
|
mFadeInactive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SnifferDelegate::getFadeInactive()
|
||||||
|
{
|
||||||
|
return mFadeInactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnifferDelegate::setFadeInactive(bool val)
|
||||||
|
{
|
||||||
|
mFadeInactive = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnifferDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
//qDebug() << "SnifferDelegate Paint Event";
|
||||||
|
|
||||||
|
if (index.column() < 2) //allow default handling of the first two columns
|
||||||
|
{
|
||||||
|
QItemDelegate::paint(painter, option, index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index.column() > 9) return;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
SnifferItem *item = static_cast<SnifferItem*>(index.internalPointer());
|
||||||
|
int idx = index.column() - 2;
|
||||||
|
int val = item->getData(idx);
|
||||||
|
int prevVal = item->getLastData(idx);
|
||||||
|
int notchPattern = item->getNotchPattern(idx);
|
||||||
|
int maskPattern;
|
||||||
|
if (val < 0) return;
|
||||||
|
|
||||||
|
QRect viewport = option.rect;
|
||||||
|
|
||||||
|
int xSpan = viewport.right() - viewport.left();
|
||||||
|
int ySpan = viewport.bottom() - viewport.top();
|
||||||
|
int yOffset = (ySpan - (xSpan / 4)) / 2;
|
||||||
|
if (yOffset < 0) yOffset = 0;
|
||||||
|
|
||||||
|
//qDebug() << "XSpan" << xSpan << " YSpan " << ySpan;
|
||||||
|
|
||||||
|
int xSector = xSpan / 8;
|
||||||
|
int v = item->getSeqInterval(index.column() - 2) * 10;
|
||||||
|
if (v > 225) v = 225;
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
|
||||||
|
for (x = 0; x < 8; x++)
|
||||||
|
{
|
||||||
|
maskPattern = 1 << (7-x);
|
||||||
|
//We look to see if each bit has changed since the last update or not. If not we
|
||||||
|
//straight draw it black if set or white if unset. If it changed then draw it green if it is newly set
|
||||||
|
//and red if newly unset
|
||||||
|
//But also, if a bit is notched we just plain draw it gray no matter what it's doing
|
||||||
|
if (notchPattern & maskPattern)
|
||||||
|
{
|
||||||
|
painter->setBrush(grayBrush);
|
||||||
|
}
|
||||||
|
else if ( (val & maskPattern) == (prevVal & maskPattern) ) //wasn't notched so has it changed? No? Then...
|
||||||
|
{
|
||||||
|
if (val & maskPattern)
|
||||||
|
{
|
||||||
|
painter->setBrush(blackBrush);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
painter->setBrush(whiteBrush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //wasn't notched and did change since last time.
|
||||||
|
{
|
||||||
|
if (val & maskPattern)
|
||||||
|
{
|
||||||
|
painter->setBrush(greenBrush);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
painter->setBrush(redBrush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mFadeInactive) painter->setOpacity((255 - v) / 255.0);
|
||||||
|
else painter->setOpacity(1.0);
|
||||||
|
painter->drawRect(viewport.left() + x * xSector, viewport.top() + yOffset, xSector, xSector);
|
||||||
|
}
|
||||||
|
|
||||||
|
//painter->setPen(QPen(QColor(v,v,v,255)));
|
||||||
|
painter->setOpacity(1.0);
|
||||||
|
painter->setPen(Qt::black);
|
||||||
|
painter->setFont(mainFont);
|
||||||
|
painter->drawText(QRect(viewport.left(), viewport.top() + xSector + yOffset, xSpan, mainFontInfo->pixelSize()), Qt::AlignCenter, Utility::formatNumber(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize SnifferDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QSize origSize = QItemDelegate::sizeHint(option, index);
|
||||||
|
origSize.setHeight(origSize.height() * 2.0);
|
||||||
|
return origSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef SNIFFERDELEGATE_H
|
||||||
|
#define SNIFFERDELEGATE_H
|
||||||
|
|
||||||
|
#include <QItemDelegate>
|
||||||
|
|
||||||
|
class SnifferDelegate : public QItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SnifferDelegate(QWidget *parent = nullptr);
|
||||||
|
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||||
|
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||||
|
bool getFadeInactive();
|
||||||
|
void setFadeInactive(bool val);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
private:
|
||||||
|
QBrush blackBrush, whiteBrush, redBrush, greenBrush, grayBrush;
|
||||||
|
QFont mainFont;
|
||||||
|
QFontInfo* mainFontInfo;
|
||||||
|
bool mFadeInactive;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,15 +3,21 @@
|
|||||||
#include "snifferitem.h"
|
#include "snifferitem.h"
|
||||||
|
|
||||||
|
|
||||||
SnifferItem::SnifferItem(const CANFrame& pFrame):
|
SnifferItem::SnifferItem(const CANFrame& pFrame, quint32 seq):
|
||||||
mNotch(0),
|
|
||||||
mID(pFrame.ID)
|
mID(pFrame.ID)
|
||||||
{
|
{
|
||||||
mMarker = {0,0};
|
for (int i = 0; i < 8; i++) {
|
||||||
mLastMarker = {0,0};
|
mNotch[i] =0;
|
||||||
|
mMarker.data[i] = 0;
|
||||||
|
mMarker.dataTimestamp[i] = 0;
|
||||||
|
mCurrent.data[i] = pFrame.data[i];
|
||||||
|
mCurrent.dataTimestamp[i] = seq;
|
||||||
|
}
|
||||||
|
mLastMarker = mMarker;
|
||||||
|
mCurrent.len = pFrame.len;
|
||||||
/* that's dirty */
|
/* that's dirty */
|
||||||
update(pFrame);
|
update(pFrame, seq, false);
|
||||||
update(pFrame);
|
update(pFrame, seq, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -30,57 +36,124 @@ float SnifferItem::getDelta() const
|
|||||||
return ((float)(mCurrentTime-mLastTime))/1000000;
|
return ((float)(mCurrentTime-mLastTime))/1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Get a data byte by index 0-7 (but not more than the length of the actual frame)
|
||||||
int SnifferItem::getData(uchar i) const
|
int SnifferItem::getData(uchar i) const
|
||||||
{
|
{
|
||||||
return (i>=mCurrent.len) ? -1 : ((uchar*) &mCurrent.data)[i];
|
return (i >= mCurrent.len) ? -1 : mCurrent.data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint8 SnifferItem::getNotchPattern(uchar i) const
|
||||||
|
{
|
||||||
|
return (i >= mCurrent.len) ? -1 : mNotch[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
quint8 SnifferItem::getLastData(uchar i) const
|
||||||
|
{
|
||||||
|
return (i >= mLast.len) ? -1 : mLast.data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 SnifferItem::getDataTimestamp(uchar i) const
|
||||||
|
{
|
||||||
|
return (i >= mCurrent.len) ? 0 : mCurrent.dataTimestamp[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 SnifferItem::getSeqInterval(uchar i) const
|
||||||
|
{
|
||||||
|
return mCurrSeqVal - getDataTimestamp(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return whether a given data byte (by index 0-7) has incremented, deincremented, or stayed the same
|
||||||
|
//since the last message
|
||||||
|
//The If checks first that we aren't past the actual data length
|
||||||
|
// then checks whether lastMarker shows that some bits have changed in the previous 200ms cycle
|
||||||
|
// then we check if the byte in mNotch has bits set and if it does we say nothing changed (notched out)
|
||||||
dc SnifferItem::dataChange(uchar i) const
|
dc SnifferItem::dataChange(uchar i) const
|
||||||
{
|
{
|
||||||
if( i<mCurrent.len &&
|
if (i >= mCurrent.len) return dc::NO;
|
||||||
((uchar*) &mLastMarker.data)[i] &&
|
|
||||||
!((uchar*) &mNotch)[i] )
|
uchar notch = mNotch[i];
|
||||||
|
uchar byt = mCurrent.data[i];
|
||||||
|
uchar last = mLast.data[i];
|
||||||
|
uchar lastMark = mLastMarker.data[i];
|
||||||
|
if( lastMark )
|
||||||
{
|
{
|
||||||
return ((uchar*) &mCurrent.data)[i] >= ((uchar*) &mLast.data)[i] ? dc::INC : dc::DEINC;
|
if (!notch) //if no notching is set
|
||||||
|
return (byt >= last ? dc::INC : dc::DEINC);
|
||||||
|
else //mNotch contained a bit pattern so use masks and do things more complicated
|
||||||
|
{
|
||||||
|
byt &= ~notch; //mask off bits that were notched
|
||||||
|
if (byt == 0) return dc::NO; //and if result is null then nothing changed (other than maybe notched bits and they don't count)
|
||||||
|
last &= ~notch; //need to mask last too
|
||||||
|
if (last == byt) return dc::NO;
|
||||||
|
return (byt >= last ? dc::INC : dc::DEINC); //then compare the masked copies to see which way the bit(s) went
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dc::NO;
|
return dc::NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int SnifferItem::elapsed() const
|
int SnifferItem::elapsed() const
|
||||||
{
|
{
|
||||||
return mTime.elapsed();
|
return mTime.elapsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SnifferItem::update(const CANFrame& pFrame)
|
//called when a new frame comes in that matches our same ID
|
||||||
|
//timeSeq is stored so we can figure out the last time a specific byte was updated
|
||||||
|
//mute is used to specify whether to mask the byte against the notching filter
|
||||||
|
//in order to hide any updates of the notched bits. This is toggleable
|
||||||
|
void SnifferItem::update(const CANFrame& pFrame, quint32 timeSeq, bool mute)
|
||||||
{
|
{
|
||||||
|
unsigned char maskedCurr, maskedData;
|
||||||
|
//qDebug() << "update with ts: " << timeSeq;
|
||||||
/* copy current to last */
|
/* copy current to last */
|
||||||
mLast = mCurrent;
|
mLast = mCurrent;
|
||||||
mLastTime = mCurrentTime;
|
mLastTime = mCurrentTime;
|
||||||
|
mCurrSeqVal = timeSeq;
|
||||||
|
|
||||||
/* copy new value */
|
/* copy new value */
|
||||||
memcpy(&mCurrent.data, pFrame.data, 8);
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
maskedData = pFrame.data[i];
|
||||||
|
if (mute) maskedData &= ~mNotch[i];
|
||||||
|
maskedCurr = mCurrent.data[i];
|
||||||
|
if (mute) maskedCurr &= ~mNotch[i];
|
||||||
|
if (maskedCurr != maskedData)
|
||||||
|
{
|
||||||
|
mCurrent.data[i] = pFrame.data[i];
|
||||||
|
mCurrent.dataTimestamp[i] = timeSeq;
|
||||||
|
}
|
||||||
|
}
|
||||||
mCurrent.len = pFrame.len;
|
mCurrent.len = pFrame.len;
|
||||||
mCurrentTime = pFrame.timestamp;
|
mCurrentTime = pFrame.timestamp;
|
||||||
|
|
||||||
/* update marker */
|
/* update marker */
|
||||||
mMarker.data |= mLast.data ^ mCurrent.data;
|
//We "OR" our stored marker with the changed bits.
|
||||||
|
//this accumulates changed bits into the marker
|
||||||
|
for (int i = 0 ; i < 8; i++) mMarker.data[i] |= mLast.data[i] ^ mCurrent.data[i]; //XOR causes only changed bits to be 1's
|
||||||
mMarker.len |= mLast.len ^ mCurrent.len;
|
mMarker.len |= mLast.len ^ mCurrent.len;
|
||||||
|
|
||||||
/* restart timeout */
|
/* restart timeout */
|
||||||
mTime.restart();
|
mTime.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Called in refresh from the model. Interval about 200ms currently.
|
||||||
|
//So, this means the marker only accumulates for 200ms then resets
|
||||||
void SnifferItem::updateMarker()
|
void SnifferItem::updateMarker()
|
||||||
{
|
{
|
||||||
mLastMarker = mMarker;
|
mLastMarker = mMarker;
|
||||||
mMarker = {0, 0};
|
for (int i = 0; i < 8; i++) mMarker.data[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Notch or un-notch this snifferitem / frame
|
||||||
void SnifferItem::notch(bool pNotch)
|
void SnifferItem::notch(bool pNotch)
|
||||||
{
|
{
|
||||||
if(pNotch)
|
if(pNotch)
|
||||||
mNotch |= mLastMarker.data;
|
{
|
||||||
|
for (int i = 0; i < 8; i++) mNotch[i] |= mLastMarker.data[i]; //add changed bits to notch value
|
||||||
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
mNotch = 0;
|
for (int i = 0; i < 8; i++) mNotch[i] = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
struct fstCan
|
struct fstCan
|
||||||
{
|
{
|
||||||
quint64 data;
|
quint8 data[8];
|
||||||
|
quint32 dataTimestamp[8];
|
||||||
int len;
|
int len;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -22,26 +23,32 @@ enum dc
|
|||||||
class SnifferItem
|
class SnifferItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SnifferItem(const CANFrame& pFrame);
|
explicit SnifferItem(const CANFrame& pFrame, quint32 seq);
|
||||||
virtual ~SnifferItem();
|
virtual ~SnifferItem();
|
||||||
|
|
||||||
quint64 getId() const;
|
quint64 getId() const;
|
||||||
float getDelta() const;
|
float getDelta() const;
|
||||||
int getData(uchar i) const;
|
int getData(uchar i) const;
|
||||||
|
quint8 getNotchPattern(uchar i) const;
|
||||||
|
quint8 getLastData(uchar i) const;
|
||||||
|
quint32 getDataTimestamp(uchar i) const;
|
||||||
|
quint32 getSeqInterval(uchar i) const;
|
||||||
dc dataChange(uchar) const;
|
dc dataChange(uchar) const;
|
||||||
int elapsed() const;
|
int elapsed() const;
|
||||||
void update(const CANFrame& pFrame);
|
void update(const CANFrame& pFrame, quint32 timeSeq, bool mute);
|
||||||
void updateMarker();
|
void updateMarker();
|
||||||
void notch(bool);
|
void notch(bool);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
quint64 mID;
|
quint32 mID;
|
||||||
struct fstCan mLast;
|
struct fstCan mLast;
|
||||||
struct fstCan mCurrent;
|
struct fstCan mCurrent;
|
||||||
struct fstCan mLastMarker;
|
struct fstCan mLastMarker;
|
||||||
struct fstCan mMarker;
|
struct fstCan mMarker;
|
||||||
quint64 mNotch;
|
quint8 mNotch[8];
|
||||||
quint64 mLastTime;
|
quint64 mLastTime;
|
||||||
quint64 mCurrentTime;
|
quint64 mCurrentTime;
|
||||||
|
quint64 mCurrSeqVal;
|
||||||
|
|
||||||
QTime mTime;
|
QTime mTime;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "sniffermodel.h"
|
#include "sniffermodel.h"
|
||||||
#include "snifferwindow.h"
|
#include "snifferwindow.h"
|
||||||
|
#include "SnifferDelegate.h"
|
||||||
|
|
||||||
SnifferModel::SnifferModel(QObject *parent)
|
SnifferModel::SnifferModel(QObject *parent)
|
||||||
: QAbstractItemModel(parent),
|
: QAbstractItemModel(parent),
|
||||||
mFilter(false)
|
mFilter(false),
|
||||||
|
mNeverExpire(false),
|
||||||
|
mFadeInactive(false),
|
||||||
|
mMuteNotched(false),
|
||||||
|
mTimeSequence(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +61,23 @@ QVariant SnifferModel::data(const QModelIndex &index, int role) const
|
|||||||
{
|
{
|
||||||
int data = item->getData(col-tc::DATA_0);
|
int data = item->getData(col-tc::DATA_0);
|
||||||
if(data >= 0)
|
if(data >= 0)
|
||||||
|
{
|
||||||
return QString("%1").arg(data, 2, 16, QLatin1Char('0')).toUpper();
|
return QString("%1").arg(data, 2, 16, QLatin1Char('0')).toUpper();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Qt::ForegroundRole:
|
||||||
|
{
|
||||||
|
if (!mFadeInactive || col < 2) return QBrush(Qt::black);
|
||||||
|
int v = item->getSeqInterval(col - 2) * 10;
|
||||||
|
//qDebug() << "mTS: " << mTimeSequence << " gDT(" << (col - 2) << ") " << item->getDataTimestamp(col - 2);
|
||||||
|
if (v > 225) v = 225;
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
return QBrush(QColor(v,v,v,255));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Qt::BackgroundRole:
|
case Qt::BackgroundRole:
|
||||||
{
|
{
|
||||||
if(tc::ID==col)
|
if(tc::ID==col)
|
||||||
@@ -143,6 +160,35 @@ QModelIndex SnifferModel::parent(const QModelIndex &) const
|
|||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SnifferModel::getNeverExpire()
|
||||||
|
{
|
||||||
|
return mNeverExpire;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SnifferModel::getFadeInactive()
|
||||||
|
{
|
||||||
|
return mFadeInactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SnifferModel::getMuteNotched()
|
||||||
|
{
|
||||||
|
return mMuteNotched;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnifferModel::setNeverExpire(bool val)
|
||||||
|
{
|
||||||
|
mNeverExpire = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnifferModel::setFadeInactive(bool val)
|
||||||
|
{
|
||||||
|
mFadeInactive = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnifferModel::setMuteNotched(bool val)
|
||||||
|
{
|
||||||
|
mMuteNotched = val;
|
||||||
|
}
|
||||||
|
|
||||||
void SnifferModel::clear()
|
void SnifferModel::clear()
|
||||||
{
|
{
|
||||||
@@ -154,20 +200,22 @@ void SnifferModel::clear()
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Called from window with a timer (currently 200ms)
|
||||||
void SnifferModel::refresh()
|
void SnifferModel::refresh()
|
||||||
{
|
{
|
||||||
QMap<quint32, SnifferItem*>::iterator i;
|
QMap<quint32, SnifferItem*>::iterator i;
|
||||||
QVector<quint32> toRemove;
|
QVector<quint32> toRemove;
|
||||||
SnifferItem* item;
|
SnifferItem* item;
|
||||||
|
|
||||||
|
mTimeSequence++;
|
||||||
|
|
||||||
/* update markers */
|
/* update markers */
|
||||||
|
|
||||||
|
|
||||||
for (i = mMap.begin(); i != mMap.end(); ++i)
|
for (i = mMap.begin(); i != mMap.end(); ++i)
|
||||||
{
|
{
|
||||||
i.value()->updateMarker();
|
i.value()->updateMarker();
|
||||||
if(i.value()->elapsed()>5000)
|
if(i.value()->elapsed()>5000 && !mNeverExpire)
|
||||||
toRemove.append(i.key());
|
toRemove.append(i.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,14 +285,15 @@ void SnifferModel::update(CANConnection*, QVector<CANFrame>& pFrames)
|
|||||||
int index = std::distance(mMap.begin(), mMap.lowerBound(frame.ID));
|
int index = std::distance(mMap.begin(), mMap.lowerBound(frame.ID));
|
||||||
/* add the frame */
|
/* add the frame */
|
||||||
beginInsertRows(QModelIndex(), index, index);
|
beginInsertRows(QModelIndex(), index, index);
|
||||||
mMap[frame.ID] = new SnifferItem(frame);
|
mMap[frame.ID] = new SnifferItem(frame, mTimeSequence);
|
||||||
|
mMap[frame.ID]->update(frame, mTimeSequence, mMuteNotched);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
|
||||||
emit idChange(frame.ID, true);
|
emit idChange(frame.ID, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
//updateData
|
//updateData
|
||||||
mMap[frame.ID]->update(frame);
|
mMap[frame.ID]->update(frame, mTimeSequence, mMuteNotched);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ public:
|
|||||||
void refresh();
|
void refresh();
|
||||||
void clear();
|
void clear();
|
||||||
void filter(fltType pType, int pId=0);
|
void filter(fltType pType, int pId=0);
|
||||||
|
bool getNeverExpire();
|
||||||
|
bool getFadeInactive();
|
||||||
|
bool getMuteNotched();
|
||||||
|
void setNeverExpire(bool val);
|
||||||
|
void setFadeInactive(bool val);
|
||||||
|
void setMuteNotched(bool val);
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void update(CANConnection*, QVector<CANFrame>&);
|
void update(CANConnection*, QVector<CANFrame>&);
|
||||||
@@ -53,6 +60,10 @@ private:
|
|||||||
QMap<quint32, SnifferItem*> mMap;
|
QMap<quint32, SnifferItem*> mMap;
|
||||||
QMap<quint32, SnifferItem*> mFilters;
|
QMap<quint32, SnifferItem*> mFilters;
|
||||||
bool mFilter;
|
bool mFilter;
|
||||||
|
bool mNeverExpire;
|
||||||
|
bool mFadeInactive;
|
||||||
|
bool mMuteNotched;
|
||||||
|
quint32 mTimeSequence;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SNIFFERMODEL_H
|
#endif // SNIFFERMODEL_H
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "ui_snifferwindow.h"
|
#include "ui_snifferwindow.h"
|
||||||
#include "helpwindow.h"
|
#include "helpwindow.h"
|
||||||
#include "connections/canconmanager.h"
|
#include "connections/canconmanager.h"
|
||||||
|
#include "SnifferDelegate.h"
|
||||||
|
|
||||||
SnifferWindow::SnifferWindow(QWidget *parent) :
|
SnifferWindow::SnifferWindow(QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
@@ -16,12 +17,17 @@ SnifferWindow::SnifferWindow(QWidget *parent) :
|
|||||||
setWindowFlags(Qt::Window);
|
setWindowFlags(Qt::Window);
|
||||||
ui->treeView->setModel(&mModel);
|
ui->treeView->setModel(&mModel);
|
||||||
|
|
||||||
|
sniffDel = new SnifferDelegate();
|
||||||
|
defaultDel = ui->treeView->itemDelegate();
|
||||||
|
|
||||||
/* set column width */
|
/* set column width */
|
||||||
ui->treeView->setColumnWidth(tc::ID, 50);
|
ui->treeView->setColumnWidth(tc::ID, 80);
|
||||||
ui->treeView->setColumnWidth(tc::LAST, 1);
|
ui->treeView->setColumnWidth(tc::LAST, 1);
|
||||||
for(int i=tc::DATA_0 ; i<=tc::DATA_7 ; i++)
|
for(int i=tc::DATA_0 ; i<=tc::DATA_7 ; i++)
|
||||||
ui->treeView->setColumnWidth(i, 30);
|
ui->treeView->setColumnWidth(i, 92);
|
||||||
|
ui->treeView->setUniformRowHeights(true);
|
||||||
ui->treeView->header()->setDefaultAlignment(Qt::AlignCenter);
|
ui->treeView->header()->setDefaultAlignment(Qt::AlignCenter);
|
||||||
|
//ui->treeView->setItemDelegate(new SnifferDelegate());
|
||||||
|
|
||||||
/* activate sorting */
|
/* activate sorting */
|
||||||
ui->listWidget->setSortingEnabled(true);
|
ui->listWidget->setSortingEnabled(true);
|
||||||
@@ -38,20 +44,75 @@ SnifferWindow::SnifferWindow(QWidget *parent) :
|
|||||||
connect(&mModel, &SnifferModel::idChange, this, &SnifferWindow::idChange);
|
connect(&mModel, &SnifferModel::idChange, this, &SnifferWindow::idChange);
|
||||||
connect(ui->listWidget, &QListWidget::itemChanged, this, &SnifferWindow::itemChanged);
|
connect(ui->listWidget, &QListWidget::itemChanged, this, &SnifferWindow::itemChanged);
|
||||||
|
|
||||||
|
connect(ui->cbFadeInactive, &QCheckBox::stateChanged, this, [this](int val){mModel.setFadeInactive(val);sniffDel->setFadeInactive(val);});
|
||||||
|
connect(ui->cbMuteNotched, &QCheckBox::stateChanged, this, [this](int val){mModel.setMuteNotched(val);});
|
||||||
|
connect(ui->cbNoExpire, &QCheckBox::stateChanged, this, [this](int val){mModel.setNeverExpire(val);});
|
||||||
|
connect(ui->cbViewBits, &QCheckBox::stateChanged, this,
|
||||||
|
[this](int val)
|
||||||
|
{
|
||||||
|
if (val) ui->treeView->setItemDelegate(sniffDel);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->treeView->setItemDelegate(defaultDel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SnifferWindow::~SnifferWindow()
|
SnifferWindow::~SnifferWindow()
|
||||||
{
|
{
|
||||||
closeEvent(NULL);
|
closeEvent(NULL);
|
||||||
|
delete sniffDel;
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SnifferWindow::readSettings()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||||
|
{
|
||||||
|
resize(settings.value("Sniffer/WindowSize", QSize(1100, 750)).toSize());
|
||||||
|
move(settings.value("Sniffer/WindowPos", QPoint(50, 50)).toPoint());
|
||||||
|
ui->treeView->setColumnWidth(0, settings.value("Sniffer/DeltaColumn", 110).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(1, settings.value("Sniffer/IDColumn", 70).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(2, settings.value("Sniffer/Data0Column", 92).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(3, settings.value("Sniffer/Data1Column", 92).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(4, settings.value("Sniffer/Data2Column", 92).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(5, settings.value("Sniffer/Data3Column", 92).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(6, settings.value("Sniffer/Data4Column", 92).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(7, settings.value("Sniffer/Data5Column", 92).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(8, settings.value("Sniffer/Data6Column", 92).toUInt());
|
||||||
|
ui->treeView->setColumnWidth(9, settings.value("Sniffer/Data7Column", 92).toUInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnifferWindow::writeSettings()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||||
|
{
|
||||||
|
settings.setValue("Sniffer/WindowSize", size());
|
||||||
|
settings.setValue("Sniffer/WindowPos", pos());
|
||||||
|
settings.setValue("Sniffer/DeltaColumn", ui->treeView->columnWidth(0));
|
||||||
|
settings.setValue("Sniffer/IDColumn", ui->treeView->columnWidth(1));
|
||||||
|
settings.setValue("Sniffer/Data0Column", ui->treeView->columnWidth(2));
|
||||||
|
settings.setValue("Sniffer/Data1Column", ui->treeView->columnWidth(3));
|
||||||
|
settings.setValue("Sniffer/Data2Column", ui->treeView->columnWidth(4));
|
||||||
|
settings.setValue("Sniffer/Data3Column", ui->treeView->columnWidth(5));
|
||||||
|
settings.setValue("Sniffer/Data4Column", ui->treeView->columnWidth(6));
|
||||||
|
settings.setValue("Sniffer/Data5Column", ui->treeView->columnWidth(7));
|
||||||
|
settings.setValue("Sniffer/Data6Column", ui->treeView->columnWidth(8));
|
||||||
|
settings.setValue("Sniffer/Data7Column", ui->treeView->columnWidth(9));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SnifferWindow::showEvent(QShowEvent* event)
|
void SnifferWindow::showEvent(QShowEvent* event)
|
||||||
{
|
{
|
||||||
QDialog::showEvent(event);
|
QDialog::showEvent(event);
|
||||||
connect(CANConManager::getInstance(), &CANConManager::framesReceived, &mModel, &SnifferModel::update);
|
connect(CANConManager::getInstance(), &CANConManager::framesReceived, &mModel, &SnifferModel::update);
|
||||||
mTimer.start();
|
mTimer.start();
|
||||||
|
readSettings();
|
||||||
installEventFilter(this);
|
installEventFilter(this);
|
||||||
qDebug() << "show";
|
qDebug() << "show";
|
||||||
}
|
}
|
||||||
@@ -64,6 +125,7 @@ void SnifferWindow::closeEvent(QCloseEvent *event)
|
|||||||
mTimer.stop();
|
mTimer.stop();
|
||||||
/* disconnect reception of frames */
|
/* disconnect reception of frames */
|
||||||
disconnect(CANConManager::getInstance(), 0, this, 0);
|
disconnect(CANConManager::getInstance(), 0, this, 0);
|
||||||
|
writeSettings();
|
||||||
/* clear model */
|
/* clear model */
|
||||||
mModel.clear();
|
mModel.clear();
|
||||||
/* clean list */
|
/* clean list */
|
||||||
@@ -127,7 +189,10 @@ void SnifferWindow::idChange(int pId, bool pAdd)
|
|||||||
QString text = QString("0x") + QString("%1").arg(pId, 3, 16, QLatin1Char('0')).toUpper();
|
QString text = QString("0x") + QString("%1").arg(pId, 3, 16, QLatin1Char('0')).toUpper();
|
||||||
item = new QListWidgetItem(text);
|
item = new QListWidgetItem(text);
|
||||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
|
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
|
||||||
item->setCheckState(mFilter ? Qt::Unchecked : Qt::Checked);
|
//item->setCheckState(mFilter ? Qt::Unchecked : Qt::Checked);
|
||||||
|
//always check new IDs now. Otherwise any that expire then come back will not be selected
|
||||||
|
//and that might be a bigger issue than defaulting them unselected.
|
||||||
|
item->setCheckState(Qt::Checked);
|
||||||
ui->listWidget->addItem(item);
|
ui->listWidget->addItem(item);
|
||||||
mMap[pId] = item;
|
mMap[pId] = item;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QListWidgetItem>
|
#include <QListWidgetItem>
|
||||||
#include "sniffermodel.h"
|
#include "sniffermodel.h"
|
||||||
|
#include "SnifferDelegate.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class snifferWindow;
|
class snifferWindow;
|
||||||
@@ -46,12 +47,16 @@ public slots:
|
|||||||
private:
|
private:
|
||||||
void filter(bool pFilter);
|
void filter(bool pFilter);
|
||||||
bool eventFilter(QObject *obj, QEvent *event);
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
void readSettings();
|
||||||
|
void writeSettings();
|
||||||
|
|
||||||
Ui::snifferWindow* ui;
|
Ui::snifferWindow* ui;
|
||||||
SnifferModel mModel;
|
SnifferModel mModel;
|
||||||
QTimer mTimer;
|
QTimer mTimer;
|
||||||
QMap<int, QListWidgetItem*> mMap;
|
QMap<int, QListWidgetItem*> mMap;
|
||||||
bool mFilter;
|
bool mFilter;
|
||||||
|
SnifferDelegate *sniffDel;
|
||||||
|
QAbstractItemDelegate *defaultDel;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SNIFFER_H
|
#endif // SNIFFER_H
|
||||||
|
|||||||
@@ -81,16 +81,6 @@
|
|||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QRadioButton" name="rbKvaser">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Kvaser</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QRadioButton" name="rbGVRET">
|
<widget class="QRadioButton" name="rbGVRET">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -101,17 +91,17 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QRadioButton" name="rbSocketCAN">
|
<widget class="QRadioButton" name="rbSocketCAN">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>SocketCAN</string>
|
<string>QT SerialBus Devices (SocketCAN, PeakCAN, etc)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="0">
|
||||||
<widget class="QRadioButton" name="rbRemote">
|
<widget class="QRadioButton" name="rbRemote">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Remote Host</string>
|
<string>Remote Host</string>
|
||||||
@@ -121,6 +111,16 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lblDeviceType">
|
||||||
|
<property name="text">
|
||||||
|
<string>Device Type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="cbDeviceType"/>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="lPort">
|
<widget class="QLabel" name="lPort">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
|||||||
@@ -6,16 +6,16 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>884</width>
|
<width>1239</width>
|
||||||
<height>915</height>
|
<height>644</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Signal Editor</string>
|
<string>Signal Editor</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="10,1,5">
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="10,1,4">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,2">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,2,1">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListWidget" name="signalsList"/>
|
<widget class="QListWidget" name="signalsList"/>
|
||||||
</item>
|
</item>
|
||||||
@@ -52,118 +52,113 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bit Length:</string>
|
<string>Bit Length:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtBitLength"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QLabel" name="label_5">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Byte Order</string>
|
<string>Byte Order</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLineEdit" name="txtBitLength"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QCheckBox" name="cbIntelFormat">
|
<widget class="QCheckBox" name="cbIntelFormat">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>LSB First (Little Endian)</string>
|
<string>LSB First (Little Endian)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Type:</string>
|
<string>Type:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="2" column="1">
|
||||||
|
<widget class="QComboBox" name="comboType"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Scale:</string>
|
<string>Scale:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtScale"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_8">
|
<widget class="QLabel" name="label_8">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bias:</string>
|
<string>Bias:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtBias"/>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="label_9">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Min Value:</string>
|
<string>Min Value:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0">
|
<item row="5" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtMinVal"/>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="label_10">
|
<widget class="QLabel" name="label_10">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max Value:</string>
|
<string>Max Value:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="0">
|
<item row="6" column="1">
|
||||||
<widget class="QLabel" name="label_11">
|
<widget class="QLineEdit" name="txtMaxVal"/>
|
||||||
<property name="text">
|
|
||||||
<string>Receiving Node:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="14" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QLabel" name="label_13">
|
|
||||||
<property name="text">
|
|
||||||
<string>Comment:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="0">
|
|
||||||
<widget class="QLabel" name="label_12">
|
<widget class="QLabel" name="label_12">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Units Name:</string>
|
<string>Units Name:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QComboBox" name="comboType"/>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtScale"/>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtBias"/>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
<item row="7" column="1">
|
||||||
<widget class="QLineEdit" name="txtMinVal"/>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtMaxVal"/>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtUnitName"/>
|
<widget class="QLineEdit" name="txtUnitName"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="1">
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Receiving Node:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
<widget class="QComboBox" name="comboReceiver"/>
|
<widget class="QComboBox" name="comboReceiver"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="14" column="1">
|
<item row="9" column="0">
|
||||||
<widget class="QLineEdit" name="txtComment"/>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="0">
|
|
||||||
<widget class="QLabel" name="label_14">
|
<widget class="QLabel" name="label_14">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Multiplexing</string>
|
<string>Multiplexing</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="12" column="1">
|
<item row="9" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="rbNotMulti">
|
<widget class="QRadioButton" name="rbNotMulti">
|
||||||
@@ -188,19 +183,28 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" column="0">
|
<item row="10" column="0">
|
||||||
<widget class="QLabel" name="label_15">
|
<widget class="QLabel" name="label_15">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Multiplex Value</string>
|
<string>Multiplex Value</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QLineEdit" name="txtMultiplexValue"/>
|
<widget class="QLineEdit" name="txtMultiplexValue"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="11" column="0">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>Comment:</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="11" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtComment"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -226,20 +230,9 @@
|
|||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>signalsList</tabstop>
|
<tabstop>signalsList</tabstop>
|
||||||
<tabstop>txtName</tabstop>
|
<tabstop>txtName</tabstop>
|
||||||
<tabstop>txtBitLength</tabstop>
|
|
||||||
<tabstop>cbIntelFormat</tabstop>
|
|
||||||
<tabstop>comboType</tabstop>
|
|
||||||
<tabstop>txtScale</tabstop>
|
|
||||||
<tabstop>txtBias</tabstop>
|
|
||||||
<tabstop>txtMinVal</tabstop>
|
|
||||||
<tabstop>txtMaxVal</tabstop>
|
|
||||||
<tabstop>txtUnitName</tabstop>
|
|
||||||
<tabstop>comboReceiver</tabstop>
|
|
||||||
<tabstop>rbNotMulti</tabstop>
|
<tabstop>rbNotMulti</tabstop>
|
||||||
<tabstop>rbMultiplexed</tabstop>
|
<tabstop>rbMultiplexed</tabstop>
|
||||||
<tabstop>rbMultiplexor</tabstop>
|
<tabstop>rbMultiplexor</tabstop>
|
||||||
<tabstop>txtMultiplexValue</tabstop>
|
|
||||||
<tabstop>txtComment</tabstop>
|
|
||||||
<tabstop>valuesTable</tabstop>
|
<tabstop>valuesTable</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
@@ -13,9 +13,11 @@
|
|||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Detailed Frame Information</string>
|
<string>Detailed Frame Information</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="10,1,5">
|
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,1">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,2">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
@@ -61,10 +63,6 @@
|
|||||||
</column>
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnSave">
|
<widget class="QPushButton" name="btnSave">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -72,9 +70,417 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,1,0,1,0">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bit Histograph</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCustomPlot" name="graphHistogram" native="true"/>
|
<widget class="QCustomPlot" name="graphHistogram" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bytes Graph</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCustomPlot" name="graphBytes" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>52</red>
|
||||||
|
<green>101</green>
|
||||||
|
<blue>164</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>52</red>
|
||||||
|
<green>101</green>
|
||||||
|
<blue>164</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>190</red>
|
||||||
|
<green>190</green>
|
||||||
|
<blue>190</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>78</red>
|
||||||
|
<green>154</green>
|
||||||
|
<blue>6</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>78</red>
|
||||||
|
<green>154</green>
|
||||||
|
<blue>6</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>190</red>
|
||||||
|
<green>190</green>
|
||||||
|
<blue>190</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>2</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>204</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>204</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>190</red>
|
||||||
|
<green>190</green>
|
||||||
|
<blue>190</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>3</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>136</red>
|
||||||
|
<green>138</green>
|
||||||
|
<blue>133</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>136</red>
|
||||||
|
<green>138</green>
|
||||||
|
<blue>133</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>190</red>
|
||||||
|
<green>190</green>
|
||||||
|
<blue>190</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>4</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>252</red>
|
||||||
|
<green>233</green>
|
||||||
|
<blue>79</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>252</red>
|
||||||
|
<green>233</green>
|
||||||
|
<blue>79</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>190</red>
|
||||||
|
<green>190</green>
|
||||||
|
<blue>190</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>5</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>114</red>
|
||||||
|
<green>159</green>
|
||||||
|
<blue>207</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>114</red>
|
||||||
|
<green>159</green>
|
||||||
|
<blue>207</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>190</red>
|
||||||
|
<green>190</green>
|
||||||
|
<blue>190</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>6</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>173</red>
|
||||||
|
<green>127</green>
|
||||||
|
<blue>168</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>173</red>
|
||||||
|
<green>127</green>
|
||||||
|
<blue>168</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>190</red>
|
||||||
|
<green>190</green>
|
||||||
|
<blue>190</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>7</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
@@ -88,7 +494,6 @@
|
|||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>listFrameID</tabstop>
|
<tabstop>listFrameID</tabstop>
|
||||||
<tabstop>treeDetails</tabstop>
|
<tabstop>treeDetails</tabstop>
|
||||||
<tabstop>btnSave</tabstop>
|
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|||||||
@@ -89,7 +89,11 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListWidget" name="listFilter"/>
|
<widget class="QListWidget" name="listFilter">
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>602</width>
|
<width>1097</width>
|
||||||
<height>752</height>
|
<height>752</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@@ -82,6 +82,34 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbNoExpire">
|
||||||
|
<property name="text">
|
||||||
|
<string>Never Expire IDs</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbMuteNotched">
|
||||||
|
<property name="text">
|
||||||
|
<string>Mute notched bits</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbFadeInactive">
|
||||||
|
<property name="text">
|
||||||
|
<string>Fade inactive bytes</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbViewBits">
|
||||||
|
<property name="text">
|
||||||
|
<string>View Bits</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|||||||
@@ -128,13 +128,13 @@ public:
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString formatTimestamp(uint64_t timestamp)
|
static QVariant formatTimestamp(uint64_t timestamp)
|
||||||
{
|
{
|
||||||
if (!sysTimeMode) {
|
if (!sysTimeMode) {
|
||||||
if (!secondsMode) return QString::number(timestamp);
|
if (!secondsMode) return (unsigned long long)(timestamp);
|
||||||
else return QString::number((double)timestamp / 1000000.0, 'f', 6);
|
else return (double)timestamp / 1000000.0;
|
||||||
}
|
}
|
||||||
else return QDateTime::fromMSecsSinceEpoch(timestamp / 1000).toString(timeFormat);
|
else return QDateTime::fromMSecsSinceEpoch(timestamp / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
//parses the input string to grab as much of it as possible while staying alpha numeric
|
//parses the input string to grab as much of it as possible while staying alpha numeric
|
||||||
|
|||||||