Merge branch 'master' into support_multiple_signal_multiplex_values
This commit is contained in:
+44
-13
@@ -4,16 +4,15 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "master"
|
- "master"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildlinux:
|
buildlinux:
|
||||||
name: Linux x64
|
name: Linux x64
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare Environment
|
- name: Prepare Environment
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-randr0 libxkbcommon-x11-0
|
sudo apt-get install libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-randr0 libxkbcommon-x11-0 libfuse2
|
||||||
|
|
||||||
- name: Prepare Qt Libraries
|
- name: Prepare Qt Libraries
|
||||||
uses: jurplel/install-qt-action@v3
|
uses: jurplel/install-qt-action@v3
|
||||||
@@ -33,14 +32,14 @@ jobs:
|
|||||||
chmod a+x linuxdeployqt-continuous-x86_64.AppImage
|
chmod a+x linuxdeployqt-continuous-x86_64.AppImage
|
||||||
./linuxdeployqt-continuous-x86_64.AppImage appdir/usr/share/applications/SavvyCAN.desktop -appimage -extra-plugins=iconengines,platformthemes/libqgtk3.so,canbus
|
./linuxdeployqt-continuous-x86_64.AppImage appdir/usr/share/applications/SavvyCAN.desktop -appimage -extra-plugins=iconengines,platformthemes/libqgtk3.so,canbus
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: SavvyCAN-Linux_x64.AppImage
|
name: SavvyCAN-Linux_x64.AppImage
|
||||||
path: SavvyCAN-*x86_64.AppImage
|
path: SavvyCAN-*x86_64.AppImage
|
||||||
|
|
||||||
buildmacos:
|
buildmacos86:
|
||||||
name: macOS x64
|
name: macOS x64
|
||||||
runs-on: macos-12
|
runs-on: macos-13
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare macOS Environment
|
- name: Prepare macOS Environment
|
||||||
@@ -61,11 +60,42 @@ jobs:
|
|||||||
mkdir -p SavvyCAN.app/Contents/MacOS/help
|
mkdir -p SavvyCAN.app/Contents/MacOS/help
|
||||||
cp -R help/* SavvyCAN.app/Contents/MacOS/help
|
cp -R help/* SavvyCAN.app/Contents/MacOS/help
|
||||||
macdeployqt SavvyCAN.app -dmg
|
macdeployqt SavvyCAN.app -dmg
|
||||||
|
mv SavvyCAN.dmg SavvyCAN_x64.dmg
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: SavvyCAN-macOS_x64.dmg
|
name: SavvyCAN-macOS_x64.dmg
|
||||||
path: SavvyCAN.dmg
|
path: SavvyCAN_x64.dmg
|
||||||
|
|
||||||
|
buildmacos-arm64:
|
||||||
|
name: macOS ARM64
|
||||||
|
runs-on: macos-14
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Prepare macOS Environment
|
||||||
|
run: |
|
||||||
|
brew install qt5
|
||||||
|
brew link qt5 --force
|
||||||
|
|
||||||
|
- name: Clone
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Compile
|
||||||
|
run: |
|
||||||
|
qmake CONFIG+=release CONFIG+=sdk_no_version_check SavvyCAN.pro
|
||||||
|
make -j`sysctl kern.aioprocmax | awk '{print $2}'`
|
||||||
|
|
||||||
|
- name: Package
|
||||||
|
run: |
|
||||||
|
mkdir -p SavvyCAN.app/Contents/MacOS/help
|
||||||
|
cp -R help/* SavvyCAN.app/Contents/MacOS/help
|
||||||
|
macdeployqt SavvyCAN.app -dmg
|
||||||
|
mv SavvyCAN.dmg SavvyCAN_arm64.dmg
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: SavvyCAN-macOS_ARM64.dmg
|
||||||
|
path: SavvyCAN_arm64.dmg
|
||||||
|
|
||||||
buildwindows:
|
buildwindows:
|
||||||
name: Windows x64
|
name: Windows x64
|
||||||
@@ -113,7 +143,7 @@ jobs:
|
|||||||
mkdir package/canbus
|
mkdir package/canbus
|
||||||
copy "${Env:Qt5_Dir}/plugins/canbus/*.*" package/canbus/
|
copy "${Env:Qt5_Dir}/plugins/canbus/*.*" package/canbus/
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: SavvyCAN-Windows_x64
|
name: SavvyCAN-Windows_x64
|
||||||
path: package
|
path: package
|
||||||
@@ -121,12 +151,12 @@ jobs:
|
|||||||
pre-release:
|
pre-release:
|
||||||
name: "pre-release"
|
name: "pre-release"
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
needs: [buildwindows, buildmacos, buildlinux]
|
needs: [buildwindows, buildmacos86, buildmacos-arm64, buildlinux]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v4.1.7
|
||||||
|
|
||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
run: zip -r SavvyCAN-Windows_x64_CIBuild.zip SavvyCAN-Windows_x64
|
run: zip -r SavvyCAN-Windows_x64_CIBuild.zip SavvyCAN-Windows_x64
|
||||||
@@ -139,12 +169,13 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
SavvyCAN-Linux_x64.AppImage/SavvyCAN-*x86_64.AppImage
|
SavvyCAN-Linux_x64.AppImage/SavvyCAN-*x86_64.AppImage
|
||||||
SavvyCAN-Windows_x64_CIBuild.zip
|
SavvyCAN-Windows_x64_CIBuild.zip
|
||||||
SavvyCAN-macOS_x64.dmg/SavvyCAN.dmg
|
SavvyCAN-macOS_x64.dmg/SavvyCAN_x64.dmg
|
||||||
|
SavvyCAN-macOS_ARM64.dmg/SavvyCAN_arm64.dmg
|
||||||
|
|
||||||
notify:
|
notify:
|
||||||
name: Notify Discord
|
name: Notify Discord
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [buildwindows, buildmacos, buildlinux]
|
needs: [buildwindows, buildmacos86, buildmacos-arm64, buildlinux]
|
||||||
steps:
|
steps:
|
||||||
- id: msg_var
|
- id: msg_var
|
||||||
name: remove newlines
|
name: remove newlines
|
||||||
|
|||||||
@@ -45,3 +45,4 @@ Makefile
|
|||||||
SavvyCAN.pro.qtds
|
SavvyCAN.pro.qtds
|
||||||
.xcode
|
.xcode
|
||||||
SavvyCAN.xcodeproj
|
SavvyCAN.xcodeproj
|
||||||
|
.vscode
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# SavvyCAN
|
# SavvyCAN
|
||||||
Qt based cross platform canbus tool
|
Qt based cross platform canbus tool
|
||||||
(C) 2015-2021 EVTV and Collin Kidder
|
(C) 2015-2024 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
|
||||||
@@ -17,9 +17,6 @@ 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 Qt SerialBus driver (socketcan, Vector, PeakCAN, TinyCAN).
|
It is now possible to use any Qt SerialBus driver (socketcan, Vector, PeakCAN, TinyCAN).
|
||||||
There may, however, be some loss of some functionality as
|
|
||||||
some functions of SavvyCAN are designed for use directly with the
|
|
||||||
EVTVDue and CANDue 2.0 boards.
|
|
||||||
|
|
||||||
It should, however, be noted that use of a capture device is not required to make use
|
It should, however, be noted that use of a capture device is not required to make use
|
||||||
of this program. It can load and save in several formats:
|
of this program. It can load and save in several formats:
|
||||||
@@ -35,6 +32,7 @@ of this program. It can load and save in several formats:
|
|||||||
9. Vehicle Spy log files
|
9. Vehicle Spy log files
|
||||||
10. CANDump / Kayak (Read only)
|
10. CANDump / Kayak (Read only)
|
||||||
11. PCAN Viewer (Read Only)
|
11. PCAN Viewer (Read Only)
|
||||||
|
12. Wireshark socketcan PCAP file (Read only)
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
@@ -50,8 +48,9 @@ to download it separately.
|
|||||||
|
|
||||||
This project requires 5.14.0 or higher because of a dependency on QtSerialBus and other new additions to Qt.
|
This project requires 5.14.0 or higher because of a dependency on QtSerialBus and other new additions to Qt.
|
||||||
|
|
||||||
NOTE: Qt6 currently lacks support for QtSerialBus and many other Qt sub-features. At this time you cannot
|
NOTE: As the code in this master branch sits, it does compile with QT6. Support for QT6 is approximately "beta" quality. Most all functions should work, please send issues if found.
|
||||||
use Qt6 to compile SavvyCAN. Support for Qt6 should be possible around Qt6.2.
|
|
||||||
|
It appears that the current binary build for MacOS requires at least MacOS 10.15
|
||||||
|
|
||||||
## Instructions for compiling:
|
## Instructions for compiling:
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -4,11 +4,15 @@
|
|||||||
#
|
#
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
|
|
||||||
|
!versionAtLeast(QT_VERSION, 5.14.0) {
|
||||||
|
error("Current version of Qt ($${QT_VERSION}) is too old, this project requires Qt 5.14 or newer")
|
||||||
|
}
|
||||||
|
|
||||||
QT = core gui printsupport qml serialbus serialport widgets help network opengl
|
QT = core gui printsupport qml serialbus serialport widgets help network opengl
|
||||||
|
|
||||||
CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT
|
CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT
|
||||||
|
|
||||||
CONFIG += c++11
|
CONFIG += c++17
|
||||||
CONFIG += NO_UNIT_TESTS
|
CONFIG += NO_UNIT_TESTS
|
||||||
|
|
||||||
DEFINES += QCUSTOMPLOT_USE_OPENGL
|
DEFINES += QCUSTOMPLOT_USE_OPENGL
|
||||||
@@ -26,6 +30,7 @@ SOURCES += main.cpp\
|
|||||||
connections/lawicel_serial.cpp \
|
connections/lawicel_serial.cpp \
|
||||||
connections/mqtt_bus.cpp \
|
connections/mqtt_bus.cpp \
|
||||||
dbc/dbcnodeduplicateeditor.cpp \
|
dbc/dbcnodeduplicateeditor.cpp \
|
||||||
|
framesenderobject.cpp \
|
||||||
mqtt/qmqtt_client.cpp \
|
mqtt/qmqtt_client.cpp \
|
||||||
mqtt/qmqtt_client_p.cpp \
|
mqtt/qmqtt_client_p.cpp \
|
||||||
mqtt/qmqtt_frame.cpp \
|
mqtt/qmqtt_frame.cpp \
|
||||||
@@ -113,6 +118,7 @@ HEADERS += mainwindow.h \
|
|||||||
connections/mqtt_bus.h \
|
connections/mqtt_bus.h \
|
||||||
dbc/dbcnodeduplicateeditor.h \
|
dbc/dbcnodeduplicateeditor.h \
|
||||||
dbc/dbcnoderebaseeditor.h \
|
dbc/dbcnoderebaseeditor.h \
|
||||||
|
framesenderobject.h \
|
||||||
mqtt/qmqtt.h \
|
mqtt/qmqtt.h \
|
||||||
mqtt/qmqtt_client.h \
|
mqtt/qmqtt_client.h \
|
||||||
mqtt/qmqtt_client_p.h \
|
mqtt/qmqtt_client_p.h \
|
||||||
@@ -255,12 +261,16 @@ unix {
|
|||||||
DISTFILES += SavvyCAN.desktop
|
DISTFILES += SavvyCAN.desktop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
windows {
|
||||||
|
RC_ICONS=icons/SavvyIcon.ico
|
||||||
|
}
|
||||||
|
|
||||||
examplefiles.files=examples
|
examplefiles.files=examples
|
||||||
examplefiles.path = $$PREFIX/share/savvycan/examples
|
examplefiles.path = $$PREFIX/share/savvycan/examples
|
||||||
INSTALLS += examplefiles
|
INSTALLS += examplefiles
|
||||||
|
|
||||||
iconfiles.files=icons
|
iconfiles.files=icons
|
||||||
iconfiles.path = $$PREFIX/share/icons
|
iconfiles.path = $$PREFIX/share
|
||||||
INSTALLS += iconfiles
|
INSTALLS += iconfiles
|
||||||
|
|
||||||
helpfiles.files=help/*
|
helpfiles.files=help/*
|
||||||
|
|||||||
@@ -182,11 +182,11 @@ UDS_HANDLER::~UDS_HANDLER()
|
|||||||
delete isoHandler;
|
delete isoHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDS_HANDLER::gotISOTPFrame(ISOTP_MESSAGE msg)
|
UDS_MESSAGE UDS_HANDLER::tryISOtoUDS(ISOTP_MESSAGE msg, bool *result)
|
||||||
{
|
{
|
||||||
qDebug() << "UDS handler got ISOTP frame";
|
|
||||||
const unsigned char *data = reinterpret_cast<const unsigned char *>(msg.payload().constData());
|
const unsigned char *data = reinterpret_cast<const unsigned char *>(msg.payload().constData());
|
||||||
int dataLen = msg.payload().count();
|
int dataLen = msg.payload().count();
|
||||||
|
*result = true;
|
||||||
UDS_MESSAGE udsMsg;
|
UDS_MESSAGE udsMsg;
|
||||||
udsMsg.bus = msg.bus;
|
udsMsg.bus = msg.bus;
|
||||||
udsMsg.setExtendedFrameFormat(msg.hasExtendedFrameFormat());
|
udsMsg.setExtendedFrameFormat(msg.hasExtendedFrameFormat());
|
||||||
@@ -208,9 +208,17 @@ void UDS_HANDLER::gotISOTPFrame(ISOTP_MESSAGE msg)
|
|||||||
{
|
{
|
||||||
udsMsg.service = data[1];
|
udsMsg.service = data[1];
|
||||||
if (dataLen > 2) udsMsg.subFunc = data[2];
|
if (dataLen > 2) udsMsg.subFunc = data[2];
|
||||||
else return;
|
else
|
||||||
|
{
|
||||||
|
*result = false;
|
||||||
|
return udsMsg;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else return;
|
else
|
||||||
|
{
|
||||||
|
*result = false;
|
||||||
|
return udsMsg;
|
||||||
|
};
|
||||||
udsMsg.payload().remove(0, 2);
|
udsMsg.payload().remove(0, 2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -220,9 +228,22 @@ void UDS_HANDLER::gotISOTPFrame(ISOTP_MESSAGE msg)
|
|||||||
udsMsg.payload().remove(0, 1);
|
udsMsg.payload().remove(0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else return;
|
else
|
||||||
|
{
|
||||||
|
*result = false;
|
||||||
|
};
|
||||||
|
return udsMsg;
|
||||||
|
}
|
||||||
|
|
||||||
emit newUDSMessage(udsMsg);
|
void UDS_HANDLER::gotISOTPFrame(ISOTP_MESSAGE msg)
|
||||||
|
{
|
||||||
|
qDebug() << "UDS handler got ISOTP frame";
|
||||||
|
UDS_MESSAGE udsMsg;
|
||||||
|
|
||||||
|
bool result;
|
||||||
|
udsMsg = tryISOtoUDS(msg, &result);
|
||||||
|
|
||||||
|
if (result) emit newUDSMessage(udsMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDS_HANDLER::setFlowCtrl(bool state)
|
void UDS_HANDLER::setFlowCtrl(bool state)
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ public:
|
|||||||
QString getShortDesc(QVector<CODE_STRUCT> &codeVector, int code);
|
QString getShortDesc(QVector<CODE_STRUCT> &codeVector, int code);
|
||||||
QString getLongDesc(QVector<CODE_STRUCT> &codeVector, int code);
|
QString getLongDesc(QVector<CODE_STRUCT> &codeVector, int code);
|
||||||
QString getDetailedMessageAnalysis(const UDS_MESSAGE &msg);
|
QString getDetailedMessageAnalysis(const UDS_MESSAGE &msg);
|
||||||
|
UDS_MESSAGE tryISOtoUDS(ISOTP_MESSAGE msg, bool *result);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void gotISOTPFrame(ISOTP_MESSAGE msg);
|
void gotISOTPFrame(ISOTP_MESSAGE msg);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "can_structs.h"
|
#include "can_structs.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
enum TriggerMask
|
enum TriggerMask
|
||||||
{
|
{
|
||||||
@@ -38,6 +39,7 @@ public:
|
|||||||
//If ID is -1 then this is the temporary storage register. This is a shadow
|
//If ID is -1 then this is the temporary storage register. This is a shadow
|
||||||
//register used to accumulate the results of a multi operation modifier.
|
//register used to accumulate the results of a multi operation modifier.
|
||||||
//if ID is -2 then this is a look up of our own data bytes stored in the class data.
|
//if ID is -2 then this is a look up of our own data bytes stored in the class data.
|
||||||
|
//Of course, if the ID is positive then we grab bytes or signals from newest message with that ID
|
||||||
class ModifierOperand
|
class ModifierOperand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -45,6 +47,7 @@ public:
|
|||||||
int bus;
|
int bus;
|
||||||
int databyte;
|
int databyte;
|
||||||
bool notOper; //should a bitwise NOT be applied to this prior to doing the actual calculation?
|
bool notOper; //should a bitwise NOT be applied to this prior to doing the actual calculation?
|
||||||
|
QString signalName; //if ID is positive and there is text in here then we'll look up the signal and use its value
|
||||||
};
|
};
|
||||||
|
|
||||||
//list of operations that can be done between the two operands
|
//list of operations that can be done between the two operands
|
||||||
@@ -73,7 +76,8 @@ public:
|
|||||||
class Modifier
|
class Modifier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int destByte;
|
int destByte; //if -1 then target one of this ID's signals instead
|
||||||
|
QString signalName;
|
||||||
QList<ModifierOp> operations;
|
QList<ModifierOp> operations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+10
-17
@@ -13,21 +13,13 @@ CANBus::CANBus()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CANBus::CANBus(const CANBus& pBus) :
|
|
||||||
speed(pBus.speed),
|
|
||||||
listenOnly(pBus.listenOnly),
|
|
||||||
singleWire(pBus.singleWire),
|
|
||||||
active(pBus.active),
|
|
||||||
canFD(pBus.canFD),
|
|
||||||
dataRate(pBus.dataRate){}
|
|
||||||
|
|
||||||
|
|
||||||
bool CANBus::operator==(const CANBus& bus) const{
|
bool CANBus::operator==(const CANBus& bus) const{
|
||||||
return speed == bus.speed &&
|
return speed == bus.speed &&
|
||||||
listenOnly == bus.listenOnly &&
|
listenOnly == bus.listenOnly &&
|
||||||
singleWire == bus.singleWire &&
|
singleWire == bus.singleWire &&
|
||||||
active == bus.active &&
|
active == bus.active &&
|
||||||
canFD == bus.canFD;
|
canFD == bus.canFD &&
|
||||||
|
dataRate == bus.dataRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANBus::setSpeed(int newSpeed){
|
void CANBus::setSpeed(int newSpeed){
|
||||||
@@ -55,11 +47,11 @@ void CANBus::setCanFD(bool mode){
|
|||||||
canFD = mode;
|
canFD = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CANBus::getSpeed(){
|
int CANBus::getSpeed() const {
|
||||||
return speed;
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CANBus::getDataRate(){
|
int CANBus::getDataRate() const {
|
||||||
return dataRate;
|
return dataRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,29 +60,30 @@ void CANBus::setDataRate(int newSpeed){
|
|||||||
dataRate = newSpeed;
|
dataRate = newSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CANBus::isListenOnly(){
|
bool CANBus::isListenOnly() const {
|
||||||
return listenOnly;
|
return listenOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CANBus::isSingleWire(){
|
bool CANBus::isSingleWire() const {
|
||||||
return singleWire;
|
return singleWire;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CANBus::isActive(){
|
bool CANBus::isActive() const {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CANBus::isCanFD(){
|
bool CANBus::isCanFD() const {
|
||||||
return canFD;
|
return canFD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QDataStream& operator<<( QDataStream & pStream, const CANBus& pCanBus )
|
QDataStream& operator<<(QDataStream & pStream, const CANBus& pCanBus)
|
||||||
{
|
{
|
||||||
pStream << pCanBus.speed;
|
pStream << pCanBus.speed;
|
||||||
pStream << pCanBus.listenOnly;
|
pStream << pCanBus.listenOnly;
|
||||||
pStream << pCanBus.singleWire;
|
pStream << pCanBus.singleWire;
|
||||||
pStream << pCanBus.active;
|
pStream << pCanBus.active;
|
||||||
|
// FIXME CANFD settings missing
|
||||||
return pStream;
|
return pStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-16
@@ -5,13 +5,6 @@
|
|||||||
|
|
||||||
class CANBus
|
class CANBus
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
CANBus();
|
|
||||||
CANBus(const CANBus&);
|
|
||||||
bool operator==(const CANBus&) const;
|
|
||||||
CANBus& operator=(const CANBus& other) = default;
|
|
||||||
//virtual ~CANBus(){}
|
|
||||||
|
|
||||||
int speed;
|
int speed;
|
||||||
bool listenOnly;
|
bool listenOnly;
|
||||||
bool singleWire;
|
bool singleWire;
|
||||||
@@ -19,28 +12,36 @@ public:
|
|||||||
bool canFD;
|
bool canFD;
|
||||||
int dataRate;
|
int dataRate;
|
||||||
|
|
||||||
|
friend QDataStream& operator<<(QDataStream & pStream, const CANBus& pCanBus);
|
||||||
|
friend QDataStream& operator>>(QDataStream & pStream, CANBus& pCanBus);
|
||||||
|
public:
|
||||||
|
CANBus();
|
||||||
|
|
||||||
|
bool operator==(const CANBus&) const;
|
||||||
|
|
||||||
void setSpeed(int); // new speed
|
void setSpeed(int); // new speed
|
||||||
void setListenOnly(bool); //bool for whether to only listen
|
void setListenOnly(bool); //bool for whether to only listen
|
||||||
void setSingleWire(bool); //bool for whether to use single wire mode
|
void setSingleWire(bool); //bool for whether to use single wire mode
|
||||||
void setActive(bool); //whether this bus should be enabled or not.
|
void setActive(bool); //whether this bus should be enabled or not.
|
||||||
void setCanFD(bool); // enable or disable CANFD support
|
void setCanFD(bool); // enable or disable CANFD support
|
||||||
int getSpeed();
|
|
||||||
int getDataRate();
|
|
||||||
void setDataRate(int newSpeed);
|
void setDataRate(int newSpeed);
|
||||||
bool isListenOnly();
|
|
||||||
bool isSingleWire();
|
int getSpeed() const;
|
||||||
bool isActive();
|
int getDataRate() const;
|
||||||
bool isCanFD();
|
bool isListenOnly() const;
|
||||||
|
bool isSingleWire() const;
|
||||||
|
bool isActive() const;
|
||||||
|
bool isCanFD() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
QDataStream& operator<<( QDataStream & pStream, const CANBus& pCanBus );
|
QDataStream& operator<<(QDataStream & pStream, const CANBus& pCanBus);
|
||||||
QDataStream & operator>>(QDataStream & pStream, CANBus& pCanBus);
|
QDataStream& operator>>(QDataStream & pStream, CANBus& pCanBus);
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(CANBus);
|
Q_DECLARE_METATYPE(CANBus);
|
||||||
|
|
||||||
struct BusData {
|
struct BusData {
|
||||||
CANBus mBus;
|
CANBus mBus;
|
||||||
bool mConfigured;
|
bool mConfigured = {};
|
||||||
QVector<CANFltObserver> mTargettedFrames;
|
QVector<CANFltObserver> mTargettedFrames;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ CANConnection* CanConFactory::create(type pType, QString pPortName, QString pDri
|
|||||||
{
|
{
|
||||||
switch(pType) {
|
switch(pType) {
|
||||||
case SERIALBUS:
|
case SERIALBUS:
|
||||||
return new SerialBusConnection(pPortName, pDriverName);
|
return new SerialBusConnection(pPortName, pDriverName, pBusSpeed, pDataRate, pCanFd);
|
||||||
case GVRET_SERIAL:
|
case GVRET_SERIAL:
|
||||||
if(pPortName.contains(".") && !pPortName.contains("tty") && !pPortName.contains("serial"))
|
if(pPortName.contains(".") && !pPortName.contains("tty") && !pPortName.contains("serial"))
|
||||||
return new GVRetSerial(pPortName, true);
|
return new GVRetSerial(pPortName, true);
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ bool CANConManager::sendFrame(const CANFrame& pFrame)
|
|||||||
workingFrame.isReceived = false;
|
workingFrame.isReceived = false;
|
||||||
if (useSystemTime)
|
if (useSystemTime)
|
||||||
{
|
{
|
||||||
workingFrame.setTimeStamp(QCanBusFrame::TimeStamp(0,QDateTime::currentMSecsSinceEpoch() * 1000));
|
workingFrame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ CANConnection::CANConnection(QString pPort,
|
|||||||
int pQueueLen,
|
int pQueueLen,
|
||||||
bool pUseThread) :
|
bool pUseThread) :
|
||||||
mNumBuses(pNumBuses),
|
mNumBuses(pNumBuses),
|
||||||
|
mSerialSpeed(pSerialSpeed),
|
||||||
mQueue(),
|
mQueue(),
|
||||||
mPort(pPort),
|
mPort(pPort),
|
||||||
mDriver(pDriver),
|
mDriver(pDriver),
|
||||||
mType(pType),
|
mType(pType),
|
||||||
mSerialSpeed(pSerialSpeed),
|
|
||||||
mIsCapSuspended(false),
|
mIsCapSuspended(false),
|
||||||
mStatus(CANCon::NOT_CONNECTED),
|
mStatus(CANCon::NOT_CONNECTED),
|
||||||
mStarted(false),
|
mStarted(false),
|
||||||
@@ -41,7 +41,12 @@ CANConnection::CANConnection(QString pPort,
|
|||||||
|
|
||||||
if (pBusSpeed > 0) mBusData[0].mBus.setSpeed(pBusSpeed);
|
if (pBusSpeed > 0) mBusData[0].mBus.setSpeed(pBusSpeed);
|
||||||
mBusData[0].mBus.setCanFD(pCanFd);
|
mBusData[0].mBus.setCanFD(pCanFd);
|
||||||
if (pDataRate > 0) mBusData[0].mBus.setDataRate(pDataRate);
|
if (pDataRate > 0) {
|
||||||
|
mBusData[0].mBus.setDataRate(pDataRate);
|
||||||
|
if (pCanFd) {
|
||||||
|
mBusData[0].mBus.setCanFD(pCanFd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* if needed, create a thread and move ourself into it */
|
/* if needed, create a thread and move ourself into it */
|
||||||
if(pUseThread) {
|
if(pUseThread) {
|
||||||
@@ -210,6 +215,10 @@ int CANConnection::getNumBuses() const{
|
|||||||
return mNumBuses;
|
return mNumBuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CANConnection::getSerialSpeed() const{
|
||||||
|
return mSerialSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CANConnection::isConfigured(int pBusId) {
|
bool CANConnection::isConfigured(int pBusId) {
|
||||||
if( pBusId < 0 || pBusId >= getNumBuses())
|
if( pBusId < 0 || pBusId >= getNumBuses())
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
int getNumBuses() const;
|
int getNumBuses() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getserialSpeed
|
||||||
|
* @return returns the serial speed of the device
|
||||||
|
*/
|
||||||
|
int getSerialSpeed() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getPort
|
* @brief getPort
|
||||||
* @return returns the port name of the device
|
* @return returns the port name of the device
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ void CANserver::readNetworkData()
|
|||||||
frame_p->setFrameType(QCanBusFrame::DataFrame);
|
frame_p->setFrameType(QCanBusFrame::DataFrame);
|
||||||
frame_p->isReceived = true;
|
frame_p->isReceived = true;
|
||||||
|
|
||||||
frame_p->setTimeStamp(QCanBusFrame::TimeStamp(0, QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
frame_p->setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||||
|
|
||||||
frame_p->setPayload(datagram.mid(dataByteLocation, length));
|
frame_p->setPayload(datagram.mid(dataByteLocation, length));
|
||||||
|
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) :
|
|||||||
//Need to make sure it tries to share the address in case there are
|
//Need to make sure it tries to share the address in case there are
|
||||||
//multiple instances of SavvyCAN running.
|
//multiple instances of SavvyCAN running.
|
||||||
rxBroadcastGVRET->bind(QHostAddress::AnyIPv4, 17222, QAbstractSocket::ShareAddress);
|
rxBroadcastGVRET->bind(QHostAddress::AnyIPv4, 17222, QAbstractSocket::ShareAddress);
|
||||||
connect(rxBroadcastGVRET, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
|
connect(rxBroadcastGVRET, &QUdpSocket::readyRead, this, &ConnectionWindow::readPendingDatagrams);
|
||||||
|
|
||||||
//Doing the same for socketcand/kayak hosts:
|
//Doing the same for socketcand/kayak hosts:
|
||||||
rxBroadcastKayak = new QUdpSocket(this);
|
rxBroadcastKayak = new QUdpSocket(this);
|
||||||
rxBroadcastKayak->bind(QHostAddress::AnyIPv4, 42000, QAbstractSocket::ShareAddress);
|
rxBroadcastKayak->bind(QHostAddress::AnyIPv4, 42000, QAbstractSocket::ShareAddress);
|
||||||
connect(rxBroadcastKayak, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
|
connect(rxBroadcastKayak, &QUdpSocket::readyRead, this, &ConnectionWindow::readPendingDatagrams);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,12 +236,12 @@ void ConnectionWindow::consoleEnableChanged(bool checked) {
|
|||||||
CANConnection* conn_p = connModel->getAtIdx(selIdx);
|
CANConnection* conn_p = connModel->getAtIdx(selIdx);
|
||||||
|
|
||||||
if (checked) { //enable console
|
if (checked) { //enable console
|
||||||
connect(conn_p, SIGNAL(debugOutput(QString)), this, SLOT(getDebugText(QString)));
|
connect(conn_p, &CANConnection::debugOutput, this, &ConnectionWindow::getDebugText, Qt::UniqueConnection);
|
||||||
connect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
connect(this, &ConnectionWindow::sendDebugData, conn_p, &CANConnection::debugInput, Qt::UniqueConnection);
|
||||||
}
|
}
|
||||||
else { //turn it off
|
else { //turn it off
|
||||||
disconnect(conn_p, SIGNAL(debugOutput(QString)), nullptr, nullptr);
|
disconnect(conn_p, &CANConnection::debugOutput, nullptr, nullptr);
|
||||||
disconnect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
disconnect(this, &ConnectionWindow::sendDebugData, conn_p, &CANConnection::debugInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +336,9 @@ void ConnectionWindow::connectionStatus(CANConStatus pStatus)
|
|||||||
Q_UNUSED(pStatus);
|
Q_UNUSED(pStatus);
|
||||||
|
|
||||||
qDebug() << "Connectionstatus changed";
|
qDebug() << "Connectionstatus changed";
|
||||||
|
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||||
connModel->refresh();
|
connModel->refresh();
|
||||||
|
ui->tableConnections->selectRow(selIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::setSuspendAll(bool pSuspend)
|
void ConnectionWindow::setSuspendAll(bool pSuspend)
|
||||||
@@ -454,8 +456,8 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
|||||||
int selIdx = current.row();
|
int selIdx = current.row();
|
||||||
CANConnection* prevConn = connModel->getAtIdx(previous.row());
|
CANConnection* prevConn = connModel->getAtIdx(previous.row());
|
||||||
if(prevConn != nullptr)
|
if(prevConn != nullptr)
|
||||||
disconnect(prevConn, SIGNAL(debugOutput(QString)), nullptr, nullptr);
|
disconnect(prevConn, &CANConnection::debugOutput, nullptr, nullptr);
|
||||||
disconnect(this, SIGNAL(sendDebugData(QByteArray)), nullptr, nullptr);
|
disconnect(this, &ConnectionWindow::sendDebugData, nullptr, nullptr);
|
||||||
|
|
||||||
/* set parameters */
|
/* set parameters */
|
||||||
if (selIdx == -1) {
|
if (selIdx == -1) {
|
||||||
@@ -472,7 +474,7 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
|||||||
if(!conn_p) return;
|
if(!conn_p) return;
|
||||||
|
|
||||||
//because this might have already been setup during the initial setup so tear that one down and then create the normal one.
|
//because this might have already been setup during the initial setup so tear that one down and then create the normal one.
|
||||||
//disconnect(conn_p, SIGNAL(debugOutput(QString)), 0, 0);
|
//disconnect(conn_p, &CANConnection::debugOutput, 0, 0);
|
||||||
|
|
||||||
numBuses = conn_p->getNumBuses();
|
numBuses = conn_p->getNumBuses();
|
||||||
int numB = ui->tabBuses->count();
|
int numB = ui->tabBuses->count();
|
||||||
@@ -485,8 +487,8 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
|||||||
populateBusDetails(0);
|
populateBusDetails(0);
|
||||||
if (ui->ckEnableConsole->isChecked())
|
if (ui->ckEnableConsole->isChecked())
|
||||||
{
|
{
|
||||||
connect(conn_p, SIGNAL(debugOutput(QString)), this, SLOT(getDebugText(QString)));
|
connect(conn_p, &CANConnection::debugOutput, this, &ConnectionWindow::getDebugText, Qt::UniqueConnection);
|
||||||
connect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
connect(this, &ConnectionWindow::sendDebugData, conn_p, &CANConnection::debugInput, Qt::UniqueConnection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -524,12 +526,11 @@ CANConnection* ConnectionWindow::create(CANCon::type pTye, QString pPortName, QS
|
|||||||
if(conn_p)
|
if(conn_p)
|
||||||
{
|
{
|
||||||
/* connect signal */
|
/* connect signal */
|
||||||
connect(conn_p, SIGNAL(status(CANConStatus)),
|
connect(conn_p, &CANConnection::status, this, &ConnectionWindow::connectionStatus);
|
||||||
this, SLOT(connectionStatus(CANConStatus)));
|
|
||||||
if (ui->ckEnableConsole->isChecked())
|
if (ui->ckEnableConsole->isChecked())
|
||||||
{
|
{
|
||||||
//set up the debug console to operate if we've selected it. Doing so here allows debugging right away during set up
|
//set up the debug console to operate if we've selected it. Doing so here allows debugging right away during set up
|
||||||
connect(conn_p, SIGNAL(debugOutput(QString)), this, SLOT(getDebugText(QString)));
|
connect(conn_p, &CANConnection::debugOutput, this, &ConnectionWindow::getDebugText, Qt::UniqueConnection);
|
||||||
}
|
}
|
||||||
/*TODO add return value and checks */
|
/*TODO add return value and checks */
|
||||||
conn_p->start();
|
conn_p->start();
|
||||||
@@ -552,13 +553,17 @@ void ConnectionWindow::loadConnections()
|
|||||||
QVector<QString> driverNames = settings.value("connections/driverNames").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>>();
|
||||||
|
|
||||||
|
QVector<int> busSpeeds = settings.value("connections/busSpeeds_0").value<QVector<int>>();
|
||||||
|
QVector<int> DataRates = settings.value("connections/DataRates_0").value<QVector<int>>();
|
||||||
|
QVector<int> isCanFds = settings.value("connections/isCanFds_0").value<QVector<int>>();
|
||||||
|
QVector<int> serialSpeeds = settings.value("connections/serialSpeeds").value<QVector<int>>();
|
||||||
//don't load the connections if the three setting arrays above aren't all the same size.
|
//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;
|
if (portNames.count() != driverNames.count() || devTypes.count() != driverNames.count() || busSpeeds.count() != driverNames.count() || isCanFds.count() != driverNames.count() ||
|
||||||
|
DataRates.count() != driverNames.count() || serialSpeeds.count() != driverNames.count() ) return;
|
||||||
|
|
||||||
for(int i = 0 ; i < portNames.count() ; i++)
|
for(int i = 0 ; i < portNames.count() ; i++)
|
||||||
{
|
{
|
||||||
//TODO: add serial speed and bus speed to this properly.
|
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i], driverNames[i], serialSpeeds[i], busSpeeds[i], isCanFds[i] ? true : false, DataRates[i]);
|
||||||
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i], driverNames[i], 0, 0, false, 0);
|
|
||||||
/* add connection to model */
|
/* add connection to model */
|
||||||
connModel->add(conn_p);
|
connModel->add(conn_p);
|
||||||
}
|
}
|
||||||
@@ -578,10 +583,19 @@ void ConnectionWindow::saveConnections()
|
|||||||
QVector<QString> driverNames;
|
QVector<QString> driverNames;
|
||||||
QVector<int> serialSpeeds;
|
QVector<int> serialSpeeds;
|
||||||
QVector<int> busSpeeds;
|
QVector<int> busSpeeds;
|
||||||
|
QVector<int> DataRates;
|
||||||
|
QVector<int> CanFds;
|
||||||
|
|
||||||
/* save connections */
|
/* save connections */
|
||||||
foreach(CANConnection* conn_p, conns)
|
foreach(CANConnection* conn_p, conns)
|
||||||
{
|
{ CANBus bus;
|
||||||
|
|
||||||
|
if (conn_p->getBusSettings(0, bus)) {
|
||||||
|
busSpeeds.append(bus.getSpeed());
|
||||||
|
CanFds.append(bus.isCanFD() ? 1 : 0);
|
||||||
|
DataRates.append(bus.getDataRate());
|
||||||
|
}
|
||||||
|
serialSpeeds.append(conn_p->getSerialSpeed());
|
||||||
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());
|
driverNames.append(conn_p->getDriver());
|
||||||
@@ -590,6 +604,10 @@ void ConnectionWindow::saveConnections()
|
|||||||
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));
|
settings.setValue("connections/driverNames", QVariant::fromValue(driverNames));
|
||||||
|
settings.setValue("connections/busSpeeds_0", QVariant::fromValue(busSpeeds));
|
||||||
|
settings.setValue("connections/isCanFds_0", QVariant::fromValue(CanFds));
|
||||||
|
settings.setValue("connections/DataRates_0", QVariant::fromValue(DataRates));
|
||||||
|
settings.setValue("connections/serialSpeeds", QVariant::fromValue(serialSpeeds));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::moveConnUp()
|
void ConnectionWindow::moveConnUp()
|
||||||
|
|||||||
@@ -685,9 +685,10 @@ void GVRetSerial::procRXChar(unsigned char c)
|
|||||||
buildTimestamp += timeBasis;
|
buildTimestamp += timeBasis;
|
||||||
if (useSystemTime)
|
if (useSystemTime)
|
||||||
{
|
{
|
||||||
buildTimestamp = QDateTime::currentMSecsSinceEpoch() * 1000l;
|
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||||
|
} else {
|
||||||
|
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, buildTimestamp));
|
||||||
}
|
}
|
||||||
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, buildTimestamp));
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
buildId = c;
|
buildId = c;
|
||||||
@@ -770,9 +771,10 @@ void GVRetSerial::procRXChar(unsigned char c)
|
|||||||
buildTimestamp += timeBasis;
|
buildTimestamp += timeBasis;
|
||||||
if (useSystemTime)
|
if (useSystemTime)
|
||||||
{
|
{
|
||||||
buildTimestamp = QDateTime::currentMSecsSinceEpoch() * 1000l;
|
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||||
|
} else {
|
||||||
|
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, buildTimestamp));
|
||||||
}
|
}
|
||||||
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, buildTimestamp));
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
buildId = c;
|
buildId = c;
|
||||||
|
|||||||
@@ -491,7 +491,26 @@ void LAWICELSerial::readSerialData()
|
|||||||
{
|
{
|
||||||
qDebug() << "Got CR!";
|
qDebug() << "Got CR!";
|
||||||
|
|
||||||
buildFrame.setTimeStamp(QDateTime::currentMSecsSinceEpoch() * 1000l);
|
if (useSystemTime)
|
||||||
|
{
|
||||||
|
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//If total length is greater than command, header and data, timestamps must be enabled.
|
||||||
|
if (data.length() > (5 + mBuildLine.mid(4, 1).toInt() * 2 + 1))
|
||||||
|
{
|
||||||
|
//Four bytes after the end of the data bytes.
|
||||||
|
buildTimestamp = mBuildLine.mid(5 + mBuildLine.mid(4, 1).toInt() * 2, 4).toInt(nullptr, 16) * 1000l;
|
||||||
|
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, buildTimestamp));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Default to system time if timestamps are disabled.
|
||||||
|
buildFrame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (mBuildLine[0].toLatin1())
|
switch (mBuildLine[0].toLatin1())
|
||||||
{
|
{
|
||||||
case 't': //standard frame
|
case 't': //standard frame
|
||||||
@@ -551,6 +570,7 @@ void LAWICELSerial::readSerialData()
|
|||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
buildFrame.setBitrateSwitch(true); //BRS enabled
|
buildFrame.setBitrateSwitch(true); //BRS enabled
|
||||||
|
[[fallthrough]];
|
||||||
case 'd': //standard fd frame, BRS disabled
|
case 'd': //standard fd frame, BRS disabled
|
||||||
//tIIILDD
|
//tIIILDD
|
||||||
buildFrame.setFlexibleDataRateFormat(true);
|
buildFrame.setFlexibleDataRateFormat(true);
|
||||||
@@ -581,6 +601,7 @@ void LAWICELSerial::readSerialData()
|
|||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
buildFrame.setBitrateSwitch(true); //BRS enabled
|
buildFrame.setBitrateSwitch(true); //BRS enabled
|
||||||
|
[[fallthrough]];
|
||||||
case 'D': //extended fd frame
|
case 'D': //extended fd frame
|
||||||
//TIIIIIIIILDD.
|
//TIIIIIIIILDD.
|
||||||
buildFrame.setFlexibleDataRateFormat(true);
|
buildFrame.setFlexibleDataRateFormat(true);
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ protected:
|
|||||||
QSerialPort *serial;
|
QSerialPort *serial;
|
||||||
int framesRapid;
|
int framesRapid;
|
||||||
CANFrame buildFrame;
|
CANFrame buildFrame;
|
||||||
|
qint64 buildTimestamp;
|
||||||
bool can0Enabled;
|
bool can0Enabled;
|
||||||
bool can0ListenOnly;
|
bool can0ListenOnly;
|
||||||
bool canFd;
|
bool canFd;
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ void MQTT_BUS::clientMessageReceived(const QMQTT::Message& message)
|
|||||||
frame_p->isReceived = true;
|
frame_p->isReceived = true;
|
||||||
if (useSystemTime)
|
if (useSystemTime)
|
||||||
{
|
{
|
||||||
frame_p->setTimeStamp(QCanBusFrame::TimeStamp(0, QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
frame_p->setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||||
}
|
}
|
||||||
else frame_p->setTimeStamp(QCanBusFrame::TimeStamp(0, timeStamp));
|
else frame_p->setTimeStamp(QCanBusFrame::TimeStamp(0, timeStamp));
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
/**** class definition ****/
|
/**** class definition ****/
|
||||||
/***********************************/
|
/***********************************/
|
||||||
|
|
||||||
SerialBusConnection::SerialBusConnection(QString portName, QString driverName) :
|
SerialBusConnection::SerialBusConnection(QString portName, QString driverName, int pBusSpeed, int pDataRate, bool pCanFd) :
|
||||||
CANConnection(portName, driverName, CANCon::SERIALBUS,0 ,0, false, 0 ,1, 4000, true),
|
CANConnection(portName, driverName, CANCon::SERIALBUS,0 ,pBusSpeed, pCanFd, pDataRate ,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 */
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ void SerialBusConnection::piSetBusSettings(int pBusIdx, CANBus bus)
|
|||||||
setBusConfig(0, bus);
|
setBusConfig(0, bus);
|
||||||
|
|
||||||
/* if bus is not active we are done */
|
/* if bus is not active we are done */
|
||||||
if(!bus.active)
|
if(!bus.isActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* set configuration */
|
/* set configuration */
|
||||||
@@ -105,10 +105,10 @@ 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.
|
||||||
//But, you can probabaly set the speed of many of the other serialbus devices so go ahead and try
|
//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);
|
mDev_p->setConfigurationParameter(QCanBusDevice::BitRateKey, bus.getSpeed());
|
||||||
mDev_p->setConfigurationParameter(QCanBusDevice::CanFdKey, bus.canFD);
|
mDev_p->setConfigurationParameter(QCanBusDevice::CanFdKey, bus.isCanFD());
|
||||||
|
|
||||||
if(bus.listenOnly)
|
if(bus.isListenOnly())
|
||||||
sbusconfig |= EN_SILENT_MODE;
|
sbusconfig |= EN_SILENT_MODE;
|
||||||
mDev_p->setConfigurationParameter(QCanBusDevice::UserKey, sbusconfig);
|
mDev_p->setConfigurationParameter(QCanBusDevice::UserKey, sbusconfig);
|
||||||
|
|
||||||
@@ -188,6 +188,7 @@ void SerialBusConnection::framesReceived()
|
|||||||
|
|
||||||
/* check frame */
|
/* check frame */
|
||||||
//if (recFrame.payload().length() <= 8) {
|
//if (recFrame.payload().length() <= 8) {
|
||||||
|
if (true) {
|
||||||
CANFrame* frame_p = getQueue().get();
|
CANFrame* frame_p = getQueue().get();
|
||||||
if(frame_p) {
|
if(frame_p) {
|
||||||
frame_p->setPayload(recFrame.payload());
|
frame_p->setPayload(recFrame.payload());
|
||||||
@@ -206,11 +207,11 @@ void SerialBusConnection::framesReceived()
|
|||||||
frame_p->setTimeStamp(recFrame.timeStamp());
|
frame_p->setTimeStamp(recFrame.timeStamp());
|
||||||
frame_p->setFrameType(recFrame.frameType());
|
frame_p->setFrameType(recFrame.frameType());
|
||||||
frame_p->setError(recFrame.error());
|
frame_p->setError(recFrame.error());
|
||||||
/* If recorded frame has a local echo, it is a Tx message, and thus should not be marked as Rx */
|
/* If recorded frame has a local echo, it is a Tx message, and thus should not be marked as Rx */
|
||||||
frame_p->isReceived = !recFrame.hasLocalEcho();
|
frame_p->isReceived = !recFrame.hasLocalEcho();
|
||||||
|
|
||||||
if (useSystemTime) {
|
if (useSystemTime) {
|
||||||
frame_p->setTimeStamp(QCanBusFrame::TimeStamp(0, QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
frame_p->setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||||
}
|
}
|
||||||
else frame_p->setTimeStamp(QCanBusFrame::TimeStamp(0, (recFrame.timeStamp().seconds() * 1000000ul + recFrame.timeStamp().microSeconds()) - timeBasis));
|
else frame_p->setTimeStamp(QCanBusFrame::TimeStamp(0, (recFrame.timeStamp().seconds() * 1000000ul + recFrame.timeStamp().microSeconds()) - timeBasis));
|
||||||
|
|
||||||
@@ -218,11 +219,9 @@ void SerialBusConnection::framesReceived()
|
|||||||
|
|
||||||
/* enqueue frame */
|
/* enqueue frame */
|
||||||
getQueue().queue();
|
getQueue().queue();
|
||||||
//}
|
}
|
||||||
#if 0
|
|
||||||
else
|
else
|
||||||
qDebug() << "can't get a frame, ERROR";
|
qDebug() << "can't get a frame, ERROR";
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ class SerialBusConnection : public CANConnection
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SerialBusConnection(QString portName, QString driverName);
|
SerialBusConnection(QString portName, QString driverName, int pBusSpeed,
|
||||||
|
int pDataRate, bool pCanFd);
|
||||||
virtual ~SerialBusConnection();
|
virtual ~SerialBusConnection();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -219,8 +219,8 @@ void SocketCANd::connectDevice()
|
|||||||
void SocketCANd::deviceConnected(int busNum)
|
void SocketCANd::deviceConnected(int busNum)
|
||||||
{
|
{
|
||||||
sendDebug("Opening CAN on Kayak Device!");
|
sendDebug("Opening CAN on Kayak Device!");
|
||||||
const char* openCanCmd = ("< open " + hostCanIDs[busNum] + " >").toStdString().c_str();
|
QString openCanCmd("< open " % hostCanIDs[busNum] % " >");
|
||||||
sendStringToTCP(openCanCmd, busNum);
|
sendStringToTCP(openCanCmd.toUtf8().data(), busNum);
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
}
|
}
|
||||||
@@ -383,8 +383,6 @@ void SocketCANd::procRXData(QString data, int busNum)
|
|||||||
mTimer.stop();
|
mTimer.stop();
|
||||||
mTimer.start();
|
mTimer.start();
|
||||||
}
|
}
|
||||||
QByteArray output;
|
|
||||||
|
|
||||||
switch (rx_state.at(busNum))
|
switch (rx_state.at(busNum))
|
||||||
{
|
{
|
||||||
case IDLE:
|
case IDLE:
|
||||||
|
|||||||
+8
-4
@@ -166,12 +166,16 @@ QString DBC_SIGNAL::processSignalTree(const CANFrame &frame)
|
|||||||
if (sig->processAsText(frame, sigString))
|
if (sig->processAsText(frame, sigString))
|
||||||
{
|
{
|
||||||
qDebug() << "Returned value: " << sigString;
|
qDebug() << "Returned value: " << sigString;
|
||||||
|
if (!build.isEmpty() && !sigString.isEmpty())
|
||||||
|
build.append("\n");
|
||||||
build.append(sigString);
|
build.append(sigString);
|
||||||
build.append("\n");
|
|
||||||
if (sig->isMultiplexor)
|
if (sig->isMultiplexor)
|
||||||
{
|
{
|
||||||
qDebug() << "Spelunkin!";
|
qDebug() << "Spelunkin!";
|
||||||
build.append(sig->processSignalTree(frame));
|
auto subTreeString = sig->processSignalTree(frame);
|
||||||
|
if (!build.isEmpty() && !subTreeString.isEmpty())
|
||||||
|
build.append("\n");
|
||||||
|
build.append(subTreeString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,12 +304,12 @@ QString DBC_SIGNAL::makePrettyOutput(double floatVal, int64_t intVal, bool outpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!foundVal) outputString += QString::number(intVal);
|
if (!foundVal) outputString += QString::number(intVal);
|
||||||
if (outputUnit) outputString += unitName;
|
if (outputUnit) outputString += " " + unitName;
|
||||||
}
|
}
|
||||||
else //otherwise display the actual number and unit (if it exists)
|
else //otherwise display the actual number and unit (if it exists)
|
||||||
{
|
{
|
||||||
outputString += (isInteger ? QString::number(intVal) : QString::number(floatVal));
|
outputString += (isInteger ? QString::number(intVal) : QString::number(floatVal));
|
||||||
if (outputUnit) outputString += unitName;
|
if (outputUnit) outputString += " " + unitName;
|
||||||
}
|
}
|
||||||
return outputString;
|
return outputString;
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-4
@@ -674,6 +674,44 @@ bool DBCFile::parseSignalMultiplexValueLine(QString line)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DBCFile::parseSignalValueTypeLine(QString line)
|
||||||
|
{
|
||||||
|
QRegularExpression regex;
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
qDebug() << "Found a signal valtype line";
|
||||||
|
regex.setPattern("^SIG\\_VALTYPE\\_ *(\\d+) *([-\\w]+) *: *(\\d+);");
|
||||||
|
match = regex.match(line);
|
||||||
|
|
||||||
|
// captured 1 is the message id
|
||||||
|
// captured 2 is the signal name
|
||||||
|
// captured 3 is the valtype
|
||||||
|
if (!match.hasMatch()) { return false; }
|
||||||
|
uint32_t id = match.captured(1).toULong() & 0x1FFFFFFFUL;
|
||||||
|
|
||||||
|
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toULong() & 0x1FFFFFFFUL);
|
||||||
|
if (msg == nullptr) { return false; }
|
||||||
|
|
||||||
|
DBC_SIGNAL *thisSignal = msg->sigHandler->findSignalByName(match.captured(2));
|
||||||
|
if (thisSignal == nullptr) { return false; }
|
||||||
|
int valType = match.captured(3).toInt();
|
||||||
|
|
||||||
|
switch (valType) {
|
||||||
|
case 1: {
|
||||||
|
thisSignal->valType = SP_FLOAT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
thisSignal->valType = DP_FLOAT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DBCFile::parseValueLine(QString line)
|
bool DBCFile::parseValueLine(QString line)
|
||||||
{
|
{
|
||||||
QRegularExpression regex;
|
QRegularExpression regex;
|
||||||
@@ -737,7 +775,7 @@ bool DBCFile::parseAttributeLine(QString line)
|
|||||||
if (foundAttr)
|
if (foundAttr)
|
||||||
{
|
{
|
||||||
qDebug() << "That message attribute does exist";
|
qDebug() << "That message attribute does exist";
|
||||||
DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toUInt() & 0x1FFFFFFFul);
|
DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toULong() & 0x1FFFFFFFul);
|
||||||
if (foundMsg)
|
if (foundMsg)
|
||||||
{
|
{
|
||||||
qDebug() << "It references a valid, registered message";
|
qDebug() << "It references a valid, registered message";
|
||||||
@@ -769,7 +807,7 @@ bool DBCFile::parseAttributeLine(QString line)
|
|||||||
if (foundAttr)
|
if (foundAttr)
|
||||||
{
|
{
|
||||||
qDebug() << "That signal attribute does exist";
|
qDebug() << "That signal attribute does exist";
|
||||||
DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toUInt() & 0x1FFFFFFFUL);
|
DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toULong() & 0x1FFFFFFFUL);
|
||||||
if (foundMsg)
|
if (foundMsg)
|
||||||
{
|
{
|
||||||
qDebug() << "It references a valid, registered message";
|
qDebug() << "It references a valid, registered message";
|
||||||
@@ -941,6 +979,11 @@ bool DBCFile::loadFile(QString fileName)
|
|||||||
if (!parseSignalMultiplexValueLine(line)) numSigFaults++;
|
if (!parseSignalMultiplexValueLine(line)) numSigFaults++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (line.startsWith("SIG_VALTYPE_ ")) //defines a signal value type
|
||||||
|
{
|
||||||
|
if (!parseSignalValueTypeLine(line)) numSigFaults++;
|
||||||
|
}
|
||||||
|
|
||||||
if (line.startsWith("BU_:")) //line specifies the nodes on this canbus
|
if (line.startsWith("BU_:")) //line specifies the nodes on this canbus
|
||||||
{
|
{
|
||||||
qDebug() << "Found a BU line";
|
qDebug() << "Found a BU line";
|
||||||
@@ -976,7 +1019,7 @@ bool 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).toUInt());
|
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toULong() & 0x1FFFFFFFul);
|
||||||
if (msg != nullptr)
|
if (msg != nullptr)
|
||||||
{
|
{
|
||||||
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(match.captured(2));
|
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(match.captured(2));
|
||||||
@@ -997,7 +1040,7 @@ bool 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).toUInt());
|
DBC_MESSAGE *msg = messageHandler->findMsgByID(match.captured(1).toULong() & 0x1FFFFFFFul);
|
||||||
if (msg != nullptr)
|
if (msg != nullptr)
|
||||||
{
|
{
|
||||||
msg->comment = match.captured(2);
|
msg->comment = match.captured(2);
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ private:
|
|||||||
bool parseSignalMultiplexValueLine(QString line);
|
bool parseSignalMultiplexValueLine(QString line);
|
||||||
DBC_MESSAGE* parseMessageLine(QString line);
|
DBC_MESSAGE* parseMessageLine(QString line);
|
||||||
bool parseValueLine(QString line);
|
bool parseValueLine(QString line);
|
||||||
|
bool parseSignalValueTypeLine(QString line);
|
||||||
bool parseAttributeLine(QString line);
|
bool parseAttributeLine(QString line);
|
||||||
bool parseDefaultAttrLine(QString line);
|
bool parseDefaultAttrLine(QString line);
|
||||||
};
|
};
|
||||||
|
|||||||
+39
-42
@@ -133,38 +133,38 @@ void FirmwareUploaderWindow::timerElapsed()
|
|||||||
|
|
||||||
void FirmwareUploaderWindow::sendFirmwareChunk()
|
void FirmwareUploaderWindow::sendFirmwareChunk()
|
||||||
{
|
{
|
||||||
CANFrame *output = new CANFrame;
|
CANFrame output;
|
||||||
int firmwareLocation = currentSendingPosition * 4;
|
int firmwareLocation = currentSendingPosition * 4;
|
||||||
int xorByte = 0;
|
int xorByte = 0;
|
||||||
output->setExtendedFrameFormat(false);
|
output.setExtendedFrameFormat(false);
|
||||||
QByteArray bytes(7,0);
|
QByteArray bytes(7,0);
|
||||||
output->bus = bus;
|
output.bus = bus;
|
||||||
output->setFrameId(baseAddress + 0x16);
|
output.setFrameId(baseAddress + 0x16);
|
||||||
output->payload()[0] = currentSendingPosition & 0xFF;
|
bytes[0] = currentSendingPosition & 0xFF;
|
||||||
output->payload()[1] = (currentSendingPosition >> 8) & 0xFF;
|
bytes[1] = (currentSendingPosition >> 8) & 0xFF;
|
||||||
output->payload()[2] = firmwareData[firmwareLocation++];
|
bytes[2] = firmwareData[firmwareLocation++];
|
||||||
output->payload()[3] = firmwareData[firmwareLocation++];
|
bytes[3] = firmwareData[firmwareLocation++];
|
||||||
output->payload()[4] = firmwareData[firmwareLocation++];
|
bytes[4] = firmwareData[firmwareLocation++];
|
||||||
output->payload()[5] = firmwareData[firmwareLocation++];
|
bytes[5] = firmwareData[firmwareLocation++];
|
||||||
for (int i = 0; i < 6; i++) xorByte = xorByte ^ static_cast<unsigned char>(output->payload()[i]);
|
for (int i = 0; i < 6; i++) xorByte ^= static_cast<unsigned char>(bytes[i]);
|
||||||
output->payload()[6] = xorByte;
|
bytes[6] = xorByte;
|
||||||
output->setPayload(bytes);
|
output.setPayload(bytes);
|
||||||
CANConManager::getInstance()->sendFrame(*output);
|
CANConManager::getInstance()->sendFrame(output);
|
||||||
timer->start();
|
timer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FirmwareUploaderWindow::sendFirmwareEnding()
|
void FirmwareUploaderWindow::sendFirmwareEnding()
|
||||||
{
|
{
|
||||||
CANFrame *output = new CANFrame;
|
CANFrame output;
|
||||||
output->setExtendedFrameFormat(false);
|
output.setExtendedFrameFormat(false);
|
||||||
output->bus = bus;
|
output.bus = bus;
|
||||||
QByteArray bytes(4,0);
|
QByteArray bytes(4,0);
|
||||||
output->setFrameId(baseAddress + 0x30);
|
output.setFrameId(baseAddress + 0x30);
|
||||||
output->payload()[3] = 0xC0;
|
bytes[3] = (char)0xC0;
|
||||||
output->payload()[2] = 0xDE;
|
bytes[2] = (char)0xDE;
|
||||||
output->payload()[1] = 0xFA;
|
bytes[1] = (char)0xFA;
|
||||||
output->payload()[0] = 0xDE;
|
bytes[0] = (char)0xDE;
|
||||||
output->setPayload(bytes);
|
output.setPayload(bytes);
|
||||||
//sendCANFrame(output, bus);
|
//sendCANFrame(output, bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,23 +182,23 @@ void FirmwareUploaderWindow::handleStartStopTransfer()
|
|||||||
qDebug() << "Base address: " + QString::number(baseAddress);
|
qDebug() << "Base address: " + QString::number(baseAddress);
|
||||||
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x10, 0x7FF, this);
|
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x10, 0x7FF, this);
|
||||||
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x20, 0x7FF, this);
|
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x20, 0x7FF, this);
|
||||||
CANFrame *output = new CANFrame;
|
CANFrame output;
|
||||||
output->setExtendedFrameFormat(false);
|
output.setExtendedFrameFormat(false);
|
||||||
QByteArray bytes(8,0);
|
QByteArray bytes(8,0);
|
||||||
output->bus = bus;
|
output.bus = bus;
|
||||||
output->setFrameId(baseAddress);
|
output.setFrameId(baseAddress);
|
||||||
output->setFrameType(QCanBusFrame::DataFrame);
|
output.setFrameType(QCanBusFrame::DataFrame);
|
||||||
|
|
||||||
bytes[0] = 0xEF;
|
bytes[0] = (char)0xEF;
|
||||||
bytes[1] = 0xBE;
|
bytes[1] = (char)0xBE;
|
||||||
bytes[2] = 0xAD;
|
bytes[2] = (char)0xAD;
|
||||||
bytes[3] = 0xDE;
|
bytes[3] = (char)0xDE;
|
||||||
bytes[4] = token & 0xFF;
|
bytes[4] = token & 0xFF;
|
||||||
bytes[5] = (token >> 8) & 0xFF;
|
bytes[5] = (token >> 8) & 0xFF;
|
||||||
bytes[6] = (token >> 16) & 0xFF;
|
bytes[6] = (token >> 16) & 0xFF;
|
||||||
bytes[7] = (token >> 24) & 0xFF;
|
bytes[7] = (token >> 24) & 0xFF;
|
||||||
output->setPayload(bytes);
|
output.setPayload(bytes);
|
||||||
CANConManager::getInstance()->sendFrame(*output);
|
CANConManager::getInstance()->sendFrame(output);
|
||||||
}
|
}
|
||||||
else //stop anything in process
|
else //stop anything in process
|
||||||
{
|
{
|
||||||
@@ -209,7 +209,6 @@ void FirmwareUploaderWindow::handleStartStopTransfer()
|
|||||||
|
|
||||||
void FirmwareUploaderWindow::handleLoadFile()
|
void FirmwareUploaderWindow::handleLoadFile()
|
||||||
{
|
{
|
||||||
QString filename;
|
|
||||||
QFileDialog dialog;
|
QFileDialog dialog;
|
||||||
|
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
@@ -221,7 +220,7 @@ void FirmwareUploaderWindow::handleLoadFile()
|
|||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted)
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
{
|
{
|
||||||
filename = dialog.selectedFiles()[0];
|
QString filename = dialog.selectedFiles().constFirst();
|
||||||
|
|
||||||
loadBinaryFile(filename);
|
loadBinaryFile(filename);
|
||||||
}
|
}
|
||||||
@@ -232,22 +231,20 @@ void FirmwareUploaderWindow::loadBinaryFile(QString filename)
|
|||||||
|
|
||||||
if (transferInProgress) handleStartStopTransfer();
|
if (transferInProgress) handleStartStopTransfer();
|
||||||
|
|
||||||
QFile *inFile = new QFile(filename);
|
QFile inFile(filename);
|
||||||
|
|
||||||
if (!inFile->open(QIODevice::ReadOnly))
|
if (!inFile.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
delete inFile;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
firmwareData = inFile->readAll();
|
firmwareData = inFile.readAll();
|
||||||
|
|
||||||
currentSendingPosition = 0;
|
currentSendingPosition = 0;
|
||||||
firmwareSize = firmwareData.length();
|
firmwareSize = firmwareData.length();
|
||||||
|
|
||||||
updateProgress();
|
updateProgress();
|
||||||
|
|
||||||
inFile->close();
|
inFile.close();
|
||||||
delete inFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+152
-28
@@ -191,6 +191,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector<CANFrame>* frameCache
|
|||||||
filters.append(QString(tr("CLX000 (*.txt *.TXT)")));
|
filters.append(QString(tr("CLX000 (*.txt *.TXT)")));
|
||||||
filters.append(QString(tr("CANServer Binary Log (*.log *.LOG)")));
|
filters.append(QString(tr("CANServer Binary Log (*.log *.LOG)")));
|
||||||
filters.append(QString(tr("Wireshark (*.pcap *.PCAP *.pcapng *.PCAPNG)")));
|
filters.append(QString(tr("Wireshark (*.pcap *.PCAP *.pcapng *.PCAPNG)")));
|
||||||
|
filters.append(QString(tr("Wireshark SocketCAN (*.pcap *.PCAP")));
|
||||||
|
|
||||||
dialog.setDirectory(settings.value("FileIO/LoadSaveDirectory", dialog.directory().path()).toString());
|
dialog.setDirectory(settings.value("FileIO/LoadSaveDirectory", dialog.directory().path()).toString());
|
||||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
@@ -237,6 +238,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector<CANFrame>* frameCache
|
|||||||
if (selectedNameFilter == filters[22]) result = loadCLX000File(filename, frameCache);
|
if (selectedNameFilter == filters[22]) result = loadCLX000File(filename, frameCache);
|
||||||
if (selectedNameFilter == filters[23]) result = loadCANServerFile(filename, frameCache);
|
if (selectedNameFilter == filters[23]) result = loadCANServerFile(filename, frameCache);
|
||||||
if (selectedNameFilter == filters[24]) result = loadWiresharkFile(filename, frameCache);
|
if (selectedNameFilter == filters[24]) result = loadWiresharkFile(filename, frameCache);
|
||||||
|
if (selectedNameFilter == filters[25]) result = loadWiresharkSocketCANFile(filename, frameCache);
|
||||||
|
|
||||||
|
|
||||||
progress.cancel();
|
progress.cancel();
|
||||||
@@ -288,6 +290,28 @@ bool FrameFileIO::autoDetectLoadFile(QString filename, QVector<CANFrame>* frames
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to load socket CAN first to avoid generic wireshark logic catching it
|
||||||
|
qDebug() << "Attempting Wireshark Socket CAN Log";
|
||||||
|
if (isWiresharkSocketCANFile(filename))
|
||||||
|
{
|
||||||
|
if (loadWiresharkSocketCANFile(filename, frames))
|
||||||
|
{
|
||||||
|
qDebug() << "Loaded as Wireshark SocketCAN Log successfully!";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This and the decoder above were both moved above TeslaAPFile as they match based on magic numbers and sometimes these files were falling into the TeslaAP decoder
|
||||||
|
qDebug() << "Attempting Wireshark Log";
|
||||||
|
if (isWiresharkFile(filename))
|
||||||
|
{
|
||||||
|
if (loadWiresharkFile(filename, frames))
|
||||||
|
{
|
||||||
|
qDebug() << "Loaded as Wireshark Log successfully!";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
qDebug() << "Attempting Tesla AP Snapshot";
|
qDebug() << "Attempting Tesla AP Snapshot";
|
||||||
if (isTeslaAPFile(filename))
|
if (isTeslaAPFile(filename))
|
||||||
{
|
{
|
||||||
@@ -308,16 +332,6 @@ bool FrameFileIO::autoDetectLoadFile(QString filename, QVector<CANFrame>* frames
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Attempting Wireshark Log";
|
|
||||||
if (isWiresharkFile(filename))
|
|
||||||
{
|
|
||||||
if (loadWiresharkFile(filename, frames))
|
|
||||||
{
|
|
||||||
qDebug() << "Loaded as Wireshark Log successfully!";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Attempting canalyzer ASC";
|
qDebug() << "Attempting canalyzer ASC";
|
||||||
if (isCanalyzerASC(filename))
|
if (isCanalyzerASC(filename))
|
||||||
{
|
{
|
||||||
@@ -1440,7 +1454,8 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
|||||||
QByteArray bytes(numBytes, 0);
|
QByteArray bytes(numBytes, 0);
|
||||||
thisFrame.isReceived = true;
|
thisFrame.isReceived = true;
|
||||||
thisFrame.bus = 0;
|
thisFrame.bus = 0;
|
||||||
if (thisFrame.frameId() > 0x10000000)
|
if ((thisFrame.frameId() > 0x10000000) ||
|
||||||
|
(tokens[3].length() >= 8))
|
||||||
{
|
{
|
||||||
thisFrame.setExtendedFrameFormat(true);
|
thisFrame.setExtendedFrameFormat(true);
|
||||||
}
|
}
|
||||||
@@ -1492,7 +1507,8 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
|||||||
//qDebug() << thisFrame.payload().length();
|
//qDebug() << thisFrame.payload().length();
|
||||||
thisFrame.isReceived = true;
|
thisFrame.isReceived = true;
|
||||||
thisFrame.bus = tokens[2].toInt();
|
thisFrame.bus = tokens[2].toInt();
|
||||||
if (thisFrame.frameId() > 0x10000000)
|
if ((thisFrame.frameId() > 0x10000000) ||
|
||||||
|
(tokens[4].length() >= 8))
|
||||||
{
|
{
|
||||||
thisFrame.setExtendedFrameFormat(true);
|
thisFrame.setExtendedFrameFormat(true);
|
||||||
}
|
}
|
||||||
@@ -1534,7 +1550,8 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
|||||||
//qDebug() << thisFrame.payload().length();
|
//qDebug() << thisFrame.payload().length();
|
||||||
thisFrame.isReceived = true;
|
thisFrame.isReceived = true;
|
||||||
thisFrame.bus = 0;
|
thisFrame.bus = 0;
|
||||||
if (thisFrame.frameId() > 0x10000000)
|
if ((thisFrame.frameId() > 0x10000000) ||
|
||||||
|
(tokens[3].length() >= 8))
|
||||||
{
|
{
|
||||||
thisFrame.setExtendedFrameFormat(true);
|
thisFrame.setExtendedFrameFormat(true);
|
||||||
}
|
}
|
||||||
@@ -1586,7 +1603,8 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
|||||||
//qDebug() << thisFrame.payload().length();
|
//qDebug() << thisFrame.payload().length();
|
||||||
thisFrame.isReceived = true;
|
thisFrame.isReceived = true;
|
||||||
thisFrame.bus = tokens[3].toInt();
|
thisFrame.bus = tokens[3].toInt();
|
||||||
if (thisFrame.frameId() > 0x10000000)
|
if ((thisFrame.frameId() > 0x10000000) ||
|
||||||
|
(tokens[4].length() >= 8))
|
||||||
{
|
{
|
||||||
thisFrame.setExtendedFrameFormat(true);
|
thisFrame.setExtendedFrameFormat(true);
|
||||||
}
|
}
|
||||||
@@ -1680,12 +1698,16 @@ bool FrameFileIO::isCanalyzerASC(QString filename)
|
|||||||
//0.001371 CANFD 1 Rx 171 A0066_Unknown 0 0 8 8 00 00 07 76 23 00 00 00 230199 119 220000 62e7 46500250 460a0250 20011736 20010205
|
//0.001371 CANFD 1 Rx 171 A0066_Unknown 0 0 8 8 00 00 07 76 23 00 00 00 230199 119 220000 62e7 46500250 460a0250 20011736 20010205
|
||||||
//Version 16.0.0
|
//Version 16.0.0
|
||||||
//0.008600 1 358 Rx d 8 04 03 50 01 F0 40 54 2C Length = 233910 BitCount = 121 ID = 856
|
//0.008600 1 358 Rx d 8 04 03 50 01 F0 40 54 2C Length = 233910 BitCount = 121 ID = 856
|
||||||
//Time bus id dir ? len databytes (Ver 8.0)
|
//Version 17.3.0
|
||||||
//Time type bus dir ID ? ? length length bytes then many values of unknown type (ver 8.1)
|
//0.001684 CANFD 1 Rx 65b 1 0 d 32 f1 01 00 00 50 00 00 00 00 00 00 00 00 00 00 40 00 88 f5 77 17 78 00 00 c0 03 00 00 00 00 00 00 213797 356 303000 11729 46500250 4b140250 20011736 2001040d
|
||||||
//Time type bus dir ID SignalName ? ? length length bytes then many values of unknown type (ver 9.0)
|
|
||||||
//Time bus id dir ? len databytes additional crap (ver 16.0)
|
//Time bus id dir ? len databytes (Ver 8.0)
|
||||||
//So it seems the file format is not entirely different based on version but rather on some other
|
//Time bus id dir ? len databytes (addl info) (ver 16.0)
|
||||||
//settings... Fun!
|
//Time type bus dir ID ? ? length length (bytes) (many values of unknown type) (ver 8.1)
|
||||||
|
//Time type bus dir ID SignalName ? ? length length bytes (then many values of unknown type)(ver 9.0)
|
||||||
|
//Time Type Bus Dir ID ? ? (length) (Real Length) (bytes) (many values of unknown type) (Ver 17.3)
|
||||||
|
//0 1 2 3 4 5 6 7 8 9 10
|
||||||
|
//This seems like a rather eclectic mix. It's almost arbitrary!
|
||||||
bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
|
bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
|
||||||
{
|
{
|
||||||
QFile *inFile = new QFile(filename);
|
QFile *inFile = new QFile(filename);
|
||||||
@@ -1736,7 +1758,7 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inHeader) continue;
|
if (inHeader) continue;
|
||||||
if (line.length() > 2)
|
if (line.length() > 2 && !line.startsWith("//"))
|
||||||
{
|
{
|
||||||
tokens = line.simplified().split(' ');
|
tokens = line.simplified().split(' ');
|
||||||
|
|
||||||
@@ -1766,7 +1788,7 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
|
|||||||
int payloadLen = tokens[8].toInt();
|
int payloadLen = tokens[8].toInt();
|
||||||
qDebug() << "PayloadLen: " << payloadLen << " Tokens: " << tokens;
|
qDebug() << "PayloadLen: " << payloadLen << " Tokens: " << tokens;
|
||||||
QByteArray bytes(payloadLen, 0);
|
QByteArray bytes(payloadLen, 0);
|
||||||
if (payloadLen > 8)
|
if (payloadLen > 64)
|
||||||
{
|
{
|
||||||
qDebug() << "Payload length too long. Original line: " << line;
|
qDebug() << "Payload length too long. Original line: " << line;
|
||||||
return false;
|
return false;
|
||||||
@@ -3766,12 +3788,17 @@ bool FrameFileIO::loadCanDumpFile(QString filename, QVector<CANFrame>* frames)
|
|||||||
if (line.contains('[')) //the expanded format (second one from the above list)
|
if (line.contains('[')) //the expanded format (second one from the above list)
|
||||||
{
|
{
|
||||||
//(1551774790.942758) can1 7A8 [8] F4 DC D1 83 0E 02 00 00
|
//(1551774790.942758) can1 7A8 [8] F4 DC D1 83 0E 02 00 00
|
||||||
|
//(1551774790.942758) can1 7A8 [08] F4 DC D1 83 0E 02 00 00
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||||
thisFrame.setFrameId(tokens[2].toLong(nullptr, 16));
|
thisFrame.setFrameId(tokens[2].toLong(nullptr, 16));
|
||||||
if (thisFrame.frameId() > 0x7FF) thisFrame.setExtendedFrameFormat(true);
|
if (thisFrame.frameId() > 0x7FF) thisFrame.setExtendedFrameFormat(true);
|
||||||
else thisFrame.setExtendedFrameFormat(false);
|
else thisFrame.setExtendedFrameFormat(false);
|
||||||
thisFrame.setFrameType(QCanBusFrame::DataFrame);
|
thisFrame.setFrameType(QCanBusFrame::DataFrame);
|
||||||
int numBytes = tokens[3].at(1) - '0';
|
int numBytes;
|
||||||
|
if (tokens[3].at(2) == ']')
|
||||||
|
numBytes = tokens[3].at(1) - '0';
|
||||||
|
else
|
||||||
|
numBytes = (tokens[3].at(1) - '0')*10 + (tokens[3].at(2) - '0');
|
||||||
QByteArray bytes(numBytes, 0);
|
QByteArray bytes(numBytes, 0);
|
||||||
for (int c = 0; c < numBytes; c++)
|
for (int c = 0; c < numBytes; c++)
|
||||||
{
|
{
|
||||||
@@ -5019,7 +5046,7 @@ bool FrameFileIO::loadWiresharkFile(QString filename, QVector<CANFrame>* frames)
|
|||||||
|
|
||||||
QByteArray ba = filename.toLocal8Bit();
|
QByteArray ba = filename.toLocal8Bit();
|
||||||
|
|
||||||
pcap_data_file = pcap_open_offline(ba.data(), errbuf);
|
pcap_data_file = pcap_open_offline(ba.data(), errbuf, PCAP_LINKTYPE_ANY);
|
||||||
if (!pcap_data_file) {
|
if (!pcap_data_file) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5046,9 +5073,13 @@ bool FrameFileIO::loadWiresharkFile(QString filename, QVector<CANFrame>* frames)
|
|||||||
thisFrame.isReceived = true; // TODO: check if tx detection is possible
|
thisFrame.isReceived = true; // TODO: check if tx detection is possible
|
||||||
|
|
||||||
thisFrame.setFrameType(QCanBusFrame::DataFrame);
|
thisFrame.setFrameType(QCanBusFrame::DataFrame);
|
||||||
thisFrame.setFrameId((0xff & *(packetData+17)) << 8 | (0xff & *(packetData+16)));
|
if ((0x80 & *(packetData+19))) {
|
||||||
if (thisFrame.frameId() <= 0x7FF) thisFrame.setExtendedFrameFormat(false);
|
thisFrame.setExtendedFrameFormat(true);
|
||||||
else thisFrame.setExtendedFrameFormat(true);
|
thisFrame.setFrameId((0x3f & *(packetData+19))<<24 | (0xff & *(packetData+18)) << 16 | (0xff & *(packetData+17)) << 8 | (0xff & *(packetData+16)));
|
||||||
|
} else {
|
||||||
|
thisFrame.setExtendedFrameFormat(false);
|
||||||
|
thisFrame.setFrameId((0xff & *(packetData+17)) << 8 | (0xff & *(packetData+16)));
|
||||||
|
}
|
||||||
thisFrame.bus = 0;
|
thisFrame.bus = 0;
|
||||||
int numBytes = *(packetData+20);
|
int numBytes = *(packetData+20);
|
||||||
QByteArray bytes(numBytes, 0);
|
QByteArray bytes(numBytes, 0);
|
||||||
@@ -5075,7 +5106,7 @@ bool FrameFileIO::isWiresharkFile(QString filename)
|
|||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
QByteArray ba = filename.toLocal8Bit();
|
QByteArray ba = filename.toLocal8Bit();
|
||||||
|
|
||||||
pcap_data_file = pcap_open_offline(ba.data(), errbuf);
|
pcap_data_file = pcap_open_offline(ba.data(), errbuf, PCAP_LINKTYPE_ANY);
|
||||||
if (!pcap_data_file) {
|
if (!pcap_data_file) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5085,3 +5116,96 @@ bool FrameFileIO::isWiresharkFile(QString filename)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FrameFileIO::loadWiresharkSocketCANFile(QString filename, QVector<CANFrame>* frames)
|
||||||
|
{
|
||||||
|
pcap_t *pcap_data_file;
|
||||||
|
CANFrame thisFrame;
|
||||||
|
long long startTimestamp = 0;
|
||||||
|
long long timeStamp;
|
||||||
|
int lineCounter = 0;
|
||||||
|
bool foundErrors = false;
|
||||||
|
pcap_pkthdr packetHeader;
|
||||||
|
const char *packetData = NULL;
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
|
||||||
|
QByteArray ba = filename.toLocal8Bit();
|
||||||
|
|
||||||
|
pcap_data_file = pcap_open_offline(ba.data(), errbuf, PCAP_LINKTYPE_SOCKETCAN);
|
||||||
|
if (!pcap_data_file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
packetData = (const char*)pcap_next(pcap_data_file, &packetHeader);
|
||||||
|
while (packetData) {
|
||||||
|
lineCounter++;
|
||||||
|
if (lineCounter > 100) {
|
||||||
|
qApp->processEvents();
|
||||||
|
lineCounter = 0;
|
||||||
|
}
|
||||||
|
thisFrame.bus = 0;
|
||||||
|
|
||||||
|
// Timestamp
|
||||||
|
timeStamp = packetHeader.ts.tv_sec * 1000000 + packetHeader.ts.tv_usec;
|
||||||
|
if (0 == startTimestamp) {
|
||||||
|
startTimestamp = timeStamp;
|
||||||
|
}
|
||||||
|
timeStamp -= startTimestamp;
|
||||||
|
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, timeStamp));
|
||||||
|
|
||||||
|
// ID and extended frame format
|
||||||
|
const quint32 can_id = qFromBigEndian<quint32>(packetData);
|
||||||
|
if (can_id & 0x80000000) {
|
||||||
|
thisFrame.setExtendedFrameFormat(true);
|
||||||
|
thisFrame.setFrameId(0x1fffffff & can_id);
|
||||||
|
} else {
|
||||||
|
thisFrame.setExtendedFrameFormat(false);
|
||||||
|
thisFrame.setFrameId(0x7ff & can_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frame type
|
||||||
|
if (can_id & 0x20000000U) {
|
||||||
|
thisFrame.setFrameType(QCanBusFrame::ErrorFrame);
|
||||||
|
} else if (can_id & 0x40000000U) {
|
||||||
|
thisFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
|
||||||
|
} else {
|
||||||
|
thisFrame.setFrameType(QCanBusFrame::DataFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Direction - This isn't actually officially supported, but CAN Bus Debugger device logs set this byte to 1 to indicate a TX frame and 0 for RX
|
||||||
|
quint8 direction = (quint8) *(packetData + 6);
|
||||||
|
thisFrame.isReceived = (direction != 1);
|
||||||
|
|
||||||
|
// Data
|
||||||
|
quint8 numBytes = (quint8) *(packetData + 4);
|
||||||
|
if (numBytes > 8) {
|
||||||
|
numBytes = 8;
|
||||||
|
}
|
||||||
|
QByteArray bytes(numBytes, 0);
|
||||||
|
for (int d = 0; d < numBytes; d++) {
|
||||||
|
bytes[d] = *(packetData + 8 + d);
|
||||||
|
}
|
||||||
|
thisFrame.setPayload(bytes);
|
||||||
|
frames->append(thisFrame);
|
||||||
|
|
||||||
|
packetData = (const char*) pcap_next(pcap_data_file, &packetHeader);
|
||||||
|
}
|
||||||
|
pcap_close(pcap_data_file);
|
||||||
|
pcap_data_file = NULL;
|
||||||
|
return !foundErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrameFileIO::isWiresharkSocketCANFile(QString filename)
|
||||||
|
{
|
||||||
|
pcap_t *pcap_data_file;
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
QByteArray ba = filename.toLocal8Bit();
|
||||||
|
|
||||||
|
pcap_data_file = pcap_open_offline(ba.data(), errbuf, PCAP_LINKTYPE_SOCKETCAN);
|
||||||
|
if (!pcap_data_file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pcap_close(pcap_data_file);
|
||||||
|
pcap_data_file = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ public:
|
|||||||
static bool loadCLX000File(QString filename, QVector<CANFrame>* frames);
|
static bool loadCLX000File(QString filename, QVector<CANFrame>* frames);
|
||||||
static bool loadCANServerFile(QString filename, QVector<CANFrame>* frames);
|
static bool loadCANServerFile(QString filename, QVector<CANFrame>* frames);
|
||||||
static bool loadWiresharkFile(QString filename, QVector<CANFrame>* frames);
|
static bool loadWiresharkFile(QString filename, QVector<CANFrame>* frames);
|
||||||
|
static bool loadWiresharkSocketCANFile(QString filename, QVector<CANFrame>* frames);
|
||||||
|
|
||||||
//functions that pre-scan a file to try to figure out if they could read it. Used to automatically determine
|
//functions that pre-scan a file to try to figure out if they could read it. Used to automatically determine
|
||||||
//file type and load it.
|
//file type and load it.
|
||||||
@@ -80,6 +81,7 @@ public:
|
|||||||
static bool isCLX000File(QString filename);
|
static bool isCLX000File(QString filename);
|
||||||
static bool isCANServerFile(QString filename);
|
static bool isCANServerFile(QString filename);
|
||||||
static bool isWiresharkFile(QString filename);
|
static bool isWiresharkFile(QString filename);
|
||||||
|
static bool isWiresharkSocketCANFile(QString filename);
|
||||||
|
|
||||||
static bool saveCRTDFile(QString, const QVector<CANFrame>*);
|
static bool saveCRTDFile(QString, const QVector<CANFrame>*);
|
||||||
static bool saveNativeCSVFile(QString, const QVector<CANFrame>*);
|
static bool saveNativeCSVFile(QString, const QVector<CANFrame>*);
|
||||||
|
|||||||
@@ -0,0 +1,457 @@
|
|||||||
|
#include "framesenderobject.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
FrameSenderObject::FrameSenderObject(const QVector<CANFrame> *frames)
|
||||||
|
{
|
||||||
|
mThread_p = new QThread();
|
||||||
|
|
||||||
|
statusCounter = 0;
|
||||||
|
modelFrames = frames;
|
||||||
|
dbcHandler = DBCHandler::getReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameSenderObject::~FrameSenderObject()
|
||||||
|
{
|
||||||
|
mThread_p->quit();
|
||||||
|
mThread_p->wait();
|
||||||
|
delete mThread_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::piStart()
|
||||||
|
{
|
||||||
|
sendingTimer = new QTimer();
|
||||||
|
sendingTimer->setTimerType(Qt::PreciseTimer);
|
||||||
|
sendingTimer->setInterval(1);
|
||||||
|
|
||||||
|
connect(sendingTimer, &QTimer::timeout, this, &FrameSenderObject::timerTriggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::piStop()
|
||||||
|
{
|
||||||
|
sendingTimer->stop();
|
||||||
|
delete sendingTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::initialize()
|
||||||
|
{
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) )
|
||||||
|
{
|
||||||
|
/* move ourself to the thread */
|
||||||
|
moveToThread(mThread_p); /*TODO handle errors */
|
||||||
|
/* connect started() */
|
||||||
|
connect(mThread_p, SIGNAL(started()), this, SLOT(initialize()));
|
||||||
|
/* start the thread */
|
||||||
|
mThread_p->start(QThread::HighPriority);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set started flag */
|
||||||
|
//mStarted = true;
|
||||||
|
|
||||||
|
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
|
||||||
|
|
||||||
|
/* in multithread case, this will be called before entering thread event loop */
|
||||||
|
return piStart();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::finalize()
|
||||||
|
{
|
||||||
|
/* 1) execute in mThread_p context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) )
|
||||||
|
{
|
||||||
|
/* if thread is finished, it means we call this function for the second time so we can leave */
|
||||||
|
if( !mThread_p->isFinished() )
|
||||||
|
{
|
||||||
|
/* we need to call piStop() */
|
||||||
|
QMetaObject::invokeMethod(this, "finalize",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
/* 3) stop thread */
|
||||||
|
mThread_p->quit();
|
||||||
|
if(!mThread_p->wait()) {
|
||||||
|
qDebug() << "can't stop thread";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2) call piStop in mThread context */
|
||||||
|
return piStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::startSending()
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "startSending",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendingElapsed.start();
|
||||||
|
sendingTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::stopSending()
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "stopPlayback",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendingTimer->stop(); //pushing this button halts automatic playback
|
||||||
|
//emit statusUpdate(currentPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::addSendRecord(FrameSendData record)
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "addSendRecord",
|
||||||
|
Qt::BlockingQueuedConnection,
|
||||||
|
Q_ARG(FrameSendData, record));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendingData.append(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::removeSendRecord(int idx)
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "removeSendRecord",
|
||||||
|
Qt::BlockingQueuedConnection,
|
||||||
|
Q_ARG(int, idx));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendingData.removeAt(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: Getting a reference to an item in a QList is a dangerous thing. If anyone
|
||||||
|
* or anything happens to reallocate the list you're screwed. So, call this, do the
|
||||||
|
* work, and drop the reference as soon as possible.
|
||||||
|
*/
|
||||||
|
FrameSendData *FrameSenderObject::getSendRecordRef(int idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= sendingData.count()) return nullptr;
|
||||||
|
return &sendingData[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called every millisecond to set the system update figures and send frames if necessary.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="timerEventArgs"></param>
|
||||||
|
///
|
||||||
|
void FrameSenderObject::timerTriggered()
|
||||||
|
{
|
||||||
|
FrameSendData *sendData;
|
||||||
|
Trigger *trigger;
|
||||||
|
|
||||||
|
sendingList.clear();
|
||||||
|
if(mutex.tryLock())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Requested tick interval was 1ms but the actual interval could be wildly different. So, we track
|
||||||
|
* by counting microseconds and accumulating. This creates decent stability even for long intervals
|
||||||
|
*/
|
||||||
|
quint64 elapsed = sendingElapsed.nsecsElapsed() / 1000ul;
|
||||||
|
if (elapsed == 0) elapsed = 1;
|
||||||
|
sendingElapsed.start();
|
||||||
|
sendingLastTimeStamp += elapsed;
|
||||||
|
//qDebug() << sendingLastTimeStamp;
|
||||||
|
//qDebug() << "El: " << elapsed;
|
||||||
|
statusCounter++;
|
||||||
|
for (int i = 0; i < sendingData.count(); i++)
|
||||||
|
{
|
||||||
|
sendData = &sendingData[i];
|
||||||
|
if (!sendData->enabled)
|
||||||
|
{
|
||||||
|
if (sendData->triggers.count() > 0)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < sendData->triggers.count(); j++) //resetting currCount when line is disabled
|
||||||
|
{
|
||||||
|
sendData->triggers[j].currCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; //abort any processing on this if it is not enabled.
|
||||||
|
}
|
||||||
|
if (sendData->triggers.count() == 0)
|
||||||
|
{
|
||||||
|
//qDebug() << "No triggers to process";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int j = 0; j < sendData->triggers.count(); j++)
|
||||||
|
{
|
||||||
|
trigger = &sendData->triggers[j];
|
||||||
|
//if ( (trigger->currCount >= trigger->maxCount) || (trigger->maxCount == -1) ) continue; //don't process if we've sent max frames we were supposed to
|
||||||
|
if (!trigger->readyCount) continue; //don't tick if not ready to tick
|
||||||
|
//is it time to fire?
|
||||||
|
trigger->msCounter += elapsed; //gives proper tracking even if timer doesn't fire as fast as it should
|
||||||
|
//qDebug() << trigger->msCounter;
|
||||||
|
if (trigger->msCounter >= (trigger->milliseconds * 1000))
|
||||||
|
{
|
||||||
|
trigger->msCounter -= (trigger->milliseconds * 1000);
|
||||||
|
sendData->count++;
|
||||||
|
trigger->currCount++;
|
||||||
|
doModifiers(i);
|
||||||
|
//updateGridRow(i);
|
||||||
|
//qDebug() << "About to try to send a frame";
|
||||||
|
//CANConManager::getInstance()->sendFrame(sendingData[i]);
|
||||||
|
sendingList.append(sendingData[i]); //queue it instead of immediate sending
|
||||||
|
if (trigger->ID > 0) trigger->readyCount = false; //reset flag if this is a timed ID trigger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if we have any frames to send after the above then send as a batch
|
||||||
|
if (sendingList.count() > 0) CANConManager::getInstance()->sendFrames(sendingList);
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "framesenderobject::handleTick() couldn't get mutex, elapsed is: " << sendingElapsed.elapsed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::buildFrameCache()
|
||||||
|
{
|
||||||
|
CANFrame thisFrame;
|
||||||
|
frameCache.clear();
|
||||||
|
for (int i = 0; i < modelFrames->count(); i++)
|
||||||
|
{
|
||||||
|
thisFrame = modelFrames->at(i);
|
||||||
|
if (!frameCache.contains(thisFrame.frameId()))
|
||||||
|
{
|
||||||
|
frameCache.insert(thisFrame.frameId(), thisFrame);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frameCache[thisFrame.frameId()] = thisFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//remember, negative numbers are special -1 = all frames deleted, -2 = totally new set of frames.
|
||||||
|
void FrameSenderObject::updatedFrames(int numFrames)
|
||||||
|
{
|
||||||
|
CANFrame thisFrame;
|
||||||
|
if (numFrames == -1) //all frames deleted.
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (numFrames == -2) //all new set of frames.
|
||||||
|
{
|
||||||
|
buildFrameCache();
|
||||||
|
}
|
||||||
|
else //just got some new frames. See if they are relevant.
|
||||||
|
{
|
||||||
|
if (numFrames > modelFrames->count()) return;
|
||||||
|
qDebug() << "New frames in sender window";
|
||||||
|
//run through the supposedly new frames in order
|
||||||
|
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
|
||||||
|
{
|
||||||
|
thisFrame = modelFrames->at(i);
|
||||||
|
if (!frameCache.contains(thisFrame.frameId()))
|
||||||
|
{
|
||||||
|
frameCache.insert(thisFrame.frameId(), thisFrame);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frameCache[thisFrame.frameId()] = thisFrame;
|
||||||
|
}
|
||||||
|
processIncomingFrame(&thisFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameSenderObject::processIncomingFrame(CANFrame *frame)
|
||||||
|
{
|
||||||
|
for (int sd = 0; sd < sendingData.count(); sd++)
|
||||||
|
{
|
||||||
|
if (sendingData[sd].triggers.count() == 0) continue;
|
||||||
|
bool passedChecks = true;
|
||||||
|
for (int trig = 0; trig < sendingData[sd].triggers.count(); trig++)
|
||||||
|
{
|
||||||
|
Trigger *thisTrigger = &sendingData[sd].triggers[trig];
|
||||||
|
//need to ensure that this trigger is actually related to frames incoming.
|
||||||
|
//Otherwise ignore it here. Only frames that have BUS and/or ID set as trigger will work here.
|
||||||
|
if (!(thisTrigger->triggerMask & (TriggerMask::TRG_BUS | TriggerMask::TRG_ID) ) ) continue;
|
||||||
|
|
||||||
|
passedChecks = true;
|
||||||
|
//qDebug() << "Trigger ID: " << thisTrigger->ID;
|
||||||
|
//qDebug() << "Frame ID: " << frame->frameId();
|
||||||
|
|
||||||
|
//Check to see if we have a bus trigger condition and if so does it match
|
||||||
|
if (thisTrigger->bus != frame->bus && (thisTrigger->triggerMask & TriggerMask::TRG_BUS) )
|
||||||
|
passedChecks = false;
|
||||||
|
|
||||||
|
//check to see if we have an ID trigger condition and if so does it match
|
||||||
|
if ((thisTrigger->triggerMask & TriggerMask::TRG_ID) && (uint32_t)thisTrigger->ID != frame->frameId() )
|
||||||
|
passedChecks = false;
|
||||||
|
|
||||||
|
//check to see if we're limiting the trigger by max count and have we reached that count?
|
||||||
|
if ( (thisTrigger->triggerMask & TriggerMask::TRG_COUNT) && (thisTrigger->currCount >= thisTrigger->maxCount) )
|
||||||
|
passedChecks = false;
|
||||||
|
|
||||||
|
//if the above passed then are we triggering not only on ID but also signal?
|
||||||
|
if (passedChecks && (thisTrigger->triggerMask & (TriggerMask::TRG_SIGNAL | TriggerMask::TRG_ID) ) )
|
||||||
|
{
|
||||||
|
bool sigCheckPassed = false;
|
||||||
|
DBC_MESSAGE *msg = dbcHandler->findMessage(thisTrigger->ID);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(thisTrigger->sigName);
|
||||||
|
if (sig)
|
||||||
|
{
|
||||||
|
//first of all, is this signal really in this message we got?
|
||||||
|
if (sig->isSignalInMessage(*frame)) sigCheckPassed = true;
|
||||||
|
//if it was and we're also filtering on value then try that next
|
||||||
|
if (sigCheckPassed && (thisTrigger->triggerMask & TriggerMask::TRG_SIGVAL))
|
||||||
|
{
|
||||||
|
double sigval = 0.0;
|
||||||
|
if (sig->processAsDouble(*frame, sigval))
|
||||||
|
{
|
||||||
|
if (abs(sigval - thisTrigger->sigValueDbl) > 0.001)
|
||||||
|
{
|
||||||
|
sigCheckPassed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else sigCheckPassed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else sigCheckPassed = false;
|
||||||
|
}
|
||||||
|
else sigCheckPassed = false;
|
||||||
|
passedChecks &= sigCheckPassed; //passedChecks can only be true if both are
|
||||||
|
}
|
||||||
|
|
||||||
|
//if all the above says it's OK then we'll go ahead and send that message.
|
||||||
|
//If a message that comes through here has a MS value then we use it as a delay
|
||||||
|
//after the check passes. This allows for delaying the sending of the frame if that
|
||||||
|
//is required. Otherwise, just send it immediately.
|
||||||
|
if (passedChecks)
|
||||||
|
{
|
||||||
|
if (thisTrigger->milliseconds == 0) //immediate reply
|
||||||
|
{
|
||||||
|
thisTrigger->currCount++;
|
||||||
|
sendingData[sd].count++;
|
||||||
|
doModifiers(sd);
|
||||||
|
//updateGridRow(sd);
|
||||||
|
CANConManager::getInstance()->sendFrame(sendingData[sd]);
|
||||||
|
}
|
||||||
|
else //delayed sending frame
|
||||||
|
{
|
||||||
|
thisTrigger->readyCount = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// given an index into the sendingData list we run the modifiers that it has set up
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index into the sendingData list</param>
|
||||||
|
void FrameSenderObject::doModifiers(int idx)
|
||||||
|
{
|
||||||
|
int shadowReg = 0; //shadow register we use to accumulate results
|
||||||
|
int first=0, second=0;
|
||||||
|
|
||||||
|
FrameSendData *sendData = &sendingData[idx];
|
||||||
|
Modifier *mod;
|
||||||
|
ModifierOp op;
|
||||||
|
|
||||||
|
if (sendData->modifiers.count() == 0) return; //if no modifiers just leave right now
|
||||||
|
|
||||||
|
//qDebug() << "Executing mods";
|
||||||
|
|
||||||
|
for (int i = 0; i < sendData->modifiers.count(); i++)
|
||||||
|
{
|
||||||
|
mod = &sendData->modifiers[i];
|
||||||
|
for (int j = 0; j < mod->operations.count(); j++)
|
||||||
|
{
|
||||||
|
op = mod->operations.at(j);
|
||||||
|
if (op.first.ID == -1)
|
||||||
|
{
|
||||||
|
first = shadowReg;
|
||||||
|
}
|
||||||
|
else first = fetchOperand(idx, op.first);
|
||||||
|
second = fetchOperand(idx, op.second);
|
||||||
|
switch (op.operation)
|
||||||
|
{
|
||||||
|
case ADDITION:
|
||||||
|
shadowReg = first + second;
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
shadowReg = first & second;
|
||||||
|
break;
|
||||||
|
case DIVISION:
|
||||||
|
shadowReg = first / second;
|
||||||
|
break;
|
||||||
|
case MULTIPLICATION:
|
||||||
|
shadowReg = first * second;
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
shadowReg = first | second;
|
||||||
|
break;
|
||||||
|
case SUBTRACTION:
|
||||||
|
shadowReg = first - second;
|
||||||
|
break;
|
||||||
|
case XOR:
|
||||||
|
shadowReg = first ^ second;
|
||||||
|
break;
|
||||||
|
case MOD:
|
||||||
|
shadowReg = first % second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Finally, drop the result into the proper data byte
|
||||||
|
QByteArray newArr(sendData->payload());
|
||||||
|
newArr[mod->destByte] = (char) shadowReg;
|
||||||
|
sendData->setPayload(newArr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int FrameSenderObject::fetchOperand(int idx, ModifierOperand op)
|
||||||
|
{
|
||||||
|
CANFrame *tempFrame = nullptr;
|
||||||
|
if (op.ID == 0) //numeric constant
|
||||||
|
{
|
||||||
|
if (op.notOper) return ~op.databyte;
|
||||||
|
else return op.databyte;
|
||||||
|
}
|
||||||
|
else if (op.ID == -2) //fetch data from a data byte within the output frame
|
||||||
|
{
|
||||||
|
if (op.notOper) return ~((unsigned char)sendingData.at(idx).payload()[op.databyte]);
|
||||||
|
else return (unsigned char)sendingData.at(idx).payload()[op.databyte];
|
||||||
|
}
|
||||||
|
else //look up external data byte
|
||||||
|
{
|
||||||
|
tempFrame = lookupFrame(op.ID, op.bus);
|
||||||
|
if (tempFrame != nullptr)
|
||||||
|
{
|
||||||
|
if (op.notOper) return ~((unsigned char)tempFrame->payload()[op.databyte]);
|
||||||
|
else return (unsigned char)tempFrame->payload()[op.databyte];
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to find the most recent frame given the input criteria
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ID">The ID to find</param>
|
||||||
|
/// <param name="bus">Which bus to look on (-1 if you don't care)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
CANFrame* FrameSenderObject::lookupFrame(int ID, int bus)
|
||||||
|
{
|
||||||
|
if (!frameCache.contains(ID)) return nullptr;
|
||||||
|
|
||||||
|
if (bus == -1 || frameCache[ID].bus == bus) return &frameCache[ID];
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#ifndef FRAMESENDEROBJECT_H
|
||||||
|
#define FRAMESENDEROBJECT_H
|
||||||
|
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMutex>
|
||||||
|
#include "can_structs.h"
|
||||||
|
#include "connections/canconmanager.h"
|
||||||
|
#include "can_trigger_structs.h"
|
||||||
|
#include "dbc/dbchandler.h"
|
||||||
|
|
||||||
|
class FrameSenderObject : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
FrameSenderObject(const QVector<CANFrame> *frames);
|
||||||
|
~FrameSenderObject();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
/**
|
||||||
|
* @brief start the device. This calls piStarted
|
||||||
|
* @note starts the working thread if required (piStart is called in the working thread context)
|
||||||
|
*/
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief stop the device. This calls piStop
|
||||||
|
* @note if a working thread is used, piStop is called before exiting the working thread
|
||||||
|
*/
|
||||||
|
void finalize();
|
||||||
|
|
||||||
|
void startSending();
|
||||||
|
void stopSending();
|
||||||
|
|
||||||
|
void addSendRecord(FrameSendData record);
|
||||||
|
void removeSendRecord(int idx);
|
||||||
|
FrameSendData *getSendRecordRef(int idx);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void timerTriggered();
|
||||||
|
void updatedFrames(int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<CANFrame> sendingList;
|
||||||
|
int currentPosition;
|
||||||
|
QTimer *sendingTimer;
|
||||||
|
QElapsedTimer sendingElapsed;
|
||||||
|
quint64 sendingLastTimeStamp;
|
||||||
|
int statusCounter;
|
||||||
|
QList<FrameSendData> sendingData;
|
||||||
|
QThread* mThread_p;
|
||||||
|
QHash<int, CANFrame> frameCache; //hash with frame ID as the key and the most recent frame as the value
|
||||||
|
const QVector<CANFrame> *modelFrames;
|
||||||
|
bool inhibitChanged = false;
|
||||||
|
QMutex mutex;
|
||||||
|
DBCHandler *dbcHandler;
|
||||||
|
|
||||||
|
void doModifiers(int);
|
||||||
|
int fetchOperand(int, ModifierOperand);
|
||||||
|
CANFrame* lookupFrame(int, int);
|
||||||
|
void buildFrameCache();
|
||||||
|
void processIncomingFrame(CANFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief starts the device
|
||||||
|
*/
|
||||||
|
void piStart();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief stops the device
|
||||||
|
*/
|
||||||
|
void piStop();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FRAMESENDEROBJECT_H
|
||||||
+29
-14
@@ -63,8 +63,8 @@ void FrameSenderWindow::setupGrid()
|
|||||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_EXT, 50);
|
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_EXT, 50);
|
||||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_REM, 50);
|
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_REM, 50);
|
||||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_DATA, 220);
|
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_DATA, 220);
|
||||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_TRIGGER, 220);
|
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_TRIGGER, 270);
|
||||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_MODS, 220);
|
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_MODS, 270);
|
||||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_COUNT, 80);
|
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_COUNT, 80);
|
||||||
ui->tableSender->setHorizontalHeaderLabels(headers);
|
ui->tableSender->setHorizontalHeaderLabels(headers);
|
||||||
}
|
}
|
||||||
@@ -693,6 +693,12 @@ void FrameSenderWindow::processModifierText(int line)
|
|||||||
//Example line:
|
//Example line:
|
||||||
//d0 = D0 + 1,d1 = id:0x200:d3 + id:0x200:d4 AND 0xF0 - Original version
|
//d0 = D0 + 1,d1 = id:0x200:d3 + id:0x200:d4 AND 0xF0 - Original version
|
||||||
//D0=D0+1,D1=ID:0x200:D3+ID:0x200:D4&0xF0
|
//D0=D0+1,D1=ID:0x200:D3+ID:0x200:D4&0xF0
|
||||||
|
|
||||||
|
//[BMS_TargetVoltage]=45 would set the value of signal BMS_TargetVoltage to 45
|
||||||
|
|
||||||
|
//[BMS_TargetVoltage]=[0x234:BMS_CurrentVoltage] + 4 would instead grab the value
|
||||||
|
//of BMS_CurrentVoltage from ID 0x234, add 4 to it, and set BMS_TargetVoltage to that value.
|
||||||
|
|
||||||
//This is certainly much harder to parse than the trigger definitions.
|
//This is certainly much harder to parse than the trigger definitions.
|
||||||
//the left side of the = has to be D0 to D7. After that there is a string of
|
//the left side of the = has to be D0 to D7. After that there is a string of
|
||||||
//data. Spaces used to be required but no longer are. This makes parsing harder but data entry easier
|
//data. Spaces used to be required but no longer are. This makes parsing harder but data entry easier
|
||||||
@@ -710,22 +716,33 @@ void FrameSenderWindow::processModifierText(int line)
|
|||||||
Modifier thisMod;
|
Modifier thisMod;
|
||||||
thisMod.destByte = 0;
|
thisMod.destByte = 0;
|
||||||
|
|
||||||
QString leftSide = Utility::grabAlphaNumeric(mods[i]);
|
QRegularExpression regex;
|
||||||
if (leftSide.startsWith("D") && leftSide.length() == 2)
|
QRegularExpressionMatch match;
|
||||||
|
|
||||||
|
regex.setPattern("^\\[(\\w+)]=(\\w+)");
|
||||||
|
match = regex.match(mods[i]);
|
||||||
|
if (match.hasMatch())
|
||||||
{
|
{
|
||||||
thisMod.destByte = leftSide.right(1).toInt();
|
thisMod.destByte = -1;
|
||||||
|
thisMod.signalName = match.captured(1);
|
||||||
|
mods[i] = match.captured(2);
|
||||||
thisMod.operations.clear();
|
thisMod.operations.clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "Something wrong with lefthand val";
|
QString leftSide = Utility::grabAlphaNumeric(mods[i]);
|
||||||
continue;
|
if (leftSide.startsWith("D") && leftSide.length() == 2)
|
||||||
}
|
{
|
||||||
if (!(Utility::grabOperation(mods[i]) == "="))
|
thisMod.destByte = leftSide.right(1).toInt();
|
||||||
{
|
thisMod.operations.clear();
|
||||||
qDebug() << "Err: No = after lefthand val";
|
if (!(Utility::grabOperation(mods[i]) == "="))
|
||||||
continue;
|
{
|
||||||
|
qDebug() << "Err: No = after lefthand val";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abort = false;
|
abort = false;
|
||||||
|
|
||||||
token = Utility::grabAlphaNumeric(mods[i]);
|
token = Utility::grabAlphaNumeric(mods[i]);
|
||||||
@@ -1054,8 +1071,6 @@ void FrameSenderWindow::processCellChange(int line, int col)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ST_COLS::SENDTAB_COL_DATA: //Data bytes
|
case ST_COLS::SENDTAB_COL_DATA: //Data bytes
|
||||||
for (int i = 0; i < 8; i++) sendingData[line].payload().data()[i] = 0;
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
|
#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
|
||||||
tokens = ui->tableSender->item(line, ST_COLS::SENDTAB_COL_DATA)->text().split(" ", Qt::SkipEmptyParts);
|
tokens = ui->tableSender->item(line, ST_COLS::SENDTAB_COL_DATA)->text().split(" ", Qt::SkipEmptyParts);
|
||||||
#else
|
#else
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Executable
+79
@@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
APP_PATH="/usr/bin/SavvyCAN"
|
||||||
|
DESKTOP_PATH="/usr/share/applications/savvycan.desktop"
|
||||||
|
ICON_PATH="/usr/share/pixmaps/SavvyCAN.png"
|
||||||
|
|
||||||
|
require_root() {
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
echo "This script must be run as root."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
echo "Usage: $0 [option]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " --help Show this help message"
|
||||||
|
echo " --uninstall Remove SavvyCAN from the system"
|
||||||
|
echo " (no option) Install or reinstall SavvyCAN"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_error() {
|
||||||
|
echo "SavvyCAN installation failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall_error() {
|
||||||
|
echo "SavvyCAN uninstallation failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$1" = "--help" ]; then
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
require_root
|
||||||
|
|
||||||
|
# Uninstall
|
||||||
|
if [ "$1" = "--uninstall" ]; then
|
||||||
|
echo "Uninstalling SavvyCAN..."
|
||||||
|
trap uninstall_error ERR
|
||||||
|
rm -f "$APP_PATH" "$DESKTOP_PATH" "$ICON_PATH"
|
||||||
|
trap - ERR
|
||||||
|
echo "SavvyCAN has been uninstalled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check required files
|
||||||
|
if [ ! -f "SavvyCAN" ]; then
|
||||||
|
echo "Missing file \"SavvyCAN\". You need to build first."
|
||||||
|
install_error
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "SavvyCAN.desktop" ]; then
|
||||||
|
echo "Missing file \"SavvyCAN.desktop\"."
|
||||||
|
install_error
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "icons/SavvyIcon.png" ]; then
|
||||||
|
echo "Missing file \"icons/SavvyIcon.png\"."
|
||||||
|
install_error
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install
|
||||||
|
if [ -f "$APP_PATH" ]; then
|
||||||
|
echo "Re-installing SavvyCAN..."
|
||||||
|
else
|
||||||
|
echo "Installing SavvyCAN..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap install_error ERR
|
||||||
|
install -Dm755 SavvyCAN "$APP_PATH"
|
||||||
|
install -Dm644 SavvyCAN.desktop "$DESKTOP_PATH"
|
||||||
|
install -Dm644 icons/SavvyIcon.png "$ICON_PATH"
|
||||||
|
trap - ERR
|
||||||
|
|
||||||
|
echo "SavvyCAN is installed."
|
||||||
+206
@@ -164,6 +164,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
connect(ui->btnExpandAll, &QAbstractButton::clicked, this, &MainWindow::expandAllRows);
|
connect(ui->btnExpandAll, &QAbstractButton::clicked, this, &MainWindow::expandAllRows);
|
||||||
connect(ui->btnCollapseAll, &QAbstractButton::clicked, this, &MainWindow::collapseAllRows);
|
connect(ui->btnCollapseAll, &QAbstractButton::clicked, this, &MainWindow::collapseAllRows);
|
||||||
|
|
||||||
|
connect(ui->tableSimpleSender, SIGNAL(cellChanged(int,int)), this, SLOT(onSenderCellChanged(int,int)));
|
||||||
|
|
||||||
lbStatusConnected.setText(tr("Connected to 0 buses"));
|
lbStatusConnected.setText(tr("Connected to 0 buses"));
|
||||||
lbHelp.setText(tr("Press F1 on any screen for help"));
|
lbHelp.setText(tr("Press F1 on any screen for help"));
|
||||||
lbHelp.setAlignment(Qt::AlignCenter);
|
lbHelp.setAlignment(Qt::AlignCenter);
|
||||||
@@ -227,12 +229,34 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
ui->actionMotorControlConfig->setVisible(false);
|
ui->actionMotorControlConfig->setVisible(false);
|
||||||
ui->actionSingle_Multi_State_2->setVisible(false);
|
ui->actionSingle_Multi_State_2->setVisible(false);
|
||||||
|
|
||||||
|
QStringList headers;
|
||||||
|
headers << "En" << "Bus" << "ID" << "Ext" << "Rem" << "Data"
|
||||||
|
<< "Interval" << "Count";
|
||||||
|
ui->tableSimpleSender->setColumnCount(8);
|
||||||
|
ui->tableSimpleSender->setColumnWidth(SIMP_COL::SC_COL_EN, 70);
|
||||||
|
ui->tableSimpleSender->setColumnWidth(SIMP_COL::SC_COL_BUS, 70);
|
||||||
|
ui->tableSimpleSender->setColumnWidth(SIMP_COL::SC_COL_ID, 70);
|
||||||
|
ui->tableSimpleSender->setColumnWidth(SIMP_COL::SC_COL_EXT, 70);
|
||||||
|
ui->tableSimpleSender->setColumnWidth(SIMP_COL::SC_COL_REM, 70);
|
||||||
|
ui->tableSimpleSender->setColumnWidth(SIMP_COL::SC_COL_DATA, 300);
|
||||||
|
ui->tableSimpleSender->setColumnWidth(SIMP_COL::SC_COL_INTERVAL, 100);
|
||||||
|
ui->tableSimpleSender->setColumnWidth(SIMP_COL::SC_COL_COUNT, 100);
|
||||||
|
ui->tableSimpleSender->setHorizontalHeaderLabels(headers);
|
||||||
|
|
||||||
|
createSenderRow();
|
||||||
|
|
||||||
|
frameSender = new FrameSenderObject(model->getListReference());
|
||||||
|
|
||||||
|
frameSender->initialize(); //creates the thread and sets things up
|
||||||
|
frameSender->startSending(); //start the timer in the object so enabled things can send
|
||||||
|
|
||||||
installEventFilter(this);
|
installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
updateTimer.stop();
|
updateTimer.stop();
|
||||||
|
frameSender->stopSending();
|
||||||
killEmAll(); //Ride the lightning
|
killEmAll(); //Ride the lightning
|
||||||
delete ui;
|
delete ui;
|
||||||
delete model;
|
delete model;
|
||||||
@@ -438,6 +462,171 @@ void MainWindow::writeSettings()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onSenderCellChanged(int row, int col)
|
||||||
|
{
|
||||||
|
if (inhibitSenderChanged) return;
|
||||||
|
qDebug() << "onCellChanged";
|
||||||
|
if (row == ui->tableSimpleSender->rowCount() - 1)
|
||||||
|
{
|
||||||
|
createSenderRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
processSenderCellChange(row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::processSenderCellChange(int line, int col)
|
||||||
|
{
|
||||||
|
qDebug() << "processSenderCellChange";
|
||||||
|
FrameSendData *tempData;
|
||||||
|
QStringList tokens;
|
||||||
|
int tempVal;
|
||||||
|
|
||||||
|
int numBuses = CANConManager::getInstance()->getNumBuses();
|
||||||
|
QByteArray arr;
|
||||||
|
|
||||||
|
tempData = frameSender->getSendRecordRef(line);
|
||||||
|
|
||||||
|
if (!tempData)
|
||||||
|
{
|
||||||
|
qDebug() << "Need to set up a new entry in senders";
|
||||||
|
FrameSendData dat;
|
||||||
|
dat.enabled = false;
|
||||||
|
dat.count = 0;
|
||||||
|
dat.frameCount = 0;
|
||||||
|
dat.bus = 0;
|
||||||
|
frameSender->addSendRecord(dat);
|
||||||
|
tempData = frameSender->getSendRecordRef(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tempData)
|
||||||
|
{
|
||||||
|
qDebug() << "No data to modify in processSenderCellChange. This is a bug!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (col)
|
||||||
|
{
|
||||||
|
case SIMP_COL::SC_COL_EN: //Enable check box
|
||||||
|
if (ui->tableSimpleSender->item(line, 0)->checkState() == Qt::Checked)
|
||||||
|
{
|
||||||
|
tempData->enabled = true;
|
||||||
|
}
|
||||||
|
else tempData->enabled = false;
|
||||||
|
qDebug() << "Setting enabled to " << tempData->enabled;
|
||||||
|
break;
|
||||||
|
case SIMP_COL::SC_COL_BUS: //Bus designation
|
||||||
|
tempVal = Utility::ParseStringToNum(ui->tableSimpleSender->item(line, SIMP_COL::SC_COL_BUS)->text());
|
||||||
|
if (tempVal < -1) tempVal = -1;
|
||||||
|
if (tempVal >= numBuses) tempVal = numBuses - 1;
|
||||||
|
tempData->bus = tempVal;
|
||||||
|
qDebug() << "Setting bus to " << tempVal;
|
||||||
|
break;
|
||||||
|
case SIMP_COL::SC_COL_ID: //ID field
|
||||||
|
tempVal = Utility::ParseStringToNum(ui->tableSimpleSender->item(line, SIMP_COL::SC_COL_ID)->text());
|
||||||
|
if (tempVal < 0) tempVal = 0;
|
||||||
|
if (tempVal > 0x7FFFFFFF) tempVal = 0x7FFFFFFF;
|
||||||
|
tempData->setFrameId(tempVal);
|
||||||
|
if (tempData->frameId() > 0x7FF) {
|
||||||
|
tempData->setExtendedFrameFormat(true);
|
||||||
|
ui->tableSimpleSender->blockSignals(true);
|
||||||
|
ui->tableSimpleSender->item(line, ST_COLS::SENDTAB_COL_EXT)->setCheckState(Qt::Checked);
|
||||||
|
ui->tableSimpleSender->blockSignals(false);
|
||||||
|
}
|
||||||
|
qDebug() << "setting ID to " << tempVal;
|
||||||
|
break;
|
||||||
|
case SIMP_COL::SC_COL_EXT:
|
||||||
|
if (ui->tableSimpleSender->item(line, SIMP_COL::SC_COL_EXT)->checkState() == Qt::Checked) {
|
||||||
|
tempData->setExtendedFrameFormat(true);
|
||||||
|
} else {
|
||||||
|
tempData->setExtendedFrameFormat(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIMP_COL::SC_COL_REM:
|
||||||
|
if (ui->tableSimpleSender->item(line, SIMP_COL::SC_COL_REM)->checkState() == Qt::Checked) {
|
||||||
|
tempData->setFrameType(QCanBusFrame::RemoteRequestFrame);
|
||||||
|
} else {
|
||||||
|
tempData->setFrameType(QCanBusFrame::DataFrame);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIMP_COL::SC_COL_DATA: //Data bytes
|
||||||
|
for (int i = 0; i < 8; i++) tempData->payload().data()[i] = 0;
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
|
||||||
|
tokens = ui->tableSimpleSender->item(line, SIMP_COL::SC_COL_DATA)->text().split(" ", Qt::SkipEmptyParts);
|
||||||
|
#else
|
||||||
|
tokens = ui->tableSimpleSender->item(line, SIMP_COL::SC_COL_DATA)->text().split(" ", QString::SkipEmptyParts);
|
||||||
|
#endif
|
||||||
|
arr.clear();
|
||||||
|
arr.reserve(tokens.count());
|
||||||
|
for (int j = 0; j < tokens.count(); j++)
|
||||||
|
{
|
||||||
|
arr.append((uint8_t)Utility::ParseStringToNum(tokens[j]));
|
||||||
|
}
|
||||||
|
tempData->setPayload(arr);
|
||||||
|
break;
|
||||||
|
case SIMP_COL::SC_COL_INTERVAL: //interval in ms
|
||||||
|
|
||||||
|
QString trigger = ui->tableSimpleSender->item(line, SIMP_COL::SC_COL_INTERVAL)->text().toUpper();
|
||||||
|
|
||||||
|
Trigger thisTrigger;
|
||||||
|
thisTrigger.bus = -1; //-1 means we don't care which
|
||||||
|
thisTrigger.ID = -1; //the rest of these being -1 means nothing has changed it
|
||||||
|
thisTrigger.maxCount = -1;
|
||||||
|
thisTrigger.milliseconds = -1;
|
||||||
|
thisTrigger.currCount = 0;
|
||||||
|
thisTrigger.msCounter = 0;
|
||||||
|
thisTrigger.triggerMask = 0;
|
||||||
|
thisTrigger.readyCount = true;
|
||||||
|
|
||||||
|
tempData->triggers.clear();
|
||||||
|
tempData->triggers.reserve(1);
|
||||||
|
|
||||||
|
if (trigger != "")
|
||||||
|
{
|
||||||
|
thisTrigger.milliseconds = Utility::ParseStringToNum(trigger);
|
||||||
|
thisTrigger.triggerMask |= TriggerMask::TRG_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thisTrigger.milliseconds < 1) thisTrigger.milliseconds = 1;
|
||||||
|
|
||||||
|
tempData->triggers.append(thisTrigger);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::createSenderRow()
|
||||||
|
{
|
||||||
|
int row = ui->tableSimpleSender->rowCount();
|
||||||
|
ui->tableSimpleSender->insertRow(row);
|
||||||
|
|
||||||
|
QTableWidgetItem *item = new QTableWidgetItem();
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
|
item->setCheckState(Qt::Unchecked);
|
||||||
|
inhibitSenderChanged = true;
|
||||||
|
ui->tableSimpleSender->setItem(row, SIMP_COL::SC_COL_EN, item);
|
||||||
|
|
||||||
|
item = new QTableWidgetItem();
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
|
item->setCheckState(Qt::Unchecked);
|
||||||
|
ui->tableSimpleSender->setItem(row, SIMP_COL::SC_COL_EXT, item);
|
||||||
|
|
||||||
|
item = new QTableWidgetItem();
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
|
item->setCheckState(Qt::Unchecked);
|
||||||
|
ui->tableSimpleSender->setItem(row, SIMP_COL::SC_COL_REM, item);
|
||||||
|
|
||||||
|
for (int i = 1; i <= SIMP_COL::SC_COL_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (i != SIMP_COL::SC_COL_EXT && i != SIMP_COL::SC_COL_REM) {
|
||||||
|
item = new QTableWidgetItem("");
|
||||||
|
ui->tableSimpleSender->setItem(row, i, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inhibitSenderChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::updateConnectionSettings(QString connectionType, QString port, int speed0, int speed1)
|
void MainWindow::updateConnectionSettings(QString connectionType, QString port, int speed0, int speed1)
|
||||||
{
|
{
|
||||||
Q_UNUSED(connectionType);
|
Q_UNUSED(connectionType);
|
||||||
@@ -825,6 +1014,18 @@ void MainWindow::tickGUIUpdate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//refresh the count for all the frame senders
|
||||||
|
FrameSendData *tempData;
|
||||||
|
int numRows = ui->tableSimpleSender->rowCount();
|
||||||
|
for (int i = 0; i < numRows; i++)
|
||||||
|
{
|
||||||
|
tempData = frameSender->getSendRecordRef(i);
|
||||||
|
if (tempData)
|
||||||
|
{
|
||||||
|
ui->tableSimpleSender->item(i, SIMP_COL::SC_COL_COUNT)->setText(QString::number( tempData->count ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rxFrames = 0;
|
rxFrames = 0;
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
@@ -1371,6 +1572,11 @@ CANFrameModel* MainWindow::getCANFrameModel()
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All functions past this point set up the various other windows that can be opened
|
||||||
|
*/
|
||||||
|
|
||||||
void MainWindow::showSettingsDialog()
|
void MainWindow::showSettingsDialog()
|
||||||
{
|
{
|
||||||
if (!settingsDialog)
|
if (!settingsDialog)
|
||||||
|
|||||||
+18
-1
@@ -10,7 +10,7 @@
|
|||||||
#include "framefileio.h"
|
#include "framefileio.h"
|
||||||
#include "dbc/dbchandler.h"
|
#include "dbc/dbchandler.h"
|
||||||
#include "bus_protocols/isotp_handler.h"
|
#include "bus_protocols/isotp_handler.h"
|
||||||
|
#include "framesenderobject.h"
|
||||||
#include "re/graphingwindow.h"
|
#include "re/graphingwindow.h"
|
||||||
#include "re/frameinfowindow.h"
|
#include "re/frameinfowindow.h"
|
||||||
#include "frameplaybackwindow.h"
|
#include "frameplaybackwindow.h"
|
||||||
@@ -40,6 +40,18 @@ class ConnectionWindow;
|
|||||||
class ISOTP_InterpreterWindow;
|
class ISOTP_InterpreterWindow;
|
||||||
class ScriptingWindow;
|
class ScriptingWindow;
|
||||||
|
|
||||||
|
enum SIMP_COL
|
||||||
|
{
|
||||||
|
SC_COL_EN = 0,
|
||||||
|
SC_COL_BUS = 1,
|
||||||
|
SC_COL_ID = 2,
|
||||||
|
SC_COL_EXT = 3,
|
||||||
|
SC_COL_REM = 4,
|
||||||
|
SC_COL_DATA = 5,
|
||||||
|
SC_COL_INTERVAL = 6,
|
||||||
|
SC_COL_COUNT = 7,
|
||||||
|
};
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
}
|
}
|
||||||
@@ -114,6 +126,7 @@ private slots:
|
|||||||
void filterClearAll();
|
void filterClearAll();
|
||||||
void headerClicked (int logicalIndex);
|
void headerClicked (int logicalIndex);
|
||||||
void DBCSettingsUpdated();
|
void DBCSettingsUpdated();
|
||||||
|
void onSenderCellChanged(int, int);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void gotFrames(int);
|
void gotFrames(int);
|
||||||
@@ -142,6 +155,7 @@ private:
|
|||||||
QByteArray inputBuffer;
|
QByteArray inputBuffer;
|
||||||
QTimer updateTimer;
|
QTimer updateTimer;
|
||||||
QElapsedTimer *elapsedTime;
|
QElapsedTimer *elapsedTime;
|
||||||
|
FrameSenderObject *frameSender;
|
||||||
int framesPerSec;
|
int framesPerSec;
|
||||||
int rxFrames;
|
int rxFrames;
|
||||||
bool inhibitFilterUpdate;
|
bool inhibitFilterUpdate;
|
||||||
@@ -151,6 +165,7 @@ private:
|
|||||||
bool CSVAbsTime;
|
bool CSVAbsTime;
|
||||||
bool bDirty; //have frames been added or subtracted since the last save/load?
|
bool bDirty; //have frames been added or subtracted since the last save/load?
|
||||||
bool useFiltered; //should sub-windows use the unfiltered or filtered frames list?
|
bool useFiltered; //should sub-windows use the unfiltered or filtered frames list?
|
||||||
|
bool inhibitSenderChanged;
|
||||||
|
|
||||||
bool continuousLogging;
|
bool continuousLogging;
|
||||||
int continuousLogFlushCounter;
|
int continuousLogFlushCounter;
|
||||||
@@ -211,6 +226,8 @@ private:
|
|||||||
bool eventFilter(QObject *obj, QEvent *event);
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
void manageRowExpansion();
|
void manageRowExpansion();
|
||||||
void disableAutoRowExpansion();
|
void disableAutoRowExpansion();
|
||||||
|
void createSenderRow();
|
||||||
|
void processSenderCellChange(int line, int col);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
|||||||
+18
-3
@@ -19,7 +19,7 @@
|
|||||||
static unsigned char pcap_buffer[MAX_CAN_PACKET_SIZE];
|
static unsigned char pcap_buffer[MAX_CAN_PACKET_SIZE];
|
||||||
static pcap_t p;
|
static pcap_t p;
|
||||||
|
|
||||||
pcap *pcap_open_offline(const char *filename, char *error_text) {
|
pcap *pcap_open_offline(const char *filename, char *error_text, int expected_link_type) {
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
|
||||||
snprintf(error_text, PCAP_ERRBUF_SIZE, "OK");
|
snprintf(error_text, PCAP_ERRBUF_SIZE, "OK");
|
||||||
@@ -48,6 +48,23 @@ pcap *pcap_open_offline(const char *filename, char *error_text) {
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int link_type;
|
||||||
|
fseek(file, PCAP_FILE_HEADER_LENGTH - 4, SEEK_SET);
|
||||||
|
bytes_read = fread(&link_type, 1, sizeof(link_type), file);
|
||||||
|
if (bytes_read != sizeof(link_type)) {
|
||||||
|
snprintf(error_text, PCAP_ERRBUF_SIZE, "Cannot read linktype word");
|
||||||
|
fclose(file);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
if (expected_link_type >= 0) {
|
||||||
|
// Check the link type
|
||||||
|
if ((int) link_type != expected_link_type) {
|
||||||
|
snprintf(error_text, PCAP_ERRBUF_SIZE, "This link type is not supported by this decoder");
|
||||||
|
fclose(file);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set the format
|
// set the format
|
||||||
// and seek past file header
|
// and seek past file header
|
||||||
if (MAGIC_NG == magic) {
|
if (MAGIC_NG == magic) {
|
||||||
@@ -61,14 +78,12 @@ pcap *pcap_open_offline(const char *filename, char *error_text) {
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
fseek(file, section_length, SEEK_SET);
|
fseek(file, section_length, SEEK_SET);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
p.is_ng = 0;
|
p.is_ng = 0;
|
||||||
fseek(file, PCAP_FILE_HEADER_LENGTH, SEEK_SET);
|
fseek(file, PCAP_FILE_HEADER_LENGTH, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
p.file = file;
|
p.file = file;
|
||||||
|
|
||||||
return(&p);
|
return(&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -8,7 +8,9 @@
|
|||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PCAP_ERRBUF_SIZE 256
|
#define PCAP_ERRBUF_SIZE (256)
|
||||||
|
#define PCAP_LINKTYPE_SOCKETCAN (227)
|
||||||
|
#define PCAP_LINKTYPE_ANY (-1)
|
||||||
|
|
||||||
struct pcap_pkthdr {
|
struct pcap_pkthdr {
|
||||||
struct timeval ts; /* time stamp */
|
struct timeval ts; /* time stamp */
|
||||||
@@ -23,7 +25,7 @@ struct pcap {
|
|||||||
|
|
||||||
typedef struct pcap pcap_t;
|
typedef struct pcap pcap_t;
|
||||||
|
|
||||||
pcap *pcap_open_offline(const char *, char *);
|
pcap *pcap_open_offline(const char *, char *, int);
|
||||||
|
|
||||||
const unsigned char *pcap_next(pcap_t *, struct pcap_pkthdr *);
|
const unsigned char *pcap_next(pcap_t *, struct pcap_pkthdr *);
|
||||||
|
|
||||||
|
|||||||
@@ -222,8 +222,8 @@ void DBCComparatorWindow::calculateDetails()
|
|||||||
|
|
||||||
ui->treeDetails->addTopLevelItem(msgDiffRoot);
|
ui->treeDetails->addTopLevelItem(msgDiffRoot);
|
||||||
|
|
||||||
QTreeWidgetItem *msgItem;
|
QTreeWidgetItem *msgItem {};
|
||||||
QTreeWidgetItem *sigTemp;
|
QTreeWidgetItem *sigTemp {};
|
||||||
|
|
||||||
for (int i = 0; i < firstDBC->messageHandler->getCount(); i++)
|
for (int i = 0; i < firstDBC->messageHandler->getCount(); i++)
|
||||||
{
|
{
|
||||||
@@ -257,7 +257,8 @@ void DBCComparatorWindow::calculateDetails()
|
|||||||
msgItem->setText(0, msgName + " (" + Utility::formatCANID(thisMsg->ID) + ")");
|
msgItem->setText(0, msgName + " (" + Utility::formatCANID(thisMsg->ID) + ")");
|
||||||
sigDiffTwo->addChild(msgItem);
|
sigDiffTwo->addChild(msgItem);
|
||||||
}
|
}
|
||||||
msgItem->addChild(missingSigItem);
|
if (msgItem)
|
||||||
|
msgItem->addChild(missingSigItem);
|
||||||
}
|
}
|
||||||
else //signal exists on both sides. See if it as changed position or length
|
else //signal exists on both sides. See if it as changed position or length
|
||||||
{
|
{
|
||||||
@@ -301,7 +302,8 @@ void DBCComparatorWindow::calculateDetails()
|
|||||||
sigTemp->setText(0, msgName + " (" + Utility::formatCANID(thisMsg->ID) + ")");
|
sigTemp->setText(0, msgName + " (" + Utility::formatCANID(thisMsg->ID) + ")");
|
||||||
sigModifiedRoot->addChild(sigTemp);
|
sigModifiedRoot->addChild(sigTemp);
|
||||||
}
|
}
|
||||||
sigTemp->addChild(sigItem);
|
if (sigTemp)
|
||||||
|
sigTemp->addChild(sigItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -851,7 +851,7 @@ void FlowViewWindow::updatePosition(bool forward)
|
|||||||
int maxVal = qMin(chunk * 8 + 8, frameCache.at(currentPosition).payload().length());
|
int maxVal = qMin(chunk * 8 + 8, frameCache.at(currentPosition).payload().length());
|
||||||
for (int i = chunk * 8; i < maxVal; i++)
|
for (int i = chunk * 8; i < maxVal; i++)
|
||||||
{
|
{
|
||||||
unsigned char thisByte = static_cast<unsigned char>(frameCache.at(currentPosition).payload().data()[i]);
|
unsigned char thisByte = static_cast<unsigned char>(frameCache.at(currentPosition).payload()[i]);
|
||||||
cngByte = currBytes[i] ^ thisByte;
|
cngByte = currBytes[i] ^ thisByte;
|
||||||
changedBits |= (uint64_t)cngByte << (8ull * (i & 7));
|
changedBits |= (uint64_t)cngByte << (8ull * (i & 7));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ FuzzingWindow::FuzzingWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
|||||||
|
|
||||||
fuzzTimer = new QTimer();
|
fuzzTimer = new QTimer();
|
||||||
|
|
||||||
|
connect(ui->btnMarkAllHigh, &QPushButton::clicked, this, &FuzzingWindow::markAllHigh);
|
||||||
|
connect(ui->btnMarkAllLow, &QPushButton::clicked, this, &FuzzingWindow::markAllLow);
|
||||||
|
connect(ui->btnMarkAllAuto, &QPushButton::clicked, this, &FuzzingWindow::markAllAuto);
|
||||||
connect(ui->btnStartStop, &QPushButton::clicked, this, &FuzzingWindow::toggleFuzzing);
|
connect(ui->btnStartStop, &QPushButton::clicked, this, &FuzzingWindow::toggleFuzzing);
|
||||||
connect(ui->btnAllFilters, &QPushButton::clicked, this, &FuzzingWindow::setAllFilters);
|
connect(ui->btnAllFilters, &QPushButton::clicked, this, &FuzzingWindow::setAllFilters);
|
||||||
connect(ui->btnNoFilters, &QPushButton::clicked, this, &FuzzingWindow::clearAllFilters);
|
connect(ui->btnNoFilters, &QPushButton::clicked, this, &FuzzingWindow::clearAllFilters);
|
||||||
@@ -508,3 +511,30 @@ void FuzzingWindow::redrawGrid()
|
|||||||
ui->bitfield->setReference(refBytes, false);
|
ui->bitfield->setReference(refBytes, false);
|
||||||
ui->bitfield->updateData(dataBytes, true);
|
ui->bitfield->updateData(dataBytes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FuzzingWindow::markAllHigh()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 512; i++)
|
||||||
|
{
|
||||||
|
bitGrid[i] = 2;
|
||||||
|
}
|
||||||
|
redrawGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FuzzingWindow::markAllLow()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 512; i++)
|
||||||
|
{
|
||||||
|
bitGrid[i] = 0;
|
||||||
|
}
|
||||||
|
redrawGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FuzzingWindow::markAllAuto()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 512; i++)
|
||||||
|
{
|
||||||
|
bitGrid[i] = 1;
|
||||||
|
}
|
||||||
|
redrawGrid();
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ private slots:
|
|||||||
void bitfieldClicked(int);
|
void bitfieldClicked(int);
|
||||||
void changedNumDataBytes(int newVal);
|
void changedNumDataBytes(int newVal);
|
||||||
void updatedFrames(int numFrames);
|
void updatedFrames(int numFrames);
|
||||||
|
void markAllHigh();
|
||||||
|
void markAllLow();
|
||||||
|
void markAllAuto();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::FuzzingWindow *ui;
|
Ui::FuzzingWindow *ui;
|
||||||
|
|||||||
+100
-105
@@ -39,7 +39,7 @@ GraphingWindow::GraphingWindow(const QVector<CANFrame> *frames, QWidget *parent)
|
|||||||
|
|
||||||
if (Utility::timeStyle == TS_CLOCK)
|
if (Utility::timeStyle == TS_CLOCK)
|
||||||
{
|
{
|
||||||
QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime);
|
QSharedPointer timeTicker = QSharedPointer<QCPAxisTickerTime>::create();
|
||||||
timeTicker->setTimeFormat("%h:%m:%s.%z");
|
timeTicker->setTimeFormat("%h:%m:%s.%z");
|
||||||
ui->graphingView->xAxis->setTicker(timeTicker);
|
ui->graphingView->xAxis->setTicker(timeTicker);
|
||||||
}
|
}
|
||||||
@@ -571,7 +571,7 @@ void GraphingWindow::removeSelectedGraph()
|
|||||||
int idx = -1;
|
int idx = -1;
|
||||||
for (int i = 0; i < graphParams.count(); i++)
|
for (int i = 0; i < graphParams.count(); i++)
|
||||||
{
|
{
|
||||||
if (graphParams[i].ref == ui->graphingView->selectedGraphs().first())
|
if (graphParams[i].ref == ui->graphingView->selectedGraphs().constFirst())
|
||||||
{
|
{
|
||||||
idx = i;
|
idx = i;
|
||||||
break;
|
break;
|
||||||
@@ -590,7 +590,7 @@ void GraphingWindow::removeSelectedGraph()
|
|||||||
|
|
||||||
graphParams.removeAt(idx);
|
graphParams.removeAt(idx);
|
||||||
|
|
||||||
ui->graphingView->removeGraph(ui->graphingView->selectedGraphs().first());
|
ui->graphingView->removeGraph(ui->graphingView->selectedGraphs().constFirst());
|
||||||
|
|
||||||
if (graphParams.count() == 0) needScaleSetup = true;
|
if (graphParams.count() == 0) needScaleSetup = true;
|
||||||
|
|
||||||
@@ -605,7 +605,7 @@ void GraphingWindow::editSelectedGraph()
|
|||||||
int idx = -1;
|
int idx = -1;
|
||||||
for (int i = 0; i < graphParams.count(); i++)
|
for (int i = 0; i < graphParams.count(); i++)
|
||||||
{
|
{
|
||||||
if (graphParams[i].ref == ui->graphingView->selectedGraphs().first())
|
if (graphParams[i].ref == ui->graphingView->selectedGraphs().constFirst())
|
||||||
{
|
{
|
||||||
idx = i;
|
idx = i;
|
||||||
break;
|
break;
|
||||||
@@ -701,7 +701,6 @@ void GraphingWindow::contextMenuRequest(QPoint pos)
|
|||||||
|
|
||||||
void GraphingWindow::saveGraphs()
|
void GraphingWindow::saveGraphs()
|
||||||
{
|
{
|
||||||
QString filename;
|
|
||||||
QFileDialog dialog(this);
|
QFileDialog dialog(this);
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
@@ -718,7 +717,7 @@ void GraphingWindow::saveGraphs()
|
|||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted)
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
{
|
{
|
||||||
filename = dialog.selectedFiles()[0];
|
QString filename = dialog.selectedFiles().constFirst();
|
||||||
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
||||||
|
|
||||||
if (dialog.selectedNameFilter() == filters[0])
|
if (dialog.selectedNameFilter() == filters[0])
|
||||||
@@ -741,7 +740,6 @@ void GraphingWindow::saveGraphs()
|
|||||||
|
|
||||||
void GraphingWindow::saveSpreadsheet()
|
void GraphingWindow::saveSpreadsheet()
|
||||||
{
|
{
|
||||||
QString filename;
|
|
||||||
QFileDialog dialog(this);
|
QFileDialog dialog(this);
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
@@ -756,14 +754,14 @@ void GraphingWindow::saveSpreadsheet()
|
|||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted)
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
{
|
{
|
||||||
filename = dialog.selectedFiles()[0];
|
QString filename = dialog.selectedFiles().constFirst();
|
||||||
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
||||||
|
|
||||||
if (!filename.contains('.')) filename += ".csv";
|
if (!filename.contains('.')) filename += ".csv";
|
||||||
|
|
||||||
QFile *outFile = new QFile(filename);
|
QFile outFile(filename);
|
||||||
|
|
||||||
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -779,12 +777,12 @@ void GraphingWindow::saveSpreadsheet()
|
|||||||
QList<GraphParams>::iterator iter;
|
QList<GraphParams>::iterator iter;
|
||||||
double xMin = std::numeric_limits<double>::max(),
|
double xMin = std::numeric_limits<double>::max(),
|
||||||
xMax = std::numeric_limits<double>::min();
|
xMax = std::numeric_limits<double>::min();
|
||||||
size_t maxCount = 0;
|
int maxCount = 0;
|
||||||
size_t numGraphs = graphParams.length();
|
int numGraphs = graphParams.length();
|
||||||
for (auto && graph : graphParams) {
|
for (auto && graph : graphParams) {
|
||||||
xMin = std::min(xMin, graph.x[0]);
|
xMin = std::min(xMin, graph.x[0]);
|
||||||
xMax = std::max(xMax, graph.x[graph.x.count() - 1]);
|
xMax = std::max(xMax, graph.x[graph.x.count() - 1]);
|
||||||
maxCount = std::max(maxCount, static_cast<size_t>(graph.x.count()));
|
maxCount = std::max(maxCount, graph.x.count());
|
||||||
}
|
}
|
||||||
qDebug() << "xMin: " << xMin;
|
qDebug() << "xMin: " << xMin;
|
||||||
qDebug() << "xMax: " << xMax;
|
qDebug() << "xMax: " << xMax;
|
||||||
@@ -795,27 +793,25 @@ void GraphingWindow::saveSpreadsheet()
|
|||||||
double xSize = xMax - xMin;
|
double xSize = xMax - xMin;
|
||||||
double sliceSize = xSize / ((double)maxCount);
|
double sliceSize = xSize / ((double)maxCount);
|
||||||
double equivValue = sliceSize / 100.0;
|
double equivValue = sliceSize / 100.0;
|
||||||
double currentX;
|
|
||||||
double value;
|
|
||||||
QList<int> indices;
|
QList<int> indices;
|
||||||
indices.reserve(numGraphs);
|
indices.reserve(numGraphs);
|
||||||
|
|
||||||
outFile->write("TimeStamp");
|
outFile.write("TimeStamp");
|
||||||
for (auto && graph : graphParams) {
|
for (auto && graph : graphParams) {
|
||||||
indices.append(0);
|
indices.append(0);
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(graph.graphName.toUtf8());
|
outFile.write(graph.graphName.toUtf8());
|
||||||
}
|
}
|
||||||
outFile->write("\n");
|
outFile.write("\n");
|
||||||
|
|
||||||
for (size_t j = 1; j < (maxCount - 1); j++)
|
for (int j = 1; j < (maxCount - 1); j++)
|
||||||
{
|
{
|
||||||
currentX = xMin + (j * sliceSize);
|
double currentX = xMin + (j * sliceSize);
|
||||||
qDebug() << "X: " << currentX;
|
qDebug() << "X: " << currentX;
|
||||||
outFile->write(QString::number(currentX, 'f').toUtf8());
|
outFile.write(QString::number(currentX, 'f').toUtf8());
|
||||||
for (size_t k = 0; k < numGraphs; k++)
|
for (int k = 0; k < numGraphs; k++)
|
||||||
{
|
{
|
||||||
value = 0.0;
|
double value = 0.0;
|
||||||
|
|
||||||
// move cursor to last sample before currentX
|
// move cursor to last sample before currentX
|
||||||
while (graphParams[k].x[indices[k]+1] < currentX)
|
while (graphParams[k].x[indices[k]+1] < currentX)
|
||||||
@@ -849,27 +845,26 @@ void GraphingWindow::saveSpreadsheet()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// find index, where x >= currentX
|
// find index, where x >= currentX
|
||||||
size_t cursor = indices[k];
|
int cursor = indices[k];
|
||||||
double span = graphParams[k].x[cursor+1] - graphParams[k].x[cursor];
|
double span = graphParams[k].x[cursor+1] - graphParams[k].x[cursor];
|
||||||
double progress = (currentX - graphParams[k].x[cursor]) / span;
|
double progress = (currentX - graphParams[k].x[cursor]) / span;
|
||||||
Q_ASSERT(progress >= 0.0 && progress <= 1.0);
|
Q_ASSERT(progress >= 0.0 && progress <= 1.0);
|
||||||
value = Utility::Lerp(graphParams[k].y[cursor], graphParams[k].y[cursor+1], progress);
|
value = Utility::Lerp(graphParams[k].y[cursor], graphParams[k].y[cursor+1], progress);
|
||||||
qDebug() << "Span: " << span << " Prog: " << progress << " Value: " << value;
|
qDebug() << "Span: " << span << " Prog: " << progress << " Value: " << value;
|
||||||
}
|
}
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(value).toUtf8());
|
outFile.write(QString::number(value).toUtf8());
|
||||||
}
|
}
|
||||||
outFile->write("\n");
|
outFile.write("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
outFile->close();
|
outFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphingWindow::saveDefinitions()
|
void GraphingWindow::saveDefinitions()
|
||||||
{
|
{
|
||||||
QString filename;
|
|
||||||
QFileDialog dialog(this);
|
QFileDialog dialog(this);
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
@@ -884,79 +879,78 @@ void GraphingWindow::saveDefinitions()
|
|||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted)
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
{
|
{
|
||||||
filename = dialog.selectedFiles()[0];
|
QString filename = dialog.selectedFiles().constFirst();
|
||||||
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
||||||
|
|
||||||
if (!filename.contains('.')) filename += ".gdf";
|
if (!filename.contains('.')) filename += ".gdf";
|
||||||
|
|
||||||
QFile *outFile = new QFile(filename);
|
QFile outFile(filename);
|
||||||
|
|
||||||
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QList<GraphParams>::iterator iter;
|
QList<GraphParams>::iterator iter;
|
||||||
for (iter = graphParams.begin(); iter != graphParams.end(); ++iter)
|
for (iter = graphParams.begin(); iter != graphParams.end(); ++iter)
|
||||||
{
|
{
|
||||||
outFile->write("Z,");
|
outFile.write("Z,");
|
||||||
outFile->write(QString::number(iter->ID, 16).toUtf8());
|
outFile.write(QString::number(iter->ID, 16).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->mask, 16).toUtf8());
|
outFile.write(QString::number(iter->mask, 16).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
if (iter->intelFormat) outFile->write(QString::number(iter->startBit).toUtf8());
|
if (iter->intelFormat) outFile.write(QString::number(iter->startBit).toUtf8());
|
||||||
else outFile->write(QString::number(iter->startBit * -1).toUtf8());
|
else outFile.write(QString::number(iter->startBit * -1).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->numBits).toUtf8());
|
outFile.write(QString::number(iter->numBits).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
if (iter->isSigned) outFile->putChar('Y');
|
if (iter->isSigned) outFile.putChar('Y');
|
||||||
else outFile->putChar('N');
|
else outFile.putChar('N');
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->bias).toUtf8());
|
outFile.write(QString::number(iter->bias).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->scale).toUtf8());
|
outFile.write(QString::number(iter->scale).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->stride).toUtf8());
|
outFile.write(QString::number(iter->stride).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->bus).toUtf8());
|
outFile.write(QString::number(iter->bus).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->lineColor.red()).toUtf8());
|
outFile.write(QString::number(iter->lineColor.red()).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->lineColor.green()).toUtf8());
|
outFile.write(QString::number(iter->lineColor.green()).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->lineColor.blue()).toUtf8());
|
outFile.write(QString::number(iter->lineColor.blue()).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(iter->graphName.toUtf8());
|
outFile.write(iter->graphName.toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->fillColor.red()).toUtf8());
|
outFile.write(QString::number(iter->fillColor.red()).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->fillColor.green()).toUtf8());
|
outFile.write(QString::number(iter->fillColor.green()).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->fillColor.blue()).toUtf8());
|
outFile.write(QString::number(iter->fillColor.blue()).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->fillColor.alpha()).toUtf8());
|
outFile.write(QString::number(iter->fillColor.alpha()).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
if (iter->drawOnlyPoints) outFile->putChar('Y');
|
if (iter->drawOnlyPoints) outFile.putChar('Y');
|
||||||
else outFile->putChar('N');
|
else outFile.putChar('N');
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->pointType).toUtf8());
|
outFile.write(QString::number(iter->pointType).toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(QString::number(iter->lineWidth).toUtf8());
|
outFile.write(QString::number(iter->lineWidth).toUtf8());
|
||||||
if (iter->associatedSignal)
|
if (iter->associatedSignal)
|
||||||
{
|
{
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(iter->associatedSignal->parentMessage->name.toUtf8());
|
outFile.write(iter->associatedSignal->parentMessage->name.toUtf8());
|
||||||
outFile->putChar(',');
|
outFile.putChar(',');
|
||||||
outFile->write(iter->associatedSignal->name.toUtf8());
|
outFile.write(iter->associatedSignal->name.toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
outFile->write("\n");
|
outFile.write("\n");
|
||||||
}
|
}
|
||||||
outFile->close();
|
outFile.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphingWindow::loadDefinitions()
|
void GraphingWindow::loadDefinitions()
|
||||||
{
|
{
|
||||||
QString filename;
|
|
||||||
QFileDialog dialog;
|
QFileDialog dialog;
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
@@ -973,17 +967,17 @@ void GraphingWindow::loadDefinitions()
|
|||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted)
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
{
|
{
|
||||||
filename = dialog.selectedFiles()[0];
|
QString filename = dialog.selectedFiles().constFirst();
|
||||||
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
||||||
|
|
||||||
QFile *inFile = new QFile(filename);
|
QFile inFile(filename);
|
||||||
QByteArray line;
|
QByteArray line;
|
||||||
|
|
||||||
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
|
if (!inFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (!inFile->atEnd()) {
|
while (!inFile.atEnd()) {
|
||||||
line = inFile->readLine().simplified();
|
line = inFile.readLine().simplified();
|
||||||
if (line.length() > 2)
|
if (line.length() > 2)
|
||||||
{
|
{
|
||||||
GraphParams gp;
|
GraphParams gp;
|
||||||
@@ -1205,7 +1199,7 @@ void GraphingWindow::loadDefinitions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inFile->close();
|
inFile.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1325,10 +1319,8 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
|||||||
double yminval=10000000.0, ymaxval = -1000000.0;
|
double yminval=10000000.0, ymaxval = -1000000.0;
|
||||||
double xminval=10000000000.0, xmaxval = -10000000000.0;
|
double xminval=10000000000.0, xmaxval = -10000000000.0;
|
||||||
GraphParams *refParam = ¶ms;
|
GraphParams *refParam = ¶ms;
|
||||||
int sBit, bits;
|
|
||||||
bool intelFormat, isSigned;
|
|
||||||
QString tempStr;
|
QString tempStr;
|
||||||
double x,y;
|
double x{}, y{};
|
||||||
|
|
||||||
qDebug() << "New Graph ID: " << params.ID;
|
qDebug() << "New Graph ID: " << params.ID;
|
||||||
qDebug() << "Start bit: " << params.startBit;
|
qDebug() << "Start bit: " << params.startBit;
|
||||||
@@ -1341,7 +1333,8 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
|||||||
for (int i = 0; i < modelFrames->count(); i++)
|
for (int i = 0; i < modelFrames->count(); i++)
|
||||||
{
|
{
|
||||||
CANFrame thisFrame = modelFrames->at(i);
|
CANFrame thisFrame = modelFrames->at(i);
|
||||||
if (thisFrame.frameId() == params.ID && thisFrame.frameType() == QCanBusFrame::DataFrame && ( ( params.bus == -1) || (params.bus == thisFrame.bus) ) ) frameCache.append(thisFrame);
|
if ( (thisFrame.frameId() == params.ID) && (thisFrame.frameType() == QCanBusFrame::DataFrame)
|
||||||
|
&& ( ( params.bus == -1) || (params.bus == thisFrame.bus) ) ) frameCache.append(thisFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
//to fix weirdness where a graph that has no data won't be able to be edited, selected, or deleted properly
|
//to fix weirdness where a graph that has no data won't be able to be edited, selected, or deleted properly
|
||||||
@@ -1360,15 +1353,17 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
|||||||
int numEntries = frameCache.count() / params.stride;
|
int numEntries = frameCache.count() / params.stride;
|
||||||
if (numEntries < 1) numEntries = 1; //could happen if stride is larger than frame count
|
if (numEntries < 1) numEntries = 1; //could happen if stride is larger than frame count
|
||||||
|
|
||||||
|
params.x.clear();
|
||||||
|
params.y.clear();
|
||||||
params.x.reserve(numEntries);
|
params.x.reserve(numEntries);
|
||||||
params.y.reserve(numEntries);
|
params.y.reserve(numEntries);
|
||||||
//params.x.fill(0, numEntries);
|
//params.x.fill(0, numEntries);
|
||||||
//params.y.fill(0, numEntries);
|
//params.y.fill(0, numEntries);
|
||||||
|
|
||||||
sBit = params.startBit;
|
int sBit = params.startBit;
|
||||||
bits = params.numBits;
|
int bits = params.numBits;
|
||||||
intelFormat = params.intelFormat;
|
bool intelFormat = params.intelFormat;
|
||||||
isSigned = params.isSigned;
|
bool isSigned = params.isSigned;
|
||||||
|
|
||||||
for (int j = 0; j < numEntries; j++)
|
for (int j = 0; j < numEntries; j++)
|
||||||
{
|
{
|
||||||
@@ -1558,16 +1553,16 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
|||||||
void GraphingWindow::moveLegend()
|
void GraphingWindow::moveLegend()
|
||||||
{
|
{
|
||||||
qDebug() << "moveLegend";
|
qDebug() << "moveLegend";
|
||||||
if (QAction* contextAction = qobject_cast<QAction*>(sender())) // make sure this slot is really called by a context menu action, so it carries the data we need
|
if (QAction* contextAction = qobject_cast<QAction*>(sender())) // make sure this slot is really called by a context menu action, so it carries the data we need
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
int dataInt = contextAction->data().toInt(&ok);
|
|
||||||
if (ok)
|
|
||||||
{
|
{
|
||||||
ui->graphingView->axisRect()->insetLayout()->setInsetAlignment(0, (Qt::Alignment)dataInt);
|
bool ok;
|
||||||
ui->graphingView->replot();
|
int dataInt = contextAction->data().toInt(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
ui->graphingView->axisRect()->insetLayout()->setInsetAlignment(0, (Qt::Alignment)dataInt);
|
||||||
|
ui->graphingView->replot();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphParams::GraphParams()
|
GraphParams::GraphParams()
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ ISOTP_InterpreterWindow::ISOTP_InterpreterWindow(const QVector<CANFrame> *frames
|
|||||||
|
|
||||||
connect(ui->tableIsoFrames, &QTableWidget::itemSelectionChanged, this, &ISOTP_InterpreterWindow::showDetailView);
|
connect(ui->tableIsoFrames, &QTableWidget::itemSelectionChanged, this, &ISOTP_InterpreterWindow::showDetailView);
|
||||||
connect(ui->btnClearList, &QPushButton::clicked, this, &ISOTP_InterpreterWindow::clearList);
|
connect(ui->btnClearList, &QPushButton::clicked, this, &ISOTP_InterpreterWindow::clearList);
|
||||||
|
connect(ui->btnSaveList, &QPushButton::clicked, this, &ISOTP_InterpreterWindow::saveList);
|
||||||
connect(ui->cbUseExtendedAddressing, SIGNAL(toggled(bool)), this, SLOT(useExtendedAddressing(bool)));
|
connect(ui->cbUseExtendedAddressing, SIGNAL(toggled(bool)), this, SLOT(useExtendedAddressing(bool)));
|
||||||
|
|
||||||
QStringList headers;
|
QStringList headers;
|
||||||
@@ -172,6 +173,80 @@ void ISOTP_InterpreterWindow::clearList()
|
|||||||
//idFilters.clear();
|
//idFilters.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A bit complicated as the list doesn't have the detailed analysis in it. Have to take each list entry
|
||||||
|
* and process it to get the details then save those details to the file as well.
|
||||||
|
*/
|
||||||
|
void ISOTP_InterpreterWindow::saveList()
|
||||||
|
{
|
||||||
|
QString buildString;
|
||||||
|
QString filename;
|
||||||
|
QFileDialog dialog(this);
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
QStringList filters;
|
||||||
|
filters.append(QString(tr("Text File (*.txt)")));
|
||||||
|
|
||||||
|
dialog.setFileMode(QFileDialog::AnyFile);
|
||||||
|
dialog.setNameFilters(filters);
|
||||||
|
dialog.setViewMode(QFileDialog::Detail);
|
||||||
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||||
|
dialog.setDirectory(settings.value("FrameInfo/LoadSaveDirectory", dialog.directory().path()).toString());
|
||||||
|
|
||||||
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
settings.setValue("FrameInfo/LoadSaveDirectory", dialog.directory().path());
|
||||||
|
filename = dialog.selectedFiles()[0];
|
||||||
|
if (!filename.contains('.')) filename += ".txt";
|
||||||
|
if (dialog.selectedNameFilter() == filters[0])
|
||||||
|
{
|
||||||
|
QFile *outFile = new QFile(filename);
|
||||||
|
|
||||||
|
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
delete outFile;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rows = messages.count();
|
||||||
|
for (int r = 0 ; r < rows; r++)
|
||||||
|
{
|
||||||
|
ISOTP_MESSAGE msg = messages.at(r);
|
||||||
|
const unsigned char *data = reinterpret_cast<const unsigned char *>(msg.payload().constData());
|
||||||
|
int dataLen = msg.payload().length();
|
||||||
|
|
||||||
|
if (msg.reportedLength != dataLen)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildString.append(QString::number(msg.timeStamp().microSeconds()) + " " + QString::number(msg.frameId(), 16) + " ");
|
||||||
|
|
||||||
|
//buildString.append(tr("Raw Payload: "));
|
||||||
|
|
||||||
|
for (int i = 0; i < dataLen; i++)
|
||||||
|
{
|
||||||
|
buildString.append(Utility::formatNumber(data[i]));
|
||||||
|
buildString.append(" ");
|
||||||
|
}
|
||||||
|
buildString.append("\n\n");
|
||||||
|
|
||||||
|
UDS_MESSAGE udsMsg;
|
||||||
|
bool result;
|
||||||
|
udsMsg = udsDecoder->tryISOtoUDS(msg, &result);
|
||||||
|
if (result)
|
||||||
|
buildString.append(udsDecoder->getDetailedMessageAnalysis(udsMsg));
|
||||||
|
buildString.append("\n*********************************************************\n");
|
||||||
|
outFile->write(buildString.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile->close();
|
||||||
|
delete outFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ISOTP_InterpreterWindow::useExtendedAddressing(bool checked)
|
void ISOTP_InterpreterWindow::useExtendedAddressing(bool checked)
|
||||||
{
|
{
|
||||||
decoder->setExtendedAddressing(checked);
|
decoder->setExtendedAddressing(checked);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ private slots:
|
|||||||
void showDetailView();
|
void showDetailView();
|
||||||
void updatedFrames(int);
|
void updatedFrames(int);
|
||||||
void clearList();
|
void clearList();
|
||||||
|
void saveList();
|
||||||
void listFilterItemChanged(QListWidgetItem *item);
|
void listFilterItemChanged(QListWidgetItem *item);
|
||||||
void filterAll();
|
void filterAll();
|
||||||
void filterNone();
|
void filterNone();
|
||||||
|
|||||||
@@ -361,7 +361,6 @@ void NewGraphDialog::loadNodes()
|
|||||||
void NewGraphDialog::loadMessages(int idx)
|
void NewGraphDialog::loadMessages(int idx)
|
||||||
{
|
{
|
||||||
int numFiles = 0;
|
int numFiles = 0;
|
||||||
DBC_MESSAGE *msg;
|
|
||||||
ui->cbMessages->clear();
|
ui->cbMessages->clear();
|
||||||
if (dbcHandler == nullptr) return;
|
if (dbcHandler == nullptr) return;
|
||||||
if ((numFiles = dbcHandler->getFileCount()) == 0) return;
|
if ((numFiles = dbcHandler->getFileCount()) == 0) return;
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ void SnifferWindow::notchTick()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ui->lblNotch->setBackgroundRole(QPalette::Background);
|
ui->lblNotch->setBackgroundRole(QPalette::Window);
|
||||||
ui->lblNotch->repaint();
|
ui->lblNotch->repaint();
|
||||||
//qDebug() << "Tock";
|
//qDebug() << "Tock";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,11 @@ ScriptingWindow::ScriptingWindow(const QVector<CANFrame> *frames, QWidget *paren
|
|||||||
connect(ui->btnRecompile, &QAbstractButton::pressed, this, &ScriptingWindow::recompileScript);
|
connect(ui->btnRecompile, &QAbstractButton::pressed, this, &ScriptingWindow::recompileScript);
|
||||||
connect(ui->btnRemoveScript, &QAbstractButton::pressed, this, &ScriptingWindow::deleteCurrentScript);
|
connect(ui->btnRemoveScript, &QAbstractButton::pressed, this, &ScriptingWindow::deleteCurrentScript);
|
||||||
connect(ui->btnRevertScript, &QAbstractButton::pressed, this, &ScriptingWindow::revertScript);
|
connect(ui->btnRevertScript, &QAbstractButton::pressed, this, &ScriptingWindow::revertScript);
|
||||||
|
connect(ui->btnReloadScript, &QAbstractButton::pressed, this, &ScriptingWindow::reloadScript);
|
||||||
connect(ui->btnSaveScript, &QAbstractButton::pressed, this, &ScriptingWindow::saveScript);
|
connect(ui->btnSaveScript, &QAbstractButton::pressed, this, &ScriptingWindow::saveScript);
|
||||||
|
connect(ui->btnSaveAsScript, &QAbstractButton::pressed, this, &ScriptingWindow::saveAsScript);
|
||||||
connect(ui->btnClearLog, &QAbstractButton::pressed, this, &ScriptingWindow::clickedLogClear);
|
connect(ui->btnClearLog, &QAbstractButton::pressed, this, &ScriptingWindow::clickedLogClear);
|
||||||
|
connect(ui->btnSaveLog, &QAbstractButton::pressed, this, &ScriptingWindow::saveLog);
|
||||||
connect(ui->listLoadedScripts, &QListWidget::currentRowChanged, this, &ScriptingWindow::changeCurrentScript);
|
connect(ui->listLoadedScripts, &QListWidget::currentRowChanged, this, &ScriptingWindow::changeCurrentScript);
|
||||||
connect(ui->tableVariables, SIGNAL(cellChanged(int,int)), this, SLOT(updatedValue(int, int)));
|
connect(ui->tableVariables, SIGNAL(cellChanged(int,int)), this, SLOT(updatedValue(int, int)));
|
||||||
|
|
||||||
@@ -301,6 +304,21 @@ void ScriptingWindow::refreshSourceWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingWindow::saveScript()
|
void ScriptingWindow::saveScript()
|
||||||
|
{
|
||||||
|
QFile *outFile = new QFile(currentScript->filePath);
|
||||||
|
|
||||||
|
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
delete outFile;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
outFile->write(editor->toPlainText().toUtf8());
|
||||||
|
currentScript->scriptText = editor->toPlainText();
|
||||||
|
outFile->close();
|
||||||
|
delete outFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::saveAsScript()
|
||||||
{
|
{
|
||||||
QString filename;
|
QString filename;
|
||||||
QFileDialog dialog(this);
|
QFileDialog dialog(this);
|
||||||
@@ -358,6 +376,38 @@ void ScriptingWindow::revertScript()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::reloadScript()
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText("Are you sure you'd like to reload from disk?");
|
||||||
|
msgBox.setInformativeText("Really do it?");
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Cancel);
|
||||||
|
int ret = msgBox.exec();
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case QMessageBox::Yes:
|
||||||
|
{
|
||||||
|
// get the latest version from disk and set in the editor/state
|
||||||
|
QFile scriptFile(currentScript->filePath);
|
||||||
|
if (scriptFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
QString contents = scriptFile.readAll();
|
||||||
|
scriptFile.close();
|
||||||
|
editor->setPlainText(contents);
|
||||||
|
currentScript->scriptText = contents;
|
||||||
|
currentScript->compileScript();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QMessageBox::No:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// should never be reached
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptingWindow::recompileScript()
|
void ScriptingWindow::recompileScript()
|
||||||
{
|
{
|
||||||
if (currentScript)
|
if (currentScript)
|
||||||
@@ -373,6 +423,45 @@ void ScriptingWindow::clickedLogClear()
|
|||||||
elapsedTime.start();
|
elapsedTime.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::saveLog()
|
||||||
|
{
|
||||||
|
QString filename;
|
||||||
|
QFileDialog dialog(this);
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
QStringList filters;
|
||||||
|
filters.append(QString(tr("Log File (*.log)")));
|
||||||
|
|
||||||
|
dialog.setDirectory(settings.value("ScriptingWindow/LoadSaveDirectory", dialog.directory().path()).toString());
|
||||||
|
dialog.setFileMode(QFileDialog::AnyFile);
|
||||||
|
dialog.setNameFilters(filters);
|
||||||
|
dialog.setViewMode(QFileDialog::Detail);
|
||||||
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||||
|
|
||||||
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
filename = dialog.selectedFiles()[0];
|
||||||
|
if (!filename.contains('.')) filename += ".log";
|
||||||
|
if (dialog.selectedNameFilter() == filters[0])
|
||||||
|
{
|
||||||
|
QFile *outFile = new QFile(filename);
|
||||||
|
|
||||||
|
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
delete outFile;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int c = ui->listLog ->count();
|
||||||
|
for (int row = 0; row < c; row++) {
|
||||||
|
outFile->write(ui->listLog->item(row)->data(Qt::DisplayRole).toString().toUtf8() + "\n");
|
||||||
|
}
|
||||||
|
outFile->close();
|
||||||
|
delete outFile;
|
||||||
|
settings.setValue("ScriptingWindow/LoadSaveDirectory", dialog.directory().path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptingWindow::log(QString text)
|
void ScriptingWindow::log(QString text)
|
||||||
{
|
{
|
||||||
ScriptContainer *cont = qobject_cast<ScriptContainer*>(sender());
|
ScriptContainer *cont = qobject_cast<ScriptContainer*>(sender());
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ private slots:
|
|||||||
void deleteCurrentScript();
|
void deleteCurrentScript();
|
||||||
void refreshSourceWindow();
|
void refreshSourceWindow();
|
||||||
void saveScript();
|
void saveScript();
|
||||||
|
void saveAsScript();
|
||||||
void revertScript();
|
void revertScript();
|
||||||
|
void reloadScript();
|
||||||
void recompileScript();
|
void recompileScript();
|
||||||
void changeCurrentScript();
|
void changeCurrentScript();
|
||||||
void newFrames(const CANConnection*, const QVector<CANFrame>&);
|
void newFrames(const CANConnection*, const QVector<CANFrame>&);
|
||||||
@@ -49,6 +51,7 @@ private:
|
|||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
void readSettings();
|
void readSettings();
|
||||||
void writeSettings();
|
void writeSettings();
|
||||||
|
void saveLog();
|
||||||
bool eventFilter(QObject *obj, QEvent *event);
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
|
||||||
Ui::ScriptingWindow *ui;
|
Ui::ScriptingWindow *ui;
|
||||||
|
|||||||
@@ -98,15 +98,18 @@ void SignalViewerWindow::processFrame(CANFrame &frame)
|
|||||||
if (!sig) return;
|
if (!sig) return;
|
||||||
if (sig->parentMessage->ID == frame.frameId())
|
if (sig->parentMessage->ID == frame.frameId())
|
||||||
{
|
{
|
||||||
if (sig->processAsText(frame, sigString, false)) //if true we could interpret the signal so update it in the list
|
if (sig->isSignalInMessage(frame)) //filter out multiplexed signals that aren't in this message.
|
||||||
{
|
{
|
||||||
QTableWidgetItem *item = ui->tableViewer->item(i, VALUE_COL);
|
if (sig->processAsText(frame, sigString, false)) //if true we could interpret the signal so update it in the list
|
||||||
if (!item)
|
|
||||||
{
|
{
|
||||||
item = new QTableWidgetItem(sigString);
|
QTableWidgetItem *item = ui->tableViewer->item(i, VALUE_COL);
|
||||||
ui->tableViewer->setItem(i, VALUE_COL, item);
|
if (!item)
|
||||||
|
{
|
||||||
|
item = new QTableWidgetItem(sigString);
|
||||||
|
ui->tableViewer->setItem(i, VALUE_COL, item);
|
||||||
|
}
|
||||||
|
else item->setText(sigString);
|
||||||
}
|
}
|
||||||
else item->setText(sigString);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="layoutWidget">
|
<widget class="QWidget" name="layoutWidget_2">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="2,0,2">
|
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="2,0,2">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridUpper"/>
|
<layout class="QGridLayout" name="gridUpper"/>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1008</width>
|
<width>1350</width>
|
||||||
<height>611</height>
|
<height>611</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
@@ -487,6 +487,27 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMarkAllHigh">
|
||||||
|
<property name="text">
|
||||||
|
<string>All High</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMarkAllLow">
|
||||||
|
<property name="text">
|
||||||
|
<string>All Low</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMarkAllAuto">
|
||||||
|
<property name="text">
|
||||||
|
<string>All Auto</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnStartStop">
|
<widget class="QPushButton" name="btnStartStop">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -534,6 +555,9 @@
|
|||||||
<tabstop>listID</tabstop>
|
<tabstop>listID</tabstop>
|
||||||
<tabstop>btnAllFilters</tabstop>
|
<tabstop>btnAllFilters</tabstop>
|
||||||
<tabstop>btnNoFilters</tabstop>
|
<tabstop>btnNoFilters</tabstop>
|
||||||
|
<tabstop>btnMarkAllHigh</tabstop>
|
||||||
|
<tabstop>btnMarkAllLow</tabstop>
|
||||||
|
<tabstop>btnMarkAllAuto</tabstop>
|
||||||
<tabstop>btnStartStop</tabstop>
|
<tabstop>btnStartStop</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
@@ -40,6 +40,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSaveList">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save List</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignLeft">
|
<item alignment="Qt::AlignLeft">
|
||||||
|
|||||||
+336
-322
@@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>800</width>
|
<width>1177</width>
|
||||||
<height>682</height>
|
<height>717</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@@ -26,336 +26,350 @@
|
|||||||
<string>SavvyCAN</string>
|
<string>SavvyCAN</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTableView" name="canFramesView">
|
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="3,1">
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>11</pointsize>
|
|
||||||
<bold>false</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="alternatingRowColors">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="verticalScrollMode">
|
|
||||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="lblRemoteConn">
|
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="4,1">
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Remote Connection Active:</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="lineRemoteKey">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>1000</width>
|
|
||||||
<height>50</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="baseSize">
|
|
||||||
<size>
|
|
||||||
<width>150</width>
|
|
||||||
<height>50</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<bold>false</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="maxLength">
|
|
||||||
<number>8</number>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="lblContMsg">
|
|
||||||
<property name="palette">
|
|
||||||
<palette>
|
|
||||||
<active>
|
|
||||||
<colorrole role="WindowText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</active>
|
|
||||||
<inactive>
|
|
||||||
<colorrole role="WindowText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</inactive>
|
|
||||||
<disabled>
|
|
||||||
<colorrole role="WindowText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>120</red>
|
|
||||||
<green>120</green>
|
|
||||||
<blue>120</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</disabled>
|
|
||||||
</palette>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>11</pointsize>
|
|
||||||
<italic>true</italic>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Total Frames Captured:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="lbNumFrames">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Frames Per Second:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="lbFPS">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnCaptureToggle">
|
|
||||||
<property name="text">
|
|
||||||
<string>Suspend Capturing</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnNormalize">
|
|
||||||
<property name="text">
|
|
||||||
<string>Normalize Frame Timing</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnClearFrames">
|
|
||||||
<property name="text">
|
|
||||||
<string>Clear Frames</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbPersistentFilters">
|
|
||||||
<property name="text">
|
|
||||||
<string>Keep Filters When Clearing</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbAutoScroll">
|
|
||||||
<property name="text">
|
|
||||||
<string>Auto Scroll Window</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbOverwrite">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Overwrite Mode</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbInterpret">
|
|
||||||
<property name="text">
|
|
||||||
<string>Interpret Frames</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnExpandAll">
|
|
||||||
<property name="text">
|
|
||||||
<string>Expand All Rows</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnCollapseAll">
|
|
||||||
<property name="text">
|
|
||||||
<string>Collapse All Rows</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Bus Filtering:</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="listBusFilters">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>175</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="flow">
|
|
||||||
<enum>QListView::LeftToRight</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Frame Filtering:</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="listFilters">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>160</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>175</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="alternatingRowColors">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnFilterAll">
|
<widget class="QTableView" name="canFramesView">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="tableSimpleSender"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lblRemoteConn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>All</string>
|
<string>Remote Connection Active:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnFilterNone">
|
<widget class="QLineEdit" name="lineRemoteKey">
|
||||||
<property name="text">
|
<property name="enabled">
|
||||||
<string>None</string>
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>1000</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lblContMsg">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>120</red>
|
||||||
|
<green>120</green>
|
||||||
|
<blue>120</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
<italic>true</italic>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Total Frames Captured:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="lbNumFrames">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Frames Per Second:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="lbFPS">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnCaptureToggle">
|
||||||
|
<property name="text">
|
||||||
|
<string>Suspend Capturing</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnNormalize">
|
||||||
|
<property name="text">
|
||||||
|
<string>Normalize Frame Timing</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnClearFrames">
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear Frames</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbPersistentFilters">
|
||||||
|
<property name="text">
|
||||||
|
<string>Keep Filters When Clearing</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbAutoScroll">
|
||||||
|
<property name="text">
|
||||||
|
<string>Auto Scroll Window</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbOverwrite">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Overwrite Mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbInterpret">
|
||||||
|
<property name="text">
|
||||||
|
<string>Interpret Frames</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnExpandAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>Expand All Rows</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnCollapseAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>Collapse All Rows</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bus Filtering:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listBusFilters">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>175</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="flow">
|
||||||
|
<enum>QListView::LeftToRight</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Frame Filtering:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listFilters">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>300</width>
|
||||||
|
<height>160</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>1000</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnFilterAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>All</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnFilterNone">
|
||||||
|
<property name="text">
|
||||||
|
<string>None</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@@ -367,7 +381,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>800</width>
|
<width>1177</width>
|
||||||
<height>26</height>
|
<height>26</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
+223
-212
@@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>681</width>
|
<width>681</width>
|
||||||
<height>828</height>
|
<height>797</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,2">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,1,2">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QFormLayout" name="formLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
@@ -49,216 +49,27 @@
|
|||||||
<widget class="CANDataGrid" name="gridData" native="true">
|
<widget class="CANDataGrid" name="gridData" native="true">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>300</width>
|
<width>280</width>
|
||||||
<height>300</height>
|
<height>280</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="baseSize">
|
<property name="baseSize">
|
||||||
<size>
|
<size>
|
||||||
<width>300</width>
|
<width>280</width>
|
||||||
<height>300</height>
|
<height>280</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_14">
|
|
||||||
<property name="text">
|
|
||||||
<string>Data Len:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtDataLen"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_13">
|
|
||||||
<property name="text">
|
|
||||||
<string>Little Endian</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QCheckBox" name="cbIntel">
|
|
||||||
<property name="text">
|
|
||||||
<string> (LSB First)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Signed:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QCheckBox" name="cbSigned">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::NoFrame</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Mask:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtMask"/>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Bias:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtBias"/>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Scale</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtScale"/>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Stride</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtStride"/>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="0">
|
|
||||||
<widget class="QLabel" name="label_16">
|
|
||||||
<property name="text">
|
|
||||||
<string>Only Points</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="1">
|
|
||||||
<widget class="QCheckBox" name="cbOnlyPoints">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="13" column="0">
|
|
||||||
<widget class="QLabel" name="label_17">
|
|
||||||
<property name="text">
|
|
||||||
<string>Point Style</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="13" column="1">
|
|
||||||
<widget class="QComboBox" name="coPointStyle"/>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="0">
|
|
||||||
<widget class="QLabel" name="label_15">
|
|
||||||
<property name="text">
|
|
||||||
<string>Line Thickness</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="1">
|
|
||||||
<widget class="QSpinBox" name="spinLineWidth">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>15</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="15" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>Line Color</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="15" column="1">
|
|
||||||
<widget class="QPushButton" name="colorSwatch">
|
|
||||||
<property name="autoFillBackground">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>CHANGE</string>
|
|
||||||
</property>
|
|
||||||
<property name="flat">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="16" column="0">
|
|
||||||
<widget class="QLabel" name="label55">
|
|
||||||
<property name="text">
|
|
||||||
<string>Fill Color</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="16" column="1">
|
|
||||||
<widget class="QPushButton" name="fillSwatch">
|
|
||||||
<property name="autoFillBackground">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>CHANGE</string>
|
|
||||||
</property>
|
|
||||||
<property name="flat">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="17" column="1">
|
|
||||||
<widget class="QPushButton" name="btnAddGraph">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add this graph</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="10" column="1">
|
|
||||||
<spacer name="verticalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="0">
|
|
||||||
<widget class="QLabel" name="label_18">
|
|
||||||
<property name="text">
|
|
||||||
<string>Associated Bus</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="1">
|
|
||||||
<widget class="QLineEdit" name="editBus">
|
|
||||||
<property name="text">
|
|
||||||
<string>-1</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
@@ -356,7 +167,7 @@
|
|||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>20</width>
|
||||||
<height>40</height>
|
<height>30</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
@@ -365,6 +176,215 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,1">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_14">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bit Len:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtDataLen"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>Little Endian</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="cbIntel">
|
||||||
|
<property name="text">
|
||||||
|
<string> (LSB First)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Signed:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QCheckBox" name="cbSigned">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mask:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtMask"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bias:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtBias"/>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Scale</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtScale"/>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Stride</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtStride"/>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_18">
|
||||||
|
<property name="text">
|
||||||
|
<string>Associated Bus</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QLineEdit" name="editBus">
|
||||||
|
<property name="text">
|
||||||
|
<string>-1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_16">
|
||||||
|
<property name="text">
|
||||||
|
<string>Only Points</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QCheckBox" name="cbOnlyPoints">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_17">
|
||||||
|
<property name="text">
|
||||||
|
<string>Point Style</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="coPointStyle"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>Line Thickness</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinLineWidth">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>15</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Line Color</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QPushButton" name="colorSwatch">
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>CHANGE</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label55">
|
||||||
|
<property name="text">
|
||||||
|
<string>Fill Color</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QPushButton" name="fillSwatch">
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>CHANGE</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnAddGraph">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add this graph</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
@@ -378,15 +398,6 @@
|
|||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>txtName</tabstop>
|
<tabstop>txtName</tabstop>
|
||||||
<tabstop>txtID</tabstop>
|
<tabstop>txtID</tabstop>
|
||||||
<tabstop>txtDataLen</tabstop>
|
|
||||||
<tabstop>cbIntel</tabstop>
|
|
||||||
<tabstop>cbSigned</tabstop>
|
|
||||||
<tabstop>txtMask</tabstop>
|
|
||||||
<tabstop>txtBias</tabstop>
|
|
||||||
<tabstop>txtScale</tabstop>
|
|
||||||
<tabstop>txtStride</tabstop>
|
|
||||||
<tabstop>colorSwatch</tabstop>
|
|
||||||
<tabstop>btnAddGraph</tabstop>
|
|
||||||
<tabstop>cbMessages</tabstop>
|
<tabstop>cbMessages</tabstop>
|
||||||
<tabstop>cbSignals</tabstop>
|
<tabstop>cbSignals</tabstop>
|
||||||
<tabstop>btnCopySignal</tabstop>
|
<tabstop>btnCopySignal</tabstop>
|
||||||
|
|||||||
+37
-5
@@ -108,6 +108,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSaveAsScript">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sa&ve As</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnRevertScript">
|
<widget class="QPushButton" name="btnRevertScript">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -115,6 +122,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnReloadScript">
|
||||||
|
<property name="text">
|
||||||
|
<string>R&eload</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnRecompile">
|
<widget class="QPushButton" name="btnRecompile">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -151,11 +165,26 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnClearLog">
|
<layout class="QHBoxLayout" name="horizontalLayout_log">
|
||||||
<property name="text">
|
<property name="alignment">
|
||||||
<string>Clear Log &Window</string>
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="contentsMargins">10, 0, 10, 0</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnClearLog">
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear Log &Window</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSaveLog">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save L&og</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
@@ -169,10 +198,13 @@
|
|||||||
<tabstop>listLoadedScripts</tabstop>
|
<tabstop>listLoadedScripts</tabstop>
|
||||||
<tabstop>tableVariables</tabstop>
|
<tabstop>tableVariables</tabstop>
|
||||||
<tabstop>btnSaveScript</tabstop>
|
<tabstop>btnSaveScript</tabstop>
|
||||||
|
<tabstop>btnSaveAsScript</tabstop>
|
||||||
<tabstop>btnRevertScript</tabstop>
|
<tabstop>btnRevertScript</tabstop>
|
||||||
|
<tabstop>btnReloadScript</tabstop>
|
||||||
<tabstop>btnRecompile</tabstop>
|
<tabstop>btnRecompile</tabstop>
|
||||||
<tabstop>cbAutoScroll</tabstop>
|
<tabstop>cbAutoScroll</tabstop>
|
||||||
<tabstop>btnClearLog</tabstop>
|
<tabstop>btnClearLog</tabstop>
|
||||||
|
<tabstop>btnSaveLog</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|||||||
Reference in New Issue
Block a user