Merge branch 'master' into support_multiple_signal_multiplex_values
This commit is contained in:
+44
-13
@@ -4,16 +4,15 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
|
||||
jobs:
|
||||
buildlinux:
|
||||
name: Linux x64
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Prepare Environment
|
||||
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
|
||||
uses: jurplel/install-qt-action@v3
|
||||
@@ -33,14 +32,14 @@ jobs:
|
||||
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
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: SavvyCAN-Linux_x64.AppImage
|
||||
path: SavvyCAN-*x86_64.AppImage
|
||||
|
||||
buildmacos:
|
||||
buildmacos86:
|
||||
name: macOS x64
|
||||
runs-on: macos-12
|
||||
runs-on: macos-13
|
||||
|
||||
steps:
|
||||
- name: Prepare macOS Environment
|
||||
@@ -61,11 +60,42 @@ jobs:
|
||||
mkdir -p SavvyCAN.app/Contents/MacOS/help
|
||||
cp -R help/* SavvyCAN.app/Contents/MacOS/help
|
||||
macdeployqt SavvyCAN.app -dmg
|
||||
mv SavvyCAN.dmg SavvyCAN_x64.dmg
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
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:
|
||||
name: Windows x64
|
||||
@@ -113,7 +143,7 @@ jobs:
|
||||
mkdir package/canbus
|
||||
copy "${Env:Qt5_Dir}/plugins/canbus/*.*" package/canbus/
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: SavvyCAN-Windows_x64
|
||||
path: package
|
||||
@@ -121,12 +151,12 @@ jobs:
|
||||
pre-release:
|
||||
name: "pre-release"
|
||||
runs-on: "ubuntu-latest"
|
||||
needs: [buildwindows, buildmacos, buildlinux]
|
||||
needs: [buildwindows, buildmacos86, buildmacos-arm64, buildlinux]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4.1.7
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: zip -r SavvyCAN-Windows_x64_CIBuild.zip SavvyCAN-Windows_x64
|
||||
@@ -139,12 +169,13 @@ jobs:
|
||||
files: |
|
||||
SavvyCAN-Linux_x64.AppImage/SavvyCAN-*x86_64.AppImage
|
||||
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:
|
||||
name: Notify Discord
|
||||
runs-on: ubuntu-latest
|
||||
needs: [buildwindows, buildmacos, buildlinux]
|
||||
needs: [buildwindows, buildmacos86, buildmacos-arm64, buildlinux]
|
||||
steps:
|
||||
- id: msg_var
|
||||
name: remove newlines
|
||||
|
||||
@@ -45,3 +45,4 @@ Makefile
|
||||
SavvyCAN.pro.qtds
|
||||
.xcode
|
||||
SavvyCAN.xcodeproj
|
||||
.vscode
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SavvyCAN
|
||||
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.
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
10. CANDump / Kayak (Read only)
|
||||
11. PCAN Viewer (Read Only)
|
||||
12. Wireshark socketcan PCAP file (Read only)
|
||||
|
||||
## 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.
|
||||
|
||||
NOTE: Qt6 currently lacks support for QtSerialBus and many other Qt sub-features. At this time you cannot
|
||||
use Qt6 to compile SavvyCAN. Support for Qt6 should be possible around Qt6.2.
|
||||
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.
|
||||
|
||||
It appears that the current binary build for MacOS requires at least MacOS 10.15
|
||||
|
||||
## 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
|
||||
|
||||
CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT
|
||||
|
||||
CONFIG += c++11
|
||||
CONFIG += c++17
|
||||
CONFIG += NO_UNIT_TESTS
|
||||
|
||||
DEFINES += QCUSTOMPLOT_USE_OPENGL
|
||||
@@ -26,6 +30,7 @@ SOURCES += main.cpp\
|
||||
connections/lawicel_serial.cpp \
|
||||
connections/mqtt_bus.cpp \
|
||||
dbc/dbcnodeduplicateeditor.cpp \
|
||||
framesenderobject.cpp \
|
||||
mqtt/qmqtt_client.cpp \
|
||||
mqtt/qmqtt_client_p.cpp \
|
||||
mqtt/qmqtt_frame.cpp \
|
||||
@@ -113,6 +118,7 @@ HEADERS += mainwindow.h \
|
||||
connections/mqtt_bus.h \
|
||||
dbc/dbcnodeduplicateeditor.h \
|
||||
dbc/dbcnoderebaseeditor.h \
|
||||
framesenderobject.h \
|
||||
mqtt/qmqtt.h \
|
||||
mqtt/qmqtt_client.h \
|
||||
mqtt/qmqtt_client_p.h \
|
||||
@@ -255,12 +261,16 @@ unix {
|
||||
DISTFILES += SavvyCAN.desktop
|
||||
}
|
||||
|
||||
windows {
|
||||
RC_ICONS=icons/SavvyIcon.ico
|
||||
}
|
||||
|
||||
examplefiles.files=examples
|
||||
examplefiles.path = $$PREFIX/share/savvycan/examples
|
||||
INSTALLS += examplefiles
|
||||
|
||||
iconfiles.files=icons
|
||||
iconfiles.path = $$PREFIX/share/icons
|
||||
iconfiles.path = $$PREFIX/share
|
||||
INSTALLS += iconfiles
|
||||
|
||||
helpfiles.files=help/*
|
||||
|
||||
@@ -182,11 +182,11 @@ UDS_HANDLER::~UDS_HANDLER()
|
||||
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());
|
||||
int dataLen = msg.payload().count();
|
||||
*result = true;
|
||||
UDS_MESSAGE udsMsg;
|
||||
udsMsg.bus = msg.bus;
|
||||
udsMsg.setExtendedFrameFormat(msg.hasExtendedFrameFormat());
|
||||
@@ -208,9 +208,17 @@ void UDS_HANDLER::gotISOTPFrame(ISOTP_MESSAGE msg)
|
||||
{
|
||||
udsMsg.service = data[1];
|
||||
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);
|
||||
}
|
||||
else
|
||||
@@ -220,9 +228,22 @@ void UDS_HANDLER::gotISOTPFrame(ISOTP_MESSAGE msg)
|
||||
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)
|
||||
|
||||
@@ -105,6 +105,7 @@ public:
|
||||
QString getShortDesc(QVector<CODE_STRUCT> &codeVector, int code);
|
||||
QString getLongDesc(QVector<CODE_STRUCT> &codeVector, int code);
|
||||
QString getDetailedMessageAnalysis(const UDS_MESSAGE &msg);
|
||||
UDS_MESSAGE tryISOtoUDS(ISOTP_MESSAGE msg, bool *result);
|
||||
|
||||
public slots:
|
||||
void gotISOTPFrame(ISOTP_MESSAGE msg);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "can_structs.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QUuid>
|
||||
|
||||
enum TriggerMask
|
||||
{
|
||||
@@ -38,6 +39,7 @@ public:
|
||||
//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.
|
||||
//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
|
||||
{
|
||||
public:
|
||||
@@ -45,6 +47,7 @@ public:
|
||||
int bus;
|
||||
int databyte;
|
||||
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
|
||||
@@ -73,7 +76,8 @@ public:
|
||||
class Modifier
|
||||
{
|
||||
public:
|
||||
int destByte;
|
||||
int destByte; //if -1 then target one of this ID's signals instead
|
||||
QString signalName;
|
||||
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{
|
||||
return speed == bus.speed &&
|
||||
listenOnly == bus.listenOnly &&
|
||||
singleWire == bus.singleWire &&
|
||||
active == bus.active &&
|
||||
canFD == bus.canFD;
|
||||
canFD == bus.canFD &&
|
||||
dataRate == bus.dataRate;
|
||||
}
|
||||
|
||||
void CANBus::setSpeed(int newSpeed){
|
||||
@@ -55,11 +47,11 @@ void CANBus::setCanFD(bool mode){
|
||||
canFD = mode;
|
||||
}
|
||||
|
||||
int CANBus::getSpeed(){
|
||||
int CANBus::getSpeed() const {
|
||||
return speed;
|
||||
}
|
||||
|
||||
int CANBus::getDataRate(){
|
||||
int CANBus::getDataRate() const {
|
||||
return dataRate;
|
||||
}
|
||||
|
||||
@@ -68,29 +60,30 @@ void CANBus::setDataRate(int newSpeed){
|
||||
dataRate = newSpeed;
|
||||
}
|
||||
|
||||
bool CANBus::isListenOnly(){
|
||||
bool CANBus::isListenOnly() const {
|
||||
return listenOnly;
|
||||
}
|
||||
|
||||
bool CANBus::isSingleWire(){
|
||||
bool CANBus::isSingleWire() const {
|
||||
return singleWire;
|
||||
}
|
||||
|
||||
bool CANBus::isActive(){
|
||||
bool CANBus::isActive() const {
|
||||
return active;
|
||||
}
|
||||
|
||||
bool CANBus::isCanFD(){
|
||||
bool CANBus::isCanFD() const {
|
||||
return canFD;
|
||||
}
|
||||
|
||||
|
||||
QDataStream& operator<<( QDataStream & pStream, const CANBus& pCanBus )
|
||||
QDataStream& operator<<(QDataStream & pStream, const CANBus& pCanBus)
|
||||
{
|
||||
pStream << pCanBus.speed;
|
||||
pStream << pCanBus.listenOnly;
|
||||
pStream << pCanBus.singleWire;
|
||||
pStream << pCanBus.active;
|
||||
// FIXME CANFD settings missing
|
||||
return pStream;
|
||||
}
|
||||
|
||||
|
||||
+17
-16
@@ -5,13 +5,6 @@
|
||||
|
||||
class CANBus
|
||||
{
|
||||
public:
|
||||
CANBus();
|
||||
CANBus(const CANBus&);
|
||||
bool operator==(const CANBus&) const;
|
||||
CANBus& operator=(const CANBus& other) = default;
|
||||
//virtual ~CANBus(){}
|
||||
|
||||
int speed;
|
||||
bool listenOnly;
|
||||
bool singleWire;
|
||||
@@ -19,28 +12,36 @@ public:
|
||||
bool canFD;
|
||||
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 setListenOnly(bool); //bool for whether to only listen
|
||||
void setSingleWire(bool); //bool for whether to use single wire mode
|
||||
void setActive(bool); //whether this bus should be enabled or not.
|
||||
void setCanFD(bool); // enable or disable CANFD support
|
||||
int getSpeed();
|
||||
int getDataRate();
|
||||
void setDataRate(int newSpeed);
|
||||
bool isListenOnly();
|
||||
bool isSingleWire();
|
||||
bool isActive();
|
||||
bool isCanFD();
|
||||
|
||||
int getSpeed() const;
|
||||
int getDataRate() const;
|
||||
bool isListenOnly() const;
|
||||
bool isSingleWire() const;
|
||||
bool isActive() const;
|
||||
bool isCanFD() const;
|
||||
};
|
||||
|
||||
QDataStream& operator<<( QDataStream & pStream, const CANBus& pCanBus );
|
||||
QDataStream & operator>>(QDataStream & pStream, CANBus& pCanBus);
|
||||
QDataStream& operator<<(QDataStream & pStream, const CANBus& pCanBus);
|
||||
QDataStream& operator>>(QDataStream & pStream, CANBus& pCanBus);
|
||||
|
||||
Q_DECLARE_METATYPE(CANBus);
|
||||
|
||||
struct BusData {
|
||||
CANBus mBus;
|
||||
bool mConfigured;
|
||||
bool mConfigured = {};
|
||||
QVector<CANFltObserver> mTargettedFrames;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ CANConnection* CanConFactory::create(type pType, QString pPortName, QString pDri
|
||||
{
|
||||
switch(pType) {
|
||||
case SERIALBUS:
|
||||
return new SerialBusConnection(pPortName, pDriverName);
|
||||
return new SerialBusConnection(pPortName, pDriverName, pBusSpeed, pDataRate, pCanFd);
|
||||
case GVRET_SERIAL:
|
||||
if(pPortName.contains(".") && !pPortName.contains("tty") && !pPortName.contains("serial"))
|
||||
return new GVRetSerial(pPortName, true);
|
||||
|
||||
@@ -222,7 +222,7 @@ bool CANConManager::sendFrame(const CANFrame& pFrame)
|
||||
workingFrame.isReceived = false;
|
||||
if (useSystemTime)
|
||||
{
|
||||
workingFrame.setTimeStamp(QCanBusFrame::TimeStamp(0,QDateTime::currentMSecsSinceEpoch() * 1000));
|
||||
workingFrame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(QDateTime::currentMSecsSinceEpoch() * 1000ul));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -13,11 +13,11 @@ CANConnection::CANConnection(QString pPort,
|
||||
int pQueueLen,
|
||||
bool pUseThread) :
|
||||
mNumBuses(pNumBuses),
|
||||
mSerialSpeed(pSerialSpeed),
|
||||
mQueue(),
|
||||
mPort(pPort),
|
||||
mDriver(pDriver),
|
||||
mType(pType),
|
||||
mSerialSpeed(pSerialSpeed),
|
||||
mIsCapSuspended(false),
|
||||
mStatus(CANCon::NOT_CONNECTED),
|
||||
mStarted(false),
|
||||
@@ -41,8 +41,13 @@ CANConnection::CANConnection(QString pPort,
|
||||
|
||||
if (pBusSpeed > 0) mBusData[0].mBus.setSpeed(pBusSpeed);
|
||||
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(pUseThread) {
|
||||
mThread_p = new QThread();
|
||||
@@ -210,6 +215,10 @@ int CANConnection::getNumBuses() const{
|
||||
return mNumBuses;
|
||||
}
|
||||
|
||||
int CANConnection::getSerialSpeed() const{
|
||||
return mSerialSpeed;
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::isConfigured(int pBusId) {
|
||||
if( pBusId < 0 || pBusId >= getNumBuses())
|
||||
|
||||
@@ -52,6 +52,12 @@ public:
|
||||
*/
|
||||
int getNumBuses() const;
|
||||
|
||||
/**
|
||||
* @brief getserialSpeed
|
||||
* @return returns the serial speed of the device
|
||||
*/
|
||||
int getSerialSpeed() const;
|
||||
|
||||
/**
|
||||
* @brief getPort
|
||||
* @return returns the port name of the device
|
||||
|
||||
@@ -214,7 +214,7 @@ void CANserver::readNetworkData()
|
||||
frame_p->setFrameType(QCanBusFrame::DataFrame);
|
||||
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));
|
||||
|
||||
|
||||
@@ -79,12 +79,12 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) :
|
||||
//Need to make sure it tries to share the address in case there are
|
||||
//multiple instances of SavvyCAN running.
|
||||
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:
|
||||
rxBroadcastKayak = new QUdpSocket(this);
|
||||
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);
|
||||
|
||||
if (checked) { //enable console
|
||||
connect(conn_p, SIGNAL(debugOutput(QString)), this, SLOT(getDebugText(QString)));
|
||||
connect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
||||
connect(conn_p, &CANConnection::debugOutput, this, &ConnectionWindow::getDebugText, Qt::UniqueConnection);
|
||||
connect(this, &ConnectionWindow::sendDebugData, conn_p, &CANConnection::debugInput, Qt::UniqueConnection);
|
||||
}
|
||||
else { //turn it off
|
||||
disconnect(conn_p, SIGNAL(debugOutput(QString)), nullptr, nullptr);
|
||||
disconnect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
||||
disconnect(conn_p, &CANConnection::debugOutput, nullptr, nullptr);
|
||||
disconnect(this, &ConnectionWindow::sendDebugData, conn_p, &CANConnection::debugInput);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,9 @@ void ConnectionWindow::connectionStatus(CANConStatus pStatus)
|
||||
Q_UNUSED(pStatus);
|
||||
|
||||
qDebug() << "Connectionstatus changed";
|
||||
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||
connModel->refresh();
|
||||
ui->tableConnections->selectRow(selIdx);
|
||||
}
|
||||
|
||||
void ConnectionWindow::setSuspendAll(bool pSuspend)
|
||||
@@ -454,8 +456,8 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
||||
int selIdx = current.row();
|
||||
CANConnection* prevConn = connModel->getAtIdx(previous.row());
|
||||
if(prevConn != nullptr)
|
||||
disconnect(prevConn, SIGNAL(debugOutput(QString)), nullptr, nullptr);
|
||||
disconnect(this, SIGNAL(sendDebugData(QByteArray)), nullptr, nullptr);
|
||||
disconnect(prevConn, &CANConnection::debugOutput, nullptr, nullptr);
|
||||
disconnect(this, &ConnectionWindow::sendDebugData, nullptr, nullptr);
|
||||
|
||||
/* set parameters */
|
||||
if (selIdx == -1) {
|
||||
@@ -472,7 +474,7 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
||||
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.
|
||||
//disconnect(conn_p, SIGNAL(debugOutput(QString)), 0, 0);
|
||||
//disconnect(conn_p, &CANConnection::debugOutput, 0, 0);
|
||||
|
||||
numBuses = conn_p->getNumBuses();
|
||||
int numB = ui->tabBuses->count();
|
||||
@@ -485,8 +487,8 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
||||
populateBusDetails(0);
|
||||
if (ui->ckEnableConsole->isChecked())
|
||||
{
|
||||
connect(conn_p, SIGNAL(debugOutput(QString)), this, SLOT(getDebugText(QString)));
|
||||
connect(this, SIGNAL(sendDebugData(QByteArray)), conn_p, SLOT(debugInput(QByteArray)));
|
||||
connect(conn_p, &CANConnection::debugOutput, this, &ConnectionWindow::getDebugText, Qt::UniqueConnection);
|
||||
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)
|
||||
{
|
||||
/* connect signal */
|
||||
connect(conn_p, SIGNAL(status(CANConStatus)),
|
||||
this, SLOT(connectionStatus(CANConStatus)));
|
||||
connect(conn_p, &CANConnection::status, this, &ConnectionWindow::connectionStatus);
|
||||
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
|
||||
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 */
|
||||
conn_p->start();
|
||||
@@ -552,13 +553,17 @@ void ConnectionWindow::loadConnections()
|
||||
QVector<QString> driverNames = settings.value("connections/driverNames").value<QVector<QString>>();
|
||||
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.
|
||||
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++)
|
||||
{
|
||||
//TODO: add serial speed and bus speed to this properly.
|
||||
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i], driverNames[i], 0, 0, false, 0);
|
||||
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i], driverNames[i], serialSpeeds[i], busSpeeds[i], isCanFds[i] ? true : false, DataRates[i]);
|
||||
/* add connection to model */
|
||||
connModel->add(conn_p);
|
||||
}
|
||||
@@ -578,10 +583,19 @@ void ConnectionWindow::saveConnections()
|
||||
QVector<QString> driverNames;
|
||||
QVector<int> serialSpeeds;
|
||||
QVector<int> busSpeeds;
|
||||
|
||||
QVector<int> DataRates;
|
||||
QVector<int> CanFds;
|
||||
|
||||
/* save connections */
|
||||
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());
|
||||
devTypes.append(conn_p->getType());
|
||||
driverNames.append(conn_p->getDriver());
|
||||
@@ -590,6 +604,10 @@ void ConnectionWindow::saveConnections()
|
||||
settings.setValue("connections/portNames", QVariant::fromValue(portNames));
|
||||
settings.setValue("connections/types", QVariant::fromValue(devTypes));
|
||||
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()
|
||||
|
||||
@@ -685,9 +685,10 @@ void GVRetSerial::procRXChar(unsigned char c)
|
||||
buildTimestamp += timeBasis;
|
||||
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;
|
||||
case 4:
|
||||
buildId = c;
|
||||
@@ -770,9 +771,10 @@ void GVRetSerial::procRXChar(unsigned char c)
|
||||
buildTimestamp += timeBasis;
|
||||
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;
|
||||
case 4:
|
||||
buildId = c;
|
||||
|
||||
@@ -491,7 +491,26 @@ void LAWICELSerial::readSerialData()
|
||||
{
|
||||
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())
|
||||
{
|
||||
case 't': //standard frame
|
||||
@@ -551,6 +570,7 @@ void LAWICELSerial::readSerialData()
|
||||
break;
|
||||
case 'b':
|
||||
buildFrame.setBitrateSwitch(true); //BRS enabled
|
||||
[[fallthrough]];
|
||||
case 'd': //standard fd frame, BRS disabled
|
||||
//tIIILDD
|
||||
buildFrame.setFlexibleDataRateFormat(true);
|
||||
@@ -581,6 +601,7 @@ void LAWICELSerial::readSerialData()
|
||||
break;
|
||||
case 'B':
|
||||
buildFrame.setBitrateSwitch(true); //BRS enabled
|
||||
[[fallthrough]];
|
||||
case 'D': //extended fd frame
|
||||
//TIIIIIIIILDD.
|
||||
buildFrame.setFlexibleDataRateFormat(true);
|
||||
|
||||
@@ -61,6 +61,7 @@ protected:
|
||||
QSerialPort *serial;
|
||||
int framesRapid;
|
||||
CANFrame buildFrame;
|
||||
qint64 buildTimestamp;
|
||||
bool can0Enabled;
|
||||
bool can0ListenOnly;
|
||||
bool canFd;
|
||||
|
||||
@@ -302,7 +302,7 @@ void MQTT_BUS::clientMessageReceived(const QMQTT::Message& message)
|
||||
frame_p->isReceived = true;
|
||||
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));
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
/**** class definition ****/
|
||||
/***********************************/
|
||||
|
||||
SerialBusConnection::SerialBusConnection(QString portName, QString driverName) :
|
||||
CANConnection(portName, driverName, CANCon::SERIALBUS,0 ,0, false, 0 ,1, 4000, true),
|
||||
SerialBusConnection::SerialBusConnection(QString portName, QString driverName, int pBusSpeed, int pDataRate, bool pCanFd) :
|
||||
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 */
|
||||
{
|
||||
}
|
||||
@@ -94,7 +94,7 @@ void SerialBusConnection::piSetBusSettings(int pBusIdx, CANBus bus)
|
||||
setBusConfig(0, bus);
|
||||
|
||||
/* if bus is not active we are done */
|
||||
if(!bus.active)
|
||||
if(!bus.isActive())
|
||||
return;
|
||||
|
||||
/* 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.
|
||||
//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::CanFdKey, bus.canFD);
|
||||
mDev_p->setConfigurationParameter(QCanBusDevice::BitRateKey, bus.getSpeed());
|
||||
mDev_p->setConfigurationParameter(QCanBusDevice::CanFdKey, bus.isCanFD());
|
||||
|
||||
if(bus.listenOnly)
|
||||
if(bus.isListenOnly())
|
||||
sbusconfig |= EN_SILENT_MODE;
|
||||
mDev_p->setConfigurationParameter(QCanBusDevice::UserKey, sbusconfig);
|
||||
|
||||
@@ -188,6 +188,7 @@ void SerialBusConnection::framesReceived()
|
||||
|
||||
/* check frame */
|
||||
//if (recFrame.payload().length() <= 8) {
|
||||
if (true) {
|
||||
CANFrame* frame_p = getQueue().get();
|
||||
if(frame_p) {
|
||||
frame_p->setPayload(recFrame.payload());
|
||||
@@ -206,11 +207,11 @@ void SerialBusConnection::framesReceived()
|
||||
frame_p->setTimeStamp(recFrame.timeStamp());
|
||||
frame_p->setFrameType(recFrame.frameType());
|
||||
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();
|
||||
|
||||
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));
|
||||
|
||||
@@ -218,11 +219,9 @@ void SerialBusConnection::framesReceived()
|
||||
|
||||
/* enqueue frame */
|
||||
getQueue().queue();
|
||||
//}
|
||||
#if 0
|
||||
}
|
||||
else
|
||||
qDebug() << "can't get a frame, ERROR";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ class SerialBusConnection : public CANConnection
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SerialBusConnection(QString portName, QString driverName);
|
||||
SerialBusConnection(QString portName, QString driverName, int pBusSpeed,
|
||||
int pDataRate, bool pCanFd);
|
||||
virtual ~SerialBusConnection();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -219,8 +219,8 @@ void SocketCANd::connectDevice()
|
||||
void SocketCANd::deviceConnected(int busNum)
|
||||
{
|
||||
sendDebug("Opening CAN on Kayak Device!");
|
||||
const char* openCanCmd = ("< open " + hostCanIDs[busNum] + " >").toStdString().c_str();
|
||||
sendStringToTCP(openCanCmd, busNum);
|
||||
QString openCanCmd("< open " % hostCanIDs[busNum] % " >");
|
||||
sendStringToTCP(openCanCmd.toUtf8().data(), busNum);
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
@@ -383,8 +383,6 @@ void SocketCANd::procRXData(QString data, int busNum)
|
||||
mTimer.stop();
|
||||
mTimer.start();
|
||||
}
|
||||
QByteArray output;
|
||||
|
||||
switch (rx_state.at(busNum))
|
||||
{
|
||||
case IDLE:
|
||||
|
||||
+8
-4
@@ -166,12 +166,16 @@ QString DBC_SIGNAL::processSignalTree(const CANFrame &frame)
|
||||
if (sig->processAsText(frame, sigString))
|
||||
{
|
||||
qDebug() << "Returned value: " << sigString;
|
||||
if (!build.isEmpty() && !sigString.isEmpty())
|
||||
build.append("\n");
|
||||
build.append(sigString);
|
||||
build.append("\n");
|
||||
if (sig->isMultiplexor)
|
||||
{
|
||||
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 (outputUnit) outputString += unitName;
|
||||
if (outputUnit) outputString += " " + unitName;
|
||||
}
|
||||
else //otherwise display the actual number and unit (if it exists)
|
||||
{
|
||||
outputString += (isInteger ? QString::number(intVal) : QString::number(floatVal));
|
||||
if (outputUnit) outputString += unitName;
|
||||
if (outputUnit) outputString += " " + unitName;
|
||||
}
|
||||
return outputString;
|
||||
}
|
||||
|
||||
+47
-4
@@ -674,6 +674,44 @@ bool DBCFile::parseSignalMultiplexValueLine(QString line)
|
||||
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)
|
||||
{
|
||||
QRegularExpression regex;
|
||||
@@ -737,7 +775,7 @@ bool DBCFile::parseAttributeLine(QString line)
|
||||
if (foundAttr)
|
||||
{
|
||||
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)
|
||||
{
|
||||
qDebug() << "It references a valid, registered message";
|
||||
@@ -769,7 +807,7 @@ bool DBCFile::parseAttributeLine(QString line)
|
||||
if (foundAttr)
|
||||
{
|
||||
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)
|
||||
{
|
||||
qDebug() << "It references a valid, registered message";
|
||||
@@ -941,6 +979,11 @@ bool DBCFile::loadFile(QString fileName)
|
||||
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
|
||||
{
|
||||
qDebug() << "Found a BU line";
|
||||
@@ -976,7 +1019,7 @@ bool DBCFile::loadFile(QString fileName)
|
||||
if (match.hasMatch())
|
||||
{
|
||||
//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)
|
||||
{
|
||||
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(match.captured(2));
|
||||
@@ -997,7 +1040,7 @@ bool DBCFile::loadFile(QString fileName)
|
||||
if (match.hasMatch())
|
||||
{
|
||||
//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)
|
||||
{
|
||||
msg->comment = match.captured(2);
|
||||
|
||||
@@ -106,6 +106,7 @@ private:
|
||||
bool parseSignalMultiplexValueLine(QString line);
|
||||
DBC_MESSAGE* parseMessageLine(QString line);
|
||||
bool parseValueLine(QString line);
|
||||
bool parseSignalValueTypeLine(QString line);
|
||||
bool parseAttributeLine(QString line);
|
||||
bool parseDefaultAttrLine(QString line);
|
||||
};
|
||||
|
||||
+39
-42
@@ -133,38 +133,38 @@ void FirmwareUploaderWindow::timerElapsed()
|
||||
|
||||
void FirmwareUploaderWindow::sendFirmwareChunk()
|
||||
{
|
||||
CANFrame *output = new CANFrame;
|
||||
CANFrame output;
|
||||
int firmwareLocation = currentSendingPosition * 4;
|
||||
int xorByte = 0;
|
||||
output->setExtendedFrameFormat(false);
|
||||
output.setExtendedFrameFormat(false);
|
||||
QByteArray bytes(7,0);
|
||||
output->bus = bus;
|
||||
output->setFrameId(baseAddress + 0x16);
|
||||
output->payload()[0] = currentSendingPosition & 0xFF;
|
||||
output->payload()[1] = (currentSendingPosition >> 8) & 0xFF;
|
||||
output->payload()[2] = firmwareData[firmwareLocation++];
|
||||
output->payload()[3] = firmwareData[firmwareLocation++];
|
||||
output->payload()[4] = firmwareData[firmwareLocation++];
|
||||
output->payload()[5] = firmwareData[firmwareLocation++];
|
||||
for (int i = 0; i < 6; i++) xorByte = xorByte ^ static_cast<unsigned char>(output->payload()[i]);
|
||||
output->payload()[6] = xorByte;
|
||||
output->setPayload(bytes);
|
||||
CANConManager::getInstance()->sendFrame(*output);
|
||||
output.bus = bus;
|
||||
output.setFrameId(baseAddress + 0x16);
|
||||
bytes[0] = currentSendingPosition & 0xFF;
|
||||
bytes[1] = (currentSendingPosition >> 8) & 0xFF;
|
||||
bytes[2] = firmwareData[firmwareLocation++];
|
||||
bytes[3] = firmwareData[firmwareLocation++];
|
||||
bytes[4] = firmwareData[firmwareLocation++];
|
||||
bytes[5] = firmwareData[firmwareLocation++];
|
||||
for (int i = 0; i < 6; i++) xorByte ^= static_cast<unsigned char>(bytes[i]);
|
||||
bytes[6] = xorByte;
|
||||
output.setPayload(bytes);
|
||||
CANConManager::getInstance()->sendFrame(output);
|
||||
timer->start();
|
||||
}
|
||||
|
||||
void FirmwareUploaderWindow::sendFirmwareEnding()
|
||||
{
|
||||
CANFrame *output = new CANFrame;
|
||||
output->setExtendedFrameFormat(false);
|
||||
output->bus = bus;
|
||||
CANFrame output;
|
||||
output.setExtendedFrameFormat(false);
|
||||
output.bus = bus;
|
||||
QByteArray bytes(4,0);
|
||||
output->setFrameId(baseAddress + 0x30);
|
||||
output->payload()[3] = 0xC0;
|
||||
output->payload()[2] = 0xDE;
|
||||
output->payload()[1] = 0xFA;
|
||||
output->payload()[0] = 0xDE;
|
||||
output->setPayload(bytes);
|
||||
output.setFrameId(baseAddress + 0x30);
|
||||
bytes[3] = (char)0xC0;
|
||||
bytes[2] = (char)0xDE;
|
||||
bytes[1] = (char)0xFA;
|
||||
bytes[0] = (char)0xDE;
|
||||
output.setPayload(bytes);
|
||||
//sendCANFrame(output, bus);
|
||||
}
|
||||
|
||||
@@ -182,23 +182,23 @@ void FirmwareUploaderWindow::handleStartStopTransfer()
|
||||
qDebug() << "Base address: " + QString::number(baseAddress);
|
||||
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x10, 0x7FF, this);
|
||||
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x20, 0x7FF, this);
|
||||
CANFrame *output = new CANFrame;
|
||||
output->setExtendedFrameFormat(false);
|
||||
CANFrame output;
|
||||
output.setExtendedFrameFormat(false);
|
||||
QByteArray bytes(8,0);
|
||||
output->bus = bus;
|
||||
output->setFrameId(baseAddress);
|
||||
output->setFrameType(QCanBusFrame::DataFrame);
|
||||
output.bus = bus;
|
||||
output.setFrameId(baseAddress);
|
||||
output.setFrameType(QCanBusFrame::DataFrame);
|
||||
|
||||
bytes[0] = 0xEF;
|
||||
bytes[1] = 0xBE;
|
||||
bytes[2] = 0xAD;
|
||||
bytes[3] = 0xDE;
|
||||
bytes[0] = (char)0xEF;
|
||||
bytes[1] = (char)0xBE;
|
||||
bytes[2] = (char)0xAD;
|
||||
bytes[3] = (char)0xDE;
|
||||
bytes[4] = token & 0xFF;
|
||||
bytes[5] = (token >> 8) & 0xFF;
|
||||
bytes[6] = (token >> 16) & 0xFF;
|
||||
bytes[7] = (token >> 24) & 0xFF;
|
||||
output->setPayload(bytes);
|
||||
CANConManager::getInstance()->sendFrame(*output);
|
||||
output.setPayload(bytes);
|
||||
CANConManager::getInstance()->sendFrame(output);
|
||||
}
|
||||
else //stop anything in process
|
||||
{
|
||||
@@ -209,7 +209,6 @@ void FirmwareUploaderWindow::handleStartStopTransfer()
|
||||
|
||||
void FirmwareUploaderWindow::handleLoadFile()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog;
|
||||
|
||||
QStringList filters;
|
||||
@@ -221,7 +220,7 @@ void FirmwareUploaderWindow::handleLoadFile()
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
QString filename = dialog.selectedFiles().constFirst();
|
||||
|
||||
loadBinaryFile(filename);
|
||||
}
|
||||
@@ -232,22 +231,20 @@ void FirmwareUploaderWindow::loadBinaryFile(QString filename)
|
||||
|
||||
if (transferInProgress) handleStartStopTransfer();
|
||||
|
||||
QFile *inFile = new QFile(filename);
|
||||
QFile inFile(filename);
|
||||
|
||||
if (!inFile->open(QIODevice::ReadOnly))
|
||||
if (!inFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
delete inFile;
|
||||
return;
|
||||
}
|
||||
|
||||
firmwareData = inFile->readAll();
|
||||
firmwareData = inFile.readAll();
|
||||
|
||||
currentSendingPosition = 0;
|
||||
firmwareSize = firmwareData.length();
|
||||
|
||||
updateProgress();
|
||||
|
||||
inFile->close();
|
||||
delete inFile;
|
||||
inFile.close();
|
||||
}
|
||||
|
||||
|
||||
+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("CANServer Binary Log (*.log *.LOG)")));
|
||||
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.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[23]) result = loadCANServerFile(filename, frameCache);
|
||||
if (selectedNameFilter == filters[24]) result = loadWiresharkFile(filename, frameCache);
|
||||
if (selectedNameFilter == filters[25]) result = loadWiresharkSocketCANFile(filename, frameCache);
|
||||
|
||||
|
||||
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";
|
||||
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";
|
||||
if (isCanalyzerASC(filename))
|
||||
{
|
||||
@@ -1440,7 +1454,8 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
||||
QByteArray bytes(numBytes, 0);
|
||||
thisFrame.isReceived = true;
|
||||
thisFrame.bus = 0;
|
||||
if (thisFrame.frameId() > 0x10000000)
|
||||
if ((thisFrame.frameId() > 0x10000000) ||
|
||||
(tokens[3].length() >= 8))
|
||||
{
|
||||
thisFrame.setExtendedFrameFormat(true);
|
||||
}
|
||||
@@ -1492,7 +1507,8 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
||||
//qDebug() << thisFrame.payload().length();
|
||||
thisFrame.isReceived = true;
|
||||
thisFrame.bus = tokens[2].toInt();
|
||||
if (thisFrame.frameId() > 0x10000000)
|
||||
if ((thisFrame.frameId() > 0x10000000) ||
|
||||
(tokens[4].length() >= 8))
|
||||
{
|
||||
thisFrame.setExtendedFrameFormat(true);
|
||||
}
|
||||
@@ -1534,7 +1550,8 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
||||
//qDebug() << thisFrame.payload().length();
|
||||
thisFrame.isReceived = true;
|
||||
thisFrame.bus = 0;
|
||||
if (thisFrame.frameId() > 0x10000000)
|
||||
if ((thisFrame.frameId() > 0x10000000) ||
|
||||
(tokens[3].length() >= 8))
|
||||
{
|
||||
thisFrame.setExtendedFrameFormat(true);
|
||||
}
|
||||
@@ -1586,7 +1603,8 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
||||
//qDebug() << thisFrame.payload().length();
|
||||
thisFrame.isReceived = true;
|
||||
thisFrame.bus = tokens[3].toInt();
|
||||
if (thisFrame.frameId() > 0x10000000)
|
||||
if ((thisFrame.frameId() > 0x10000000) ||
|
||||
(tokens[4].length() >= 8))
|
||||
{
|
||||
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
|
||||
//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
|
||||
//Time bus id dir ? len databytes (Ver 8.0)
|
||||
//Time type bus dir ID ? ? length length bytes then 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 bus id dir ? len databytes additional crap (ver 16.0)
|
||||
//So it seems the file format is not entirely different based on version but rather on some other
|
||||
//settings... Fun!
|
||||
//Version 17.3.0
|
||||
//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 bus id dir ? len databytes (Ver 8.0)
|
||||
//Time bus id dir ? len databytes (addl info) (ver 16.0)
|
||||
//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)
|
||||
{
|
||||
QFile *inFile = new QFile(filename);
|
||||
@@ -1736,7 +1758,7 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
|
||||
}
|
||||
}
|
||||
if (inHeader) continue;
|
||||
if (line.length() > 2)
|
||||
if (line.length() > 2 && !line.startsWith("//"))
|
||||
{
|
||||
tokens = line.simplified().split(' ');
|
||||
|
||||
@@ -1766,7 +1788,7 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
|
||||
int payloadLen = tokens[8].toInt();
|
||||
qDebug() << "PayloadLen: " << payloadLen << " Tokens: " << tokens;
|
||||
QByteArray bytes(payloadLen, 0);
|
||||
if (payloadLen > 8)
|
||||
if (payloadLen > 64)
|
||||
{
|
||||
qDebug() << "Payload length too long. Original line: " << line;
|
||||
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)
|
||||
{
|
||||
//(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
|
||||
thisFrame.setFrameId(tokens[2].toLong(nullptr, 16));
|
||||
if (thisFrame.frameId() > 0x7FF) thisFrame.setExtendedFrameFormat(true);
|
||||
else thisFrame.setExtendedFrameFormat(false);
|
||||
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);
|
||||
for (int c = 0; c < numBytes; c++)
|
||||
{
|
||||
@@ -5019,7 +5046,7 @@ bool FrameFileIO::loadWiresharkFile(QString filename, QVector<CANFrame>* frames)
|
||||
|
||||
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) {
|
||||
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.setFrameType(QCanBusFrame::DataFrame);
|
||||
thisFrame.setFrameId((0xff & *(packetData+17)) << 8 | (0xff & *(packetData+16)));
|
||||
if (thisFrame.frameId() <= 0x7FF) thisFrame.setExtendedFrameFormat(false);
|
||||
else thisFrame.setExtendedFrameFormat(true);
|
||||
if ((0x80 & *(packetData+19))) {
|
||||
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;
|
||||
int numBytes = *(packetData+20);
|
||||
QByteArray bytes(numBytes, 0);
|
||||
@@ -5075,7 +5106,7 @@ bool FrameFileIO::isWiresharkFile(QString filename)
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@@ -5085,3 +5116,96 @@ bool FrameFileIO::isWiresharkFile(QString filename)
|
||||
|
||||
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 loadCANServerFile(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
|
||||
//file type and load it.
|
||||
@@ -80,6 +81,7 @@ public:
|
||||
static bool isCLX000File(QString filename);
|
||||
static bool isCANServerFile(QString filename);
|
||||
static bool isWiresharkFile(QString filename);
|
||||
static bool isWiresharkSocketCANFile(QString filename);
|
||||
|
||||
static bool saveCRTDFile(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_REM, 50);
|
||||
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_MODS, 220);
|
||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_TRIGGER, 270);
|
||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_MODS, 270);
|
||||
ui->tableSender->setColumnWidth(ST_COLS::SENDTAB_COL_COUNT, 80);
|
||||
ui->tableSender->setHorizontalHeaderLabels(headers);
|
||||
}
|
||||
@@ -693,6 +693,12 @@ void FrameSenderWindow::processModifierText(int 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&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.
|
||||
//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
|
||||
@@ -710,22 +716,33 @@ void FrameSenderWindow::processModifierText(int line)
|
||||
Modifier thisMod;
|
||||
thisMod.destByte = 0;
|
||||
|
||||
QString leftSide = Utility::grabAlphaNumeric(mods[i]);
|
||||
if (leftSide.startsWith("D") && leftSide.length() == 2)
|
||||
QRegularExpression regex;
|
||||
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();
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Something wrong with lefthand val";
|
||||
continue;
|
||||
}
|
||||
if (!(Utility::grabOperation(mods[i]) == "="))
|
||||
{
|
||||
qDebug() << "Err: No = after lefthand val";
|
||||
continue;
|
||||
QString leftSide = Utility::grabAlphaNumeric(mods[i]);
|
||||
if (leftSide.startsWith("D") && leftSide.length() == 2)
|
||||
{
|
||||
thisMod.destByte = leftSide.right(1).toInt();
|
||||
thisMod.operations.clear();
|
||||
if (!(Utility::grabOperation(mods[i]) == "="))
|
||||
{
|
||||
qDebug() << "Err: No = after lefthand val";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abort = false;
|
||||
|
||||
token = Utility::grabAlphaNumeric(mods[i]);
|
||||
@@ -1054,8 +1071,6 @@ void FrameSenderWindow::processCellChange(int line, int col)
|
||||
}
|
||||
break;
|
||||
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 )
|
||||
tokens = ui->tableSender->item(line, ST_COLS::SENDTAB_COL_DATA)->text().split(" ", Qt::SkipEmptyParts);
|
||||
#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->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"));
|
||||
lbHelp.setText(tr("Press F1 on any screen for help"));
|
||||
lbHelp.setAlignment(Qt::AlignCenter);
|
||||
@@ -227,12 +229,34 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->actionMotorControlConfig->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);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
updateTimer.stop();
|
||||
frameSender->stopSending();
|
||||
killEmAll(); //Ride the lightning
|
||||
delete ui;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
//}
|
||||
}
|
||||
@@ -1371,6 +1572,11 @@ CANFrameModel* MainWindow::getCANFrameModel()
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* All functions past this point set up the various other windows that can be opened
|
||||
*/
|
||||
|
||||
void MainWindow::showSettingsDialog()
|
||||
{
|
||||
if (!settingsDialog)
|
||||
|
||||
+18
-1
@@ -10,7 +10,7 @@
|
||||
#include "framefileio.h"
|
||||
#include "dbc/dbchandler.h"
|
||||
#include "bus_protocols/isotp_handler.h"
|
||||
|
||||
#include "framesenderobject.h"
|
||||
#include "re/graphingwindow.h"
|
||||
#include "re/frameinfowindow.h"
|
||||
#include "frameplaybackwindow.h"
|
||||
@@ -40,6 +40,18 @@ class ConnectionWindow;
|
||||
class ISOTP_InterpreterWindow;
|
||||
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 {
|
||||
class MainWindow;
|
||||
}
|
||||
@@ -114,6 +126,7 @@ private slots:
|
||||
void filterClearAll();
|
||||
void headerClicked (int logicalIndex);
|
||||
void DBCSettingsUpdated();
|
||||
void onSenderCellChanged(int, int);
|
||||
|
||||
public slots:
|
||||
void gotFrames(int);
|
||||
@@ -142,6 +155,7 @@ private:
|
||||
QByteArray inputBuffer;
|
||||
QTimer updateTimer;
|
||||
QElapsedTimer *elapsedTime;
|
||||
FrameSenderObject *frameSender;
|
||||
int framesPerSec;
|
||||
int rxFrames;
|
||||
bool inhibitFilterUpdate;
|
||||
@@ -151,6 +165,7 @@ private:
|
||||
bool CSVAbsTime;
|
||||
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 inhibitSenderChanged;
|
||||
|
||||
bool continuousLogging;
|
||||
int continuousLogFlushCounter;
|
||||
@@ -211,6 +226,8 @@ private:
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
void manageRowExpansion();
|
||||
void disableAutoRowExpansion();
|
||||
void createSenderRow();
|
||||
void processSenderCellChange(int line, int col);
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
+18
-3
@@ -19,7 +19,7 @@
|
||||
static unsigned char pcap_buffer[MAX_CAN_PACKET_SIZE];
|
||||
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;
|
||||
|
||||
snprintf(error_text, PCAP_ERRBUF_SIZE, "OK");
|
||||
@@ -48,6 +48,23 @@ pcap *pcap_open_offline(const char *filename, char *error_text) {
|
||||
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
|
||||
// and seek past file header
|
||||
if (MAGIC_NG == magic) {
|
||||
@@ -61,14 +78,12 @@ pcap *pcap_open_offline(const char *filename, char *error_text) {
|
||||
return (NULL);
|
||||
}
|
||||
fseek(file, section_length, SEEK_SET);
|
||||
|
||||
} else {
|
||||
p.is_ng = 0;
|
||||
fseek(file, PCAP_FILE_HEADER_LENGTH, SEEK_SET);
|
||||
}
|
||||
|
||||
p.file = file;
|
||||
|
||||
return(&p);
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -8,7 +8,9 @@
|
||||
#include <winsock.h>
|
||||
#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 timeval ts; /* time stamp */
|
||||
@@ -23,7 +25,7 @@ struct pcap {
|
||||
|
||||
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 *);
|
||||
|
||||
|
||||
@@ -222,8 +222,8 @@ void DBCComparatorWindow::calculateDetails()
|
||||
|
||||
ui->treeDetails->addTopLevelItem(msgDiffRoot);
|
||||
|
||||
QTreeWidgetItem *msgItem;
|
||||
QTreeWidgetItem *sigTemp;
|
||||
QTreeWidgetItem *msgItem {};
|
||||
QTreeWidgetItem *sigTemp {};
|
||||
|
||||
for (int i = 0; i < firstDBC->messageHandler->getCount(); i++)
|
||||
{
|
||||
@@ -257,7 +257,8 @@ void DBCComparatorWindow::calculateDetails()
|
||||
msgItem->setText(0, msgName + " (" + Utility::formatCANID(thisMsg->ID) + ")");
|
||||
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
|
||||
{
|
||||
@@ -301,7 +302,8 @@ void DBCComparatorWindow::calculateDetails()
|
||||
sigTemp->setText(0, msgName + " (" + Utility::formatCANID(thisMsg->ID) + ")");
|
||||
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());
|
||||
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;
|
||||
changedBits |= (uint64_t)cngByte << (8ull * (i & 7));
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ FuzzingWindow::FuzzingWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
|
||||
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->btnAllFilters, &QPushButton::clicked, this, &FuzzingWindow::setAllFilters);
|
||||
connect(ui->btnNoFilters, &QPushButton::clicked, this, &FuzzingWindow::clearAllFilters);
|
||||
@@ -508,3 +511,30 @@ void FuzzingWindow::redrawGrid()
|
||||
ui->bitfield->setReference(refBytes, false);
|
||||
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 changedNumDataBytes(int newVal);
|
||||
void updatedFrames(int numFrames);
|
||||
void markAllHigh();
|
||||
void markAllLow();
|
||||
void markAllAuto();
|
||||
|
||||
private:
|
||||
Ui::FuzzingWindow *ui;
|
||||
|
||||
+100
-105
@@ -39,7 +39,7 @@ GraphingWindow::GraphingWindow(const QVector<CANFrame> *frames, QWidget *parent)
|
||||
|
||||
if (Utility::timeStyle == TS_CLOCK)
|
||||
{
|
||||
QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime);
|
||||
QSharedPointer timeTicker = QSharedPointer<QCPAxisTickerTime>::create();
|
||||
timeTicker->setTimeFormat("%h:%m:%s.%z");
|
||||
ui->graphingView->xAxis->setTicker(timeTicker);
|
||||
}
|
||||
@@ -571,7 +571,7 @@ void GraphingWindow::removeSelectedGraph()
|
||||
int idx = -1;
|
||||
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;
|
||||
break;
|
||||
@@ -590,7 +590,7 @@ void GraphingWindow::removeSelectedGraph()
|
||||
|
||||
graphParams.removeAt(idx);
|
||||
|
||||
ui->graphingView->removeGraph(ui->graphingView->selectedGraphs().first());
|
||||
ui->graphingView->removeGraph(ui->graphingView->selectedGraphs().constFirst());
|
||||
|
||||
if (graphParams.count() == 0) needScaleSetup = true;
|
||||
|
||||
@@ -605,7 +605,7 @@ void GraphingWindow::editSelectedGraph()
|
||||
int idx = -1;
|
||||
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;
|
||||
break;
|
||||
@@ -701,7 +701,6 @@ void GraphingWindow::contextMenuRequest(QPoint pos)
|
||||
|
||||
void GraphingWindow::saveGraphs()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog(this);
|
||||
QSettings settings;
|
||||
|
||||
@@ -718,7 +717,7 @@ void GraphingWindow::saveGraphs()
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
QString filename = dialog.selectedFiles().constFirst();
|
||||
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
||||
|
||||
if (dialog.selectedNameFilter() == filters[0])
|
||||
@@ -741,7 +740,6 @@ void GraphingWindow::saveGraphs()
|
||||
|
||||
void GraphingWindow::saveSpreadsheet()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog(this);
|
||||
QSettings settings;
|
||||
|
||||
@@ -756,14 +754,14 @@ void GraphingWindow::saveSpreadsheet()
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
QString filename = dialog.selectedFiles().constFirst();
|
||||
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
@@ -779,12 +777,12 @@ void GraphingWindow::saveSpreadsheet()
|
||||
QList<GraphParams>::iterator iter;
|
||||
double xMin = std::numeric_limits<double>::max(),
|
||||
xMax = std::numeric_limits<double>::min();
|
||||
size_t maxCount = 0;
|
||||
size_t numGraphs = graphParams.length();
|
||||
int maxCount = 0;
|
||||
int numGraphs = graphParams.length();
|
||||
for (auto && graph : graphParams) {
|
||||
xMin = std::min(xMin, graph.x[0]);
|
||||
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() << "xMax: " << xMax;
|
||||
@@ -795,27 +793,25 @@ void GraphingWindow::saveSpreadsheet()
|
||||
double xSize = xMax - xMin;
|
||||
double sliceSize = xSize / ((double)maxCount);
|
||||
double equivValue = sliceSize / 100.0;
|
||||
double currentX;
|
||||
double value;
|
||||
QList<int> indices;
|
||||
indices.reserve(numGraphs);
|
||||
|
||||
outFile->write("TimeStamp");
|
||||
outFile.write("TimeStamp");
|
||||
for (auto && graph : graphParams) {
|
||||
indices.append(0);
|
||||
outFile->putChar(',');
|
||||
outFile->write(graph.graphName.toUtf8());
|
||||
outFile.putChar(',');
|
||||
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;
|
||||
outFile->write(QString::number(currentX, 'f').toUtf8());
|
||||
for (size_t k = 0; k < numGraphs; k++)
|
||||
outFile.write(QString::number(currentX, 'f').toUtf8());
|
||||
for (int k = 0; k < numGraphs; k++)
|
||||
{
|
||||
value = 0.0;
|
||||
double value = 0.0;
|
||||
|
||||
// move cursor to last sample before currentX
|
||||
while (graphParams[k].x[indices[k]+1] < currentX)
|
||||
@@ -849,27 +845,26 @@ void GraphingWindow::saveSpreadsheet()
|
||||
else
|
||||
{
|
||||
// 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 progress = (currentX - graphParams[k].x[cursor]) / span;
|
||||
Q_ASSERT(progress >= 0.0 && progress <= 1.0);
|
||||
value = Utility::Lerp(graphParams[k].y[cursor], graphParams[k].y[cursor+1], progress);
|
||||
qDebug() << "Span: " << span << " Prog: " << progress << " Value: " << value;
|
||||
}
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(value).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(value).toUtf8());
|
||||
}
|
||||
outFile->write("\n");
|
||||
outFile.write("\n");
|
||||
}
|
||||
|
||||
outFile->close();
|
||||
outFile.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GraphingWindow::saveDefinitions()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog(this);
|
||||
QSettings settings;
|
||||
|
||||
@@ -884,79 +879,78 @@ void GraphingWindow::saveDefinitions()
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
QString filename = dialog.selectedFiles().constFirst();
|
||||
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
||||
|
||||
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;
|
||||
|
||||
QList<GraphParams>::iterator iter;
|
||||
for (iter = graphParams.begin(); iter != graphParams.end(); ++iter)
|
||||
{
|
||||
outFile->write("Z,");
|
||||
outFile->write(QString::number(iter->ID, 16).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->mask, 16).toUtf8());
|
||||
outFile->putChar(',');
|
||||
if (iter->intelFormat) outFile->write(QString::number(iter->startBit).toUtf8());
|
||||
else outFile->write(QString::number(iter->startBit * -1).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->numBits).toUtf8());
|
||||
outFile->putChar(',');
|
||||
if (iter->isSigned) outFile->putChar('Y');
|
||||
else outFile->putChar('N');
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->bias).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->scale).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->stride).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->bus).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->lineColor.red()).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->lineColor.green()).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->lineColor.blue()).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(iter->graphName.toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->fillColor.red()).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->fillColor.green()).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->fillColor.blue()).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->fillColor.alpha()).toUtf8());
|
||||
outFile->putChar(',');
|
||||
if (iter->drawOnlyPoints) outFile->putChar('Y');
|
||||
else outFile->putChar('N');
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->pointType).toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(QString::number(iter->lineWidth).toUtf8());
|
||||
outFile.write("Z,");
|
||||
outFile.write(QString::number(iter->ID, 16).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->mask, 16).toUtf8());
|
||||
outFile.putChar(',');
|
||||
if (iter->intelFormat) outFile.write(QString::number(iter->startBit).toUtf8());
|
||||
else outFile.write(QString::number(iter->startBit * -1).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->numBits).toUtf8());
|
||||
outFile.putChar(',');
|
||||
if (iter->isSigned) outFile.putChar('Y');
|
||||
else outFile.putChar('N');
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->bias).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->scale).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->stride).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->bus).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->lineColor.red()).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->lineColor.green()).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->lineColor.blue()).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(iter->graphName.toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->fillColor.red()).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->fillColor.green()).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->fillColor.blue()).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->fillColor.alpha()).toUtf8());
|
||||
outFile.putChar(',');
|
||||
if (iter->drawOnlyPoints) outFile.putChar('Y');
|
||||
else outFile.putChar('N');
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->pointType).toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(QString::number(iter->lineWidth).toUtf8());
|
||||
if (iter->associatedSignal)
|
||||
{
|
||||
outFile->putChar(',');
|
||||
outFile->write(iter->associatedSignal->parentMessage->name.toUtf8());
|
||||
outFile->putChar(',');
|
||||
outFile->write(iter->associatedSignal->name.toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(iter->associatedSignal->parentMessage->name.toUtf8());
|
||||
outFile.putChar(',');
|
||||
outFile.write(iter->associatedSignal->name.toUtf8());
|
||||
}
|
||||
|
||||
outFile->write("\n");
|
||||
outFile.write("\n");
|
||||
}
|
||||
outFile->close();
|
||||
outFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphingWindow::loadDefinitions()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog;
|
||||
QSettings settings;
|
||||
|
||||
@@ -973,17 +967,17 @@ void GraphingWindow::loadDefinitions()
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
QString filename = dialog.selectedFiles().constFirst();
|
||||
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
|
||||
|
||||
QFile *inFile = new QFile(filename);
|
||||
QFile inFile(filename);
|
||||
QByteArray line;
|
||||
|
||||
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
if (!inFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return;
|
||||
|
||||
while (!inFile->atEnd()) {
|
||||
line = inFile->readLine().simplified();
|
||||
while (!inFile.atEnd()) {
|
||||
line = inFile.readLine().simplified();
|
||||
if (line.length() > 2)
|
||||
{
|
||||
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 xminval=10000000000.0, xmaxval = -10000000000.0;
|
||||
GraphParams *refParam = ¶ms;
|
||||
int sBit, bits;
|
||||
bool intelFormat, isSigned;
|
||||
QString tempStr;
|
||||
double x,y;
|
||||
double x{}, y{};
|
||||
|
||||
qDebug() << "New Graph ID: " << params.ID;
|
||||
qDebug() << "Start bit: " << params.startBit;
|
||||
@@ -1341,7 +1333,8 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
||||
for (int i = 0; i < modelFrames->count(); 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
|
||||
@@ -1360,15 +1353,17 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
||||
int numEntries = frameCache.count() / params.stride;
|
||||
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.y.reserve(numEntries);
|
||||
//params.x.fill(0, numEntries);
|
||||
//params.y.fill(0, numEntries);
|
||||
|
||||
sBit = params.startBit;
|
||||
bits = params.numBits;
|
||||
intelFormat = params.intelFormat;
|
||||
isSigned = params.isSigned;
|
||||
int sBit = params.startBit;
|
||||
int bits = params.numBits;
|
||||
bool intelFormat = params.intelFormat;
|
||||
bool isSigned = params.isSigned;
|
||||
|
||||
for (int j = 0; j < numEntries; j++)
|
||||
{
|
||||
@@ -1558,16 +1553,16 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
||||
void GraphingWindow::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
|
||||
{
|
||||
bool ok;
|
||||
int dataInt = contextAction->data().toInt(&ok);
|
||||
if (ok)
|
||||
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
|
||||
{
|
||||
ui->graphingView->axisRect()->insetLayout()->setInsetAlignment(0, (Qt::Alignment)dataInt);
|
||||
ui->graphingView->replot();
|
||||
bool ok;
|
||||
int dataInt = contextAction->data().toInt(&ok);
|
||||
if (ok)
|
||||
{
|
||||
ui->graphingView->axisRect()->insetLayout()->setInsetAlignment(0, (Qt::Alignment)dataInt);
|
||||
ui->graphingView->replot();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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->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)));
|
||||
|
||||
QStringList headers;
|
||||
@@ -172,6 +173,80 @@ void ISOTP_InterpreterWindow::clearList()
|
||||
//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)
|
||||
{
|
||||
decoder->setExtendedAddressing(checked);
|
||||
|
||||
@@ -26,6 +26,7 @@ private slots:
|
||||
void showDetailView();
|
||||
void updatedFrames(int);
|
||||
void clearList();
|
||||
void saveList();
|
||||
void listFilterItemChanged(QListWidgetItem *item);
|
||||
void filterAll();
|
||||
void filterNone();
|
||||
|
||||
@@ -361,7 +361,6 @@ void NewGraphDialog::loadNodes()
|
||||
void NewGraphDialog::loadMessages(int idx)
|
||||
{
|
||||
int numFiles = 0;
|
||||
DBC_MESSAGE *msg;
|
||||
ui->cbMessages->clear();
|
||||
if (dbcHandler == nullptr) return;
|
||||
if ((numFiles = dbcHandler->getFileCount()) == 0) return;
|
||||
|
||||
@@ -181,7 +181,7 @@ void SnifferWindow::notchTick()
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->lblNotch->setBackgroundRole(QPalette::Background);
|
||||
ui->lblNotch->setBackgroundRole(QPalette::Window);
|
||||
ui->lblNotch->repaint();
|
||||
//qDebug() << "Tock";
|
||||
}
|
||||
|
||||
@@ -41,8 +41,11 @@ ScriptingWindow::ScriptingWindow(const QVector<CANFrame> *frames, QWidget *paren
|
||||
connect(ui->btnRecompile, &QAbstractButton::pressed, this, &ScriptingWindow::recompileScript);
|
||||
connect(ui->btnRemoveScript, &QAbstractButton::pressed, this, &ScriptingWindow::deleteCurrentScript);
|
||||
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->btnSaveAsScript, &QAbstractButton::pressed, this, &ScriptingWindow::saveAsScript);
|
||||
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->tableVariables, SIGNAL(cellChanged(int,int)), this, SLOT(updatedValue(int, int)));
|
||||
|
||||
@@ -301,6 +304,21 @@ void ScriptingWindow::refreshSourceWindow()
|
||||
}
|
||||
|
||||
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;
|
||||
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()
|
||||
{
|
||||
if (currentScript)
|
||||
@@ -373,6 +423,45 @@ void ScriptingWindow::clickedLogClear()
|
||||
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)
|
||||
{
|
||||
ScriptContainer *cont = qobject_cast<ScriptContainer*>(sender());
|
||||
|
||||
@@ -37,7 +37,9 @@ private slots:
|
||||
void deleteCurrentScript();
|
||||
void refreshSourceWindow();
|
||||
void saveScript();
|
||||
void saveAsScript();
|
||||
void revertScript();
|
||||
void reloadScript();
|
||||
void recompileScript();
|
||||
void changeCurrentScript();
|
||||
void newFrames(const CANConnection*, const QVector<CANFrame>&);
|
||||
@@ -49,6 +51,7 @@ private:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
void saveLog();
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
|
||||
Ui::ScriptingWindow *ui;
|
||||
|
||||
@@ -98,15 +98,18 @@ void SignalViewerWindow::processFrame(CANFrame &frame)
|
||||
if (!sig) return;
|
||||
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 (!item)
|
||||
if (sig->processAsText(frame, sigString, false)) //if true we could interpret the signal so update it in the list
|
||||
{
|
||||
item = new QTableWidgetItem(sigString);
|
||||
ui->tableViewer->setItem(i, VALUE_COL, item);
|
||||
QTableWidgetItem *item = ui->tableViewer->item(i, VALUE_COL);
|
||||
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>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<widget class="QWidget" name="layoutWidget_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="2,0,2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridUpper"/>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1008</width>
|
||||
<width>1350</width>
|
||||
<height>611</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
@@ -487,6 +487,27 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
<widget class="QPushButton" name="btnStartStop">
|
||||
<property name="text">
|
||||
@@ -534,6 +555,9 @@
|
||||
<tabstop>listID</tabstop>
|
||||
<tabstop>btnAllFilters</tabstop>
|
||||
<tabstop>btnNoFilters</tabstop>
|
||||
<tabstop>btnMarkAllHigh</tabstop>
|
||||
<tabstop>btnMarkAllLow</tabstop>
|
||||
<tabstop>btnMarkAllAuto</tabstop>
|
||||
<tabstop>btnStartStop</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
|
||||
@@ -40,6 +40,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSaveList">
|
||||
<property name="text">
|
||||
<string>Save List</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item alignment="Qt::AlignLeft">
|
||||
|
||||
+336
-322
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>682</height>
|
||||
<width>1177</width>
|
||||
<height>717</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -26,336 +26,350 @@
|
||||
<string>SavvyCAN</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0">
|
||||
<item>
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="3,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblRemoteConn">
|
||||
<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">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="4,1">
|
||||
<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">
|
||||
<string>All</string>
|
||||
<string>Remote Connection Active:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnFilterNone">
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
<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="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>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -367,7 +381,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<width>1177</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
+223
-212
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>681</width>
|
||||
<height>828</height>
|
||||
<height>797</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -15,7 +15,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,1,2">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
@@ -49,216 +49,27 @@
|
||||
<widget class="CANDataGrid" name="gridData" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>300</height>
|
||||
<width>280</width>
|
||||
<height>280</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>300</height>
|
||||
<width>280</width>
|
||||
<height>280</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
@@ -356,7 +167,7 @@
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -365,6 +176,215 @@
|
||||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
@@ -378,15 +398,6 @@
|
||||
<tabstops>
|
||||
<tabstop>txtName</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>cbSignals</tabstop>
|
||||
<tabstop>btnCopySignal</tabstop>
|
||||
|
||||
+37
-5
@@ -108,6 +108,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSaveAsScript">
|
||||
<property name="text">
|
||||
<string>Sa&ve As</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRevertScript">
|
||||
<property name="text">
|
||||
@@ -115,6 +122,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnReloadScript">
|
||||
<property name="text">
|
||||
<string>R&eload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRecompile">
|
||||
<property name="text">
|
||||
@@ -151,11 +165,26 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnClearLog">
|
||||
<property name="text">
|
||||
<string>Clear Log &Window</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_log">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<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>
|
||||
</layout>
|
||||
</item>
|
||||
@@ -169,10 +198,13 @@
|
||||
<tabstop>listLoadedScripts</tabstop>
|
||||
<tabstop>tableVariables</tabstop>
|
||||
<tabstop>btnSaveScript</tabstop>
|
||||
<tabstop>btnSaveAsScript</tabstop>
|
||||
<tabstop>btnRevertScript</tabstop>
|
||||
<tabstop>btnReloadScript</tabstop>
|
||||
<tabstop>btnRecompile</tabstop>
|
||||
<tabstop>cbAutoScroll</tabstop>
|
||||
<tabstop>btnClearLog</tabstop>
|
||||
<tabstop>btnSaveLog</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
Reference in New Issue
Block a user