Merge pull request #67 from collin80/WIP2
Merge WIP2 changes into Master
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# SavvyCAN
|
||||
QT based cross platform canbus tool
|
||||
(C) 2015-2016 EVTV and Collin Kidder
|
||||
(C) 2015-2017 EVTV and 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
|
||||
@@ -14,7 +14,7 @@ You are highly recommended to use the CANDue board from EVTV:
|
||||
The CANDue board must be running the GVRET firmware which can also be found
|
||||
within the collin80 repos.
|
||||
|
||||
It is very soon to be possible to use any SocketCAN compatible device
|
||||
It is now possible to use any SocketCAN compatible device
|
||||
under LINUX. 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.
|
||||
@@ -40,6 +40,10 @@ 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)
|
||||
|
||||
Requires QScintilla library available at:
|
||||
|
||||
https://www.riverbankcomputing.com/software/qscintilla/download
|
||||
@@ -50,18 +54,20 @@ http://www.qcustomplot.com/
|
||||
|
||||
However, this source code is integrated into the source for SavvyCAN and one isn't required to download it separately.
|
||||
|
||||
This project will soon require 5.6.0 or higher because of an upcoming dependency on QSerialBus but currently
|
||||
should compile with QT 5.5
|
||||
This project requires 5.6.0 or higher because of a dependency on QSerialBus which is an optional download
|
||||
with QT 5.6 (so, be sure to select it)
|
||||
|
||||
Instructions for compiling with Ubuntu:
|
||||
Instructions for compiling:
|
||||
|
||||
sudo apt-get install qt5-default qtdeclarative5-dev libqt5serialport5-dev libudev-dev
|
||||
Download the newest stable version of Qt directly from qt.io (You need 5.6.x or newer)
|
||||
|
||||
download and extract QScintilla (see above for link), assume it is extracted in QScintilla-gpl-2.9.1
|
||||
|
||||
cd ~/QScintilla-gpl-2.9.1/Qt4Qt5
|
||||
|
||||
qmake qscintilla.pro
|
||||
You will need to either put your copy of QT into your path or specify the path to qmake directly
|
||||
|
||||
~/Qt/5.7/gcc_64/bin/qmake qscintilla.pro
|
||||
|
||||
make
|
||||
|
||||
@@ -75,7 +81,7 @@ git clone https://github.com/collin80/SavvyCAN.git
|
||||
|
||||
cd SavvyCAN
|
||||
|
||||
qmake
|
||||
~/Qt/5.7/gcc_64/bin/qmake
|
||||
|
||||
make
|
||||
|
||||
|
||||
+85
-62
@@ -4,7 +4,7 @@
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui
|
||||
QT += core gui serialbus
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets serialport printsupport qml
|
||||
|
||||
@@ -21,95 +21,118 @@ SOURCES += main.cpp\
|
||||
canframemodel.cpp \
|
||||
utility.cpp \
|
||||
qcustomplot.cpp \
|
||||
graphingwindow.cpp \
|
||||
frameinfowindow.cpp \
|
||||
newgraphdialog.cpp \
|
||||
frameplaybackwindow.cpp \
|
||||
serialworker.cpp \
|
||||
candatagrid.cpp \
|
||||
flowviewwindow.cpp \
|
||||
framesenderwindow.cpp \
|
||||
dbchandler.cpp \
|
||||
dbcmaineditor.cpp \
|
||||
dbcsignaleditor.cpp \
|
||||
framefileio.cpp \
|
||||
filecomparatorwindow.cpp \
|
||||
mainsettingsdialog.cpp \
|
||||
firmwareuploaderwindow.cpp \
|
||||
discretestatewindow.cpp \
|
||||
connectionwindow.cpp \
|
||||
scriptingwindow.cpp \
|
||||
scriptcontainer.cpp \
|
||||
canfilter.cpp \
|
||||
rangestatewindow.cpp \
|
||||
dbc_classes.cpp \
|
||||
dbcloadsavewindow.cpp \
|
||||
fuzzingwindow.cpp \
|
||||
udsscanwindow.cpp \
|
||||
can_structs.cpp \
|
||||
isotp_interpreterwindow.cpp \
|
||||
isotp_handler.cpp \
|
||||
motorcontrollerconfigwindow.cpp
|
||||
motorcontrollerconfigwindow.cpp \
|
||||
connections/canconnection.cpp \
|
||||
connections/socketcan.cpp \
|
||||
connections/canconfactory.cpp \
|
||||
connections/gvretserial.cpp \
|
||||
connections/canconmanager.cpp \
|
||||
re/sniffer/snifferitem.cpp \
|
||||
re/sniffer/sniffermodel.cpp \
|
||||
re/sniffer/snifferwindow.cpp \
|
||||
dbc/dbc_classes.cpp \
|
||||
dbc/dbchandler.cpp \
|
||||
dbc/dbcloadsavewindow.cpp \
|
||||
dbc/dbcmaineditor.cpp \
|
||||
dbc/dbcsignaleditor.cpp \
|
||||
re/discretestatewindow.cpp \
|
||||
re/filecomparatorwindow.cpp \
|
||||
re/flowviewwindow.cpp \
|
||||
re/frameinfowindow.cpp \
|
||||
re/fuzzingwindow.cpp \
|
||||
re/isotp_handler.cpp \
|
||||
re/isotp_interpreterwindow.cpp \
|
||||
re/rangestatewindow.cpp \
|
||||
re/udsscanwindow.cpp \
|
||||
connections/canbus.cpp \
|
||||
connections/canconnectionmodel.cpp \
|
||||
connections/connectionwindow.cpp \
|
||||
re/graphingwindow.cpp \
|
||||
re/newgraphdialog.cpp \
|
||||
bisectwindow.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
can_structs.h \
|
||||
canframemodel.h \
|
||||
utility.h \
|
||||
qcustomplot.h \
|
||||
graphingwindow.h \
|
||||
frameinfowindow.h \
|
||||
newgraphdialog.h \
|
||||
frameplaybackwindow.h \
|
||||
serialworker.h \
|
||||
candatagrid.h \
|
||||
flowviewwindow.h \
|
||||
framesenderwindow.h \
|
||||
can_trigger_structs.h \
|
||||
dbc_classes.h \
|
||||
dbchandler.h \
|
||||
dbcmaineditor.h \
|
||||
dbcsignaleditor.h \
|
||||
framefileio.h \
|
||||
config.h \
|
||||
filecomparatorwindow.h \
|
||||
mainsettingsdialog.h \
|
||||
firmwareuploaderwindow.h \
|
||||
discretestatewindow.h \
|
||||
connectionwindow.h \
|
||||
scriptingwindow.h \
|
||||
scriptcontainer.h \
|
||||
canfilter.h \
|
||||
rangestatewindow.h \
|
||||
dbcloadsavewindow.h \
|
||||
fuzzingwindow.h \
|
||||
udsscanwindow.h \
|
||||
isotp_interpreterwindow.h \
|
||||
isotp_handler.h \
|
||||
motorcontrollerconfigwindow.h
|
||||
utils/lfqueue.h \
|
||||
motorcontrollerconfigwindow.h \
|
||||
connections/canconnection.h \
|
||||
connections/socketcan.h \
|
||||
connections/canconconst.h \
|
||||
connections/canconfactory.h \
|
||||
connections/gvretserial.h \
|
||||
connections/canconmanager.h \
|
||||
re/sniffer/snifferitem.h \
|
||||
re/sniffer/sniffermodel.h \
|
||||
re/sniffer/snifferwindow.h \
|
||||
dbc/dbc_classes.h \
|
||||
dbc/dbchandler.h \
|
||||
dbc/dbcloadsavewindow.h \
|
||||
dbc/dbcmaineditor.h \
|
||||
dbc/dbcsignaleditor.h \
|
||||
re/discretestatewindow.h \
|
||||
re/filecomparatorwindow.h \
|
||||
re/flowviewwindow.h \
|
||||
re/frameinfowindow.h \
|
||||
re/fuzzingwindow.h \
|
||||
re/isotp_handler.h \
|
||||
re/isotp_interpreterwindow.h \
|
||||
re/rangestatewindow.h \
|
||||
re/udsscanwindow.h \
|
||||
connections/canbus.h \
|
||||
connections/canconnectionmodel.h \
|
||||
connections/connectionwindow.h \
|
||||
re/graphingwindow.h \
|
||||
re/newgraphdialog.h \
|
||||
bisectwindow.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
graphingwindow.ui \
|
||||
frameinfowindow.ui \
|
||||
newgraphdialog.ui \
|
||||
frameplaybackwindow.ui \
|
||||
candatagrid.ui \
|
||||
flowviewwindow.ui \
|
||||
framesenderwindow.ui \
|
||||
dbcmaineditor.ui \
|
||||
dbcsignaleditor.ui \
|
||||
filecomparatorwindow.ui \
|
||||
mainsettingsdialog.ui \
|
||||
firmwareuploaderwindow.ui \
|
||||
discretestatewindow.ui \
|
||||
connectionwindow.ui \
|
||||
scriptingwindow.ui \
|
||||
rangestatewindow.ui \
|
||||
dbcloadsavewindow.ui \
|
||||
fuzzingwindow.ui \
|
||||
udsscanwindow.ui \
|
||||
isotp_interpreterwindow.ui \
|
||||
deltawindow.ui \
|
||||
motorcontrollerconfigwindow.ui
|
||||
FORMS += ui/candatagrid.ui \
|
||||
ui/connectionwindow.ui \
|
||||
ui/dbcloadsavewindow.ui \
|
||||
ui/dbcmaineditor.ui \
|
||||
ui/dbcsignaleditor.ui \
|
||||
ui/discretestatewindow.ui \
|
||||
ui/filecomparatorwindow.ui \
|
||||
ui/firmwareuploaderwindow.ui \
|
||||
ui/flowviewwindow.ui \
|
||||
ui/frameinfowindow.ui \
|
||||
ui/frameplaybackwindow.ui \
|
||||
ui/framesenderwindow.ui \
|
||||
ui/fuzzingwindow.ui \
|
||||
ui/graphingwindow.ui \
|
||||
ui/isotp_interpreterwindow.ui \
|
||||
ui/mainsettingsdialog.ui \
|
||||
ui/mainwindow.ui \
|
||||
ui/motorcontrollerconfigwindow.ui \
|
||||
ui/newgraphdialog.ui \
|
||||
ui/rangestatewindow.ui \
|
||||
ui/scriptingwindow.ui \
|
||||
ui/snifferwindow.ui \
|
||||
ui/udsscanwindow.ui \
|
||||
ui/bisectwindow.ui
|
||||
|
||||
DISTFILES +=
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "bisectwindow.h"
|
||||
#include "ui_bisectwindow.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "framefileio.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <algorithm>
|
||||
|
||||
BisectWindow::BisectWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::BisectWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
modelFrames = frames;
|
||||
|
||||
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
|
||||
connect(ui->btnCalculate, &QAbstractButton::clicked, this, &BisectWindow::handleCalculateButton);
|
||||
connect(ui->btnReplaceFrames, &QAbstractButton::clicked, this, &BisectWindow::handleReplaceButton);
|
||||
connect(ui->btnSaveFrames, &QAbstractButton::clicked, this, &BisectWindow::handleSaveButton);
|
||||
connect(ui->slideFrameNumber, &QSlider::sliderReleased, this, &BisectWindow::updateFrameNumText);
|
||||
connect(ui->slidePercentage, &QSlider::sliderReleased, this, &BisectWindow::updatePercentText);
|
||||
connect(ui->editFrameNumber, &QLineEdit::editingFinished, this, &BisectWindow::updateFrameNumSlider);
|
||||
connect(ui->editPercentage, &QLineEdit::editingFinished, this, &BisectWindow::updatePercentSlider);
|
||||
}
|
||||
|
||||
BisectWindow::~BisectWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void BisectWindow::showEvent(QShowEvent* event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
refreshIDList();
|
||||
refreshFrameNumbers();
|
||||
updateFrameNumText();
|
||||
updatePercentText();
|
||||
}
|
||||
|
||||
void BisectWindow::refreshIDList()
|
||||
{
|
||||
int id;
|
||||
for (int i = 0; i < modelFrames->count(); i++)
|
||||
{
|
||||
id = modelFrames->at(i).ID;
|
||||
if (!foundID.contains(id))
|
||||
{
|
||||
foundID.append(id);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(foundID.begin(), foundID.end());
|
||||
|
||||
foreach (int id, foundID) {
|
||||
ui->cbIDLower->addItem(Utility::formatNumber(id));
|
||||
ui->cbIDUpper->addItem(Utility::formatNumber(id));
|
||||
}
|
||||
}
|
||||
|
||||
void BisectWindow::refreshFrameNumbers()
|
||||
{
|
||||
ui->labelMainListNum->setText(QString::number(modelFrames->count()));
|
||||
ui->labelSplitNum->setText(QString::number(splitFrames.count()));
|
||||
ui->slideFrameNumber->setMaximum(modelFrames->count());
|
||||
}
|
||||
|
||||
void BisectWindow::updatedFrames(int numFrames)
|
||||
{
|
||||
if (numFrames == -1) //all frames deleted
|
||||
{
|
||||
refreshFrameNumbers();
|
||||
}
|
||||
else if (numFrames == -2) //all new set of frames. Reset
|
||||
{
|
||||
refreshFrameNumbers();
|
||||
refreshIDList();
|
||||
}
|
||||
else //just got some new frames. See if they are relevant.
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void BisectWindow::handleCalculateButton()
|
||||
{
|
||||
splitFrames.clear();
|
||||
bool saveLower = ui->rbLowerSection->isChecked();
|
||||
int targetFrameNum;
|
||||
if (ui->rbFrameNumber->isChecked() || ui->rbPercentage->isChecked())
|
||||
{
|
||||
if (ui->rbFrameNumber->isChecked()) targetFrameNum = ui->slideFrameNumber->value();
|
||||
else targetFrameNum = modelFrames->count() * ui->slidePercentage->value() / 10000;
|
||||
if (saveLower)
|
||||
{
|
||||
for (int i = 0; i < targetFrameNum; i++) splitFrames.append(modelFrames->at(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = targetFrameNum; i < modelFrames->count(); i++) splitFrames.append(modelFrames->at(i));
|
||||
}
|
||||
}
|
||||
else if (ui->rbIDRange->isChecked())
|
||||
{
|
||||
uint32_t lowerID = Utility::ParseStringToNum2(ui->cbIDLower->currentText());
|
||||
uint32_t upperID = Utility::ParseStringToNum2(ui->cbIDUpper->currentText());
|
||||
for (int i = 0; i < modelFrames->count(); i++)
|
||||
{
|
||||
if (modelFrames->at(i).ID >= lowerID && modelFrames->at(i).ID <= upperID) splitFrames.append(modelFrames->at(i));
|
||||
}
|
||||
}
|
||||
refreshFrameNumbers();
|
||||
}
|
||||
|
||||
void BisectWindow::handleReplaceButton()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BisectWindow::handleSaveButton()
|
||||
{
|
||||
QMessageBox msg;
|
||||
QString filename;
|
||||
if (FrameFileIO::saveFrameFile(filename, &splitFrames))
|
||||
{
|
||||
msg.setText(tr("Successfully saved file"));
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.setText(tr("Error while attempting to save."));
|
||||
}
|
||||
msg.exec();
|
||||
}
|
||||
|
||||
void BisectWindow::updateFrameNumSlider()
|
||||
{
|
||||
ui->slideFrameNumber->setValue(ui->editFrameNumber->text().toInt());
|
||||
}
|
||||
|
||||
void BisectWindow::updatePercentSlider()
|
||||
{
|
||||
ui->slidePercentage->setValue(ui->editPercentage->text().toFloat() * 100);
|
||||
}
|
||||
|
||||
void BisectWindow::updateFrameNumText()
|
||||
{
|
||||
ui->editFrameNumber->setText(QString::number(ui->slideFrameNumber->value()));
|
||||
}
|
||||
|
||||
void BisectWindow::updatePercentText()
|
||||
{
|
||||
ui->editPercentage->setText(QString::number(ui->slidePercentage->value() / 100.0f));
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef BISECTWINDOW_H
|
||||
#define BISECTWINDOW_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "can_structs.h"
|
||||
|
||||
namespace Ui {
|
||||
class BisectWindow;
|
||||
}
|
||||
|
||||
class BisectWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BisectWindow(const QVector<CANFrame> *frames, QWidget *parent = 0);
|
||||
~BisectWindow();
|
||||
void showEvent(QShowEvent*);
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
void sendFrameBatch(const QList<CANFrame> *);
|
||||
|
||||
private slots:
|
||||
void updatedFrames(int numFrames);
|
||||
void handleSaveButton();
|
||||
void handleReplaceButton();
|
||||
void handleCalculateButton();
|
||||
void updateFrameNumSlider();
|
||||
void updatePercentSlider();
|
||||
void updateFrameNumText();
|
||||
void updatePercentText();
|
||||
|
||||
private:
|
||||
Ui::BisectWindow *ui;
|
||||
const QVector<CANFrame> *modelFrames;
|
||||
QVector<CANFrame> splitFrames;
|
||||
QList<int> foundID;
|
||||
|
||||
void refreshIDList();
|
||||
void refreshFrameNumbers();
|
||||
};
|
||||
|
||||
#endif // BISECTWINDOW_H
|
||||
|
||||
|
||||
+21
-5
@@ -1,21 +1,37 @@
|
||||
#ifndef CAN_STRUCTS_H
|
||||
#define CAN_STRUCTS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <stdint.h>
|
||||
|
||||
class CANFrame
|
||||
struct CANFrame
|
||||
{
|
||||
public:
|
||||
int ID;
|
||||
int bus;
|
||||
uint32_t ID;
|
||||
uint32_t bus;
|
||||
bool extended;
|
||||
bool isReceived; //did we receive this or send it?
|
||||
int len;
|
||||
uint32_t len;
|
||||
unsigned char data[8];
|
||||
uint64_t timestamp;
|
||||
};
|
||||
|
||||
class CANFlt
|
||||
{
|
||||
public:
|
||||
quint32 id;
|
||||
quint32 mask;
|
||||
QObject * observer; //used to target the specific object that setup this filter
|
||||
|
||||
bool operator ==(const CANFlt &b) const
|
||||
{
|
||||
if ( (id == b.id) && (mask == b.mask) && (observer == b.observer) ) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct J1939ID
|
||||
{
|
||||
public:
|
||||
@@ -32,7 +48,7 @@ public:
|
||||
struct ISOTP_MESSAGE
|
||||
{
|
||||
public:
|
||||
int ID;
|
||||
uint32_t ID;
|
||||
int bus;
|
||||
bool extended;
|
||||
bool isReceived;
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ public:
|
||||
void setFilter(uint32_t id, uint32_t mask, int bus);
|
||||
bool checkFilter(uint32_t id, int bus);
|
||||
|
||||
private:
|
||||
public:
|
||||
uint32_t ID;
|
||||
uint32_t mask;
|
||||
int bus;
|
||||
|
||||
+36
-32
@@ -3,6 +3,15 @@
|
||||
#include <QFile>
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
CANFrameModel::~CANFrameModel()
|
||||
{
|
||||
frames.clear();
|
||||
filteredFrames.clear();
|
||||
filters.clear();
|
||||
}
|
||||
|
||||
|
||||
int CANFrameModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
@@ -38,12 +47,12 @@ CANFrameModel::CANFrameModel(QObject *parent)
|
||||
if (QSysInfo::WordSize > 32)
|
||||
{
|
||||
qDebug() << "64 bit OS detected. Requesting a large preallocation";
|
||||
preallocSize = 50000000;
|
||||
preallocSize = 20000000;
|
||||
}
|
||||
else //if compiling for 32 bit you can't ask for gigabytes of preallocation so tone it down.
|
||||
{
|
||||
qDebug() << "32 bit OS detected. Requesting a much restricted prealloc";
|
||||
preallocSize = 5000000;
|
||||
preallocSize = 4000000;
|
||||
}
|
||||
|
||||
frames.reserve(preallocSize);
|
||||
@@ -122,7 +131,7 @@ void CANFrameModel::setOverwriteMode(bool mode)
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void CANFrameModel::setFilterState(int ID, bool state)
|
||||
void CANFrameModel::setFilterState(unsigned int ID, bool state)
|
||||
{
|
||||
if (!filters.contains(ID)) return;
|
||||
filters[ID] = state;
|
||||
@@ -235,15 +244,15 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
|
||||
DBC_MESSAGE *msg = dbcHandler->findMessage(thisFrame);
|
||||
if (msg != NULL)
|
||||
{
|
||||
tempString.append("\r\n");
|
||||
tempString.append(msg->name + " " + msg->comment + "\r\n");
|
||||
tempString.append("\n");
|
||||
tempString.append(msg->name + " " + msg->comment + "\n");
|
||||
for (int j = 0; j < msg->sigHandler->getCount(); j++)
|
||||
{
|
||||
QString sigString;
|
||||
if (msg->sigHandler->findSignalByIdx(j)->processAsText(thisFrame, sigString))
|
||||
{
|
||||
tempString.append(sigString);
|
||||
tempString.append("\r\n");
|
||||
tempString.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +263,7 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
@@ -298,8 +307,10 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation,
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void CANFrameModel::addFrame(const CANFrame &frame, bool autoRefresh = false)
|
||||
|
||||
void CANFrameModel::addFrame(const CANFrame& frame, bool autoRefresh = false)
|
||||
{
|
||||
/*TODO: remove mutex */
|
||||
mutex.lock();
|
||||
CANFrame tempFrame;
|
||||
tempFrame = frame;
|
||||
@@ -361,6 +372,15 @@ void CANFrameModel::addFrame(const CANFrame &frame, bool autoRefresh = false)
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
void CANFrameModel::addFrames(const CANConnection*, const QVector<CANFrame>& pFrames)
|
||||
{
|
||||
foreach(const CANFrame& frame, pFrames)
|
||||
{
|
||||
addFrame(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void CANFrameModel::sendRefresh()
|
||||
{
|
||||
qDebug() << "Sending mass refresh";
|
||||
@@ -392,38 +412,22 @@ void CANFrameModel::sendRefresh(int pos)
|
||||
//issue a refresh for the last num entries in the model.
|
||||
//used by the serial worker to do batch updates so it doesn't
|
||||
//have to send thousands of messages per second
|
||||
void CANFrameModel::sendBulkRefresh(int num)
|
||||
int CANFrameModel::sendBulkRefresh()
|
||||
{
|
||||
//yes, num was sent to us by the serial worker but we actually have a better idea
|
||||
//of how many by tracking the number we last knew about as opposed to how many rows there
|
||||
//are now.
|
||||
num = filteredFrames.count() - lastUpdateNumFrames;
|
||||
int num = filteredFrames.count() - lastUpdateNumFrames;
|
||||
if (num <= 0) return 0;
|
||||
|
||||
if (num < 0) return;
|
||||
|
||||
//qDebug() << "Num: " << num;
|
||||
|
||||
if (num == 0 && !overwriteDups) return;
|
||||
if (filteredFrames.count() == 0) return;
|
||||
if (num == 0 && !overwriteDups) return 0;
|
||||
if (filteredFrames.count() == 0) return 0;
|
||||
|
||||
lastUpdateNumFrames += num; //done this way to avoid asking for filteredFrames.count() again
|
||||
|
||||
qDebug() << "Bulk refresh of " << num;
|
||||
|
||||
if (!overwriteDups)
|
||||
{
|
||||
//if (num > filteredFrames.count()) num = filteredFrames.count();
|
||||
//qDebug() << "From " << (filteredFrames.count() - num) << " to " << (filteredFrames.count() - 1);
|
||||
//beginInsertRows(QModelIndex(), filteredFrames.count() - num, filteredFrames.count() - 1);
|
||||
//endInsertRows();
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
void CANFrameModel::clearFrames()
|
||||
@@ -476,7 +480,7 @@ void CANFrameModel::insertFrames(const QVector<CANFrame> &newFrames)
|
||||
if (needFilterRefresh) emit updatedFiltersList();
|
||||
}
|
||||
|
||||
int CANFrameModel::getIndexFromTimeID(int ID, double timestamp)
|
||||
int CANFrameModel::getIndexFromTimeID(unsigned int ID, double timestamp)
|
||||
{
|
||||
int bestIndex = -1;
|
||||
uint64_t intTimeStamp = timestamp * 1000000l;
|
||||
|
||||
+10
-5
@@ -7,7 +7,8 @@
|
||||
#include <QDebug>
|
||||
#include <QMutex>
|
||||
#include "can_structs.h"
|
||||
#include "dbchandler.h"
|
||||
#include "dbc/dbchandler.h"
|
||||
#include "connections/canconnection.h"
|
||||
|
||||
class CANFrameModel: public QAbstractTableModel
|
||||
{
|
||||
@@ -15,6 +16,7 @@ class CANFrameModel: public QAbstractTableModel
|
||||
|
||||
public:
|
||||
CANFrameModel(QObject *parent = 0);
|
||||
virtual ~CANFrameModel();
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
@@ -23,16 +25,15 @@ public:
|
||||
int columnCount(const QModelIndex &) const;
|
||||
int totalFrameCount();
|
||||
|
||||
void addFrame(const CANFrame &, bool);
|
||||
void sendRefresh();
|
||||
void sendRefresh(int);
|
||||
void sendBulkRefresh(int);
|
||||
int sendBulkRefresh();
|
||||
void clearFrames();
|
||||
void setDBCHandler(DBCHandler *);
|
||||
void setInterpetMode(bool);
|
||||
void setOverwriteMode(bool);
|
||||
void setHexMode(bool);
|
||||
void setFilterState(int ID, bool state);
|
||||
void setFilterState(unsigned int ID, bool state);
|
||||
void setAllFilters(bool state);
|
||||
void setSecondsMode(bool);
|
||||
void loadFilterFile(QString filename);
|
||||
@@ -41,11 +42,15 @@ public:
|
||||
void recalcOverwrite();
|
||||
bool needsFilterRefresh();
|
||||
void insertFrames(const QVector<CANFrame> &newFrames);
|
||||
int getIndexFromTimeID(int ID, double timestamp);
|
||||
int getIndexFromTimeID(unsigned int ID, double timestamp);
|
||||
const QVector<CANFrame> *getListReference() const; //thou shalt not modify these frames externally!
|
||||
const QVector<CANFrame> *getFilteredListReference() const; //Thus saith the Lord, NO.
|
||||
const QMap<int, bool> *getFiltersReference() const; //this neither
|
||||
|
||||
public slots:
|
||||
void addFrame(const CANFrame&, bool);
|
||||
void addFrames(const CANConnection*, const QVector<CANFrame>&);
|
||||
|
||||
signals:
|
||||
void updatedFiltersList();
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef CONFIG
|
||||
#define CONFIG
|
||||
|
||||
#define VERSION 157
|
||||
#define VERSION 161
|
||||
|
||||
//try to keep this in sync.
|
||||
//SavvyCAN will complain if you connect a GVRET board with a revision
|
||||
//less than this number.
|
||||
#define CURRENT_GVRET_VER 331
|
||||
#define CURRENT_GVRET_VER 334
|
||||
|
||||
#endif // CONFIG
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include <QObject>
|
||||
#include "canbus.h"
|
||||
|
||||
CANBus::CANBus()
|
||||
{
|
||||
speed = 250000;
|
||||
listenOnly = false;
|
||||
singleWire = false;
|
||||
active = false;
|
||||
}
|
||||
|
||||
|
||||
CANBus::CANBus(const CANBus& pBus) :
|
||||
speed(pBus.speed),
|
||||
listenOnly(pBus.listenOnly),
|
||||
singleWire(pBus.singleWire),
|
||||
active(pBus.active) {}
|
||||
|
||||
|
||||
bool CANBus::operator==(const CANBus& bus) const{
|
||||
return speed == bus.speed &&
|
||||
listenOnly == bus.listenOnly &&
|
||||
singleWire == bus.singleWire &&
|
||||
active == bus.active;
|
||||
}
|
||||
|
||||
void CANBus::setSpeed(int newSpeed){
|
||||
speed = newSpeed;
|
||||
}
|
||||
|
||||
void CANBus::setListenOnly(bool mode){
|
||||
listenOnly = mode;
|
||||
}
|
||||
|
||||
void CANBus::setSingleWire(bool mode){
|
||||
singleWire = mode;
|
||||
}
|
||||
|
||||
void CANBus::setEnabled(bool mode){
|
||||
active = mode;
|
||||
}
|
||||
|
||||
int CANBus::getSpeed(){
|
||||
return speed;
|
||||
}
|
||||
|
||||
bool CANBus::isListenOnly(){
|
||||
return listenOnly;
|
||||
}
|
||||
|
||||
bool CANBus::isSingleWire(){
|
||||
return singleWire;
|
||||
}
|
||||
|
||||
bool CANBus::isActive(){
|
||||
return active;
|
||||
}
|
||||
|
||||
|
||||
QDataStream& operator<<( QDataStream & pStream, const CANBus& pCanBus )
|
||||
{
|
||||
pStream << pCanBus.speed;
|
||||
pStream << pCanBus.listenOnly;
|
||||
pStream << pCanBus.singleWire;
|
||||
pStream << pCanBus.active;
|
||||
return pStream;
|
||||
}
|
||||
|
||||
QDataStream & operator>>(QDataStream & pStream, CANBus& pCanBus)
|
||||
{
|
||||
pStream >> pCanBus.speed;
|
||||
pStream >> pCanBus.listenOnly;
|
||||
pStream >> pCanBus.singleWire;
|
||||
pStream >> pCanBus.active;
|
||||
return pStream;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef CANBus_H
|
||||
#define CANBus_H
|
||||
#include <QDataStream>
|
||||
|
||||
class CANBus
|
||||
{
|
||||
public:
|
||||
CANBus();
|
||||
CANBus(const CANBus&);
|
||||
bool operator==(const CANBus&) const;
|
||||
virtual ~CANBus(){};
|
||||
|
||||
int speed;
|
||||
bool listenOnly;
|
||||
bool singleWire;
|
||||
bool active; //is this bus turned on?
|
||||
|
||||
|
||||
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 setEnabled(bool); //whether this bus should be enabled or not.
|
||||
int getSpeed();
|
||||
bool isListenOnly();
|
||||
bool isSingleWire();
|
||||
bool isActive();
|
||||
};
|
||||
|
||||
QDataStream& operator<<( QDataStream & pStream, const CANBus& pCanBus );
|
||||
QDataStream & operator>>(QDataStream & pStream, CANBus& pCanBus);
|
||||
|
||||
Q_DECLARE_METATYPE(CANBus);
|
||||
|
||||
#endif // CANBus_H
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef CANCONCONST_H
|
||||
#define CANCONCONST_H
|
||||
|
||||
namespace CANCon {
|
||||
|
||||
/**
|
||||
* @brief The status enum
|
||||
*/
|
||||
enum status
|
||||
{
|
||||
NOT_CONNECTED, /*!< device is not connected */
|
||||
CONNECTED /*!< device is connected */
|
||||
};
|
||||
|
||||
enum type
|
||||
{
|
||||
GVRET_SERIAL,
|
||||
KVASER,
|
||||
SOCKETCAN,
|
||||
NONE
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CANCONCONST_H
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <QString>
|
||||
#include "canconfactory.h"
|
||||
#include "socketcan.h"
|
||||
#include "gvretserial.h"
|
||||
|
||||
using namespace CANCon;
|
||||
|
||||
CANConnection* CanConFactory::create(type pType, QString pPortName)
|
||||
{
|
||||
switch(pType) {
|
||||
case SOCKETCAN:
|
||||
return new SocketCan(pPortName);
|
||||
case GVRET_SERIAL:
|
||||
return new GVRetSerial(pPortName);
|
||||
default: {}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef CANCONFACTORY_H
|
||||
#define CANCONFACTORY_H
|
||||
|
||||
#include "canconconst.h"
|
||||
#include "canconnection.h"
|
||||
|
||||
class CanConFactory
|
||||
{
|
||||
public:
|
||||
static CANConnection* create(CANCon::type, QString pPortName);
|
||||
};
|
||||
|
||||
#endif // CANCONFACTORY_H
|
||||
@@ -0,0 +1,234 @@
|
||||
#include <QDateTime>
|
||||
|
||||
#include "canconmanager.h"
|
||||
|
||||
|
||||
CANConManager* CANConManager::mInstance = NULL;
|
||||
|
||||
CANConManager* CANConManager::getInstance()
|
||||
{
|
||||
if(!mInstance)
|
||||
mInstance = new CANConManager();
|
||||
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
|
||||
CANConManager::CANConManager(QObject *parent): QObject(parent)
|
||||
{
|
||||
connect(&mTimer, SIGNAL(timeout()), this, SLOT(refreshCanList()));
|
||||
mTimer.setInterval(125); /*tick 8 times a second */
|
||||
mTimer.setSingleShot(false);
|
||||
mTimer.start();
|
||||
|
||||
resetTimeBasis();
|
||||
}
|
||||
|
||||
void CANConManager::resetTimeBasis()
|
||||
{
|
||||
mTimestampBasis = QDateTime::currentMSecsSinceEpoch() * 1000;
|
||||
}
|
||||
|
||||
CANConManager::~CANConManager()
|
||||
{
|
||||
mTimer.stop();
|
||||
mInstance = NULL;
|
||||
}
|
||||
|
||||
|
||||
void CANConManager::add(CANConnection* pConn_p)
|
||||
{
|
||||
mConns.append(pConn_p);
|
||||
emit connectionStatusUpdated(getNumBuses());
|
||||
}
|
||||
|
||||
|
||||
void CANConManager::remove(CANConnection* pConn_p)
|
||||
{
|
||||
//disconnect(pConn_p, 0, this, 0);
|
||||
mConns.removeOne(pConn_p);
|
||||
emit connectionStatusUpdated(getNumBuses());
|
||||
}
|
||||
|
||||
//Get total number of buses currently registered with the program
|
||||
int CANConManager::getNumBuses()
|
||||
{
|
||||
int buses = 0;
|
||||
foreach(CANConnection* conn_p, mConns)
|
||||
{
|
||||
buses += conn_p->getNumBuses();
|
||||
}
|
||||
return buses;
|
||||
}
|
||||
|
||||
void CANConManager::refreshCanList()
|
||||
{
|
||||
QObject* sender_p = QObject::sender();
|
||||
|
||||
if( sender_p != &mTimer)
|
||||
{
|
||||
/* if we are not the sender, the signal is coming from a connection */
|
||||
/* refresh only the given connection */
|
||||
if(mConns.contains((CANConnection*) sender_p))
|
||||
refreshConnection((CANConnection*)sender_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (CANConnection* conn_p, mConns)
|
||||
refreshConnection((CANConnection*)conn_p);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CANConManager::getTimeBasis()
|
||||
{
|
||||
return mTimestampBasis;
|
||||
}
|
||||
|
||||
QList<CANConnection*>& CANConManager::getConnections()
|
||||
{
|
||||
return mConns;
|
||||
}
|
||||
|
||||
|
||||
CANConnection* CANConManager::getByName(const QString& pName) const
|
||||
{
|
||||
foreach(CANConnection* conn_p, mConns)
|
||||
{
|
||||
if(conn_p->getPort() == pName)
|
||||
return conn_p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void CANConManager::refreshConnection(CANConnection* pConn_p)
|
||||
{
|
||||
if (pConn_p->getQueue().peek() == NULL) return;
|
||||
|
||||
CANFrame* frame_p = NULL;
|
||||
QVector<CANFrame> frames;
|
||||
|
||||
//Each connection only knows about its own bus numbers
|
||||
//so this variable is used to fix that up to turn local bus numbers
|
||||
//into system global bus numbers for display.
|
||||
int busBase = 0;
|
||||
|
||||
foreach (CANConnection* conn, mConns)
|
||||
{
|
||||
if (conn != pConn_p) busBase += conn->getNumBuses();
|
||||
else break;
|
||||
}
|
||||
|
||||
//qDebug() << "Bus fixup number: " << busBase;
|
||||
|
||||
while( (frame_p = pConn_p->getQueue().peek() ) ) {
|
||||
frame_p->bus += busBase;
|
||||
//qDebug() << "Rx of frame from bus: " << frame_p->bus;
|
||||
frames.append(*frame_p);
|
||||
pConn_p->getQueue().dequeue();
|
||||
}
|
||||
|
||||
if(frames.size())
|
||||
emit framesReceived(pConn_p, frames);
|
||||
}
|
||||
|
||||
/*
|
||||
* Uses the requested bus to look up which CANConnection object handles this bus based on the order of
|
||||
* the objects and how many buses they implement. For instance, if the request is to send on bus 2
|
||||
* and there is a GVRET object first then a socketcan object it'll send on the socketcan object as
|
||||
* gvret will have claimed buses 0 and 1 and socketcan bus 2. But, each actual CANConnection expects
|
||||
* its own bus numbers to start at zero so the frame bus number has to be offset accordingly.
|
||||
* Also keep in mind that the CANConnection "sendFrame" function uses a blocking queued connection
|
||||
* and so will force the frame to be delivered before it keeps going. This allows on the stack variables
|
||||
* to be used but is slow. This function uses an on the stack copy of the frame so the way it works
|
||||
* is a good thing but performance will suffer. TODO: Investigate a way to use non-blocking calls.
|
||||
*/
|
||||
bool CANConManager::sendFrame(const CANFrame& pFrame)
|
||||
{
|
||||
int busBase = 0;
|
||||
CANFrame workingFrame = pFrame;
|
||||
CANFrame *txFrame;
|
||||
|
||||
foreach (CANConnection* conn, mConns)
|
||||
{
|
||||
//check if this CAN connection is supposed to handle the requested bus
|
||||
if (pFrame.bus < (uint32_t)(busBase + conn->getNumBuses()))
|
||||
{
|
||||
workingFrame.bus -= busBase;
|
||||
workingFrame.isReceived = false;
|
||||
workingFrame.timestamp = ((QDateTime::currentMSecsSinceEpoch() * 1000) - mTimestampBasis);
|
||||
txFrame = conn->getQueue().get();
|
||||
*txFrame = workingFrame;
|
||||
conn->getQueue().queue();
|
||||
return conn->sendFrame(workingFrame);
|
||||
}
|
||||
busBase += conn->getNumBuses();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CANConManager::sendFrames(const QList<CANFrame>& pFrames)
|
||||
{
|
||||
foreach(const CANFrame& frame, pFrames)
|
||||
{
|
||||
if(!sendFrame(frame))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//For each device associated with buses go through and see if that device has a bus
|
||||
//that the filter should apply to. If so forward the data on but fudge
|
||||
//the bus numbers if bus wasn't -1 so that they're local to the device
|
||||
bool CANConManager::addTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver)
|
||||
{
|
||||
int tempBusVal;
|
||||
int busBase = 0;
|
||||
|
||||
foreach (CANConnection* conn, mConns)
|
||||
{
|
||||
if (pBusId == -1) conn->addTargettedFrame(pBusId, ID, mask, receiver);
|
||||
else
|
||||
{
|
||||
tempBusVal = pBusId >> busBase;
|
||||
tempBusVal &= ((1 << conn->getNumBuses()) - 1);
|
||||
if (tempBusVal) {
|
||||
qDebug() << "Forwarding targetted frame setting to a connection object";
|
||||
conn->addTargettedFrame(tempBusVal, ID, mask, receiver);
|
||||
}
|
||||
}
|
||||
busBase += conn->getNumBuses();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CANConManager::removeTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver)
|
||||
{
|
||||
int tempBusVal;
|
||||
int busBase = 0;
|
||||
|
||||
foreach (CANConnection* conn, mConns)
|
||||
{
|
||||
if (pBusId == -1) conn->removeTargettedFrame(pBusId, ID, mask, receiver);
|
||||
else
|
||||
{
|
||||
tempBusVal = pBusId >> busBase;
|
||||
tempBusVal &= ((1 << conn->getNumBuses()) - 1);
|
||||
if (tempBusVal) conn->removeTargettedFrame(tempBusVal, ID, mask, receiver);
|
||||
}
|
||||
busBase += conn->getNumBuses();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CANConManager::removeAllTargettedFrames(QObject *receiver)
|
||||
{
|
||||
foreach (CANConnection* conn, mConns)
|
||||
{
|
||||
conn->removeAllTargettedFrames(receiver);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef CANCONMANAGER_H
|
||||
#define CANCONMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "canconnection.h"
|
||||
|
||||
class CANConManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static CANConManager* getInstance();
|
||||
virtual ~CANConManager();
|
||||
|
||||
void add(CANConnection* pConn_p);
|
||||
void remove(CANConnection* pConn_p);
|
||||
QList<CANConnection*>& getConnections();
|
||||
|
||||
CANConnection* getByName(const QString& pName) const;
|
||||
|
||||
uint64_t getTimeBasis();
|
||||
void resetTimeBasis();
|
||||
|
||||
int getNumBuses();
|
||||
|
||||
/**
|
||||
* @brief sendFrame sends a single frame out the desired bus
|
||||
* @param pFrame - reference to a CANFrame struct that has been filled out for sending
|
||||
* @return bool specifying whether the send succeeded or not
|
||||
* @note Finds which CANConnection object is responsible for this bus and automatically converts bus number to pass properly to CANConnection
|
||||
*/
|
||||
bool sendFrame(const CANFrame& pFrame);
|
||||
|
||||
//just the multi-frame version of above function.
|
||||
bool sendFrames(const QList<CANFrame>& pFrames);
|
||||
|
||||
/**
|
||||
* @brief Add a new filter for the targetted frames. If a frame matches it will immediately be sent via the targettedFrameReceived signal
|
||||
* @param pBusId - Which bus to bond to. -1 for any, otherwise a bitfield of buses (but 0 = first bus, etc)
|
||||
* @param ID - 11 or 29 bit ID to match against
|
||||
* @param mask - 11 or 29 bit mask used for filter
|
||||
* @param receiver - Pointer to a QObject that wants to receive notification when filter is matched
|
||||
* @return true if filter was able to be added, false otherwise.
|
||||
*/
|
||||
bool addTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver);
|
||||
|
||||
/**
|
||||
* @brief Try to find a matching filter in the list and remove it, no longer targetting those frames
|
||||
* @param pBusId - Which bus to bond to. Doesn't have to match the call to addTargettedFrame exactly. You could disconnect just one bus for instance.
|
||||
* @param ID - 11 or 29 bit ID to match against
|
||||
* @param mask - 11 or 29 bit mask used for filter
|
||||
* @param receiver - Pointer to a QObject that wants to receive notification when filter is matched
|
||||
* @return true if filter was found and deleted, false otherwise.
|
||||
*/
|
||||
bool removeTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver);
|
||||
|
||||
bool removeAllTargettedFrames(QObject *receiver);
|
||||
|
||||
signals:
|
||||
void framesReceived(CANConnection* pConn_p, QVector<CANFrame>& pFrames);
|
||||
void connectionStatusUpdated(int conns);
|
||||
|
||||
private slots:
|
||||
void refreshCanList();
|
||||
|
||||
private:
|
||||
explicit CANConManager(QObject *parent = 0);
|
||||
void refreshConnection(CANConnection* pConn_p);
|
||||
|
||||
static CANConManager* mInstance;
|
||||
QList<CANConnection*> mConns;
|
||||
QTimer mTimer;
|
||||
uint64_t mTimestampBasis;
|
||||
};
|
||||
|
||||
#endif // CANCONNECTIONMODEL_H
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
#include <QThread>
|
||||
#include "canconnection.h"
|
||||
|
||||
|
||||
struct BusData {
|
||||
CANBus mBus;
|
||||
bool mConfigured;
|
||||
QVector<CANFlt> mTargettedFrames;
|
||||
};
|
||||
|
||||
|
||||
CANConnection::CANConnection(QString pPort,
|
||||
CANCon::type pType,
|
||||
int pNumBuses,
|
||||
int pQueueLen,
|
||||
bool pUseThread) :
|
||||
mQueue(),
|
||||
mNumBuses(pNumBuses),
|
||||
mPort(pPort),
|
||||
mType(pType),
|
||||
mIsCapSuspended(false),
|
||||
mStatus(CANCon::NOT_CONNECTED),
|
||||
mStarted(false),
|
||||
mThread_p(NULL)
|
||||
{
|
||||
/* register types */
|
||||
qRegisterMetaType<CANBus>("CANBus");
|
||||
qRegisterMetaType<CANFrame>("CANFrame");
|
||||
qRegisterMetaType<CANCon::status>("CANCon::status");
|
||||
qRegisterMetaType<CANFlt>("CANFlt");
|
||||
|
||||
/* set queue size */
|
||||
mQueue.setSize(pQueueLen); /*TODO add check on returned value */
|
||||
|
||||
/* allocate buses */
|
||||
/* TODO: change those tables for a vector */
|
||||
mBusData_p = new BusData[mNumBuses];
|
||||
for(int i=0 ; i<mNumBuses ; i++) {
|
||||
mBusData_p[i].mConfigured = false;
|
||||
}
|
||||
|
||||
/* if needed, create a thread and move ourself into it */
|
||||
if(pUseThread) {
|
||||
mThread_p = new QThread();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CANConnection::~CANConnection()
|
||||
{
|
||||
/* stop and delete thread */
|
||||
if(mThread_p) {
|
||||
mThread_p->quit();
|
||||
mThread_p->wait();
|
||||
delete mThread_p;
|
||||
mThread_p = NULL;
|
||||
}
|
||||
|
||||
if(mBusData_p) {
|
||||
delete[] mBusData_p;
|
||||
mBusData_p = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::start()
|
||||
{
|
||||
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(start()));
|
||||
/* start the thread */
|
||||
mThread_p->start(QThread::HighPriority);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set started flag */
|
||||
mStarted = true;
|
||||
|
||||
/* in multithread case, this will be called before entering thread event loop */
|
||||
return piStarted();
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::suspend(bool pSuspend)
|
||||
{
|
||||
/* execute in mThread_p context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
QMetaObject::invokeMethod(this, "suspend",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(bool, pSuspend));
|
||||
return;
|
||||
}
|
||||
|
||||
return piSuspend(pSuspend);
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::stop()
|
||||
{
|
||||
/* 1) execute in mThread_p context */
|
||||
if( mThread_p && mStarted && (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, "stop",
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::getBusSettings(int pBusIdx, CANBus& pBus)
|
||||
{
|
||||
/* make sure we execute in mThread context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
bool ret;
|
||||
QMetaObject::invokeMethod(this, "getBusSettings",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, ret),
|
||||
Q_ARG(int , pBusIdx),
|
||||
Q_ARG(CANBus& , pBus));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return piGetBusSettings(pBusIdx, pBus);
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::setBusSettings(int pBusIdx, CANBus pBus)
|
||||
{
|
||||
/* make sure we execute in mThread context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
QMetaObject::invokeMethod(this, "setBusSettings",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(int, pBusIdx),
|
||||
Q_ARG(CANBus, pBus));
|
||||
return;
|
||||
}
|
||||
|
||||
return piSetBusSettings(pBusIdx, pBus);
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::sendFrame(const CANFrame& pFrame)
|
||||
{
|
||||
/* make sure we execute in mThread context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) )
|
||||
{
|
||||
bool ret;
|
||||
QMetaObject::invokeMethod(this, "sendFrame",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, ret),
|
||||
Q_ARG(const CANFrame&, pFrame));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return piSendFrame(pFrame);
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::sendFrames(const QList<CANFrame>& pFrames)
|
||||
{
|
||||
/* make sure we execute in mThread context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) )
|
||||
{
|
||||
bool ret;
|
||||
QMetaObject::invokeMethod(this, "sendFrames",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, ret),
|
||||
Q_ARG(const QList<CANFrame>&, pFrames));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return piSendFrames(pFrames);
|
||||
}
|
||||
|
||||
|
||||
int CANConnection::getNumBuses() const{
|
||||
return mNumBuses;
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::isConfigured(int pBusId) {
|
||||
if( pBusId < 0 || pBusId >= getNumBuses())
|
||||
return false;
|
||||
return mBusData_p[pBusId].mConfigured;
|
||||
}
|
||||
|
||||
void CANConnection::setConfigured(int pBusId, bool pConfigured) {
|
||||
if( pBusId < 0 || pBusId >= getNumBuses())
|
||||
return;
|
||||
mBusData_p[pBusId].mConfigured = pConfigured;
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::getBusConfig(int pBusId, CANBus& pBus) {
|
||||
if( pBusId < 0 || pBusId >= getNumBuses() || !isConfigured(pBusId))
|
||||
return false;
|
||||
|
||||
pBus = mBusData_p[pBusId].mBus;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::setBusConfig(int pBusId, CANBus& pBus) {
|
||||
if( pBusId < 0 || pBusId >= getNumBuses())
|
||||
return;
|
||||
|
||||
mBusData_p[pBusId].mConfigured = true;
|
||||
mBusData_p[pBusId].mBus = pBus;
|
||||
}
|
||||
|
||||
|
||||
QString CANConnection::getPort() {
|
||||
return mPort;
|
||||
}
|
||||
|
||||
|
||||
LFQueue<CANFrame>& CANConnection::getQueue() {
|
||||
return mQueue;
|
||||
}
|
||||
|
||||
|
||||
CANCon::type CANConnection::getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
|
||||
CANCon::status CANConnection::getStatus() {
|
||||
return (CANCon::status) mStatus.load();
|
||||
}
|
||||
|
||||
void CANConnection::setStatus(CANCon::status pStatus) {
|
||||
mStatus.store(pStatus);
|
||||
}
|
||||
|
||||
bool CANConnection::isCapSuspended() {
|
||||
return mIsCapSuspended;
|
||||
}
|
||||
|
||||
void CANConnection::setCapSuspended(bool pIsSuspended) {
|
||||
mIsCapSuspended = pIsSuspended;
|
||||
}
|
||||
|
||||
bool CANConnection::addTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver)
|
||||
{
|
||||
/*
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
bool ret;
|
||||
QMetaObject::invokeMethod(this, "addTargettedFrame",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, ret),
|
||||
Q_ARG(int, pBusId),
|
||||
Q_ARG(uint32_t , ID),
|
||||
Q_ARG(uint32_t , mask),
|
||||
Q_ARG(QObject *, receiver));
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
/* sanity checks */
|
||||
if(pBusId < -1 || pBusId >= (1 << getNumBuses()))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < getNumBuses(); i++)
|
||||
{
|
||||
if ( (pBusId == -1) || (pBusId && (1 << i)) ) {
|
||||
qDebug() << "Connection is registering a new targetted frame filter, local bus " << i;
|
||||
CANFlt target;
|
||||
target.id = ID;
|
||||
target.mask = mask;
|
||||
target.observer = receiver;
|
||||
mBusData_p[i].mTargettedFrames.append(target);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CANConnection::removeTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver)
|
||||
{
|
||||
/*
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
bool ret;
|
||||
QMetaObject::invokeMethod(this, "removeTargettedFrame",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, ret),
|
||||
Q_ARG(int, pBusId),
|
||||
Q_ARG(uint32_t , ID),
|
||||
Q_ARG(uint32_t , mask),
|
||||
Q_ARG(QObject *, receiver));
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
/* sanity checks */
|
||||
if(pBusId < -1 || pBusId >= (1 << getNumBuses()))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < getNumBuses(); i++)
|
||||
{
|
||||
if (pBusId == -1 || (pBusId && (1 << i)))
|
||||
{
|
||||
CANFlt target;
|
||||
target.id = ID;
|
||||
target.mask = mask;
|
||||
target.observer = receiver;
|
||||
mBusData_p[i].mTargettedFrames.removeAll(target);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CANConnection::removeAllTargettedFrames(QObject *receiver)
|
||||
{
|
||||
for (int i = 0; i < getNumBuses(); i++) {
|
||||
foreach (const CANFlt filt, mBusData_p[i].mTargettedFrames)
|
||||
{
|
||||
if (filt.observer == receiver) mBusData_p[i].mTargettedFrames.removeOne(filt);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CANConnection::checkTargettedFrame(CANFrame &frame)
|
||||
{
|
||||
unsigned int maskedID;
|
||||
qDebug() << "Got frame with ID " << frame.ID << " on bus " << frame.bus;
|
||||
foreach (const CANFlt filt, mBusData_p[frame.bus].mTargettedFrames)
|
||||
{
|
||||
qDebug() << "Checking filter with id " << filt.id << " mask " << filt.mask;
|
||||
maskedID = frame.ID & filt.mask;
|
||||
if (maskedID == filt.id) {
|
||||
qDebug() << "In connection object I got a targetted frame. Forwarding it.";
|
||||
QMetaObject::invokeMethod(filt.observer, "gotTargettedFrame",Qt::QueuedConnection, Q_ARG(CANFrame, frame));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CANConnection::piSendFrames(const QList<CANFrame>& pFrames)
|
||||
{
|
||||
foreach(const CANFrame& frame, pFrames)
|
||||
{
|
||||
if(!piSendFrame(frame))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
#ifndef CANCONNECTION_H
|
||||
#define CANCONNECTION_H
|
||||
|
||||
#include <Qt>
|
||||
#include <QObject>
|
||||
#include "utils/lfqueue.h"
|
||||
#include "can_structs.h"
|
||||
#include "canbus.h"
|
||||
#include "canconconst.h"
|
||||
|
||||
struct BusData;
|
||||
|
||||
class CANConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief CANConnection constructor
|
||||
* @param pPort: string containing port name
|
||||
* @param pType: the type of connection @ref CANCon::type
|
||||
* @param pNumBuses: the number of buses the device has
|
||||
* @param pQueueLen: the length of the lock free queue to use
|
||||
* @param pUseThread: if set to true, object will be execute in a dedicated thread
|
||||
*/
|
||||
CANConnection(QString pPort,
|
||||
CANCon::type pType,
|
||||
int pNumBuses,
|
||||
int pQueueLen,
|
||||
bool pUseThread);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief CANConnection destructor
|
||||
*/
|
||||
|
||||
virtual ~CANConnection();
|
||||
|
||||
/**
|
||||
* @brief getNumBuses
|
||||
* @return returns the number of buses of the device
|
||||
*/
|
||||
int getNumBuses() const;
|
||||
|
||||
/**
|
||||
* @brief getPort
|
||||
* @return returns the port name of the device
|
||||
*/
|
||||
QString getPort();
|
||||
|
||||
/**
|
||||
* @brief getQueue
|
||||
* @return the lock free queue of the device
|
||||
*/
|
||||
LFQueue<CANFrame>& getQueue();
|
||||
|
||||
/**
|
||||
* @brief getType
|
||||
* @return the @ref CANCon::type of the device
|
||||
*/
|
||||
CANCon::type getType();
|
||||
|
||||
/**
|
||||
* @brief getStatus
|
||||
* @return the @ref CANCon::status of the device (either connected or not)
|
||||
*/
|
||||
CANCon::status getStatus();
|
||||
|
||||
|
||||
signals:
|
||||
/*not implemented yet */
|
||||
void error(const QString &);
|
||||
void deviceInfo(int, int); //First param = driver version (or version of whatever you want), second param a status byte
|
||||
|
||||
//bus number, bus speed, status (bit 0 = enabled, 1 = single wire, 2 = listen only)
|
||||
//3 = Use value stored for enabled, 4 = use value passed for single wire, 5 = use value passed for listen only
|
||||
//6 = use value passed for speed. This allows bus status to be updated but set that some things aren't really
|
||||
//being passed. Just set for things that really are being updated.
|
||||
void busStatus(int, int, int);
|
||||
|
||||
/**
|
||||
* @brief event sent when a frame matching a filter is received
|
||||
*/
|
||||
void targettedFrameReceived(CANFrame frame);
|
||||
|
||||
/**
|
||||
* @brief event emitted when the CANCon::status of the connection changes (connected->not_connected or the other way round)
|
||||
* @param pStatus: the new status of the device
|
||||
*/
|
||||
void status(CANCon::status pStatus);
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* @brief start the device. This calls piStarted
|
||||
* @note starts the working thread if required (piStarted is called in the working thread context)
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* @brief stop the device. This calls piStop
|
||||
* @note if a working thread is used, piStop is called before exiting the working thread
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* @brief setBusSettings
|
||||
* @param pBusIdx: the index of the bus for which settings have to be set
|
||||
* @param pBus: the settings to set
|
||||
* @note this calls piSetBusSettings in the working thread context (if one has been started)
|
||||
*/
|
||||
void setBusSettings(int pBusIdx, CANBus pBus);
|
||||
|
||||
/**
|
||||
* @brief getBusSettings
|
||||
* @param pBusIdx: the index of the bus for which settings have to be retrieved
|
||||
* @param pBus: the CANBus struct to fill with information
|
||||
* @return true if operation succeeds, false if pBusIdx is invalid or bus has not been configured yet
|
||||
* @note this calls piGetBusSettings in the working thread context (if one has been started)
|
||||
*/
|
||||
bool getBusSettings(int pBusIdx, CANBus& pBus);
|
||||
|
||||
/**
|
||||
* @brief suspends/restarts data capture
|
||||
* @param pSuspend: suspends capture if true else restarts it
|
||||
* @note this calls piSuspend (in the working thread context if one has been started)
|
||||
* @note the caller shall not access the queue when capture is suspended,
|
||||
* @note the callee is expected to flush the queue
|
||||
*/
|
||||
void suspend(bool pSuspend);
|
||||
|
||||
/**
|
||||
* @brief provides device with the frame to send
|
||||
* @param pFrame: the frame to send
|
||||
* @return false if parameter is invalid (bus id for instance)
|
||||
* @note this calls piSendFrame (in the working thread context if one has been started)
|
||||
*/
|
||||
bool sendFrame(const CANFrame& pFrame);
|
||||
|
||||
/**
|
||||
* @brief provides device with a list of frames to send
|
||||
* @param pFrame: the list of frames to send
|
||||
* @return false if parameter is invalid (bus id for instance)
|
||||
* @note this calls piSendFrameBatch (in the working thread context if one has been started)
|
||||
*/
|
||||
bool sendFrames(const QList<CANFrame>& pFrames);
|
||||
|
||||
/**
|
||||
* @brief Add a new filter for the targetted frames. If a frame matches it will immediately be sent via the targettedFrameReceived signal
|
||||
* @param pBusId - Which bus to bond to. -1 for any, otherwise a bitfield of buses (but 0 = first bus, etc)
|
||||
* @param ID - 11 or 29 bit ID to match against
|
||||
* @param mask - 11 or 29 bit mask used for filter
|
||||
* @param receiver - Pointer to a QObject that wants to receive notification when filter is matched
|
||||
* @return true if filter was able to be added, false otherwise.
|
||||
*/
|
||||
bool addTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver);
|
||||
|
||||
/**
|
||||
* @brief Try to find a matching filter in the list and remove it, no longer targetting those frames
|
||||
* @param pBusId - Which bus to bond to. Doesn't have to match the call to addTargettedFrame exactly. You could disconnect just one bus for instance.
|
||||
* @param ID - 11 or 29 bit ID to match against
|
||||
* @param mask - 11 or 29 bit mask used for filter
|
||||
* @param receiver - Pointer to a QObject that wants to receive notification when filter is matched
|
||||
* @return true if filter was found and deleted, false otherwise.
|
||||
*/
|
||||
bool removeTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver);
|
||||
|
||||
/**
|
||||
* @brief Removes all registered filters for the passed receiver
|
||||
* @param receiver - Pointer to a QObject that registered one or more filters
|
||||
* @return true if filter(s) was/were found and deleted, false otherwise.
|
||||
*/
|
||||
bool removeAllTargettedFrames(QObject *receiver);
|
||||
|
||||
protected:
|
||||
|
||||
//determine if the passed frame is part of a filter or not.
|
||||
void checkTargettedFrame(CANFrame &frame);
|
||||
|
||||
/**
|
||||
* @brief setStatus
|
||||
* @param pStatus: the status to set
|
||||
*/
|
||||
void setStatus(CANCon::status pStatus);
|
||||
|
||||
/**
|
||||
* @brief isConfigured
|
||||
* @param pBusId
|
||||
* @return true if bus is configured
|
||||
*/
|
||||
bool isConfigured(int pBusId);
|
||||
|
||||
/**
|
||||
* @brief setConfigured
|
||||
* @param pBusId
|
||||
* @param pConfigured
|
||||
* @note it is not necessary to call this function to set pBusId configured, it is enough to call @ref setBusConfig
|
||||
*/
|
||||
void setConfigured(int pBusId, bool pConfigured);
|
||||
|
||||
/**
|
||||
* @brief getBusConfig
|
||||
* @param pBusId
|
||||
* @param pBus
|
||||
* @return true if operation succeeds, false if pBusIdx is invalid or bus has not been configured yet
|
||||
*/
|
||||
bool getBusConfig(int pBusId, CANBus& pBus);
|
||||
|
||||
/**
|
||||
* @brief setBusConfig
|
||||
* @param pBusId: the index of the bus for which settings have to be set
|
||||
* @param pBus: the settings to set
|
||||
*/
|
||||
void setBusConfig(int pBusId, CANBus& pBus);
|
||||
|
||||
/**
|
||||
* @brief isCapSuspended
|
||||
* @return true if the capture is suspended
|
||||
*/
|
||||
bool isCapSuspended();
|
||||
|
||||
/**
|
||||
* @brief setCapSuspended
|
||||
* @param pIsSuspended
|
||||
*/
|
||||
void setCapSuspended(bool pIsSuspended);
|
||||
|
||||
protected:
|
||||
|
||||
/**************************************************************/
|
||||
/*********** protected interface to implement *******/
|
||||
/**************************************************************/
|
||||
|
||||
/**
|
||||
* @brief starts the device
|
||||
*/
|
||||
virtual void piStarted() = 0;
|
||||
|
||||
/**
|
||||
* @brief stops the device
|
||||
*/
|
||||
virtual void piStop() = 0;
|
||||
|
||||
/**
|
||||
* @brief piSetBusSettings
|
||||
* @param pBusIdx: the index of the bus for which settings have to be set
|
||||
* @param pBus: the settings to set
|
||||
*/
|
||||
virtual void piSetBusSettings(int pBusIdx, CANBus pBus) = 0;
|
||||
|
||||
/**
|
||||
* @brief piGetBusSettings
|
||||
* @param pBusIdx: the index of the bus for which settings have to be retrieved
|
||||
* @param pBus: the CANBus struct to fill with information
|
||||
* @return true if operation succeeds, false if pBusIdx is invalid or bus has not been configured yet
|
||||
*/
|
||||
virtual bool piGetBusSettings(int pBusIdx, CANBus& pBus) = 0;
|
||||
|
||||
/**
|
||||
* @brief suspends/restarts data capture
|
||||
* @param pSuspend: suspends capture if true else restarts it
|
||||
* @note the caller will not access the queue when capture is suspended, so it is safe for callee to flush the queue
|
||||
*/
|
||||
virtual void piSuspend(bool pSuspend) = 0;
|
||||
|
||||
/**
|
||||
* @brief provides device with the frame to send
|
||||
* @param pFrame: the frame to send
|
||||
* @return false if parameter is invalid (bus id for instance)
|
||||
*/
|
||||
virtual bool piSendFrame(const CANFrame&) = 0;
|
||||
|
||||
/**
|
||||
* @brief provides device with a list of frames to send
|
||||
* @param pFrame: the list of frames to send
|
||||
* @return false if parameter is invalid (bus id for instance)
|
||||
* @note implementing this function is optional
|
||||
*/
|
||||
virtual bool piSendFrames(const QList<CANFrame>&);
|
||||
|
||||
private:
|
||||
LFQueue<CANFrame> mQueue;
|
||||
const int mNumBuses;
|
||||
const QString mPort;
|
||||
const CANCon::type mType;
|
||||
bool mIsCapSuspended;
|
||||
QAtomicInt mStatus;
|
||||
bool mStarted;
|
||||
BusData* mBusData_p;
|
||||
QThread* mThread_p;
|
||||
};
|
||||
|
||||
#endif // CANCONNECTION_H
|
||||
@@ -0,0 +1,190 @@
|
||||
#include "canconnectionmodel.h"
|
||||
#include "connections/canconnection.h"
|
||||
#include "connections/canconmanager.h"
|
||||
|
||||
CANConnectionModel::CANConnectionModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
CANConnectionModel::~CANConnectionModel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QVariant CANConnectionModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case 0:
|
||||
return QString(tr("Bus"));
|
||||
break;
|
||||
case 1:
|
||||
return QString(tr("Type"));
|
||||
break;
|
||||
case 2:
|
||||
return QString(tr("Port"));
|
||||
break;
|
||||
case 3:
|
||||
return QString(tr("Speed"));
|
||||
break;
|
||||
case 4:
|
||||
return QString(tr("Listen Only"));
|
||||
break;
|
||||
case 5:
|
||||
return QString(tr("Single Wire"));
|
||||
break;
|
||||
case 6:
|
||||
return QString(tr("Status"));
|
||||
break;
|
||||
case 7:
|
||||
return QString(tr("Active"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
return QString::number(section + 1);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
int CANConnectionModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 7;
|
||||
}
|
||||
|
||||
|
||||
int CANConnectionModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
int rows=0;
|
||||
QList<CANConnection*>& conns = CANConManager::getInstance()->getConnections();
|
||||
|
||||
foreach(const CANConnection* conn_p, conns)
|
||||
rows+=conn_p->getNumBuses();
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
QVariant CANConnectionModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
int busId;
|
||||
CANConnection *conn_p = getAtIdx(index.row(), busId);
|
||||
if(!conn_p)
|
||||
return QVariant();
|
||||
|
||||
CANBus bus;
|
||||
bool ret;
|
||||
ret = conn_p->getBusSettings(busId, bus);
|
||||
if(!ret) return QVariant();
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case 0: //bus
|
||||
//return QString::number(busId);
|
||||
return QString::number(index.row());
|
||||
break;
|
||||
case 1: //type
|
||||
if (conn_p)
|
||||
switch (conn_p->getType()) {
|
||||
case CANCon::KVASER: return "KVASER";
|
||||
case CANCon::SOCKETCAN: return "SocketCAN";
|
||||
case CANCon::GVRET_SERIAL: return "GVRET";
|
||||
default: {}
|
||||
}
|
||||
else qDebug() << "Tried to show connection type but connection was NULL";
|
||||
break;
|
||||
case 2: //port
|
||||
if (conn_p) return conn_p->getPort();
|
||||
else qDebug() << "Tried to show connection port but connection was NULL";
|
||||
break;
|
||||
case 3: //speed
|
||||
return QString::number(bus.speed);
|
||||
case 4: //Listen Only
|
||||
return (bus.listenOnly) ? "True" : "False";
|
||||
case 5: //Single Wire
|
||||
return (bus.singleWire) ? "True" : "False";
|
||||
case 6: //Status
|
||||
return (conn_p->getStatus()==CANCon::CONNECTED) ? "Connected" : "Not Connected";
|
||||
case 7: //Active
|
||||
return (bus.active) ? "True" : "False";
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
void CANConnectionModel::add(CANConnection* pConn_p)
|
||||
{
|
||||
CANConManager* manager = CANConManager::getInstance();
|
||||
|
||||
beginResetModel();
|
||||
manager->add(pConn_p);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
void CANConnectionModel::remove(CANConnection* pConn_p)
|
||||
{
|
||||
CANConManager* manager = CANConManager::getInstance();
|
||||
|
||||
beginResetModel();
|
||||
manager->remove(pConn_p);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
CANConnection* CANConnectionModel::getAtIdx(int pIdx, int& pBusId) const
|
||||
{
|
||||
if (pIdx < 0)
|
||||
return NULL;
|
||||
|
||||
int i=0;
|
||||
QList<CANConnection*>& conns = CANConManager::getInstance()->getConnections();
|
||||
|
||||
foreach(CANConnection* conn_p, conns)
|
||||
{
|
||||
if( i <= pIdx && pIdx < i+conn_p->getNumBuses() ) {
|
||||
pBusId = pIdx - i;
|
||||
return conn_p;
|
||||
}
|
||||
|
||||
i+= conn_p->getNumBuses();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void CANConnectionModel::refresh(int pIndex)
|
||||
{
|
||||
QModelIndex begin;
|
||||
QModelIndex end;
|
||||
|
||||
if(pIndex>=0) {
|
||||
begin = createIndex(pIndex, 0);
|
||||
end = createIndex(pIndex, columnCount()-1);
|
||||
}
|
||||
else {
|
||||
begin = createIndex(0, 0);
|
||||
end = createIndex(rowCount()-1, columnCount()-1);
|
||||
}
|
||||
dataChanged(begin, end, QVector<int>(Qt::DisplayRole));
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef CANCONNECTIONMODEL_H
|
||||
#define CANCONNECTIONMODEL_H
|
||||
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "canbus.h"
|
||||
#include "connections/canconnection.h"
|
||||
#include "connectionwindow.h"
|
||||
|
||||
|
||||
class CANConnectionModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CANConnectionModel(QObject *parent = 0);
|
||||
virtual ~CANConnectionModel();
|
||||
|
||||
// from abstractmodel:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
void add(CANConnection* pConn_p);
|
||||
void remove(CANConnection* pConn_p);
|
||||
|
||||
CANConnection* getAtIdx(int, int&) const;
|
||||
void refresh(int pIndex=-1);
|
||||
};
|
||||
|
||||
#endif // CANCONNECTIONMODEL_H
|
||||
@@ -0,0 +1,512 @@
|
||||
#include <QCanBus>
|
||||
#include <QThread>
|
||||
|
||||
#include "connectionwindow.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui_connectionwindow.h"
|
||||
#include "connections/canconfactory.h"
|
||||
#include "connections/canconmanager.h"
|
||||
#include "canbus.h"
|
||||
|
||||
|
||||
|
||||
ConnectionWindow::ConnectionWindow(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ConnectionWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QSettings settings;
|
||||
|
||||
qRegisterMetaType<CANBus>("CANBus");
|
||||
qRegisterMetaType<const CANFrame *>("const CANFrame *");
|
||||
qRegisterMetaType<const QList<CANFrame> *>("const QList<CANFrame> *");
|
||||
|
||||
|
||||
connModel = new CANConnectionModel(this);
|
||||
ui->tableConnections->setModel(connModel);
|
||||
ui->tableConnections->setColumnWidth(0, 50);
|
||||
ui->tableConnections->setColumnWidth(1, 110);
|
||||
ui->tableConnections->setColumnWidth(2, 110);
|
||||
ui->tableConnections->setColumnWidth(3, 110);
|
||||
ui->tableConnections->setColumnWidth(4, 75);
|
||||
ui->tableConnections->setColumnWidth(5, 75);
|
||||
ui->tableConnections->setColumnWidth(6, 75);
|
||||
ui->tableConnections->setColumnWidth(7, 75);
|
||||
ui->ckSingleWire->setChecked(settings.value("Main/SingleWireMode", false).toBool());
|
||||
|
||||
ui->cbSpeed->addItem(tr("125000"));
|
||||
ui->cbSpeed->addItem(tr("250000"));
|
||||
ui->cbSpeed->addItem(tr("500000"));
|
||||
ui->cbSpeed->addItem(tr("1000000"));
|
||||
ui->cbSpeed->addItem(tr("33333"));
|
||||
|
||||
/* load connection configuration */
|
||||
loadConnections();
|
||||
|
||||
ui->rbSocketCAN->setEnabled(isSocketCanAvailable());
|
||||
#ifdef Q_OS_WIN
|
||||
ui->rbKvaser->setEnabled(true);
|
||||
#endif
|
||||
|
||||
connect(ui->btnOK, &QAbstractButton::clicked, this, &ConnectionWindow::handleOKButton);
|
||||
connect(ui->rbGVRET, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||
connect(ui->rbKvaser, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||
connect(ui->rbSocketCAN, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||
connect(ui->btnRevert, &QPushButton::clicked, this, &ConnectionWindow::handleRevert);
|
||||
connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &ConnectionWindow::currentRowChanged);
|
||||
connect(ui->btnNewConn, &QPushButton::clicked, this, &ConnectionWindow::handleNewConn);
|
||||
connect(ui->btnActivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleEnableAll);
|
||||
connect(ui->btnDeactivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleDisableAll);
|
||||
connect(ui->btnRemoveBus, &QPushButton::clicked, this, &ConnectionWindow::handleRemoveConn);
|
||||
}
|
||||
|
||||
ConnectionWindow::~ConnectionWindow()
|
||||
{
|
||||
QList<CANConnection*>& conns = CANConManager::getInstance()->getConnections();
|
||||
CANConnection* conn_p;
|
||||
|
||||
/* save configuration */
|
||||
saveConnections();
|
||||
|
||||
/* delete connections */
|
||||
while(!conns.isEmpty())
|
||||
{
|
||||
conn_p = conns.takeFirst();
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::showEvent(QShowEvent* event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
qDebug() << "Show connectionwindow";
|
||||
ui->tableConnections->selectRow(0);
|
||||
currentRowChanged(ui->tableConnections->currentIndex(), ui->tableConnections->currentIndex());
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::setSuspendAll(bool pSuspend)
|
||||
{
|
||||
QList<CANConnection*>& conns = CANConManager::getInstance()->getConnections();
|
||||
|
||||
foreach(CANConnection* conn_p, conns)
|
||||
conn_p->suspend(pSuspend);
|
||||
|
||||
connModel->refresh();
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::setActiveAll(bool pActive)
|
||||
{
|
||||
CANBus bus;
|
||||
QList<CANConnection*>& conns = CANConManager::getInstance()->getConnections();
|
||||
|
||||
foreach(CANConnection* conn_p, conns)
|
||||
{
|
||||
for(int i=0 ; i<conn_p->getNumBuses() ; i++) {
|
||||
if( conn_p->getBusSettings(i, bus) ) {
|
||||
bus.active = pActive;
|
||||
conn_p->setBusSettings(i, bus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
connModel->refresh();
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::handleNewConn()
|
||||
{
|
||||
ui->tableConnections->setCurrentIndex(QModelIndex());
|
||||
currentRowChanged(ui->tableConnections->currentIndex(), ui->tableConnections->currentIndex());
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::handleEnableAll()
|
||||
{
|
||||
setActiveAll(true);
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleDisableAll()
|
||||
{
|
||||
setActiveAll(false);
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleConnTypeChanged()
|
||||
{
|
||||
if (ui->rbGVRET->isChecked()) selectSerial();
|
||||
if (ui->rbKvaser->isChecked()) selectKvaser();
|
||||
if (ui->rbSocketCAN->isChecked()) selectSocketCan();
|
||||
}
|
||||
|
||||
|
||||
/* status */
|
||||
void ConnectionWindow::connectionStatus(CANCon::status pStatus)
|
||||
{
|
||||
Q_UNUSED(pStatus);
|
||||
|
||||
qDebug() << "Connectionstatus changed";
|
||||
connModel->refresh();
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::handleOKButton()
|
||||
{
|
||||
int whichRow = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||
|
||||
CANConnection* conn_p = NULL;
|
||||
|
||||
if (whichRow > -1)
|
||||
{
|
||||
/* set information for selected connection */
|
||||
int busId;
|
||||
CANBus bus;
|
||||
bool ret;
|
||||
|
||||
conn_p = connModel->getAtIdx(whichRow, busId);
|
||||
if(!conn_p) return;
|
||||
|
||||
ret = conn_p->getBusSettings(busId, bus);
|
||||
if(!ret) return;
|
||||
|
||||
|
||||
bus.setListenOnly(ui->ckListenOnly->isChecked());
|
||||
bus.setSingleWire(ui->ckSingleWire->isChecked());
|
||||
bus.setEnabled(ui->ckEnabled->isChecked());
|
||||
bus.setSpeed(ui->cbSpeed->currentText().toInt());
|
||||
/* update bus settings */
|
||||
conn_p->setBusSettings(busId, bus);
|
||||
|
||||
connModel->refresh(whichRow);
|
||||
}
|
||||
else if( ! CANConManager::getInstance()->getByName(getPortName()) )
|
||||
{
|
||||
/* create connection */
|
||||
conn_p = create(getConnectionType(), getPortName());
|
||||
if(!conn_p)
|
||||
return;
|
||||
|
||||
for (int i=0 ; i<conn_p->getNumBuses() ; i++) {
|
||||
/* set bus configuration */
|
||||
CANBus bus;
|
||||
bus.active = ui->ckEnabled->isChecked();
|
||||
bus.listenOnly = ui->ckListenOnly->isChecked();
|
||||
bus.singleWire = ui->ckSingleWire->isChecked();
|
||||
|
||||
bus.speed = ui->cbSpeed->currentText().toInt();
|
||||
|
||||
/* update bus settings */
|
||||
conn_p->setBusSettings(i, bus);
|
||||
}
|
||||
|
||||
/* add connection to model */
|
||||
connModel->add(conn_p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
Q_UNUSED(previous);
|
||||
|
||||
int selIdx = current.row();
|
||||
|
||||
/* enable / diable connection type */
|
||||
ui->stPort->setEnabled(selIdx==-1);
|
||||
ui->gbType->setEnabled(selIdx==-1);
|
||||
ui->lPort->setEnabled(selIdx==-1);
|
||||
|
||||
/* set parameters */
|
||||
if (selIdx == -1)
|
||||
{
|
||||
ui->btnOK->setText(tr("Create New Connection"));
|
||||
ui->rbGVRET->setChecked(true);
|
||||
ui->ckListenOnly->setChecked(false);
|
||||
ui->ckSingleWire->setChecked(false);
|
||||
ui->ckEnabled->setChecked(false);
|
||||
setSpeed(0);
|
||||
setPortName(CANCon::GVRET_SERIAL, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
int busId;
|
||||
bool ret;
|
||||
CANBus bus;
|
||||
CANConnection* conn_p = connModel->getAtIdx(selIdx, busId);
|
||||
if(!conn_p) return;
|
||||
ret = conn_p->getBusSettings(busId, bus);
|
||||
if(!ret) return;
|
||||
|
||||
ui->btnOK->setText(tr("Update Connection Settings"));
|
||||
ui->ckListenOnly->setChecked(bus.isListenOnly());
|
||||
ui->ckSingleWire->setChecked(bus.isSingleWire());
|
||||
ui->ckEnabled->setChecked(bus.isActive());
|
||||
setSpeed(bus.getSpeed());
|
||||
setPortName(conn_p->getType(), conn_p->getPort());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::selectSerial()
|
||||
{
|
||||
/* set combobox page visible */
|
||||
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||
ui->cbSpeed->setEnabled(true);
|
||||
|
||||
ui->cbPort->clear();
|
||||
ports = QSerialPortInfo::availablePorts();
|
||||
|
||||
for (int i = 0; i < ports.count(); i++)
|
||||
ui->cbPort->addItem(ports[i].portName());
|
||||
}
|
||||
|
||||
void ConnectionWindow::selectKvaser()
|
||||
{
|
||||
/* set combobox page visible */
|
||||
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||
ui->cbSpeed->setEnabled(false);
|
||||
}
|
||||
|
||||
void ConnectionWindow::selectSocketCan()
|
||||
{
|
||||
/* set edit text page visible */
|
||||
ui->stPort->setCurrentWidget(ui->etPage);
|
||||
}
|
||||
|
||||
void ConnectionWindow::setSpeed(int speed0)
|
||||
{
|
||||
for (int i = 0; i < ui->cbSpeed->count(); i++)
|
||||
{
|
||||
if (ui->cbSpeed->itemText(i).toInt() == speed0)
|
||||
{
|
||||
ui->cbSpeed->setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* add custom speed */
|
||||
ui->cbSpeed->addItem(QString::number(speed0));
|
||||
ui->cbSpeed->setCurrentIndex(ui->cbSpeed->count() - 1);
|
||||
}
|
||||
|
||||
void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName)
|
||||
{
|
||||
switch(pType)
|
||||
{
|
||||
case CANCon::GVRET_SERIAL:
|
||||
ui->rbGVRET->setChecked(true);
|
||||
ui->cbSpeed->setEnabled(true);
|
||||
ui->ckListenOnly->setEnabled(true);
|
||||
ui->ckSingleWire->setEnabled(true);
|
||||
break;
|
||||
case CANCon::KVASER:
|
||||
ui->rbKvaser->setChecked(true);
|
||||
break;
|
||||
case CANCon::SOCKETCAN:
|
||||
ui->rbSocketCAN->setChecked(true);
|
||||
//you can't configure any of the below three with socketcan so dim them out
|
||||
ui->cbSpeed->setEnabled(false);
|
||||
ui->ckListenOnly->setEnabled(false);
|
||||
ui->ckSingleWire->setEnabled(false);
|
||||
break;
|
||||
default: {}
|
||||
}
|
||||
|
||||
/* refresh names whenever needed */
|
||||
handleConnTypeChanged();
|
||||
|
||||
switch(pType)
|
||||
{
|
||||
case CANCon::GVRET_SERIAL:
|
||||
{
|
||||
int idx = ui->cbPort->findText(pPortName);
|
||||
if( idx<0 ) idx=0;
|
||||
ui->cbPort->setCurrentIndex(idx);
|
||||
break;
|
||||
}
|
||||
case CANCon::SOCKETCAN:
|
||||
{
|
||||
ui->lePort->setText(pPortName);
|
||||
break;
|
||||
}
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-1 means leave it at whatever it booted up to. 0 means disable. Otherwise the actual rate we want.
|
||||
int ConnectionWindow::getSpeed()
|
||||
{
|
||||
switch (ui->cbSpeed->currentIndex())
|
||||
{
|
||||
case -1:
|
||||
case 0:
|
||||
return -1;
|
||||
case 1:
|
||||
return 0;
|
||||
default:
|
||||
return (ui->cbSpeed->currentText().toInt());
|
||||
}
|
||||
}
|
||||
|
||||
QString ConnectionWindow::getPortName()
|
||||
{
|
||||
switch( getConnectionType() ) {
|
||||
case CANCon::GVRET_SERIAL:
|
||||
case CANCon::KVASER:
|
||||
return ui->cbPort->currentText();
|
||||
case CANCon::SOCKETCAN:
|
||||
return ui->lePort->text();
|
||||
default:
|
||||
qDebug() << "getPortName: can't get port";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
CANCon::type ConnectionWindow::getConnectionType()
|
||||
{
|
||||
if (ui->rbGVRET->isChecked()) return CANCon::GVRET_SERIAL;
|
||||
if (ui->rbKvaser->isChecked()) return CANCon::KVASER;
|
||||
if (ui->rbSocketCAN->isChecked()) return CANCon::SOCKETCAN;
|
||||
|
||||
qDebug() << "getConnectionType: error";
|
||||
return CANCon::NONE;
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::setSWMode(bool mode)
|
||||
{
|
||||
ui->ckSingleWire->setChecked(mode);
|
||||
}
|
||||
|
||||
bool ConnectionWindow::getSWMode()
|
||||
{
|
||||
if (ui->ckSingleWire->checkState() == Qt::Checked) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleRemoveConn()
|
||||
{
|
||||
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||
if (selIdx <0) return;
|
||||
|
||||
qDebug() << "remove connection at index: " << selIdx;
|
||||
|
||||
int busId;
|
||||
CANConnection* conn_p = connModel->getAtIdx(selIdx, busId);
|
||||
if(!conn_p) return;
|
||||
|
||||
/* remove connection from model & manager */
|
||||
connModel->remove(conn_p);
|
||||
|
||||
/* stop and delete connection */
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
|
||||
/* select first connection in list */
|
||||
ui->tableConnections->selectRow(0);
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleRevert()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool ConnectionWindow::isSocketCanAvailable()
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
foreach (const QByteArray &backend, QCanBus::instance()->plugins()) {
|
||||
if (backend == "socketcan")
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
CANConnection* ConnectionWindow::create(CANCon::type pTye, QString pPortName)
|
||||
{
|
||||
CANConnection* conn_p;
|
||||
|
||||
/* create connection */
|
||||
conn_p = CanConFactory::create(pTye, pPortName);
|
||||
if(conn_p)
|
||||
{
|
||||
/* connect signal */
|
||||
connect(conn_p, SIGNAL(status(CANCon::status)),
|
||||
this, SLOT(connectionStatus(CANCon::status)));
|
||||
|
||||
/*TODO add return value and checks */
|
||||
conn_p->start();
|
||||
}
|
||||
return conn_p;
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::loadConnections()
|
||||
{
|
||||
qRegisterMetaTypeStreamOperators<QVector<QString>>();
|
||||
qRegisterMetaTypeStreamOperators<QVector<int>>();
|
||||
qRegisterMetaTypeStreamOperators<CANBus>();
|
||||
qRegisterMetaTypeStreamOperators<QList<CANBus>>();
|
||||
|
||||
QSettings settings;
|
||||
|
||||
/* fill connection list */
|
||||
QVector<QString> portNames = settings.value("connections/portNames").value<QVector<QString>>();
|
||||
QVector<int> devTypes = settings.value("connections/types").value<QVector<int>>();
|
||||
QList<CANBus> busses = settings.value("connections/busses").value<QList<CANBus>>();
|
||||
|
||||
|
||||
for(int i=0 ; i<portNames.count() ; i++)
|
||||
{
|
||||
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i]);
|
||||
if(conn_p)
|
||||
{
|
||||
for(int j=0 ; j<conn_p->getNumBuses() ; j++)
|
||||
conn_p->setBusSettings(j, busses.takeFirst());
|
||||
}
|
||||
/* add connection to model */
|
||||
connModel->add(conn_p);
|
||||
}
|
||||
|
||||
if (connModel->rowCount() > 0) {
|
||||
ui->tableConnections->selectRow(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionWindow::saveConnections()
|
||||
{
|
||||
QList<CANConnection*>& conns = CANConManager::getInstance()->getConnections();
|
||||
|
||||
QSettings settings;
|
||||
QVector<QString> portNames;
|
||||
QVector<int> devTypes;
|
||||
QList<CANBus> busses;
|
||||
|
||||
/* save connections */
|
||||
foreach(CANConnection* conn_p, conns)
|
||||
{
|
||||
portNames.append(conn_p->getPort());
|
||||
devTypes.append(conn_p->getType());
|
||||
|
||||
for(int i=0 ; i<conn_p->getNumBuses() ; i++)
|
||||
{
|
||||
CANBus bus;
|
||||
conn_p->getBusSettings(i, bus);
|
||||
busses.append(bus);
|
||||
}
|
||||
}
|
||||
|
||||
settings.setValue("connections/portNames", QVariant::fromValue(portNames));
|
||||
settings.setValue("connections/types", QVariant::fromValue(devTypes));
|
||||
settings.setValue("connections/busses", QVariant::fromValue(busses));
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#ifndef CONNECTIONWINDOW_H
|
||||
#define CONNECTIONWINDOW_H
|
||||
|
||||
|
||||
|
||||
#include <QSerialPortInfo>
|
||||
#include <QDialog>
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
#include <QTimer>
|
||||
#include <QItemSelection>
|
||||
#include "canconnectionmodel.h"
|
||||
#include "connections/canconnection.h"
|
||||
|
||||
|
||||
class CANConnectionModel;
|
||||
|
||||
namespace Ui {
|
||||
class ConnectionWindow;
|
||||
}
|
||||
|
||||
|
||||
class ConnectionWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConnectionWindow(QWidget *parent = 0);
|
||||
~ConnectionWindow();
|
||||
void showEvent(QShowEvent *);
|
||||
|
||||
CANCon::type getConnectionType();
|
||||
bool getSWMode();
|
||||
|
||||
signals:
|
||||
void updateBusSettings(CANBus *bus);
|
||||
void updatePortName(QString port);
|
||||
|
||||
public slots:
|
||||
void setSpeed(int speed0);
|
||||
void setSWMode(bool mode);
|
||||
|
||||
void setSuspendAll(bool pSuspend);
|
||||
|
||||
private slots:
|
||||
void handleOKButton();
|
||||
void handleConnTypeChanged();
|
||||
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void handleRemoveConn();
|
||||
void handleEnableAll();
|
||||
void handleDisableAll();
|
||||
void handleRevert();
|
||||
void handleNewConn();
|
||||
void connectionStatus(CANCon::status);
|
||||
|
||||
private:
|
||||
Ui::ConnectionWindow *ui;
|
||||
QList<QSerialPortInfo> ports;
|
||||
QSettings *settings;
|
||||
CANConnectionModel *connModel;
|
||||
|
||||
void selectSerial();
|
||||
void selectKvaser();
|
||||
void selectSocketCan();
|
||||
bool isSocketCanAvailable();
|
||||
int getSpeed();
|
||||
QString getPortName();
|
||||
void setPortName(CANCon::type pType, QString pPortName);
|
||||
|
||||
void setActiveAll(bool pActive);
|
||||
CANConnection* create(CANCon::type pTye, QString pPortName);
|
||||
void loadConnections();
|
||||
void saveConnections();
|
||||
};
|
||||
|
||||
#endif // CONNECTIONWINDOW_H
|
||||
@@ -1,56 +1,190 @@
|
||||
#include "serialworker.h"
|
||||
|
||||
#include <QSerialPort>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QCanBusFrame>
|
||||
#include <QSerialPortInfo>
|
||||
#include <QSettings>
|
||||
|
||||
SerialWorker::SerialWorker(CANFrameModel *model, QObject *parent) : QObject(parent)
|
||||
#include "gvretserial.h"
|
||||
|
||||
GVRetSerial::GVRetSerial(QString portName) :
|
||||
CANConnection(portName, CANCon::GVRET_SERIAL, 2, 4000, true),
|
||||
mTimer(this) /*NB: set this as parent of timer to manage it from working thread */
|
||||
{
|
||||
qDebug() << "GVRetSerial()";
|
||||
|
||||
serial = NULL;
|
||||
rx_state = IDLE;
|
||||
rx_step = 0;
|
||||
buildFrame = new CANFrame;
|
||||
canModel = model;
|
||||
ticker = NULL;
|
||||
framesRapid = 0;
|
||||
capturing = true;
|
||||
gotValidated = true;
|
||||
isAutoRestart = false;
|
||||
targetID = -1;
|
||||
|
||||
txTimestampBasis = QDateTime::currentMSecsSinceEpoch();
|
||||
timeBasis = 0;
|
||||
lastSystemTimeBasis = 0;
|
||||
timeAtGVRETSync = 0;
|
||||
|
||||
readSettings();
|
||||
}
|
||||
|
||||
SerialWorker::~SerialWorker()
|
||||
{
|
||||
if (serial != NULL)
|
||||
{
|
||||
if (serial->isOpen())
|
||||
{
|
||||
serial->clear();
|
||||
serial->close();
|
||||
|
||||
}
|
||||
serial->disconnect(); //disconnect all signals
|
||||
delete serial;
|
||||
}
|
||||
if (ticker != NULL) ticker->stop();
|
||||
GVRetSerial::~GVRetSerial()
|
||||
{
|
||||
stop();
|
||||
qDebug() << "~GVRetSerial()";
|
||||
}
|
||||
|
||||
void SerialWorker::run()
|
||||
{
|
||||
ticker = new QTimer;
|
||||
connect(ticker, SIGNAL(timeout()), this, SLOT(handleTick()));
|
||||
|
||||
ticker->setInterval(250); //tick four times per second
|
||||
ticker->setSingleShot(false); //keep ticking
|
||||
ticker->start();
|
||||
void GVRetSerial::piStarted()
|
||||
{
|
||||
connectDevice();
|
||||
|
||||
/* start timer */
|
||||
connect(&mTimer, SIGNAL(timeout()), this, SLOT(handleTick()));
|
||||
mTimer.setInterval(250); //tick four times per second
|
||||
mTimer.setSingleShot(false); //keep ticking
|
||||
mTimer.start();
|
||||
}
|
||||
|
||||
void SerialWorker::readSettings()
|
||||
|
||||
void GVRetSerial::piSuspend(bool pSuspend)
|
||||
{
|
||||
/* update capSuspended */
|
||||
setCapSuspended(pSuspend);
|
||||
|
||||
/* flush queue if we are suspended */
|
||||
if(isCapSuspended())
|
||||
getQueue().flush();
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::piStop()
|
||||
{
|
||||
mTimer.stop();
|
||||
disconnectDevice();
|
||||
}
|
||||
|
||||
|
||||
bool GVRetSerial::piGetBusSettings(int pBusIdx, CANBus& pBus)
|
||||
{
|
||||
return getBusConfig(pBusIdx, pBus);
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::piSetBusSettings(int pBusIdx, CANBus bus)
|
||||
{
|
||||
/* sanity checks */
|
||||
if( (pBusIdx < 0) || pBusIdx >= getNumBuses())
|
||||
return;
|
||||
|
||||
/* copy bus config */
|
||||
setBusConfig(pBusIdx, bus);
|
||||
|
||||
qDebug() << "About to update bus " << pBusIdx << " on GVRET";
|
||||
if (pBusIdx == 0)
|
||||
{
|
||||
can0Baud = bus.getSpeed();
|
||||
can0Baud |= 0x80000000;
|
||||
if (bus.isActive())
|
||||
{
|
||||
can0Baud |= 0x40000000;
|
||||
can0Enabled = true;
|
||||
}
|
||||
else can0Enabled = false;
|
||||
|
||||
if (bus.isListenOnly())
|
||||
{
|
||||
can0Baud |= 0x20000000;
|
||||
can0ListenOnly = true;
|
||||
}
|
||||
else can0ListenOnly = false;
|
||||
}
|
||||
else if (pBusIdx == 1)
|
||||
{
|
||||
can1Baud = bus.getSpeed();
|
||||
can1Baud |= 0x80000000;
|
||||
if (bus.isActive())
|
||||
{
|
||||
can1Baud |= 0x40000000;
|
||||
can1Enabled = true;
|
||||
}
|
||||
else can1Enabled = false;
|
||||
|
||||
if (bus.isListenOnly())
|
||||
{
|
||||
can1Baud |= 0x20000000;
|
||||
can1ListenOnly = true;
|
||||
}
|
||||
else can1ListenOnly = false;
|
||||
|
||||
if (bus.isSingleWire())
|
||||
{
|
||||
can1Baud |= 0x10000000;
|
||||
deviceSingleWireMode = 1;
|
||||
}
|
||||
else deviceSingleWireMode = 0;
|
||||
}
|
||||
|
||||
/* update baud rates */
|
||||
QByteArray buffer;
|
||||
qDebug() << "Got signal to update bauds. 1: " << can0Baud <<" 2: " << can1Baud;
|
||||
buffer[0] = (char)0xF1; //start of a command over serial
|
||||
buffer[1] = 5; //setup canbus
|
||||
buffer[2] = (unsigned char)(can0Baud & 0xFF); //four bytes of ID LSB first
|
||||
buffer[3] = (unsigned char)(can0Baud >> 8);
|
||||
buffer[4] = (unsigned char)(can0Baud >> 16);
|
||||
buffer[5] = (unsigned char)(can0Baud >> 24);
|
||||
buffer[6] = (unsigned char)(can1Baud & 0xFF); //four bytes of ID LSB first
|
||||
buffer[7] = (unsigned char)(can1Baud >> 8);
|
||||
buffer[8] = (unsigned char)(can1Baud >> 16);
|
||||
buffer[9] = (unsigned char)(can1Baud >> 24);
|
||||
buffer[10] = 0;
|
||||
if (serial == NULL) return;
|
||||
if (!serial->isOpen()) return;
|
||||
serial->write(buffer);
|
||||
}
|
||||
|
||||
|
||||
bool GVRetSerial::piSendFrame(const CANFrame& frame)
|
||||
{
|
||||
QByteArray buffer;
|
||||
unsigned int c;
|
||||
int ID;
|
||||
|
||||
//qDebug() << "Sending out GVRET frame with id " << frame.ID << " on bus " << frame.bus;
|
||||
|
||||
framesRapid++;
|
||||
|
||||
if (serial == NULL) return false;
|
||||
if (!serial->isOpen()) return false;
|
||||
//if (!isConnected) return false;
|
||||
|
||||
ID = frame.ID;
|
||||
if (frame.extended) ID |= 1 << 31;
|
||||
|
||||
buffer[0] = (char)0xF1; //start of a command over serial
|
||||
buffer[1] = 0; //command ID for sending a CANBUS frame
|
||||
buffer[2] = (unsigned char)(ID & 0xFF); //four bytes of ID LSB first
|
||||
buffer[3] = (unsigned char)(ID >> 8);
|
||||
buffer[4] = (unsigned char)(ID >> 16);
|
||||
buffer[5] = (unsigned char)(ID >> 24);
|
||||
buffer[6] = (unsigned char)((frame.bus) & 1);
|
||||
buffer[7] = (unsigned char)frame.len;
|
||||
for (c = 0; c < frame.len; c++)
|
||||
{
|
||||
buffer[8 + c] = frame.data[c];
|
||||
}
|
||||
buffer[8 + frame.len] = 0;
|
||||
|
||||
//qDebug() << "writing " << buffer.length() << " bytes to serial port";
|
||||
serial->write(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
void GVRetSerial::readSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
@@ -59,30 +193,25 @@ void SerialWorker::readSettings()
|
||||
doValidation = true;
|
||||
}
|
||||
else doValidation = false;
|
||||
//doValidation=false;
|
||||
}
|
||||
|
||||
void SerialWorker::setSerialPort(QSerialPortInfo *port)
|
||||
|
||||
void GVRetSerial::connectDevice()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
currentPort = port;
|
||||
/* disconnect device */
|
||||
if(serial)
|
||||
disconnectDevice();
|
||||
|
||||
if (serial != NULL)
|
||||
{
|
||||
if (serial->isOpen())
|
||||
{
|
||||
serial->clear();
|
||||
serial->close();
|
||||
}
|
||||
serial->disconnect(); //disconnect all signals
|
||||
delete serial;
|
||||
/* open new device */
|
||||
serial = new QSerialPort(QSerialPortInfo(getPort()));
|
||||
if(!serial) {
|
||||
qDebug() << "can't open serial port " << getPort();
|
||||
return;
|
||||
}
|
||||
|
||||
serial = new QSerialPort(*port);
|
||||
|
||||
qDebug() << "Serial port name is " << port->portName();
|
||||
//serial->setBaudRate(10000000); //more speed! probably does nothing for USB serial
|
||||
/* configure */
|
||||
serial->setDataBits(serial->Data8);
|
||||
serial->setFlowControl(serial->HardwareControl); //this is important though
|
||||
if (!serial->open(QIODevice::ReadWrite))
|
||||
@@ -91,6 +220,8 @@ void SerialWorker::setSerialPort(QSerialPortInfo *port)
|
||||
}
|
||||
serial->setDataTerminalReady(true); //you do need to set these or the fan gets dirty
|
||||
serial->setRequestToSend(true);
|
||||
|
||||
|
||||
QByteArray output;
|
||||
output.append((char)0xE7); //this puts the device into binary comm mode
|
||||
output.append((char)0xE7);
|
||||
@@ -101,7 +232,7 @@ void SerialWorker::setSerialPort(QSerialPortInfo *port)
|
||||
output.append((char)0xF1); //another command to the GVRET
|
||||
output.append((char)0x07); //request device information
|
||||
|
||||
output.append((char)0xF1);
|
||||
/*output.append((char)0xF1);
|
||||
output.append((char)0x08); //setting singlewire mode
|
||||
if (settings.value("Main/SingleWireMode", false).toBool())
|
||||
{
|
||||
@@ -110,7 +241,7 @@ void SerialWorker::setSerialPort(QSerialPortInfo *port)
|
||||
else
|
||||
{
|
||||
output.append((char)0xFF); //signal we don't want single wire mode
|
||||
}
|
||||
}*/
|
||||
|
||||
output.append((char)0xF1); //yet another command
|
||||
output.append((char)0x09); //comm validation command
|
||||
@@ -121,26 +252,51 @@ void SerialWorker::setSerialPort(QSerialPortInfo *port)
|
||||
continuousTimeSync = true;
|
||||
|
||||
serial->write(output);
|
||||
if (doValidation) connected = false;
|
||||
else connected = true;
|
||||
|
||||
if(doValidation) {
|
||||
QTimer::singleShot(1000, this, SLOT(connectionTimeout()));
|
||||
}
|
||||
else {
|
||||
setStatus(CANCon::CONNECTED);
|
||||
emit status(getStatus());
|
||||
}
|
||||
|
||||
/* connect reading event */
|
||||
connect(serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
||||
if (doValidation) QTimer::singleShot(1000, this, SLOT(connectionTimeout()));
|
||||
}
|
||||
|
||||
void SerialWorker::connectionTimeout()
|
||||
{
|
||||
//one second after trying to connect are we actually connected?
|
||||
if (!connected) //no?
|
||||
|
||||
void GVRetSerial::disconnectDevice() {
|
||||
if (serial != NULL)
|
||||
{
|
||||
//then emit the the failure signal and see if anyone cares
|
||||
qDebug() << "Failed to connect to GVRET at that com port";
|
||||
//ticker->stop();
|
||||
closeSerialPort(); //make sure it's properly closed anyway
|
||||
emit connectionFailure();
|
||||
if (serial->isOpen())
|
||||
{
|
||||
serial->clear();
|
||||
serial->close();
|
||||
|
||||
}
|
||||
serial->disconnect(); //disconnect all signals
|
||||
delete serial;
|
||||
serial = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SerialWorker::readSerialData()
|
||||
|
||||
void GVRetSerial::connectionTimeout()
|
||||
{
|
||||
//one second after trying to connect are we actually connected?
|
||||
//if (CANCon::NOT_CONNECTED==getStatus()) //no?
|
||||
if (!gotValidated)
|
||||
{
|
||||
//then emit the the failure signal and see if anyone cares
|
||||
qDebug() << "Failed to connect to GVRET at that com port";
|
||||
|
||||
disconnectDevice();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::readSerialData()
|
||||
{
|
||||
QByteArray data = serial->readAll();
|
||||
unsigned char c;
|
||||
@@ -148,86 +304,13 @@ void SerialWorker::readSerialData()
|
||||
for (int i = 0; i < data.length(); i++)
|
||||
{
|
||||
c = data.at(i);
|
||||
//qDebug() << c << " " << QString::number(c, 16) << " " << QString(c);
|
||||
procRXChar(c);
|
||||
}
|
||||
if (framesRapid > 0)
|
||||
{
|
||||
emit frameUpdateRapid(framesRapid);
|
||||
framesRapid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SerialWorker::sendFrame(const CANFrame *frame, int bus = 0)
|
||||
{
|
||||
QByteArray buffer;
|
||||
int c;
|
||||
int ID;
|
||||
CANFrame tempFrame = *frame;
|
||||
tempFrame.isReceived = false;
|
||||
tempFrame.timestamp = ((QDateTime::currentMSecsSinceEpoch() - txTimestampBasis) * 1000);
|
||||
|
||||
//qDebug() << "Sending out frame with id " << frame->ID;
|
||||
|
||||
//show our sent frames in the list too. This happens even if we're not connected.
|
||||
canModel->addFrame(tempFrame, false);
|
||||
framesRapid++;
|
||||
|
||||
if (serial == NULL) return;
|
||||
if (!serial->isOpen()) return;
|
||||
if (!connected) return;
|
||||
|
||||
ID = frame->ID;
|
||||
if (frame->extended) ID |= 1 << 31;
|
||||
|
||||
buffer[0] = (char)0xF1; //start of a command over serial
|
||||
buffer[1] = 0; //command ID for sending a CANBUS frame
|
||||
buffer[2] = (unsigned char)(ID & 0xFF); //four bytes of ID LSB first
|
||||
buffer[3] = (unsigned char)(ID >> 8);
|
||||
buffer[4] = (unsigned char)(ID >> 16);
|
||||
buffer[5] = (unsigned char)(ID >> 24);
|
||||
buffer[6] = (unsigned char)(bus & 1);
|
||||
buffer[7] = (unsigned char)frame->len;
|
||||
for (c = 0; c < frame->len; c++)
|
||||
{
|
||||
buffer[8 + c] = frame->data[c];
|
||||
}
|
||||
buffer[8 + frame->len] = 0;
|
||||
|
||||
//qDebug() << "writing " << buffer.length() << " bytes to serial port";
|
||||
serial->write(buffer);
|
||||
}
|
||||
|
||||
//a simple way for another thread to pass us a bunch of frames to send.
|
||||
//Don't get carried away here. The GVRET firmware only has finite
|
||||
//buffers and besides, the other end will get buried in traffic.
|
||||
void SerialWorker::sendFrameBatch(const QList<CANFrame> *frames)
|
||||
{
|
||||
sendBulkMutex.lock();
|
||||
for (int i = 0; i < frames->length(); i++) sendFrame(&frames->at(i), frames->at(i).bus);
|
||||
sendBulkMutex.unlock();
|
||||
}
|
||||
|
||||
void SerialWorker::updateBaudRates(int Speed1, int Speed2)
|
||||
{
|
||||
QByteArray buffer;
|
||||
qDebug() << "Got signal to update bauds. 1: " << Speed1 <<" 2: " << Speed2;
|
||||
buffer[0] = (char)0xF1; //start of a command over serial
|
||||
buffer[1] = 5; //setup canbus
|
||||
buffer[2] = (unsigned char)(Speed1 & 0xFF); //four bytes of ID LSB first
|
||||
buffer[3] = (unsigned char)(Speed1 >> 8);
|
||||
buffer[4] = (unsigned char)(Speed1 >> 16);
|
||||
buffer[5] = (unsigned char)(Speed1 >> 24);
|
||||
buffer[6] = (unsigned char)(Speed2 & 0xFF); //four bytes of ID LSB first
|
||||
buffer[7] = (unsigned char)(Speed2 >> 8);
|
||||
buffer[8] = (unsigned char)(Speed2 >> 16);
|
||||
buffer[9] = (unsigned char)(Speed2 >> 24);
|
||||
buffer[10] = 0;
|
||||
if (serial == NULL) return;
|
||||
if (!serial->isOpen()) return;
|
||||
serial->write(buffer);
|
||||
}
|
||||
|
||||
void SerialWorker::procRXChar(unsigned char c)
|
||||
void GVRetSerial::procRXChar(unsigned char c)
|
||||
{
|
||||
switch (rx_state)
|
||||
{
|
||||
@@ -277,58 +360,70 @@ void SerialWorker::procRXChar(unsigned char c)
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
buildFrame->timestamp = c;
|
||||
buildFrame.timestamp = c;
|
||||
break;
|
||||
case 1:
|
||||
buildFrame->timestamp |= (uint)(c << 8);
|
||||
buildFrame.timestamp |= (uint)(c << 8);
|
||||
break;
|
||||
case 2:
|
||||
buildFrame->timestamp |= (uint)c << 16;
|
||||
buildFrame.timestamp |= (uint)c << 16;
|
||||
break;
|
||||
case 3:
|
||||
buildFrame->timestamp |= (uint)c << 24;
|
||||
buildFrame.timestamp |= (uint)c << 24;
|
||||
|
||||
buildFrame.timestamp += timeBasis;
|
||||
break;
|
||||
case 4:
|
||||
buildFrame->ID = c;
|
||||
buildFrame.ID = c;
|
||||
break;
|
||||
case 5:
|
||||
buildFrame->ID |= c << 8;
|
||||
buildFrame.ID |= c << 8;
|
||||
break;
|
||||
case 6:
|
||||
buildFrame->ID |= c << 16;
|
||||
buildFrame.ID |= c << 16;
|
||||
break;
|
||||
case 7:
|
||||
buildFrame->ID |= c << 24;
|
||||
if ((buildFrame->ID & 1 << 31) == 1 << 31)
|
||||
buildFrame.ID |= c << 24;
|
||||
if ((buildFrame.ID & 1 << 31) == 1u << 31)
|
||||
{
|
||||
buildFrame->ID &= 0x7FFFFFFF;
|
||||
buildFrame->extended = true;
|
||||
buildFrame.ID &= 0x7FFFFFFF;
|
||||
buildFrame.extended = true;
|
||||
}
|
||||
else buildFrame->extended = false;
|
||||
else buildFrame.extended = false;
|
||||
break;
|
||||
case 8:
|
||||
buildFrame->len = c & 0xF;
|
||||
if (buildFrame->len > 8) buildFrame->len = 8;
|
||||
buildFrame->bus = (c & 0xF0) >> 4;
|
||||
buildFrame.len = c & 0xF;
|
||||
if (buildFrame.len > 8) buildFrame.len = 8;
|
||||
buildFrame.bus = (c & 0xF0) >> 4;
|
||||
break;
|
||||
default:
|
||||
if (rx_step < buildFrame->len + 9)
|
||||
if (rx_step < buildFrame.len + 9)
|
||||
{
|
||||
buildFrame->data[rx_step - 9] = c;
|
||||
buildFrame.data[rx_step - 9] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
rx_state = IDLE;
|
||||
rx_step = 0;
|
||||
//qDebug() << "emit from serial handler to main form id: " << buildFrame->ID;
|
||||
if (capturing)
|
||||
buildFrame.isReceived = true;
|
||||
|
||||
if (!isCapSuspended())
|
||||
{
|
||||
buildFrame->isReceived = true;
|
||||
canModel->addFrame(*buildFrame, false);
|
||||
/* get frame from queue */
|
||||
CANFrame* frame_p = getQueue().get();
|
||||
if(frame_p) {
|
||||
//qDebug() << "GVRET got frame on bus " << frame_p->bus;
|
||||
/* copy frame */
|
||||
*frame_p = buildFrame;
|
||||
checkTargettedFrame(buildFrame);
|
||||
/* enqueue frame */
|
||||
getQueue().queue();
|
||||
}
|
||||
else
|
||||
qDebug() << "can't get a frame, ERROR";
|
||||
|
||||
//take the time the frame came in and try to resync the time base.
|
||||
if (continuousTimeSync) txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - (buildFrame->timestamp / 1000);
|
||||
framesRapid++;
|
||||
if (buildFrame->ID == targetID) emit gotTargettedFrame(canModel->rowCount() - 1);
|
||||
//if (continuousTimeSync) txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - (buildFrame.timestamp / 1000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -350,7 +445,10 @@ void SerialWorker::procRXChar(unsigned char c)
|
||||
case 3:
|
||||
buildTimeBasis += ((uint32_t)c << 24);
|
||||
qDebug() << "GVRET firmware reports timestamp of " << buildTimeBasis;
|
||||
txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - ((uint64_t)buildTimeBasis / (uint64_t)1000ull);
|
||||
timeAtGVRETSync = QDateTime::currentMSecsSinceEpoch() * 1000;
|
||||
|
||||
rebuildLocalTimeBasis();
|
||||
|
||||
continuousTimeSync = false;
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
@@ -381,7 +479,8 @@ void SerialWorker::procRXChar(unsigned char c)
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
can0Enabled = c;
|
||||
can0Enabled = (c & 0xF);
|
||||
can0ListenOnly = (c >> 4);
|
||||
break;
|
||||
case 1:
|
||||
can0Baud = c;
|
||||
@@ -396,7 +495,9 @@ void SerialWorker::procRXChar(unsigned char c)
|
||||
can0Baud |= c << 24;
|
||||
break;
|
||||
case 5:
|
||||
can1Enabled = c;
|
||||
can1Enabled = (c & 0xF);
|
||||
can1ListenOnly = (c >> 4);
|
||||
deviceSingleWireMode = (c >> 6);
|
||||
break;
|
||||
case 6:
|
||||
can1Baud = c;
|
||||
@@ -412,10 +513,28 @@ void SerialWorker::procRXChar(unsigned char c)
|
||||
rx_state = IDLE;
|
||||
qDebug() << "Baud 0 = " << can0Baud;
|
||||
qDebug() << "Baud 1 = " << can1Baud;
|
||||
if (!can1Enabled) can1Baud = 0;
|
||||
if (!can0Enabled) can0Baud = 0;
|
||||
connected = true;
|
||||
emit connectionSuccess(can0Baud, can1Baud);
|
||||
|
||||
can0Baud |= 0x80000000;
|
||||
if (can0Enabled) can0Baud |= 0x40000000;
|
||||
if (can0ListenOnly) can0Baud |= 0x20000000;
|
||||
|
||||
can1Baud |= 0x80000000;
|
||||
if (can1Enabled) can1Baud |= 0x40000000;
|
||||
if (can1ListenOnly) can1Baud |= 0x20000000;
|
||||
if (deviceSingleWireMode > 0) can1Baud |= 0x10000000;
|
||||
|
||||
setStatus(CANCon::CONNECTED);
|
||||
emit status(getStatus());
|
||||
|
||||
int can0Status = 0x78; //updating everything we can update
|
||||
int can1Status = 0x78;
|
||||
if (can0Enabled) can0Status +=1;
|
||||
if (can0ListenOnly) can0Status += 4;
|
||||
if (can1Enabled) can1Status += 1;
|
||||
if (deviceSingleWireMode > 0) can1Status += 2;
|
||||
if (can1ListenOnly) can1Status += 4;
|
||||
//emit busStatus(busBase, can0Baud & 0xFFFFF, can0Status);
|
||||
//emit busStatus(busBase + 1, can1Baud & 0xFFFFF, can1Status);
|
||||
break;
|
||||
}
|
||||
rx_step++;
|
||||
@@ -458,11 +577,29 @@ void SerialWorker::procRXChar(unsigned char c)
|
||||
}
|
||||
}
|
||||
|
||||
void SerialWorker::handleTick()
|
||||
void GVRetSerial::rebuildLocalTimeBasis()
|
||||
{
|
||||
//qDebug() << "Tick!";
|
||||
qDebug() << "Rebuilding GVRET time base. GVRET local base = " << buildTimeBasis;
|
||||
|
||||
if (connected)
|
||||
/*
|
||||
our time basis is the value we have to modulate the main system basis by in order
|
||||
to sync the GVRET timestamps to the rest of the system.
|
||||
The rest of the system uses CANConManager::getInstance()->getTimeBasis as the basis.
|
||||
GVRET returns to us the current time since boot up in microseconds.
|
||||
timeAtGVRETSync stores the "system" timestamp when the GVRET timestamp was retrieved.
|
||||
*/
|
||||
lastSystemTimeBasis = CANConManager::getInstance()->getTimeBasis();
|
||||
int64_t systemDelta = timeAtGVRETSync - lastSystemTimeBasis;
|
||||
int32_t localDelta = buildTimeBasis - systemDelta;
|
||||
timeBasis = -localDelta;
|
||||
}
|
||||
|
||||
void GVRetSerial::handleTick()
|
||||
{
|
||||
if (lastSystemTimeBasis != CANConManager::getInstance()->getTimeBasis()) rebuildLocalTimeBasis();
|
||||
//qDebug() << "Tick!";
|
||||
/*
|
||||
if( CANCon::CONNECTED == getStatus() )
|
||||
{
|
||||
if (!gotValidated && doValidation)
|
||||
{
|
||||
@@ -470,24 +607,23 @@ void SerialWorker::handleTick()
|
||||
if (serial->isOpen()) //if it's still false we have a problem...
|
||||
{
|
||||
qDebug() << "Comm validation failed. ";
|
||||
closeSerialPort(); //start by stopping everything.
|
||||
|
||||
setStatus(CANCon::NOT_CONNECTED);
|
||||
emit status(getStatus());
|
||||
|
||||
disconnectDevice(); //start by stopping everything.
|
||||
//Then wait 500ms and restart the connection automatically
|
||||
QTimer::singleShot(500, this, SLOT(handleReconnect()));
|
||||
QTimer::singleShot(500, this, SLOT(connectDevice()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
if (doValidation && serial && serial->isOpen()) sendCommValidation();
|
||||
}
|
||||
|
||||
void SerialWorker::handleReconnect()
|
||||
{
|
||||
qDebug() << "Automatically reopening the connection";
|
||||
setSerialPort(currentPort); //then go back through the re-init
|
||||
}
|
||||
|
||||
void SerialWorker::sendCommValidation()
|
||||
void GVRetSerial::sendCommValidation()
|
||||
{
|
||||
QByteArray output;
|
||||
|
||||
@@ -501,35 +637,5 @@ void SerialWorker::sendCommValidation()
|
||||
serial->write(output);
|
||||
}
|
||||
|
||||
//totally shuts down the whole thing
|
||||
void SerialWorker::closeSerialPort()
|
||||
{
|
||||
if (serial == NULL) return;
|
||||
if (serial->isOpen())
|
||||
{
|
||||
serial->clear();
|
||||
serial->close();
|
||||
}
|
||||
serial->disconnect();
|
||||
//do not stop the ticker here. It always stays running now.
|
||||
//ticker->stop();
|
||||
delete serial;
|
||||
serial = NULL;
|
||||
}
|
||||
|
||||
void SerialWorker::stopFrameCapture()
|
||||
{
|
||||
qDebug() << "Stopping frame capture";
|
||||
capturing = false;
|
||||
}
|
||||
|
||||
void SerialWorker::startFrameCapture()
|
||||
{
|
||||
qDebug() << "Starting up frame capture";
|
||||
capturing = true;
|
||||
}
|
||||
|
||||
void SerialWorker::targetFrameID(int target)
|
||||
{
|
||||
targetID = target;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef GVRETSERIAL_H
|
||||
#define GVRETSERIAL_H
|
||||
|
||||
#include <QSerialPort>
|
||||
#include <QCanBusDevice>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
/*************/
|
||||
#include <QDateTime>
|
||||
/*************/
|
||||
|
||||
#include "canframemodel.h"
|
||||
#include "canconnection.h"
|
||||
#include "canconmanager.h"
|
||||
|
||||
namespace SERIALSTATE {
|
||||
|
||||
enum STATE //keep this enum synchronized with the Arduino firmware project
|
||||
{
|
||||
IDLE,
|
||||
GET_COMMAND,
|
||||
BUILD_CAN_FRAME,
|
||||
TIME_SYNC,
|
||||
GET_DIG_INPUTS,
|
||||
GET_ANALOG_INPUTS,
|
||||
SET_DIG_OUTPUTS,
|
||||
SETUP_CANBUS,
|
||||
GET_CANBUS_PARAMS,
|
||||
GET_DEVICE_INFO,
|
||||
SET_SINGLEWIRE_MODE
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
using namespace SERIALSTATE;
|
||||
class GVRetSerial : public CANConnection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GVRetSerial(QString portName);
|
||||
virtual ~GVRetSerial();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void piStarted();
|
||||
virtual void piStop();
|
||||
virtual void piSetBusSettings(int pBusIdx, CANBus pBus);
|
||||
virtual bool piGetBusSettings(int pBusIdx, CANBus& pBus);
|
||||
virtual void piSuspend(bool pSuspend);
|
||||
virtual bool piSendFrame(const CANFrame&) ;
|
||||
|
||||
void disconnectDevice();
|
||||
|
||||
private slots:
|
||||
void connectDevice();
|
||||
void connectionTimeout();
|
||||
void readSerialData();
|
||||
void handleTick();
|
||||
|
||||
private:
|
||||
void readSettings();
|
||||
void procRXChar(unsigned char);
|
||||
void sendCommValidation();
|
||||
void rebuildLocalTimeBasis();
|
||||
|
||||
protected:
|
||||
QTimer mTimer;
|
||||
QThread mThread;
|
||||
|
||||
bool doValidation;
|
||||
bool gotValidated;
|
||||
bool isAutoRestart;
|
||||
bool continuousTimeSync;
|
||||
QSerialPort *serial;
|
||||
int framesRapid;
|
||||
STATE rx_state;
|
||||
uint32_t rx_step;
|
||||
CANFrame buildFrame;
|
||||
int can0Baud, can1Baud;
|
||||
bool can0Enabled, can1Enabled;
|
||||
bool can0ListenOnly, can1ListenOnly;
|
||||
int deviceBuildNum;
|
||||
int deviceSingleWireMode;
|
||||
uint32_t buildTimeBasis;
|
||||
int32_t timeBasis;
|
||||
uint64_t lastSystemTimeBasis;
|
||||
uint64_t timeAtGVRETSync;
|
||||
};
|
||||
|
||||
#endif // GVRETSERIAL_H
|
||||
@@ -0,0 +1,240 @@
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QCanBusFrame>
|
||||
|
||||
#include "socketcan.h"
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/**** class definition ****/
|
||||
/***********************************/
|
||||
|
||||
SocketCan::SocketCan(QString portName) :
|
||||
CANConnection(portName, CANCon::SOCKETCAN, 1, 4000, true),
|
||||
mDev_p(NULL),
|
||||
mTimer(this) /*NB: set connection as parent of timer to manage it from working thread */
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SocketCan::~SocketCan()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piStarted()
|
||||
{
|
||||
connect(&mTimer, SIGNAL(timeout()), this, SLOT(testConnection()));
|
||||
mTimer.setInterval(1000);
|
||||
mTimer.setSingleShot(false); //keep ticking
|
||||
mTimer.start();
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piSuspend(bool pSuspend)
|
||||
{
|
||||
/* update capSuspended */
|
||||
setCapSuspended(pSuspend);
|
||||
|
||||
/* flush queue if we are suspended */
|
||||
if(isCapSuspended())
|
||||
getQueue().flush();
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piStop() {
|
||||
mTimer.stop();
|
||||
disconnectDevice();
|
||||
}
|
||||
|
||||
|
||||
bool SocketCan::piGetBusSettings(int pBusIdx, CANBus& pBus)
|
||||
{
|
||||
return getBusConfig(pBusIdx, pBus);
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piSetBusSettings(int pBusIdx, CANBus bus)
|
||||
{
|
||||
/* sanity checks */
|
||||
if(0 != pBusIdx)
|
||||
return;
|
||||
|
||||
/* disconnect device if we have one connected */
|
||||
if(mDev_p)
|
||||
disconnectDevice();
|
||||
|
||||
/* copy bus config */
|
||||
setBusConfig(0, bus);
|
||||
|
||||
/* if bus is not active we are done */
|
||||
if(!bus.active)
|
||||
return;
|
||||
|
||||
/* create device */
|
||||
mDev_p = QCanBus::instance()->createDevice("socketcan", getPort());
|
||||
if (!mDev_p) {
|
||||
disconnectDevice();
|
||||
qDebug() << "can't create device";
|
||||
return;
|
||||
}
|
||||
|
||||
/* connect slots */
|
||||
connect(mDev_p, &QCanBusDevice::errorOccurred, this, &SocketCan::errorReceived);
|
||||
connect(mDev_p, &QCanBusDevice::framesWritten, this, &SocketCan::framesWritten);
|
||||
connect(mDev_p, &QCanBusDevice::framesReceived, this, &SocketCan::framesReceived);
|
||||
|
||||
/* set configuration */
|
||||
/*if (p.useConfigurationEnabled) {
|
||||
foreach (const SettingsDialog::ConfigurationItem &item, p.configurations)
|
||||
mDev->setConfigurationParameter(item.first, item.second);
|
||||
}*/
|
||||
|
||||
//You cannot set the speed of a socketcan interface, it has to be set with console commands.
|
||||
//mDev_p->setConfigurationParameter(QCanBusDevice::BitRateKey, bus.speed);
|
||||
|
||||
/* connect device */
|
||||
if (!mDev_p->connectDevice()) {
|
||||
disconnectDevice();
|
||||
qDebug() << "can't connect device";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SocketCan::piSendFrame(const CANFrame& pFrame)
|
||||
{
|
||||
/* sanity checks */
|
||||
if(0 != pFrame.bus || pFrame.len>8)
|
||||
return false;
|
||||
|
||||
/* fill frame */
|
||||
QCanBusFrame frame;
|
||||
frame.setFrameId(pFrame.ID);
|
||||
frame.setExtendedFrameFormat(false);
|
||||
frame.setPayload(QByteArray((const char*)pFrame.data, pFrame.len));
|
||||
|
||||
return mDev_p->writeFrame(frame);
|
||||
}
|
||||
|
||||
|
||||
/***********************************/
|
||||
/**** private methods ****/
|
||||
/***********************************/
|
||||
|
||||
|
||||
/* disconnect device */
|
||||
void SocketCan::disconnectDevice() {
|
||||
if(mDev_p) {
|
||||
mDev_p->disconnectDevice();
|
||||
delete mDev_p;
|
||||
mDev_p = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::errorReceived(QCanBusDevice::CanBusError error) const
|
||||
{
|
||||
switch (error) {
|
||||
case QCanBusDevice::ReadError:
|
||||
case QCanBusDevice::WriteError:
|
||||
case QCanBusDevice::ConnectionError:
|
||||
case QCanBusDevice::ConfigurationError:
|
||||
case QCanBusDevice::UnknownError:
|
||||
qWarning() << mDev_p->errorString();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SocketCan::framesWritten(qint64 count)
|
||||
{
|
||||
Q_UNUSED(count);
|
||||
//qDebug() << "Number of frames written:" << count;
|
||||
}
|
||||
|
||||
void SocketCan::framesReceived()
|
||||
{
|
||||
uint64_t timeBasis = CANConManager::getInstance()->getTimeBasis();
|
||||
|
||||
/* sanity checks */
|
||||
if(!mDev_p)
|
||||
return;
|
||||
|
||||
/* read frame */
|
||||
while(true)
|
||||
{
|
||||
const QCanBusFrame recFrame = mDev_p->readFrame();
|
||||
|
||||
/* exit case */
|
||||
if(!recFrame.isValid())
|
||||
break;
|
||||
|
||||
/* drop frame if capture is suspended */
|
||||
if(isCapSuspended())
|
||||
continue;
|
||||
|
||||
/* check frame */
|
||||
if( !recFrame.payload().isEmpty() &&
|
||||
recFrame.payload().length()<=8 )
|
||||
{
|
||||
CANFrame* frame_p = getQueue().get();
|
||||
if(frame_p) {
|
||||
frame_p->len = recFrame.payload().length();
|
||||
frame_p->bus = 0;
|
||||
memcpy(frame_p->data, recFrame.payload().data(), frame_p->len);
|
||||
frame_p->extended = false;
|
||||
frame_p->ID = recFrame.frameId();
|
||||
frame_p->isReceived = true;
|
||||
frame_p->timestamp = (recFrame.timeStamp().seconds()*1000000 + recFrame.timeStamp().microSeconds()) - timeBasis;
|
||||
|
||||
checkTargettedFrame(*frame_p);
|
||||
|
||||
/* enqueue frame */
|
||||
getQueue().queue();
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
qDebug() << "can't get a frame, ERROR";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::testConnection() {
|
||||
QCanBusDevice* dev_p = QCanBus::instance()->createDevice("socketcan", getPort());
|
||||
|
||||
switch(getStatus())
|
||||
{
|
||||
case CANCon::CONNECTED:
|
||||
if (!dev_p || !dev_p->connectDevice()) {
|
||||
/* we have lost connectivity */
|
||||
disconnectDevice();
|
||||
|
||||
setStatus(CANCon::NOT_CONNECTED);
|
||||
emit status(getStatus());
|
||||
}
|
||||
break;
|
||||
case CANCon::NOT_CONNECTED:
|
||||
if (dev_p && dev_p->connectDevice()) {
|
||||
if(!mDev_p) {
|
||||
/* try to reconnect */
|
||||
CANBus bus;
|
||||
if(getBusConfig(0, bus))
|
||||
setBusSettings(0, bus);
|
||||
}
|
||||
/* disconnect test instance */
|
||||
dev_p->disconnectDevice();
|
||||
|
||||
setStatus(CANCon::CONNECTED);
|
||||
emit status(getStatus());
|
||||
}
|
||||
break;
|
||||
default: {}
|
||||
}
|
||||
|
||||
if(dev_p)
|
||||
delete dev_p;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef SocketCan_H
|
||||
#define SocketCan_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QCanBus>
|
||||
#include <QTimer>
|
||||
#include <qthread.h>
|
||||
|
||||
#include "canframemodel.h"
|
||||
#include "canconnection.h"
|
||||
#include "canconmanager.h"
|
||||
|
||||
|
||||
class SocketCan : public CANConnection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SocketCan(QString portName);
|
||||
virtual ~SocketCan();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void piStarted();
|
||||
virtual void piStop();
|
||||
virtual void piSetBusSettings(int pBusIdx, CANBus pBus);
|
||||
virtual bool piGetBusSettings(int pBusIdx, CANBus& pBus);
|
||||
virtual void piSuspend(bool pSuspend);
|
||||
virtual bool piSendFrame(const CANFrame&);
|
||||
|
||||
void disconnectDevice();
|
||||
|
||||
private slots:
|
||||
void errorReceived(QCanBusDevice::CanBusError) const;
|
||||
void framesWritten(qint64 count);
|
||||
void framesReceived();
|
||||
void testConnection();
|
||||
|
||||
protected:
|
||||
QCanBusDevice* mDev_p;
|
||||
QTimer mTimer;
|
||||
};
|
||||
|
||||
|
||||
#endif // SocketCan_H
|
||||
@@ -1,247 +0,0 @@
|
||||
#include "connectionwindow.h"
|
||||
#include "ui_connectionwindow.h"
|
||||
#include <QtNetwork/QNetworkInterface>
|
||||
|
||||
ConnectionWindow::ConnectionWindow(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ConnectionWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
settings = new QSettings();
|
||||
|
||||
int temp = settings->value("Main/DefaultConnectionType", 0).toInt();
|
||||
|
||||
if (temp == 0) currentConnType = ConnectionType::GVRET_SERIAL;
|
||||
if (temp == 1) currentConnType = ConnectionType::KVASER;
|
||||
if (temp == 2) currentConnType = ConnectionType::SOCKETCAN;
|
||||
|
||||
currentPortName = settings->value("Main/DefaultConnectionPort", "").toString();
|
||||
|
||||
currentSpeed1 = -1;
|
||||
currentSpeed2 = -1;
|
||||
|
||||
ui->ckSingleWire->setChecked(settings->value("Main/SingleWireMode", false).toBool());
|
||||
|
||||
ui->cbSpeed0->addItem(tr("<Default>"));
|
||||
ui->cbSpeed0->addItem(tr("Disabled"));
|
||||
ui->cbSpeed0->addItem(tr("125000"));
|
||||
ui->cbSpeed0->addItem(tr("250000"));
|
||||
ui->cbSpeed0->addItem(tr("500000"));
|
||||
ui->cbSpeed0->addItem(tr("1000000"));
|
||||
ui->cbSpeed0->addItem(tr("33333"));
|
||||
|
||||
ui->cbSpeed1->addItem(tr("<Default>"));
|
||||
ui->cbSpeed1->addItem(tr("Disabled"));
|
||||
ui->cbSpeed1->addItem(tr("125000"));
|
||||
ui->cbSpeed1->addItem(tr("250000"));
|
||||
ui->cbSpeed1->addItem(tr("500000"));
|
||||
ui->cbSpeed1->addItem(tr("1000000"));
|
||||
ui->cbSpeed1->addItem(tr("33333"));
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
ui->rbSocketCAN->setEnabled(true);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
ui->rbKvaser->setEnabled(true);
|
||||
#endif
|
||||
|
||||
connect(ui->btnOK, SIGNAL(clicked(bool)), this, SLOT(handleOKButton()));
|
||||
connect(ui->rbGVRET, SIGNAL(toggled(bool)), this, SLOT(handleConnTypeChanged()));
|
||||
connect(ui->rbKvaser, SIGNAL(toggled(bool)), this, SLOT(handleConnTypeChanged()));
|
||||
connect(ui->rbSocketCAN, SIGNAL(toggled(bool)), this, SLOT(handleConnTypeChanged()));
|
||||
}
|
||||
|
||||
ConnectionWindow::~ConnectionWindow()
|
||||
{
|
||||
delete settings;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ConnectionWindow::showEvent(QShowEvent* event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
qDebug() << "Show connectionwindow";
|
||||
handleConnTypeChanged();
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleConnTypeChanged()
|
||||
{
|
||||
if (ui->rbGVRET->isChecked()) getSerialPorts();
|
||||
if (ui->rbKvaser->isChecked()) getKvaserPorts();
|
||||
if (ui->rbSocketCAN->isChecked()) getSocketcanPorts();
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleOKButton()
|
||||
{
|
||||
QString conn;
|
||||
int connType = 0;
|
||||
|
||||
if (ui->rbGVRET->isChecked())
|
||||
{
|
||||
conn = "GVRET";
|
||||
connType = 0;
|
||||
currentConnType = ConnectionType::GVRET_SERIAL;
|
||||
}
|
||||
|
||||
if (ui->rbKvaser->isChecked())
|
||||
{
|
||||
conn = "KVASER";
|
||||
connType = 1;
|
||||
currentConnType = ConnectionType::KVASER;
|
||||
}
|
||||
|
||||
if (ui->rbSocketCAN->isChecked())
|
||||
{
|
||||
conn = "SOCKETCAN";
|
||||
connType = 2;
|
||||
currentConnType = ConnectionType::SOCKETCAN;
|
||||
}
|
||||
|
||||
currentPortName = getPortName();
|
||||
currentSpeed1 = getSpeed0();
|
||||
currentSpeed2 = getSpeed1();
|
||||
|
||||
settings->setValue("Main/DefaultConnectionPort", currentPortName);
|
||||
settings->setValue("Main/DefaultConnectionType", connType);
|
||||
settings->setValue("Main/SingleWireMode", ui->ckSingleWire->isChecked());
|
||||
|
||||
emit updateConnectionSettings(conn, getPortName(), getSpeed0(), getSpeed1());
|
||||
|
||||
this->close();
|
||||
}
|
||||
|
||||
void ConnectionWindow::getSerialPorts()
|
||||
{
|
||||
ui->cbPort->clear();
|
||||
ports = QSerialPortInfo::availablePorts();
|
||||
|
||||
for (int i = 0; i < ports.count(); i++)
|
||||
{
|
||||
ui->cbPort->addItem(ports[i].portName());
|
||||
if (currentPortName == ports[i].portName()) ui->cbPort->setCurrentIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionWindow::getKvaserPorts()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ConnectionWindow::getSocketcanPorts()
|
||||
{
|
||||
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
|
||||
QString interfaceName;
|
||||
|
||||
ui->cbPort->clear();
|
||||
|
||||
foreach (QNetworkInterface interface, interfaces)
|
||||
{
|
||||
interfaceName = interface.name().toLower();
|
||||
qDebug() << "Interface: " << interface.name();
|
||||
if (interfaceName.contains("can"))
|
||||
{
|
||||
ui->cbPort->addItem(interfaceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionWindow::setSpeeds(int speed0, int speed1)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
qDebug() << speed0 << "X" << speed1;
|
||||
|
||||
for (int i = 0; i < ui->cbSpeed0->count(); i++)
|
||||
{
|
||||
if (ui->cbSpeed0->itemText(i).toInt() == speed0)
|
||||
{
|
||||
ui->cbSpeed0->setCurrentIndex(i);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
ui->cbSpeed0->addItem(QString::number(speed0));
|
||||
ui->cbSpeed0->setCurrentIndex(ui->cbSpeed0->count() - 1);
|
||||
}
|
||||
|
||||
found = false;
|
||||
for (int i = 0; i < ui->cbSpeed1->count(); i++)
|
||||
{
|
||||
if (ui->cbSpeed1->itemText(i).toInt() == speed1)
|
||||
{
|
||||
ui->cbSpeed1->setCurrentIndex(i);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
ui->cbSpeed1->addItem(QString::number(speed1));
|
||||
ui->cbSpeed1->setCurrentIndex(ui->cbSpeed1->count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-1 means leave it at whatever it booted up to. 0 means disable. Otherwise the actual rate we want.
|
||||
int ConnectionWindow::getSpeed0()
|
||||
{
|
||||
switch (ui->cbSpeed0->currentIndex())
|
||||
{
|
||||
case -1:
|
||||
return -1;
|
||||
break;
|
||||
case 0:
|
||||
return -1;
|
||||
break;
|
||||
case 1:
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return (ui->cbSpeed0->currentText().toInt());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ConnectionWindow::getSpeed1()
|
||||
{
|
||||
switch (ui->cbSpeed1->currentIndex())
|
||||
{
|
||||
case -1:
|
||||
return -1;
|
||||
break;
|
||||
case 0:
|
||||
return -1;
|
||||
break;
|
||||
case 1:
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return (ui->cbSpeed1->currentText().toInt());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QString ConnectionWindow::getPortName()
|
||||
{
|
||||
return (ui->cbPort->currentText());
|
||||
}
|
||||
|
||||
ConnectionType::ConnectionType ConnectionWindow::getConnectionType()
|
||||
{
|
||||
if (ui->rbGVRET->isChecked()) return ConnectionType::GVRET_SERIAL;
|
||||
if (ui->rbKvaser->isChecked()) return ConnectionType::KVASER;
|
||||
if (ui->rbSocketCAN->isChecked()) return ConnectionType::SOCKETCAN;
|
||||
}
|
||||
|
||||
void ConnectionWindow::setCAN1SWMode(bool mode)
|
||||
{
|
||||
ui->ckSingleWire->setChecked(mode);
|
||||
}
|
||||
|
||||
bool ConnectionWindow::getCAN1SWMode()
|
||||
{
|
||||
if (ui->ckSingleWire->checkState() == Qt::Checked) return true;
|
||||
return false;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
#ifndef CONNECTIONWINDOW_H
|
||||
#define CONNECTIONWINDOW_H
|
||||
|
||||
#include <QSerialPortInfo>
|
||||
#include <QDialog>
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
|
||||
namespace Ui {
|
||||
class ConnectionWindow;
|
||||
}
|
||||
|
||||
namespace ConnectionType
|
||||
{
|
||||
enum ConnectionType
|
||||
{
|
||||
GVRET_SERIAL,
|
||||
KVASER,
|
||||
SOCKETCAN
|
||||
};
|
||||
}
|
||||
|
||||
class ConnectionWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConnectionWindow(QWidget *parent = 0);
|
||||
~ConnectionWindow();
|
||||
void showEvent(QShowEvent *);
|
||||
int getSpeed0();
|
||||
int getSpeed1();
|
||||
QString getPortName(); //name of port to connect to
|
||||
ConnectionType::ConnectionType getConnectionType();
|
||||
bool getCAN1SWMode();
|
||||
|
||||
signals:
|
||||
void updateConnectionSettings(QString connectionType, QString port, int speed0, int speed1);
|
||||
|
||||
public slots:
|
||||
void setSpeeds(int speed0, int speed1);
|
||||
void setCAN1SWMode(bool mode);
|
||||
|
||||
private slots:
|
||||
void handleOKButton();
|
||||
void handleConnTypeChanged();
|
||||
|
||||
private:
|
||||
Ui::ConnectionWindow *ui;
|
||||
QList<QSerialPortInfo> ports;
|
||||
QSettings *settings;
|
||||
|
||||
ConnectionType::ConnectionType currentConnType;
|
||||
QString currentPortName;
|
||||
int currentSpeed1, currentSpeed2;
|
||||
|
||||
void getSerialPorts();
|
||||
void getKvaserPorts();
|
||||
void getSocketcanPorts();
|
||||
};
|
||||
|
||||
#endif // CONNECTIONWINDOW_H
|
||||
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ConnectionWindow</class>
|
||||
<widget class="QWidget" name="ConnectionWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>335</width>
|
||||
<height>235</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Connection Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Connection Type</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbGVRET">
|
||||
<property name="text">
|
||||
<string>GVRET Serial</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbKvaser">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Kvaser</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbSocketCAN">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SocketCAN</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbPort"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>CAN0 Speed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>CAN1 Speed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QComboBox" name="cbSpeed0"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cbSpeed1"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ckSingleWire">
|
||||
<property name="text">
|
||||
<string>Set CAN1 to Single Wire Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnOK">
|
||||
<property name="text">
|
||||
<string>Update Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -37,6 +37,7 @@ bool DBCSignalHandler::addSignal(DBC_SIGNAL &sig)
|
||||
|
||||
bool DBCSignalHandler::removeSignal(DBC_SIGNAL *sig)
|
||||
{
|
||||
Q_UNUSED(sig);
|
||||
//if (sigs.removeAll(*sig) > 0) return true;
|
||||
return false;
|
||||
}
|
||||
@@ -75,7 +76,7 @@ int DBCSignalHandler::getCount()
|
||||
return sigs.count();
|
||||
}
|
||||
|
||||
DBC_MESSAGE* DBCMessageHandler::findMsgByID(int id)
|
||||
DBC_MESSAGE* DBCMessageHandler::findMsgByID(uint32_t id)
|
||||
{
|
||||
if (messages.count() == 0) return NULL;
|
||||
for (int i = 0; i < messages.count(); i++)
|
||||
@@ -117,6 +118,7 @@ bool DBCMessageHandler::addMessage(DBC_MESSAGE &msg)
|
||||
|
||||
bool DBCMessageHandler::removeMessage(DBC_MESSAGE *msg)
|
||||
{
|
||||
Q_UNUSED(msg);
|
||||
//if (messages.removeAll(*msg) > 0) return true;
|
||||
return false;
|
||||
}
|
||||
@@ -130,7 +132,7 @@ bool DBCMessageHandler::removeMessageByIndex(int idx)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBCMessageHandler::removeMessage(int ID)
|
||||
bool DBCMessageHandler::removeMessage(uint32_t ID)
|
||||
{
|
||||
bool foundSome = false;
|
||||
if (messages.count() == 0) return false;
|
||||
@@ -302,7 +304,7 @@ void DBCFile::loadFile(QString fileName)
|
||||
{
|
||||
int offset = 0;
|
||||
bool isMultiplexor = false;
|
||||
bool isMultiplexed = false;
|
||||
//bool isMultiplexed = false;
|
||||
DBC_SIGNAL sig;
|
||||
|
||||
sig.multiplexValue = 0;
|
||||
@@ -326,7 +328,7 @@ void DBCFile::loadFile(QString fileName)
|
||||
if (match.hasMatch())
|
||||
{
|
||||
qDebug() << "Multiplexed signal";
|
||||
isMultiplexed = true;
|
||||
//isMultiplexed = true;
|
||||
sig.isMultiplexed = true;
|
||||
sig.multiplexValue = match.captured(2).toInt();
|
||||
offset = 1;
|
||||
@@ -805,7 +807,7 @@ DBC_MESSAGE* DBCHandler::findMessage(const CANFrame &frame)
|
||||
{
|
||||
for(int i = 0; i < loadedFiles.count(); i++)
|
||||
{
|
||||
if (loadedFiles[i].getAssocBus() == -1 || frame.bus == loadedFiles[i].getAssocBus())
|
||||
if (loadedFiles[i].getAssocBus() == -1 || frame.bus == (unsigned int)loadedFiles[i].getAssocBus())
|
||||
{
|
||||
DBC_MESSAGE* msg = loadedFiles[i].messageHandler->findMsgByID(frame.ID);
|
||||
if (msg != NULL) return msg;
|
||||
@@ -32,13 +32,13 @@ class DBCMessageHandler: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DBC_MESSAGE *findMsgByID(int id);
|
||||
DBC_MESSAGE *findMsgByID(uint32_t id);
|
||||
DBC_MESSAGE *findMsgByIdx(int idx);
|
||||
DBC_MESSAGE *findMsgByName(QString name);
|
||||
bool addMessage(DBC_MESSAGE &msg);
|
||||
bool removeMessage(DBC_MESSAGE *msg);
|
||||
bool removeMessageByIndex(int idx);
|
||||
bool removeMessage(int ID);
|
||||
bool removeMessage(uint32_t ID);
|
||||
bool removeMessage(QString name);
|
||||
void removeAllMessages();
|
||||
int getCount();
|
||||
@@ -114,6 +114,7 @@ void DBCLoadSaveWindow::cellChanged(int row, int col)
|
||||
|
||||
void DBCLoadSaveWindow::cellDoubleClicked(int row, int col)
|
||||
{
|
||||
Q_UNUSED(col)
|
||||
editorWindow->setFileIdx(row);
|
||||
editorWindow->show();
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
|
||||
#define MT_COLUMN_COUNT 5
|
||||
|
||||
DBCMainEditor::DBCMainEditor(DBCHandler *handler, const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::DBCMainEditor)
|
||||
@@ -26,7 +28,7 @@ DBCMainEditor::DBCMainEditor(DBCHandler *handler, const QVector<CANFrame> *frame
|
||||
|
||||
QStringList headers2;
|
||||
headers2 << "Msg ID" << "Msg Name" << "Data Len" << "Signals" << "Comment";
|
||||
ui->MessagesTable->setColumnCount(5);
|
||||
ui->MessagesTable->setColumnCount(MT_COLUMN_COUNT);
|
||||
ui->MessagesTable->setColumnWidth(0, 80);
|
||||
ui->MessagesTable->setColumnWidth(1, 240);
|
||||
ui->MessagesTable->setColumnWidth(2, 80);
|
||||
@@ -210,148 +212,125 @@ void DBCMainEditor::onCellChangedNode(int row,int col)
|
||||
|
||||
void DBCMainEditor::onCellChangedMessage(int row,int col)
|
||||
{
|
||||
QTableWidgetItem* item = NULL;
|
||||
bool ret = false;
|
||||
DBC_MESSAGE *msg = NULL;
|
||||
uint msgID;
|
||||
|
||||
if (inhibitCellChanged) return;
|
||||
|
||||
qDebug() << "Editing row: " << row << " col: " << col;
|
||||
|
||||
QTableWidgetItem *replacement = NULL;
|
||||
int msgID;
|
||||
QString msgName;
|
||||
int msgLen;
|
||||
QString msgComment;
|
||||
DBC_MESSAGE newMsg;
|
||||
DBC_NODE *node = dbcFile->findNodeByIdx(ui->NodesTable->currentRow());
|
||||
DBC_MESSAGE *msg;
|
||||
if (node == NULL)
|
||||
{
|
||||
qDebug() << "No node set?!? This is bad!";
|
||||
return;
|
||||
//dbcHandler->findNodeByIdx(0);
|
||||
}
|
||||
|
||||
msgID = Utility::ParseStringToNum(ui->MessagesTable->item(row, 0)->text());
|
||||
qDebug() << "Msg ID of edited: " << msgID;
|
||||
item = ui->MessagesTable->item(row, 0);
|
||||
if(!item) return;
|
||||
|
||||
msgID = Utility::ParseStringToNum2(item->text(), &ret);
|
||||
msg = dbcFile->messageHandler->findMsgByID(msgID);
|
||||
|
||||
switch(col)
|
||||
{
|
||||
case 0: //msg id
|
||||
if (row == ui->MessagesTable->rowCount() - 1) //new record
|
||||
{
|
||||
if (dbcFile->messageHandler->findMsgByID(msgID) != NULL)
|
||||
/* sanity checks */
|
||||
if(!ret)
|
||||
{
|
||||
/* bad message id */
|
||||
ui->MessagesTable->item(row, 0)->setText("");
|
||||
return;
|
||||
}
|
||||
if (msg != NULL)
|
||||
{
|
||||
QMessageBox msg;
|
||||
msg.setParent(0);
|
||||
msg.setText("An existing msg with that ID already exists! Aborting!");
|
||||
msg.exec();
|
||||
|
||||
ui->MessagesTable->item(row, 0)->setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
/* insert row */
|
||||
DBC_MESSAGE newMsg;
|
||||
newMsg.ID = msgID;
|
||||
newMsg.name = "";
|
||||
newMsg.sender = node;
|
||||
newMsg.len = 0;
|
||||
for (int i = 0; i < referenceFrames->length(); i++)
|
||||
{
|
||||
if (referenceFrames->at(i).ID == msgID)
|
||||
if ((uint) referenceFrames->at(i).ID == msgID)
|
||||
{
|
||||
newMsg.len = referenceFrames->at(i).len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dbcFile->messageHandler->addMessage(newMsg);
|
||||
}
|
||||
else //editing an existing record
|
||||
{
|
||||
if (msg != NULL) msg->ID = msgID;
|
||||
}
|
||||
inhibitCellChanged = true;
|
||||
replacement = new QTableWidgetItem(Utility::formatNumber(msgID));
|
||||
ui->MessagesTable->setItem(row, col, replacement);
|
||||
replacement = new QTableWidgetItem(QString::number(newMsg.len));
|
||||
ui->MessagesTable->setItem(row, 2, replacement);
|
||||
inhibitCellChanged = false;
|
||||
break;
|
||||
|
||||
/* insert message in table */
|
||||
inhibitCellChanged = true;
|
||||
|
||||
item = ui->MessagesTable->item(row, 0);
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
||||
item->setText(Utility::formatNumber(msgID));
|
||||
|
||||
for(int i=1 ; i<MT_COLUMN_COUNT ; i++)
|
||||
{
|
||||
item = ui->MessagesTable->item(row, i);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
}
|
||||
|
||||
/* set length */
|
||||
item = ui->MessagesTable->item(row, 2);
|
||||
item->setText(QString::number(newMsg.len));
|
||||
|
||||
inhibitCellChanged = false;
|
||||
|
||||
/* insert a new row */
|
||||
insertBlankRow();
|
||||
break;
|
||||
}
|
||||
case 1: //msg name
|
||||
msgName = ui->MessagesTable->item(row, col)->text().simplified().replace(' ', '_');
|
||||
{
|
||||
QString msgName = ui->MessagesTable->item(row, 1)->text().simplified().replace(' ', '_');
|
||||
if (msgName.length() == 0) return;
|
||||
if (row == ui->MessagesTable->rowCount() - 1) //new record
|
||||
if( ret && (msg!=NULL) )
|
||||
msg->name = msgName;
|
||||
break;
|
||||
}
|
||||
case 2: //data length
|
||||
{
|
||||
if (dbcFile->messageHandler->findMsgByName(msgName) != NULL)
|
||||
bool parseOk = false;
|
||||
uint msgLen = ui->MessagesTable->item(row, col)->text().toUInt(&parseOk);
|
||||
|
||||
/* sanity checks */
|
||||
if(!parseOk)
|
||||
{
|
||||
QMessageBox msg;
|
||||
msg.setParent(0);
|
||||
msg.setText("An existing msg with that name already exists! Aborting!");
|
||||
msg.exec();
|
||||
ui->MessagesTable->item(row, col)->setText("");
|
||||
return;
|
||||
}
|
||||
newMsg.ID = -1;
|
||||
newMsg.name = msgName;
|
||||
newMsg.sender = node;
|
||||
dbcFile->messageHandler->addMessage(newMsg);
|
||||
}
|
||||
else
|
||||
if (msgLen > 8)
|
||||
{
|
||||
if (msg != NULL) msg->name = msgName;
|
||||
msgLen = 8;
|
||||
ui->MessagesTable->item(row, col)->setText(QString::number(msgLen));
|
||||
}
|
||||
inhibitCellChanged = true;
|
||||
replacement = new QTableWidgetItem(msgName);
|
||||
ui->MessagesTable->setItem(row, col, replacement);
|
||||
inhibitCellChanged = false;
|
||||
break;
|
||||
|
||||
case 2: //data length
|
||||
msgLen = ui->MessagesTable->item(row, col)->text().toInt();
|
||||
if (msgLen < 0) msgLen = 0;
|
||||
if (msgLen > 8) msgLen = 8;
|
||||
if (row == ui->MessagesTable->rowCount() - 1) //new record
|
||||
{
|
||||
DBC_MESSAGE newMsg;
|
||||
newMsg.ID = -1;
|
||||
newMsg.name = "";
|
||||
newMsg.len = msgLen;
|
||||
newMsg.sender = node;
|
||||
dbcFile->messageHandler->addMessage(newMsg);
|
||||
}
|
||||
else //editing an existing record
|
||||
{
|
||||
if (msg != NULL) msg->len = msgLen;
|
||||
}
|
||||
inhibitCellChanged = true;
|
||||
replacement = new QTableWidgetItem(QString::number(msgLen, 16));
|
||||
ui->MessagesTable->setItem(row, col, replacement);
|
||||
inhibitCellChanged = false;
|
||||
|
||||
if( ret && (msg!=NULL) )
|
||||
msg->len = msgLen;
|
||||
break;
|
||||
}
|
||||
case 3: //signals (number) - we don't handle anything here. User cannot directly change this value
|
||||
break;
|
||||
case 4: //comment
|
||||
msgComment = ui->MessagesTable->item(row, col)->text().simplified();
|
||||
if (row == ui->MessagesTable->rowCount() - 1) //new record
|
||||
{
|
||||
DBC_MESSAGE newMsg;
|
||||
newMsg.ID = -1;
|
||||
newMsg.name = "";
|
||||
newMsg.len = 0;
|
||||
newMsg.comment = msgComment;
|
||||
newMsg.sender = node;
|
||||
dbcFile->messageHandler->addMessage(newMsg);
|
||||
}
|
||||
else //editing an existing record
|
||||
{
|
||||
if (msg != NULL) msg->comment = msgComment;
|
||||
}
|
||||
inhibitCellChanged = true;
|
||||
replacement = new QTableWidgetItem(msgComment);
|
||||
ui->MessagesTable->setItem(row, col, replacement);
|
||||
inhibitCellChanged = false;
|
||||
QString msgComment = ui->MessagesTable->item(row, col)->text().simplified();
|
||||
if( ret && (msgComment!=NULL) )
|
||||
msg->comment = msgComment;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (row == ui->MessagesTable->rowCount() - 1)
|
||||
{
|
||||
ui->MessagesTable->insertRow(ui->MessagesTable->rowCount());
|
||||
}
|
||||
|
||||
ui->MessagesTable->setCurrentCell(row, col);
|
||||
@@ -426,6 +405,7 @@ void DBCMainEditor::refreshNodesTable()
|
||||
|
||||
//insert a fresh entry at the bottom that contains nothing
|
||||
ui->NodesTable->insertRow(ui->NodesTable->rowCount());
|
||||
ui->NodesTable->selectRow(0);
|
||||
}
|
||||
|
||||
void DBCMainEditor::refreshMessagesTable(const DBC_NODE *node)
|
||||
@@ -466,5 +446,17 @@ void DBCMainEditor::refreshMessagesTable(const DBC_NODE *node)
|
||||
}
|
||||
|
||||
//insert blank record that can be used to add new messages
|
||||
ui->MessagesTable->insertRow(ui->MessagesTable->rowCount());
|
||||
insertBlankRow();
|
||||
}
|
||||
|
||||
void DBCMainEditor::insertBlankRow()
|
||||
{
|
||||
int rowIdx = ui->MessagesTable->rowCount();
|
||||
ui->MessagesTable->insertRow(rowIdx);
|
||||
for(int i=1 ; i<MT_COLUMN_COUNT ; i++)
|
||||
{
|
||||
QTableWidgetItem *item = new QTableWidgetItem("");
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
||||
ui->MessagesTable->setItem(rowIdx, i, item);
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ private:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
void insertBlankRow();
|
||||
|
||||
};
|
||||
|
||||
@@ -348,6 +348,10 @@ void DBCSignalEditor::addNewSignal()
|
||||
void DBCSignalEditor::deleteCurrentSignal()
|
||||
{
|
||||
int currIdx = ui->signalsList->currentRow();
|
||||
|
||||
if(currIdx==ui->signalsList->count()-1)
|
||||
return;
|
||||
|
||||
if (currIdx > -1)
|
||||
{
|
||||
delete(ui->signalsList->item(currIdx));
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DeltaWindow</class>
|
||||
<widget class="QDialog" name="DeltaWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>978</width>
|
||||
<height>654</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+16
-12
@@ -36,6 +36,7 @@ FirmwareUploaderWindow::FirmwareUploaderWindow(const QVector<CANFrame> *frames,
|
||||
FirmwareUploaderWindow::~FirmwareUploaderWindow()
|
||||
{
|
||||
timer->stop();
|
||||
CANConManager::getInstance()->removeAllTargettedFrames(this);
|
||||
delete timer;
|
||||
delete ui;
|
||||
}
|
||||
@@ -47,7 +48,7 @@ void FirmwareUploaderWindow::updateProgress()
|
||||
|
||||
void FirmwareUploaderWindow::updatedFrames(int numFrames)
|
||||
{
|
||||
CANFrame thisFrame;
|
||||
//CANFrame thisFrame;
|
||||
if (numFrames == -1) //all frames deleted.
|
||||
{
|
||||
}
|
||||
@@ -66,10 +67,10 @@ void FirmwareUploaderWindow::updatedFrames(int numFrames)
|
||||
}
|
||||
}
|
||||
|
||||
void FirmwareUploaderWindow::gotTargettedFrame(int frameLoc)
|
||||
void FirmwareUploaderWindow::gotTargettedFrame(CANFrame frame)
|
||||
{
|
||||
const CANFrame &frame = modelFrames->at(frameLoc);
|
||||
if (frame.ID == (baseAddress + 0x10)) {
|
||||
qDebug() << "FUW: Got targetted frame with id " << frame.ID;
|
||||
if (frame.ID == (uint32_t)(baseAddress + 0x10)) {
|
||||
qDebug() << "Start firmware reply";
|
||||
if ((frame.data[0] == 0xAD) && (frame.data[1] == 0xDE))
|
||||
{
|
||||
@@ -81,7 +82,7 @@ void FirmwareUploaderWindow::gotTargettedFrame(int frameLoc)
|
||||
if ((frame.data[6] == ((token >> 16) & 0xFF)) && (frame.data[7] == ((token >> 24) & 0xFF)))
|
||||
{
|
||||
qDebug() << "starting firmware process";
|
||||
MainWindow::getReference()->setTargettedID(baseAddress + 0x20);
|
||||
//MainWindow::getReference()->setTargettedID(baseAddress + 0x20);
|
||||
transferInProgress = true;
|
||||
sendFirmwareChunk();
|
||||
}
|
||||
@@ -90,7 +91,7 @@ void FirmwareUploaderWindow::gotTargettedFrame(int frameLoc)
|
||||
}
|
||||
}
|
||||
|
||||
if (frame.ID == (baseAddress + 0x20)) {
|
||||
if (frame.ID == (uint32_t)(baseAddress + 0x20)) {
|
||||
qDebug() << "Firmware reception success reply";
|
||||
int seq = frame.data[0] + (256 * frame.data[1]);
|
||||
if (seq == currentSendingPosition)
|
||||
@@ -126,6 +127,7 @@ void FirmwareUploaderWindow::sendFirmwareChunk()
|
||||
int xorByte = 0;
|
||||
output->extended = false;
|
||||
output->len = 7;
|
||||
output->bus = bus;
|
||||
output->ID = baseAddress + 0x16;
|
||||
output->data[0] = currentSendingPosition & 0xFF;
|
||||
output->data[1] = (currentSendingPosition >> 8) & 0xFF;
|
||||
@@ -135,7 +137,7 @@ void FirmwareUploaderWindow::sendFirmwareChunk()
|
||||
output->data[5] = firmwareData[firmwareLocation++];
|
||||
for (int i = 0; i < 6; i++) xorByte = xorByte ^ output->data[i];
|
||||
output->data[6] = xorByte;
|
||||
sendCANFrame(output, bus);
|
||||
sendCANFrame(output);
|
||||
timer->start();
|
||||
}
|
||||
|
||||
@@ -143,13 +145,14 @@ void FirmwareUploaderWindow::sendFirmwareEnding()
|
||||
{
|
||||
CANFrame *output = new CANFrame;
|
||||
output->extended = false;
|
||||
output->bus = bus;
|
||||
output->len = 4;
|
||||
output->ID = baseAddress + 0x30;
|
||||
output->data[3] = 0xC0;
|
||||
output->data[2] = 0xDE;
|
||||
output->data[1] = 0xFA;
|
||||
output->data[0] = 0xDE;
|
||||
sendCANFrame(output, bus);
|
||||
//sendCANFrame(output, bus);
|
||||
}
|
||||
|
||||
void FirmwareUploaderWindow::handleStartStopTransfer()
|
||||
@@ -164,10 +167,12 @@ void FirmwareUploaderWindow::handleStartStopTransfer()
|
||||
bus = ui->spinBus->value();
|
||||
baseAddress = Utility::ParseStringToNum(ui->txtBaseAddr->text());
|
||||
qDebug() << "Base address: " + QString::number(baseAddress);
|
||||
MainWindow::getReference()->setTargettedID(baseAddress + 0x10);
|
||||
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x10, 0x7FF, this);
|
||||
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x20, 0x7FF, this);
|
||||
CANFrame *output = new CANFrame;
|
||||
output->extended = false;
|
||||
output->len = 8;
|
||||
output->bus = bus;
|
||||
output->ID = baseAddress;
|
||||
|
||||
output->data[0] = 0xEF;
|
||||
@@ -178,12 +183,12 @@ void FirmwareUploaderWindow::handleStartStopTransfer()
|
||||
output->data[5] = (token >> 8) & 0xFF;
|
||||
output->data[6] = (token >> 16) & 0xFF;
|
||||
output->data[7] = (token >> 24) & 0xFF;
|
||||
sendCANFrame(output, bus);
|
||||
sendCANFrame(output);
|
||||
}
|
||||
else //stop anything in process
|
||||
{
|
||||
ui->btnStartStop->setText("Start Upload");
|
||||
MainWindow::getReference()->setTargettedID(-1);
|
||||
CANConManager::getInstance()->removeAllTargettedFrames(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +196,6 @@ void FirmwareUploaderWindow::handleLoadFile()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog;
|
||||
bool result = false;
|
||||
|
||||
QStringList filters;
|
||||
filters.append(QString(tr("Raw firmware binary (*.bin)")));
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include <QDialog>
|
||||
#include <QTimer>
|
||||
#include "can_structs.h"
|
||||
#include "connections/canconmanager.h"
|
||||
#include "utility.h"
|
||||
#include "serialworker.h"
|
||||
|
||||
namespace Ui {
|
||||
class FirmwareUploaderWindow;
|
||||
@@ -20,10 +20,10 @@ public:
|
||||
~FirmwareUploaderWindow();
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
void sendCANFrame(const CANFrame *);
|
||||
|
||||
public slots:
|
||||
void gotTargettedFrame(int frameLoc);
|
||||
void gotTargettedFrame(CANFrame frame);
|
||||
|
||||
private slots:
|
||||
void handleLoadFile();
|
||||
|
||||
+31
-32
@@ -246,6 +246,8 @@ bool FrameFileIO::loadVehicleSpyFile(QString filename, QVector<CANFrame> *frames
|
||||
|
||||
bool FrameFileIO::saveVehicleSpyFile(QString filename, const QVector<CANFrame> *frames)
|
||||
{
|
||||
Q_UNUSED(filename);
|
||||
Q_UNUSED(frames);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -324,7 +326,7 @@ bool FrameFileIO::loadCRTDFile(QString filename, QVector<CANFrame>* frames)
|
||||
else thisFrame.isReceived = true;
|
||||
thisFrame.bus = 0;
|
||||
thisFrame.len = tokens.length() - 3;
|
||||
for (int d = 0; d < thisFrame.len; d++)
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++)
|
||||
{
|
||||
if (tokens[d + 3] != "")
|
||||
{
|
||||
@@ -381,7 +383,7 @@ bool FrameFileIO::saveCRTDFile(QString filename, const QVector<CANFrame>* frames
|
||||
outFile->write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8());
|
||||
outFile->putChar(' ');
|
||||
|
||||
for (int temp = 0; temp < frames->at(c).len; temp++)
|
||||
for (unsigned int temp = 0; temp < frames->at(c).len; temp++)
|
||||
{
|
||||
outFile->write(QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8());
|
||||
outFile->putChar(' ');
|
||||
@@ -440,7 +442,7 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
|
||||
thisFrame.bus = 0;
|
||||
thisFrame.extended = false;
|
||||
QList<QByteArray> tokens = line.mid(41, thisFrame.len * 3).split(' ');
|
||||
for (int d = 0; d < thisFrame.len; d++)
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++)
|
||||
{
|
||||
if (tokens[d] != "")
|
||||
{
|
||||
@@ -512,9 +514,9 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector<CANFrame>* frames)
|
||||
{
|
||||
thisFrame.isReceived = true;
|
||||
thisFrame.bus = tokens[3].toInt();
|
||||
thisFrame.len = tokens[4].toInt();
|
||||
thisFrame.len = tokens[4].toUInt();
|
||||
for (int c = 0; c < 8; c++) thisFrame.data[c] = 0;
|
||||
for (int d = 0; d < thisFrame.len; d++)
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++)
|
||||
thisFrame.data[d] = tokens[5 + d].toInt(NULL, 16);
|
||||
}
|
||||
else if (fileVersion == 2)
|
||||
@@ -522,10 +524,10 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector<CANFrame>* frames)
|
||||
if (tokens[3].at(0) == 'R') thisFrame.isReceived = true;
|
||||
else thisFrame.isReceived = false;
|
||||
thisFrame.bus = tokens[4].toInt();
|
||||
thisFrame.len = tokens[5].toInt();
|
||||
if (thisFrame.len + 6 > tokens.length()) thisFrame.len = tokens.length() - 6;
|
||||
thisFrame.len = tokens[5].toUInt();
|
||||
if (thisFrame.len + 6 > (unsigned int) tokens.length()) thisFrame.len = tokens.length() - 6;
|
||||
for (int c = 0; c < 8; c++) thisFrame.data[c] = 0;
|
||||
for (int d = 0; d < thisFrame.len; d++)
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++)
|
||||
thisFrame.data[d] = tokens[6 + d].toInt(NULL, 16);
|
||||
}
|
||||
|
||||
@@ -580,7 +582,7 @@ bool FrameFileIO::saveNativeCSVFile(QString filename, const QVector<CANFrame>* f
|
||||
outFile->write(QString::number(frames->at(c).len).toUtf8());
|
||||
outFile->putChar(44);
|
||||
|
||||
for (int temp = 0; temp < 8; temp++)
|
||||
for (unsigned int temp = 0; temp < 8; temp++)
|
||||
{
|
||||
if (temp < frames->at(c).len)
|
||||
outFile->write(QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8());
|
||||
@@ -636,7 +638,7 @@ bool FrameFileIO::loadGenericCSVFile(QString filename, QVector<CANFrame>* frames
|
||||
QList<QByteArray> dataTok = tokens[1].split(' ');
|
||||
thisFrame.len = dataTok.length();
|
||||
if (thisFrame.len > 8) thisFrame.len = 8;
|
||||
for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = dataTok[d].toInt(NULL, 16);
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = dataTok[d].toInt(NULL, 16);
|
||||
|
||||
frames->append(thisFrame);
|
||||
}
|
||||
@@ -674,7 +676,7 @@ bool FrameFileIO::saveGenericCSVFile(QString filename, const QVector<CANFrame>*
|
||||
outFile->write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8());
|
||||
outFile->putChar(44);
|
||||
|
||||
for (int temp = 0; temp < frames->at(c).len; temp++)
|
||||
for (unsigned int temp = 0; temp < frames->at(c).len; temp++)
|
||||
{
|
||||
outFile->write(QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8());
|
||||
outFile->putChar(' ');
|
||||
@@ -762,10 +764,9 @@ bool FrameFileIO::loadLogFile(QString filename, QVector<CANFrame>* frames)
|
||||
if (tokens[4] == "s") thisFrame.extended = false;
|
||||
else thisFrame.extended = true;
|
||||
thisFrame.bus = tokens[2].toInt() - 1;
|
||||
thisFrame.len = tokens[5].toInt();
|
||||
thisFrame.len = tokens[5].toUInt();
|
||||
if (thisFrame.len > 8) thisFrame.len = 8;
|
||||
if (thisFrame.len < 0) thisFrame.len = 0;
|
||||
for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = tokens[d + 6].toInt(NULL, 16);
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = tokens[d + 6].toInt(NULL, 16);
|
||||
frames->append(thisFrame);
|
||||
}
|
||||
else foundErrors = true;
|
||||
@@ -825,7 +826,7 @@ bool FrameFileIO::saveLogFile(QString filename, const QVector<CANFrame>* frames)
|
||||
else outFile->write(" s ");
|
||||
outFile->write(QString::number(frames->at(c).len).toUtf8() + " ");
|
||||
|
||||
for (int temp = 0; temp < frames->at(c).len; temp++)
|
||||
for (unsigned int temp = 0; temp < frames->at(c).len; temp++)
|
||||
{
|
||||
outFile->write(QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8());
|
||||
outFile->putChar(' ');
|
||||
@@ -902,7 +903,7 @@ bool FrameFileIO::loadIXXATFile(QString filename, QVector<CANFrame>* frames)
|
||||
|
||||
QStringList dataToks = unQuote(tokens[4]).simplified().split(' ');
|
||||
thisFrame.len = dataToks.length();
|
||||
for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = dataToks[d].toInt(NULL, 16);
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = dataToks[d].toInt(NULL, 16);
|
||||
frames->append(thisFrame);
|
||||
}
|
||||
else foundErrors = true;
|
||||
@@ -955,7 +956,7 @@ bool FrameFileIO::saveIXXATFile(QString filename, const QVector<CANFrame>* frame
|
||||
else outFile->write(",\"Std\"");
|
||||
outFile->write(",\"\",\"");
|
||||
|
||||
for (int temp = 0; temp < frames->at(c).len; temp++)
|
||||
for (unsigned int temp = 0; temp < frames->at(c).len; temp++)
|
||||
{
|
||||
outFile->write(QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8());
|
||||
outFile->putChar(' ');
|
||||
@@ -1018,7 +1019,7 @@ bool FrameFileIO::loadCANDOFile(QString filename, QVector<CANFrame>* frames)
|
||||
|
||||
if (thisFrame.len <= 8 && thisFrame.ID <= 0x7FF)
|
||||
{
|
||||
for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = (unsigned char)data[4 + d];
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = (unsigned char)data[4 + d];
|
||||
frames->append(thisFrame);
|
||||
}
|
||||
else foundErrors = true;
|
||||
@@ -1050,8 +1051,8 @@ bool FrameFileIO::saveCANDOFile(QString filename, const QVector<CANFrame>* frame
|
||||
ms = (thisFrame.timestamp / 1000);
|
||||
data[0] = (((ms / 1000) % 60) << 2) + ((ms % 1000) >> 8);
|
||||
data[1] = (char)(ms & 0xFF);
|
||||
data[2] = 0xFF;
|
||||
data[3] = 0xFF;
|
||||
data[2] = (char)0xFF;
|
||||
data[3] = (char)0xFF;
|
||||
for (int l = 0; l < 8; l++) data[4 + l] = 0;
|
||||
outFile->write(data);
|
||||
|
||||
@@ -1063,7 +1064,7 @@ bool FrameFileIO::saveCANDOFile(QString filename, const QVector<CANFrame>* frame
|
||||
qApp->processEvents();
|
||||
lineCounter = 0;
|
||||
}
|
||||
for (int j = 0; j < 8; j++) data[4 + j] = 0xFF;
|
||||
for (int j = 0; j < 8; j++) data[4 + j] = (char)0xFF;
|
||||
|
||||
thisFrame = frames->at(c);
|
||||
if (!thisFrame.extended)
|
||||
@@ -1074,7 +1075,7 @@ bool FrameFileIO::saveCANDOFile(QString filename, const QVector<CANFrame>* frame
|
||||
data[1] = (char)(ms & 0xFF);
|
||||
data[2] = (char)(id & 0xFF);
|
||||
data[3] = (char)((id >> 8) + (thisFrame.len << 4));
|
||||
for (int d = 0; d < thisFrame.len; d++) data[4 + d] = (char)thisFrame.data[d];
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++) data[4 + d] = (char)thisFrame.data[d];
|
||||
outFile->write(data);
|
||||
}
|
||||
}
|
||||
@@ -1140,11 +1141,10 @@ bool FrameFileIO::loadMicrochipFile(QString filename, QVector<CANFrame>* frames)
|
||||
if (thisFrame.ID <= 0x7FF) thisFrame.extended = false;
|
||||
else thisFrame.extended = true;
|
||||
thisFrame.bus = 0;
|
||||
thisFrame.len = tokens[3].toInt();
|
||||
thisFrame.len = tokens[3].toUInt();
|
||||
if (thisFrame.len > 8) thisFrame.len = 8;
|
||||
if (thisFrame.len < 0) thisFrame.len = 0;
|
||||
if (thisFrame.len + 4 > tokens.length()) thisFrame.len = tokens.length() - 4;
|
||||
for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = (unsigned char)Utility::ParseStringToNum(tokens[4 + d]);
|
||||
if (thisFrame.len + 4 > (unsigned int) tokens.length()) thisFrame.len = tokens.length() - 4;
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = (unsigned char)Utility::ParseStringToNum(tokens[4 + d]);
|
||||
frames->append(thisFrame);
|
||||
}
|
||||
else foundErrors = true;
|
||||
@@ -1206,7 +1206,7 @@ bool FrameFileIO::saveMicrochipFile(QString filename, const QVector<CANFrame>* f
|
||||
outFile->write("0x" + QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8() + ";");
|
||||
outFile->write(QString::number(frames->at(c).len).toUtf8() + ";");
|
||||
|
||||
for (int temp = 0; temp < frames->at(c).len; temp++)
|
||||
for (unsigned int temp = 0; temp < frames->at(c).len; temp++)
|
||||
{
|
||||
outFile->write("0x" + QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8());
|
||||
outFile->putChar(';');
|
||||
@@ -1299,12 +1299,11 @@ bool FrameFileIO::loadTraceFile(QString filename, QVector<CANFrame>* frames)
|
||||
if (thisFrame.ID <= 0x7FF) thisFrame.extended = false;
|
||||
else thisFrame.extended = true;
|
||||
thisFrame.bus = 0;
|
||||
thisFrame.len = tokens[3].toInt();
|
||||
if (thisFrame.len < 0) thisFrame.len = 0;
|
||||
thisFrame.len = tokens[3].toUInt();
|
||||
if (thisFrame.len > 8) thisFrame.len = 8;
|
||||
QList<QByteArray> dataToks = tokens[4].split(' ');
|
||||
if (thisFrame.len > dataToks.length()) thisFrame.len = dataToks.length();
|
||||
for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = (unsigned char)dataToks[d].toInt(NULL, 16);
|
||||
if (thisFrame.len > (unsigned int) dataToks.length()) thisFrame.len = (unsigned int) dataToks.length();
|
||||
for (unsigned int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = (unsigned char)dataToks[d].toInt(NULL, 16);
|
||||
frames->append(thisFrame);
|
||||
}
|
||||
else foundErrors = true;
|
||||
@@ -1391,7 +1390,7 @@ bool FrameFileIO::saveTraceFile(QString filename, const QVector<CANFrame> * fram
|
||||
|
||||
outFile->write(QString::number(frames->at(c).len).toUtf8() + "\t");
|
||||
|
||||
for (int temp = 0; temp < frames->at(c).len; temp++)
|
||||
for (unsigned int temp = 0; temp < frames->at(c).len; temp++)
|
||||
{
|
||||
outFile->write(QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8());
|
||||
outFile->putChar(' ');
|
||||
|
||||
+8
-2
@@ -22,6 +22,14 @@ class FrameFileIO: public QObject
|
||||
public:
|
||||
FrameFileIO();
|
||||
|
||||
//these present a GUI to the user and allow them to pick the file to load/save
|
||||
//The QString returns the filename that was selected and so is really a sort of return value
|
||||
//The QVector is used as either the target for loading or the source for saving.
|
||||
//These routines call the below loading/saving functions so no need to use them directly if you don't want.
|
||||
static bool loadFrameFile(QString &, QVector<CANFrame>*);
|
||||
static bool saveFrameFile(QString &, const QVector<CANFrame>*);
|
||||
|
||||
//These do the actual loading and saving and can be used directly if you'd prefer
|
||||
static bool loadCRTDFile(QString, QVector<CANFrame>*);
|
||||
static bool loadNativeCSVFile(QString, QVector<CANFrame>*);
|
||||
static bool loadGenericCSVFile(QString, QVector<CANFrame>*);
|
||||
@@ -40,8 +48,6 @@ public:
|
||||
static bool saveIXXATFile(QString, const QVector<CANFrame>*);
|
||||
static bool saveCANDOFile(QString, const QVector<CANFrame>*);
|
||||
static bool saveVehicleSpyFile(QString, const QVector<CANFrame>*);
|
||||
static bool loadFrameFile(QString &, QVector<CANFrame>*);
|
||||
static bool saveFrameFile(QString &, const QVector<CANFrame>*);
|
||||
static bool loadCanDumpFile(QString, QVector<CANFrame>*);
|
||||
static bool loadPCANFile(QString, QVector<CANFrame>*);
|
||||
|
||||
|
||||
+24
-29
@@ -4,6 +4,7 @@
|
||||
#include <QFileDialog>
|
||||
#include <QMenu>
|
||||
#include <QSettings>
|
||||
#include "connections/canconmanager.h"
|
||||
|
||||
/*
|
||||
* Notes about new functionality:
|
||||
@@ -18,22 +19,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
FramePlaybackWindow::FramePlaybackWindow(const QVector<CANFrame> *frames, SerialWorker *worker, QWidget *parent) :
|
||||
FramePlaybackWindow::FramePlaybackWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::FramePlaybackWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->comboCANBus->addItem(tr("None"));
|
||||
ui->comboCANBus->addItem(tr("0"));
|
||||
ui->comboCANBus->addItem(tr("1"));
|
||||
ui->comboCANBus->addItem(tr("Both"));
|
||||
|
||||
int numBuses = CANConManager::getInstance()->getNumBuses();
|
||||
for (int n = 0; n < numBuses; n++) ui->comboCANBus->addItem(QString::number(n));
|
||||
ui->comboCANBus->addItem(tr("All"));
|
||||
ui->comboCANBus->addItem(tr("From File"));
|
||||
|
||||
readSettings();
|
||||
|
||||
modelFrames = frames;
|
||||
serialWorker = worker;
|
||||
|
||||
playbackTimer = new QTimer();
|
||||
|
||||
@@ -70,9 +70,6 @@ FramePlaybackWindow::FramePlaybackWindow(const QVector<CANFrame> *frames, Serial
|
||||
|
||||
playbackTimer->setInterval(ui->spinPlaySpeed->value()); //set the timer to the default value of the control
|
||||
|
||||
connect(this, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int)), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(sendFrameBatch(const QList<CANFrame>*)), worker, SLOT(sendFrameBatch(const QList<CANFrame>*)), Qt::QueuedConnection);
|
||||
|
||||
QStringList headers;
|
||||
headers << "Source" << "Loops";
|
||||
ui->tblSequence->setColumnCount(2);
|
||||
@@ -85,8 +82,6 @@ FramePlaybackWindow::~FramePlaybackWindow()
|
||||
{
|
||||
delete ui;
|
||||
|
||||
disconnect(serialWorker);
|
||||
|
||||
playbackTimer->stop();
|
||||
delete playbackTimer;
|
||||
}
|
||||
@@ -405,7 +400,7 @@ void FramePlaybackWindow::btnBackOneClick()
|
||||
playbackActive = false;
|
||||
|
||||
updatePosition(false);
|
||||
emit sendFrameBatch(&sendingBuffer);
|
||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||
}
|
||||
|
||||
void FramePlaybackWindow::btnPauseClick()
|
||||
@@ -456,7 +451,7 @@ void FramePlaybackWindow::btnFwdOneClick()
|
||||
playbackTimer->stop();
|
||||
playbackActive = false;
|
||||
updatePosition(true);
|
||||
emit sendFrameBatch(&sendingBuffer);
|
||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||
}
|
||||
|
||||
void FramePlaybackWindow::changePlaybackSpeed(int newSpeed)
|
||||
@@ -471,8 +466,6 @@ void FramePlaybackWindow::changeLooping(bool check)
|
||||
|
||||
void FramePlaybackWindow::changeSendingBus(int newIdx)
|
||||
{
|
||||
//falls out neatly this way. 0 = no sending, 1 = bus 0, 2 = bus 1, 3 = both, 4 = from file
|
||||
//the index is exactly the same as the whichSendBus bitfield.
|
||||
whichBusSend = newIdx;
|
||||
}
|
||||
|
||||
@@ -522,7 +515,7 @@ void FramePlaybackWindow::timerTriggered()
|
||||
updatePosition(false);
|
||||
}
|
||||
}
|
||||
emit sendFrameBatch(&sendingBuffer);
|
||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||
}
|
||||
|
||||
void FramePlaybackWindow::updatePosition(bool forward)
|
||||
@@ -596,23 +589,25 @@ void FramePlaybackWindow::updatePosition(bool forward)
|
||||
int originalBus = thisFrame->bus;
|
||||
if (currentSeqItem->idFilters.find(thisFrame->ID).value())
|
||||
{
|
||||
//index 0 is none, 1 is Bus 0, 2 is bus 1, 3 is both, 4 is from file
|
||||
if (whichBusSend & 4)
|
||||
if (whichBusSend < ui->comboCANBus->count() - 2)
|
||||
{
|
||||
thisFrame->bus = whichBusSend;
|
||||
sendingBuffer.append(*thisFrame);
|
||||
}
|
||||
else if (whichBusSend == (ui->comboCANBus->count() - 2)) //all
|
||||
{
|
||||
for (int c = 0; c < ui->comboCANBus->count() - 2; c++)
|
||||
{
|
||||
thisFrame->bus = c;
|
||||
sendingBuffer.append(*thisFrame);
|
||||
}
|
||||
}
|
||||
else //from file so retain original bus and send as-is
|
||||
{
|
||||
sendingBuffer.append(*thisFrame);
|
||||
}
|
||||
if (whichBusSend & 1)
|
||||
{
|
||||
thisFrame->bus = 0;
|
||||
sendingBuffer.append(*thisFrame);
|
||||
}
|
||||
if (whichBusSend & 2)
|
||||
{
|
||||
thisFrame->bus = 1;
|
||||
sendingBuffer.append(*thisFrame);
|
||||
}
|
||||
|
||||
thisFrame->bus = originalBus;
|
||||
updateFrameLabel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <QListWidget>
|
||||
#include <QTimer>
|
||||
#include "can_structs.h"
|
||||
#include "serialworker.h"
|
||||
#include "framefileio.h"
|
||||
|
||||
namespace Ui {
|
||||
@@ -27,7 +26,7 @@ class FramePlaybackWindow : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FramePlaybackWindow(const QVector<CANFrame> *frames, SerialWorker *worker, QWidget *parent = 0);
|
||||
explicit FramePlaybackWindow(const QVector<CANFrame> *frames, QWidget *parent = 0);
|
||||
~FramePlaybackWindow();
|
||||
|
||||
private slots:
|
||||
@@ -53,10 +52,6 @@ private slots:
|
||||
void saveFilters();
|
||||
void loadFilters();
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
void sendFrameBatch(const QList<CANFrame> *);
|
||||
|
||||
private:
|
||||
Ui::FramePlaybackWindow *ui;
|
||||
QList<int> foundID;
|
||||
@@ -65,7 +60,6 @@ private:
|
||||
const QVector<CANFrame> *modelFrames;
|
||||
int currentPosition;
|
||||
QTimer *playbackTimer;
|
||||
SerialWorker *serialWorker;
|
||||
bool playbackActive;
|
||||
bool playbackForward;
|
||||
int whichBusSend;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QFileDialog>
|
||||
#include <QDebug>
|
||||
#include "mainwindow.h"
|
||||
#include "connections/canconmanager.h"
|
||||
|
||||
/*
|
||||
* notes: need to ensure that you grab pointers when modifying data structures and dont
|
||||
@@ -139,9 +140,9 @@ void FrameSenderWindow::processIncomingFrame(CANFrame *frame)
|
||||
Trigger *thisTrigger = &sendingData[sd].triggers[trig];
|
||||
qDebug() << "Trigger ID: " << thisTrigger->ID;
|
||||
qDebug() << "Frame ID: " << frame->ID;
|
||||
if (thisTrigger->ID > 0 && thisTrigger->ID == frame->ID)
|
||||
if (thisTrigger->ID > 0 && (uint32_t)thisTrigger->ID == frame->ID)
|
||||
{
|
||||
if (thisTrigger->bus == frame->bus || thisTrigger->bus == -1)
|
||||
if ((uint32_t)thisTrigger->bus == frame->bus || thisTrigger->bus == -1)
|
||||
{
|
||||
if (thisTrigger->currCount < thisTrigger->maxCount)
|
||||
{
|
||||
@@ -151,7 +152,7 @@ void FrameSenderWindow::processIncomingFrame(CANFrame *frame)
|
||||
sendingData[sd].count++;
|
||||
doModifiers(sd);
|
||||
updateGridRow(sd);
|
||||
sendCANFrame(&sendingData[sd], sendingData[sd].bus);
|
||||
CANConManager::getInstance()->sendFrame(sendingData[sd]);
|
||||
}
|
||||
else //delayed sending frame
|
||||
{
|
||||
@@ -354,7 +355,7 @@ void FrameSenderWindow::handleTick()
|
||||
doModifiers(i);
|
||||
updateGridRow(i);
|
||||
qDebug() << "About to try to send a frame";
|
||||
emit sendCANFrame(&sendingData[i], sendingData[i].bus);
|
||||
CANConManager::getInstance()->sendFrame(sendingData[i]);
|
||||
if (trigger->ID > 0) trigger->readyCount = false; //reset flag if this is a timed ID trigger
|
||||
}
|
||||
}
|
||||
@@ -457,7 +458,7 @@ CANFrame* FrameSenderWindow::lookupFrame(int ID, int bus)
|
||||
{
|
||||
if (!frameCache.contains(ID)) return NULL;
|
||||
|
||||
if (bus == -1 || frameCache[ID].bus == bus) return &frameCache[ID];
|
||||
if (bus == -1 || frameCache[ID].bus == (unsigned int)bus) return &frameCache[ID];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -471,7 +472,7 @@ void FrameSenderWindow::processModifierText(int line)
|
||||
{
|
||||
qDebug() << "processModifierText";
|
||||
QString modString;
|
||||
bool firstOp = true;
|
||||
//bool firstOp = true;
|
||||
bool abort = false;
|
||||
QString token;
|
||||
ModifierOp thisOp;
|
||||
@@ -495,7 +496,6 @@ void FrameSenderWindow::processModifierText(int line)
|
||||
{
|
||||
Modifier thisMod;
|
||||
thisMod.destByte = 0;
|
||||
firstOp = true;
|
||||
|
||||
QString leftSide = Utility::grabAlphaNumeric(mods[i]);
|
||||
if (leftSide.startsWith("D") && leftSide.length() == 2)
|
||||
@@ -701,7 +701,7 @@ void FrameSenderWindow::updateGridRow(int idx)
|
||||
QTableWidgetItem *item = ui->tableSender->item(gridLine, 7);
|
||||
if (item == NULL) item = new QTableWidgetItem();
|
||||
item->setText(QString::number(temp->count));
|
||||
for (int i = 0; i < temp->len; i++)
|
||||
for (unsigned int i = 0; i < temp->len; i++)
|
||||
{
|
||||
dataString.append(Utility::formatNumber(temp->data[i]));
|
||||
dataString.append(" ");
|
||||
|
||||
@@ -30,9 +30,6 @@ private slots:
|
||||
void loadGrid();
|
||||
void updatedFrames(int);
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
|
||||
private:
|
||||
Ui::FrameSenderWindow *ui;
|
||||
QList<FrameSendData> sendingData;
|
||||
|
||||
+79
-175
@@ -4,9 +4,8 @@
|
||||
#include <QDateTime>
|
||||
#include <QFileDialog>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include "canframemodel.h"
|
||||
#include "connections/canconmanager.h"
|
||||
#include "utility.h"
|
||||
#include "serialworker.h"
|
||||
|
||||
/*
|
||||
Compile for all platforms and create release (remember to include QScintilla libs) and make Win32 binary.
|
||||
@@ -47,7 +46,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
|
||||
this->setWindowTitle("Savvy CAN V" + QString::number(VERSION));
|
||||
|
||||
model = new CANFrameModel();
|
||||
model = new CANFrameModel(this); // set parent to mainwindow to prevent canframemodel to change thread (might be done by setModel but just in case)
|
||||
|
||||
ui->canFramesView->setModel(model);
|
||||
|
||||
readSettings();
|
||||
@@ -61,26 +61,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->canFramesView->setColumnWidth(6, 275);
|
||||
QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader();
|
||||
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
|
||||
//enabling the below line kills performance in every way imaginable. Left here as a warning. Do not do this.
|
||||
//ui->canFramesView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
worker = new SerialWorker(model);
|
||||
worker->moveToThread(&serialWorkerThread);
|
||||
connect(&serialWorkerThread, &QThread::finished, worker, &QObject::deleteLater);
|
||||
connect(&serialWorkerThread, &QThread::started, worker, &SerialWorker::run); //setup timers within the proper thread
|
||||
connect(this, &MainWindow::sendSerialPort, worker, &SerialWorker::setSerialPort, Qt::QueuedConnection);
|
||||
connect(worker, &SerialWorker::frameUpdateRapid, this, &MainWindow::gotFrames, Qt::QueuedConnection);
|
||||
connect(this, &MainWindow::updateBaudRates, worker, &SerialWorker::updateBaudRates, Qt::QueuedConnection);
|
||||
connect(this, &MainWindow::sendCANFrame, worker, &SerialWorker::sendFrame, Qt::QueuedConnection);
|
||||
connect(worker, &SerialWorker::connectionSuccess, this, &MainWindow::connectionSucceeded, Qt::QueuedConnection);
|
||||
connect(worker, &SerialWorker::connectionFailure, this, &MainWindow::connectionFailed, Qt::QueuedConnection);
|
||||
connect(worker, &SerialWorker::deviceInfo, this, &MainWindow::gotDeviceInfo, Qt::QueuedConnection);
|
||||
connect(this, &MainWindow::closeSerialPort, worker, &SerialWorker::closeSerialPort, Qt::QueuedConnection);
|
||||
connect(this, &MainWindow::startFrameCapturing, worker, &SerialWorker::startFrameCapture);
|
||||
connect(this, &MainWindow::stopFrameCapturing, worker, &SerialWorker::stopFrameCapture);
|
||||
connect(this, &MainWindow::settingsUpdated, worker, &SerialWorker::readSettings);
|
||||
serialWorkerThread.start();
|
||||
serialWorkerThread.setPriority(QThread::HighPriority);
|
||||
|
||||
graphingWindow = NULL;
|
||||
frameInfoWindow = NULL;
|
||||
@@ -100,6 +80,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
udsScanWindow = NULL;
|
||||
motorctrlConfigWindow = NULL;
|
||||
isoWindow = NULL;
|
||||
snifferWindow = NULL;
|
||||
bisectWindow = NULL;
|
||||
dbcHandler = new DBCHandler;
|
||||
bDirty = false;
|
||||
inhibitFilterUpdate = false;
|
||||
@@ -109,7 +91,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
model->setDBCHandler(dbcHandler);
|
||||
|
||||
connect(ui->actionSetup, SIGNAL(triggered(bool)), SLOT(showConnectionSettingsWindow()));
|
||||
connect(ui->actionConnect, SIGNAL(triggered(bool)), this, SLOT(connButtonPress()));
|
||||
connect(ui->actionOpen_Log_File, &QAction::triggered, this, &MainWindow::handleLoadFile);
|
||||
connect(ui->actionGraph_Dta, &QAction::triggered, this, &MainWindow::showGraphingWindow);
|
||||
connect(ui->actionFrame_Data_Analysis, &QAction::triggered, this, &MainWindow::showFrameDataAnalysis);
|
||||
@@ -144,9 +125,13 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
connect(ui->actionFuzzing, &QAction::triggered, this, &MainWindow::showFuzzingWindow);
|
||||
connect(ui->actionUDS_Scanner, &QAction::triggered, this, &MainWindow::showUDSScanWindow);
|
||||
connect(ui->actionISO_TP_Decoder, &QAction::triggered, this, &MainWindow::showISOInterpreterWindow);
|
||||
connect(ui->actionSniffer, &QAction::triggered, this, &MainWindow::showSnifferWindow);
|
||||
connect(ui->actionMotorControlConfig, &QAction::triggered, this, &MainWindow::showMCConfigWindow);
|
||||
connect(ui->actionCapture_Bisector, &QAction::triggered, this, &MainWindow::showBisectWindow);
|
||||
|
||||
lbStatusConnected.setText(tr("Not connected"));
|
||||
connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames);
|
||||
|
||||
lbStatusConnected.setText(tr("Connected to 0 buses"));
|
||||
updateFileStatus();
|
||||
lbStatusDatabase.setText(tr("No DBC database loaded"));
|
||||
ui->statusBar->addWidget(&lbStatusConnected);
|
||||
@@ -157,7 +142,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->lbNumFrames->setText("0");
|
||||
|
||||
connect(&updateTimer, &QTimer::timeout, this, &MainWindow::tickGUIUpdate);
|
||||
updateTimer.setInterval(250);
|
||||
updateTimer.setInterval(500); //test 250);
|
||||
updateTimer.start();
|
||||
|
||||
elapsedTime = new QTime;
|
||||
@@ -178,15 +163,19 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
qDebug() << "normal row height = " << normalRowHeight;
|
||||
model->clearFrames();
|
||||
|
||||
//connect(CANConManager::getInstance(), CANConManager::connectionStatusUpdated, this, MainWindow::connectionStatusUpdated);
|
||||
connect(CANConManager::getInstance(), SIGNAL(connectionStatusUpdated(int)), this, SLOT(connectionStatusUpdated(int)));
|
||||
|
||||
//Automatically create the connection window so it can be updated even if we never opened it.
|
||||
connectionWindow = new ConnectionWindow();
|
||||
connect(connectionWindow, SIGNAL(updateConnectionSettings(QString,QString,int,int)), this, SLOT(updateConnectionSettings(QString,QString,int,int)));
|
||||
connect(this, SIGNAL(suspendCapturing(bool)), connectionWindow, SLOT(setSuspendAll(bool)));
|
||||
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
serialWorkerThread.quit();
|
||||
serialWorkerThread.wait();
|
||||
//serialWorkerThread.quit();
|
||||
//serialWorkerThread.wait();
|
||||
//delete worker;
|
||||
|
||||
if (graphingWindow)
|
||||
@@ -284,13 +273,24 @@ MainWindow::~MainWindow()
|
||||
isoWindow->close();
|
||||
delete isoWindow;
|
||||
}
|
||||
if (snifferWindow)
|
||||
{
|
||||
snifferWindow->close();
|
||||
delete snifferWindow;
|
||||
snifferWindow = NULL;
|
||||
}
|
||||
|
||||
delete elapsedTime;
|
||||
if (bisectWindow)
|
||||
{
|
||||
bisectWindow->close();
|
||||
delete bisectWindow;
|
||||
bisectWindow = NULL;
|
||||
}
|
||||
|
||||
delete ui;
|
||||
delete dbcHandler;
|
||||
model->clearFrames();
|
||||
delete model;
|
||||
delete elapsedTime;
|
||||
delete dbcHandler;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::exitApp()
|
||||
@@ -311,6 +311,7 @@ void MainWindow::exitApp()
|
||||
if (fuzzingWindow) fuzzingWindow->close();
|
||||
if (udsScanWindow) udsScanWindow->close();
|
||||
if (isoWindow) isoWindow->close();
|
||||
if (snifferWindow) snifferWindow->close();
|
||||
this->close();
|
||||
}
|
||||
|
||||
@@ -340,16 +341,16 @@ void MainWindow::readSettings()
|
||||
ui->cbAutoScroll->setChecked(true);
|
||||
}
|
||||
|
||||
/*
|
||||
int cType = settings.value("Main/DefaultConnectionType", 0).toInt();
|
||||
if (cType == 0) connType = "GVRET";
|
||||
if (cType == 1) connType = "KVASER";
|
||||
if (cType == 2) connType = "SOCKETCAN";
|
||||
portName = settings.value("Main/DefaultConnectionPort", "").toString();
|
||||
canSpeed0 = -1;
|
||||
canSpeed1 = -1;
|
||||
*/
|
||||
|
||||
qDebug() << connType;
|
||||
qDebug() << portName;
|
||||
//qDebug() << connType;
|
||||
//qDebug() << portName;
|
||||
|
||||
//"Main/SingleWireMode"
|
||||
|
||||
@@ -380,52 +381,18 @@ void MainWindow::writeSettings()
|
||||
|
||||
void MainWindow::updateConnectionSettings(QString connectionType, QString port, int speed0, int speed1)
|
||||
{
|
||||
connType = connectionType;
|
||||
portName = port;
|
||||
Q_UNUSED(connectionType);
|
||||
Q_UNUSED(port);
|
||||
Q_UNUSED(speed0);
|
||||
Q_UNUSED(speed1);
|
||||
//connType = connectionType;
|
||||
//portName = port;
|
||||
|
||||
canSpeed0 = speed0;
|
||||
canSpeed1 = speed1;
|
||||
//canSpeed0 = speed0;
|
||||
//canSpeed1 = speed1;
|
||||
if (isConnected)
|
||||
{
|
||||
emit updateBaudRates(speed0, speed1);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::connButtonPress()
|
||||
{
|
||||
if (!isConnected)
|
||||
{
|
||||
if (connType == "GVRET")
|
||||
{
|
||||
QList<QSerialPortInfo> ports;
|
||||
ports = QSerialPortInfo::availablePorts();
|
||||
|
||||
for (int i = 0; i < ports.count(); i++)
|
||||
{
|
||||
if (ports[i].portName() == portName)
|
||||
{
|
||||
portInfo = ports[i];
|
||||
//need to create some way to send single wire mode to serial port code
|
||||
emit sendSerialPort(&portInfo);
|
||||
lbStatusConnected.setText(tr("Attempting to connect to port ") + portName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (connType == "KVASER")
|
||||
{
|
||||
|
||||
}
|
||||
else if (connType == "SOCKETCAN")
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
emit closeSerialPort();
|
||||
isConnected = false;
|
||||
lbStatusConnected.setText(tr("Not Connected"));
|
||||
ui->actionConnect->setText(tr("Connect"));
|
||||
//emit updateBaudRates(speed0, speed1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,19 +484,20 @@ void MainWindow::filterClearAll()
|
||||
|
||||
void MainWindow::tickGUIUpdate()
|
||||
{
|
||||
rxFrames = model->sendBulkRefresh();
|
||||
//if(rxFrames>0)
|
||||
//{
|
||||
int elapsed = elapsedTime->elapsed();
|
||||
if(elapsed) {
|
||||
framesPerSec += rxFrames * 1000 / elapsed - (framesPerSec / 4);
|
||||
framesPerSec = rxFrames * 1000 / elapsed;
|
||||
elapsedTime->restart();
|
||||
}
|
||||
else
|
||||
framesPerSec = 0;
|
||||
|
||||
model->sendBulkRefresh(rxFrames);
|
||||
|
||||
ui->lbNumFrames->setText(QString::number(model->rowCount()));
|
||||
if (ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom();
|
||||
ui->lbFPS->setText(QString::number(framesPerSec / 4));
|
||||
ui->lbFPS->setText(QString::number(framesPerSec));
|
||||
if (rxFrames > 0)
|
||||
{
|
||||
bDirty = true;
|
||||
@@ -539,6 +507,7 @@ void MainWindow::tickGUIUpdate()
|
||||
if (model->needsFilterRefresh()) updateFilterList();
|
||||
|
||||
rxFrames = 0;
|
||||
//}
|
||||
}
|
||||
|
||||
void MainWindow::gotFrames(int framesSinceLastUpdate)
|
||||
@@ -572,6 +541,7 @@ void MainWindow::clearFrames()
|
||||
{
|
||||
ui->canFramesView->scrollToTop();
|
||||
model->clearFrames();
|
||||
CANConManager::getInstance()->resetTimeBasis();
|
||||
ui->lbNumFrames->setText(QString::number(model->rowCount()));
|
||||
bDirty = false;
|
||||
loadedFileName = "";
|
||||
@@ -585,16 +555,6 @@ void MainWindow::normalizeTiming()
|
||||
emit framesUpdated(-2); //claim an all new set of frames because every frame was updated.
|
||||
}
|
||||
|
||||
void MainWindow::changeBaudRates()
|
||||
{
|
||||
int Speed1 = 0, Speed2 = 0;
|
||||
|
||||
//Speed1 = ui->cbSpeed1->currentText().toInt();
|
||||
//Speed2 = ui->cbSpeed2->currentText().toInt();
|
||||
|
||||
emit updateBaudRates(Speed1, Speed2);
|
||||
}
|
||||
|
||||
void MainWindow::handleLoadFile()
|
||||
{
|
||||
QString filename;
|
||||
@@ -726,7 +686,7 @@ Data Bytes: 88 10 00 13 BB 00 06 00
|
||||
outFile->write(builderString.toUtf8());
|
||||
|
||||
builderString = tr("Data Bytes: ");
|
||||
for (int temp = 0; temp < thisFrame.len; temp++)
|
||||
for (unsigned int temp = 0; temp < thisFrame.len; temp++)
|
||||
{
|
||||
builderString += Utility::formatNumber(thisFrame.data[temp]) + " ";
|
||||
}
|
||||
@@ -761,52 +721,16 @@ void MainWindow::toggleCapture()
|
||||
{
|
||||
allowCapture = !allowCapture;
|
||||
if (allowCapture)
|
||||
{
|
||||
ui->btnCaptureToggle->setText("Suspend Capturing");
|
||||
emit startFrameCapturing();
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->btnCaptureToggle->setText("Restart Capturing");
|
||||
emit stopFrameCapturing();
|
||||
}
|
||||
|
||||
emit suspendCapturing(!allowCapture);
|
||||
}
|
||||
|
||||
void MainWindow::connectionSucceeded(int baud0, int baud1)
|
||||
void MainWindow::connectionStatusUpdated(int conns)
|
||||
{
|
||||
lbStatusConnected.setText(tr("Connected to GVRET"));
|
||||
//finally, find the baud rate in the list of rates or
|
||||
//add it to the bottom if needed (that'll be weird though...
|
||||
/*
|
||||
int idx = ui->cbSpeed1->findText(QString::number(baud0));
|
||||
if (idx > -1) ui->cbSpeed1->setCurrentIndex(idx);
|
||||
else
|
||||
{
|
||||
ui->cbSpeed1->addItem(QString::number(baud0));
|
||||
ui->cbSpeed1->setCurrentIndex(ui->cbSpeed1->count() - 1);
|
||||
}
|
||||
|
||||
idx = ui->cbSpeed2->findText(QString::number(baud1));
|
||||
if (idx > -1) ui->cbSpeed2->setCurrentIndex(idx);
|
||||
else
|
||||
{
|
||||
ui->cbSpeed2->addItem(QString::number(baud1));
|
||||
ui->cbSpeed2->setCurrentIndex(ui->cbSpeed2->count() - 1);
|
||||
}
|
||||
*/
|
||||
if (connectionWindow) connectionWindow->setSpeeds(baud0, baud1);
|
||||
//ui->btnConnect->setEnabled(false);
|
||||
ui->actionConnect->setText(tr("Disconnect"));
|
||||
isConnected = true;
|
||||
}
|
||||
|
||||
void MainWindow::connectionFailed()
|
||||
{
|
||||
lbStatusConnected.setText(tr("Failed to connect!"));
|
||||
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("Connection to the GVRET firmware failed.\nYou might have an old version of GVRET\nor may have chosen the wrong serial port.");
|
||||
msgBox.exec();
|
||||
lbStatusConnected.setText(tr("Connected to ") + QString::number(conns) + tr(" buses"));
|
||||
}
|
||||
|
||||
void MainWindow::updateFileStatus()
|
||||
@@ -835,33 +759,6 @@ void MainWindow::updateFileStatus()
|
||||
lbStatusFilename.setText(output);
|
||||
}
|
||||
|
||||
void MainWindow::gotDeviceInfo(int build, int swCAN)
|
||||
{
|
||||
QString str = tr("Connected to GVRET ") + QString::number(build);
|
||||
if (swCAN == 1) str += "(SW)";
|
||||
lbStatusConnected.setText(str);
|
||||
|
||||
if (build < CURRENT_GVRET_VER)
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("It appears that you are not running\nan up-to-date version of GVRET\n\nYour version: "
|
||||
+ QString::number(build) +"\nCurrent Version: " + QString::number(CURRENT_GVRET_VER)
|
||||
+ "\n\nPlease upgrade your firmware version.\nOtherwise, you may experience difficulties.");
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
if (connectionWindow)
|
||||
{
|
||||
if (swCAN == 1) connectionWindow->setCAN1SWMode(true);
|
||||
else connectionWindow->setCAN1SWMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setTargettedID(int id)
|
||||
{
|
||||
worker->targetFrameID(id);
|
||||
}
|
||||
|
||||
void MainWindow::showSettingsDialog()
|
||||
{
|
||||
if (!settingsDialog)
|
||||
@@ -914,6 +811,22 @@ void MainWindow::showISOInterpreterWindow()
|
||||
isoWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::showSnifferWindow()
|
||||
{
|
||||
if (!snifferWindow)
|
||||
snifferWindow = new SnifferWindow(this);
|
||||
snifferWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::showBisectWindow()
|
||||
{
|
||||
if (!bisectWindow)
|
||||
{
|
||||
bisectWindow = new BisectWindow(model->getListReference());
|
||||
}
|
||||
bisectWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::showFrameSenderWindow()
|
||||
{
|
||||
if (!frameSenderWindow)
|
||||
@@ -922,8 +835,6 @@ void MainWindow::showFrameSenderWindow()
|
||||
frameSenderWindow = new FrameSenderWindow(model->getListReference());
|
||||
else
|
||||
frameSenderWindow = new FrameSenderWindow(model->getFilteredListReference());
|
||||
|
||||
connect(frameSenderWindow, &FrameSenderWindow::sendCANFrame, worker, &SerialWorker::sendFrame);
|
||||
}
|
||||
frameSenderWindow->show();
|
||||
}
|
||||
@@ -933,9 +844,9 @@ void MainWindow::showPlaybackWindow()
|
||||
if (!playbackWindow)
|
||||
{
|
||||
if (!useFiltered)
|
||||
playbackWindow = new FramePlaybackWindow(model->getListReference(), worker);
|
||||
playbackWindow = new FramePlaybackWindow(model->getListReference());
|
||||
else
|
||||
playbackWindow = new FramePlaybackWindow(model->getFilteredListReference(), worker);
|
||||
playbackWindow = new FramePlaybackWindow(model->getFilteredListReference());
|
||||
}
|
||||
playbackWindow->show();
|
||||
}
|
||||
@@ -945,8 +856,6 @@ void MainWindow::showFirmwareUploaderWindow()
|
||||
if (!firmwareUploaderWindow)
|
||||
{
|
||||
firmwareUploaderWindow = new FirmwareUploaderWindow(model->getListReference());
|
||||
connect(firmwareUploaderWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int)));
|
||||
connect(worker, SIGNAL(gotTargettedFrame(int)), firmwareUploaderWindow, SLOT(gotTargettedFrame(int)));
|
||||
}
|
||||
firmwareUploaderWindow->show();
|
||||
}
|
||||
@@ -974,8 +883,6 @@ void MainWindow::showFuzzingWindow()
|
||||
if (!fuzzingWindow)
|
||||
{
|
||||
fuzzingWindow = new FuzzingWindow(model->getListReference());
|
||||
connect(fuzzingWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int)));
|
||||
connect(fuzzingWindow, SIGNAL(sendFrameBatch(const QList<CANFrame>*)), worker, SLOT(sendFrameBatch(const QList<CANFrame>*)));
|
||||
}
|
||||
fuzzingWindow->show();
|
||||
}
|
||||
@@ -985,8 +892,8 @@ void MainWindow::showMCConfigWindow()
|
||||
if (!motorctrlConfigWindow)
|
||||
{
|
||||
motorctrlConfigWindow = new MotorControllerConfigWindow(model->getListReference());
|
||||
connect(motorctrlConfigWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int)));
|
||||
connect(motorctrlConfigWindow, SIGNAL(sendFrameBatch(const QList<CANFrame>*)), worker, SLOT(sendFrameBatch(const QList<CANFrame>*)));
|
||||
//connect(motorctrlConfigWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int)));
|
||||
//connect(motorctrlConfigWindow, SIGNAL(sendFrameBatch(const QList<CANFrame>*)), worker, SLOT(sendFrameBatch(const QList<CANFrame>*)));
|
||||
}
|
||||
motorctrlConfigWindow->show();
|
||||
}
|
||||
@@ -996,7 +903,6 @@ void MainWindow::showUDSScanWindow()
|
||||
if (!udsScanWindow)
|
||||
{
|
||||
udsScanWindow = new UDSScanWindow(model->getListReference());
|
||||
connect(udsScanWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int)));
|
||||
}
|
||||
udsScanWindow->show();
|
||||
}
|
||||
@@ -1006,7 +912,6 @@ void MainWindow::showScriptingWindow()
|
||||
if (!scriptingWindow)
|
||||
{
|
||||
scriptingWindow = new ScriptingWindow(model->getListReference());
|
||||
connect(scriptingWindow, &ScriptingWindow::sendCANFrame, worker, &SerialWorker::sendFrame);
|
||||
}
|
||||
scriptingWindow->show();
|
||||
}
|
||||
@@ -1060,7 +965,6 @@ void MainWindow::showConnectionSettingsWindow()
|
||||
if (!connectionWindow)
|
||||
{
|
||||
connectionWindow = new ConnectionWindow();
|
||||
connect(connectionWindow, SIGNAL(updateConnectionSettings(QString,QString,int,int)), this, SLOT(updateConnectionSettings(QString,QString,int,int)));
|
||||
}
|
||||
connectionWindow->show();
|
||||
}
|
||||
|
||||
+23
-29
@@ -8,26 +8,30 @@
|
||||
#include "canframemodel.h"
|
||||
#include "can_structs.h"
|
||||
#include "framefileio.h"
|
||||
#include "graphingwindow.h"
|
||||
#include "frameinfowindow.h"
|
||||
#include "re/graphingwindow.h"
|
||||
#include "re/frameinfowindow.h"
|
||||
#include "frameplaybackwindow.h"
|
||||
#include "flowviewwindow.h"
|
||||
#include "bisectwindow.h"
|
||||
#include "re/flowviewwindow.h"
|
||||
#include "framesenderwindow.h"
|
||||
#include "filecomparatorwindow.h"
|
||||
#include "dbchandler.h"
|
||||
#include "dbcmaineditor.h"
|
||||
#include "re/filecomparatorwindow.h"
|
||||
#include "dbc/dbchandler.h"
|
||||
#include "dbc/dbcmaineditor.h"
|
||||
#include "mainsettingsdialog.h"
|
||||
#include "firmwareuploaderwindow.h"
|
||||
#include "discretestatewindow.h"
|
||||
#include "connectionwindow.h"
|
||||
#include "re/discretestatewindow.h"
|
||||
#include "connections/connectionwindow.h"
|
||||
#include "scriptingwindow.h"
|
||||
#include "rangestatewindow.h"
|
||||
#include "dbcloadsavewindow.h"
|
||||
#include "fuzzingwindow.h"
|
||||
#include "udsscanwindow.h"
|
||||
#include "isotp_interpreterwindow.h"
|
||||
#include "re/rangestatewindow.h"
|
||||
#include "dbc/dbcloadsavewindow.h"
|
||||
#include "re/fuzzingwindow.h"
|
||||
#include "re/udsscanwindow.h"
|
||||
#include "re/sniffer/snifferwindow.h"
|
||||
#include "re/isotp_interpreterwindow.h"
|
||||
#include "motorcontrollerconfigwindow.h"
|
||||
|
||||
class ConnectionWindow;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
@@ -40,7 +44,6 @@ public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
static QString loadedFileName;
|
||||
static MainWindow *getReference();
|
||||
void setTargettedID(int);
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
@@ -49,7 +52,6 @@ private slots:
|
||||
void handleSaveFilteredFile();
|
||||
void handleSaveFilters();
|
||||
void handleLoadFilters();
|
||||
void connButtonPress();
|
||||
void showGraphingWindow();
|
||||
void showFrameDataAnalysis();
|
||||
void clearFrames();
|
||||
@@ -69,12 +71,11 @@ private slots:
|
||||
void showMCConfigWindow();
|
||||
void showUDSScanWindow();
|
||||
void showISOInterpreterWindow();
|
||||
void showSnifferWindow();
|
||||
void showBisectWindow();
|
||||
void exitApp();
|
||||
void handleSaveDecoded();
|
||||
void changeBaudRates();
|
||||
void connectionFailed();
|
||||
void gotDeviceInfo(int, int);
|
||||
void connectionSucceeded(int, int);
|
||||
void connectionStatusUpdated(int conns);
|
||||
void gridClicked(QModelIndex);
|
||||
void gridDoubleClicked(QModelIndex);
|
||||
void interpretToggled(bool);
|
||||
@@ -94,12 +95,8 @@ public slots:
|
||||
void updateConnectionSettings(QString connectionType, QString port, int speed0, int speed1);
|
||||
|
||||
signals:
|
||||
void sendSerialPort(QSerialPortInfo *port);
|
||||
void closeSerialPort();
|
||||
void updateBaudRates(int, int);
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
void stopFrameCapturing();
|
||||
void startFrameCapturing();
|
||||
void suspendCapturing(bool);
|
||||
|
||||
//-1 = frames cleared, -2 = a new file has been loaded (so all frames are different), otherwise # of new frames
|
||||
void framesUpdated(int numFrames); //something has updated the frame list
|
||||
@@ -114,8 +111,6 @@ private:
|
||||
//canbus related data
|
||||
CANFrameModel *model;
|
||||
DBCHandler *dbcHandler;
|
||||
QThread serialWorkerThread;
|
||||
SerialWorker *worker;
|
||||
QByteArray inputBuffer;
|
||||
QTimer updateTimer;
|
||||
QTime *elapsedTime;
|
||||
@@ -146,7 +141,9 @@ private:
|
||||
FuzzingWindow *fuzzingWindow;
|
||||
UDSScanWindow *udsScanWindow;
|
||||
ISOTP_InterpreterWindow *isoWindow;
|
||||
SnifferWindow* snifferWindow;
|
||||
MotorControllerConfigWindow *motorctrlConfigWindow;
|
||||
BisectWindow* bisectWindow;
|
||||
|
||||
//various private storage
|
||||
QLabel lbStatusConnected;
|
||||
@@ -154,9 +151,6 @@ private:
|
||||
QLabel lbStatusDatabase;
|
||||
int normalRowHeight;
|
||||
bool isConnected;
|
||||
QSerialPortInfo portInfo;
|
||||
QString connType, portName;
|
||||
int canSpeed0, canSpeed1;
|
||||
|
||||
//private methods
|
||||
void saveDecodedTextFile(QString);
|
||||
|
||||
@@ -267,6 +267,8 @@ void DiscreteStateWindow::handleTick()
|
||||
{
|
||||
case DWStates::IDLE:
|
||||
break;
|
||||
case DWStates::DONE:
|
||||
break;
|
||||
case DWStates::COUNTDOWN_SIGNAL:
|
||||
ticksUntilStateChange--;
|
||||
if (ticksUntilStateChange == 0)
|
||||
@@ -334,7 +336,7 @@ void DiscreteStateWindow::calculateResults()
|
||||
frameCache.clear();
|
||||
for (int i = 0; i < modelFrames->count(); i++)
|
||||
{
|
||||
if (modelFrames->at(i).ID == it.key()) frameCache.append(modelFrames->at(i));
|
||||
if (modelFrames->at(i).ID == (unsigned int)it.key()) frameCache.append(modelFrames->at(i));
|
||||
}
|
||||
for (int bits = maxBits; bits >= minBits; bits--)
|
||||
{
|
||||
@@ -112,7 +112,7 @@ void FileComparatorWindow::calculateDetails()
|
||||
CANFrame frame = interestedFrames.at(x);
|
||||
if (interestedIDs.contains(frame.ID)) //if we saw this ID before then add to the QList in there
|
||||
{
|
||||
for (int y = 0; y < frame.len; y++)
|
||||
for (unsigned int y = 0; y < frame.len; y++)
|
||||
{
|
||||
interestedIDs[frame.ID].values[y][frame.data[y]]++;
|
||||
tmp = frame.data[y];
|
||||
@@ -137,7 +137,7 @@ void FileComparatorWindow::calculateDetails()
|
||||
}
|
||||
}
|
||||
//memset(newData->values, 0, 256 * 8);
|
||||
for (int y = 0; y < frame.len; y++)
|
||||
for (unsigned int y = 0; y < frame.len; y++)
|
||||
{
|
||||
newData->values[y][frame.data[y]] = 1;
|
||||
tmp = frame.data[y];
|
||||
@@ -154,7 +154,7 @@ void FileComparatorWindow::calculateDetails()
|
||||
CANFrame frame = referenceFrames.at(x);
|
||||
if (referenceIDs.contains(frame.ID)) //if we saw this ID before then add to the QList in there
|
||||
{
|
||||
for (int y = 0; y < frame.len; y++)
|
||||
for (unsigned int y = 0; y < frame.len; y++)
|
||||
{
|
||||
referenceIDs[frame.ID].values[y][frame.data[y]]++;
|
||||
tmp = frame.data[y];
|
||||
@@ -177,7 +177,7 @@ void FileComparatorWindow::calculateDetails()
|
||||
}
|
||||
}
|
||||
//memset(newData->values, 0, 256 * 8);
|
||||
for (int y = 0; y < frame.len; y++)
|
||||
for (unsigned int y = 0; y < frame.len; y++)
|
||||
{
|
||||
newData->values[y][frame.data[y]] = 1;
|
||||
tmp = frame.data[y];
|
||||
@@ -371,7 +371,7 @@ void FlowViewWindow::updatedFrames(int numFrames)
|
||||
else //just got some new frames. See if they are relevant.
|
||||
{
|
||||
if (numFrames > modelFrames->count()) return;
|
||||
int refID;
|
||||
unsigned int refID;
|
||||
if (frameCache.count() > 0) refID = frameCache[0].ID;
|
||||
else refID = 0;
|
||||
bool needRefresh = false;
|
||||
@@ -382,7 +382,7 @@ void FlowViewWindow::updatedFrames(int numFrames)
|
||||
if (!foundID.contains(thisFrame.ID))
|
||||
{
|
||||
foundID.append(thisFrame.ID);
|
||||
QListWidgetItem* item = new QListWidgetItem(Utility::formatNumber(thisFrame.ID), ui->listFrameID);
|
||||
/*QListWidgetItem* item =*/ new QListWidgetItem(Utility::formatNumber(thisFrame.ID), ui->listFrameID);
|
||||
}
|
||||
|
||||
if (thisFrame.ID == refID)
|
||||
@@ -495,7 +495,7 @@ void FlowViewWindow::refreshIDList()
|
||||
if (!foundID.contains(id))
|
||||
{
|
||||
foundID.append(id);
|
||||
QListWidgetItem* item = new QListWidgetItem(Utility::formatNumber(id), ui->listFrameID);
|
||||
/*QListWidgetItem* item = */ new QListWidgetItem(Utility::formatNumber(id), ui->listFrameID);
|
||||
}
|
||||
}
|
||||
//default is to sort in ascending order
|
||||
@@ -510,7 +510,7 @@ void FlowViewWindow::updateFrameLabel()
|
||||
void FlowViewWindow::changeID(QString newID)
|
||||
{
|
||||
//parse the ID and then load up the frame cache with just messages with that ID.
|
||||
int id = Utility::ParseStringToNum(newID);
|
||||
uint32_t id = (uint32_t)Utility::ParseStringToNum(newID);
|
||||
frameCache.clear();
|
||||
|
||||
if (modelFrames->count() == 0) return;
|
||||
@@ -531,7 +531,7 @@ void FlowViewWindow::changeID(QString newID)
|
||||
if (frameCache.count() == 0) return;
|
||||
|
||||
removeAllGraphs();
|
||||
for (int c = 0; c < frameCache.at(0).len; c++)
|
||||
for (uint32_t c = 0; c < frameCache.at(0).len; c++)
|
||||
{
|
||||
createGraph(c);
|
||||
}
|
||||
@@ -84,7 +84,7 @@ void FrameInfoWindow::updatedFrames(int numFrames)
|
||||
else //just got some new frames. See if they are relevant.
|
||||
{
|
||||
if (numFrames > modelFrames->count()) return;
|
||||
int currID = 0;
|
||||
unsigned int currID = 0;
|
||||
if (ui->listFrameID->currentItem())
|
||||
currID = ui->listFrameID->currentItem()->text().toInt(NULL, 16);
|
||||
bool foundID = false;
|
||||
@@ -140,7 +140,7 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
||||
for (int i = 0; i < modelFrames->count(); i++)
|
||||
{
|
||||
CANFrame thisFrame = modelFrames->at(i);
|
||||
if (thisFrame.ID == targettedID) frameCache.append(thisFrame);
|
||||
if (thisFrame.ID == (unsigned int)targettedID) frameCache.append(thisFrame);
|
||||
}
|
||||
|
||||
ui->treeDetails->clear();
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "utility.h"
|
||||
#include <QDebug>
|
||||
#include "mainwindow.h"
|
||||
#include "connections/canconmanager.h"
|
||||
|
||||
FuzzingWindow::FuzzingWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@@ -36,9 +37,10 @@ FuzzingWindow::FuzzingWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
|
||||
fuzzTimer->setInterval(ui->spinTiming->value());
|
||||
|
||||
ui->cbBuses->addItem(tr("0"));
|
||||
ui->cbBuses->addItem(tr("1"));
|
||||
ui->cbBuses->addItem(tr("Both"));
|
||||
int numBuses = CANConManager::getInstance()->getNumBuses();
|
||||
for (int n = 0; n < numBuses; n++) ui->cbBuses->addItem(QString::number(n));
|
||||
ui->cbBuses->addItem(tr("All"));
|
||||
|
||||
}
|
||||
|
||||
FuzzingWindow::~FuzzingWindow()
|
||||
@@ -48,7 +50,6 @@ FuzzingWindow::~FuzzingWindow()
|
||||
|
||||
void FuzzingWindow::updatedFrames(int numFrames)
|
||||
{
|
||||
CANFrame thisFrame;
|
||||
int id;
|
||||
if (numFrames == -1) //all frames deleted. Kill the display
|
||||
{
|
||||
@@ -111,8 +112,7 @@ void FuzzingWindow::timerTriggered()
|
||||
{
|
||||
CANFrame thisFrame;
|
||||
sendingBuffer.clear();
|
||||
int buses = ui->cbBuses->currentIndex() + 1;
|
||||
if (buses == 0) buses = 1;
|
||||
int buses = ui->cbBuses->currentIndex();
|
||||
for (int count = 0; count < ui->spinBurst->value(); count++)
|
||||
{
|
||||
thisFrame.ID = currentID;
|
||||
@@ -121,22 +121,26 @@ void FuzzingWindow::timerTriggered()
|
||||
else thisFrame.extended = false;
|
||||
thisFrame.bus = 0; //hard coded for now. TODO: do not hard code
|
||||
thisFrame.len = ui->spinBytes->value();
|
||||
if (buses & 1)
|
||||
|
||||
if (buses < (ui->cbBuses->count() - 1))
|
||||
{
|
||||
thisFrame.bus = 0;
|
||||
thisFrame.bus = buses;
|
||||
sendingBuffer.append(thisFrame);
|
||||
}
|
||||
if (buses & 2)
|
||||
else //fuzz all the buses! HACK THE PLANET! Er, something...
|
||||
{
|
||||
thisFrame.bus = 1;
|
||||
for (int j = 0; j < ui->cbBuses->count() - 1; j++)
|
||||
{
|
||||
thisFrame.bus = j;
|
||||
sendingBuffer.append(thisFrame);
|
||||
}
|
||||
}
|
||||
|
||||
calcNextID();
|
||||
calcNextBitPattern();
|
||||
numSentFrames++;
|
||||
}
|
||||
emit sendFrameBatch(&sendingBuffer);
|
||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||
ui->lblNumFrames->setText("# of sent frames: " + QString::number(numSentFrames));
|
||||
}
|
||||
|
||||
@@ -252,7 +256,7 @@ void FuzzingWindow::calcNextBitPattern()
|
||||
for (int bit = 0; bit < 8; bit++)
|
||||
{
|
||||
thisBit = bitGrid[byt * 8 + bit];
|
||||
if (thisBit == 1 && (byt * 8 + bit) == bitAccum)
|
||||
if ( (thisBit == 1) && (unsigned int)(byt * 8 + bit) == bitAccum)
|
||||
{
|
||||
currentBytes[byt] |= (1 << bit);
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
~FuzzingWindow();
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
void sendCANFrame(const CANFrame *);
|
||||
void sendFrameBatch(const QList<CANFrame> *);
|
||||
|
||||
private slots:
|
||||
@@ -178,6 +178,7 @@ void GraphingWindow::plottableDoubleClick(QCPAbstractPlottable* plottable, QMous
|
||||
|
||||
void GraphingWindow::gotCenterTimeID(int32_t ID, double timestamp)
|
||||
{
|
||||
Q_UNUSED(ID)
|
||||
//its problematic to try to highlight a graph since we get the ID
|
||||
//and timestamp not the signal in question so there is no real way
|
||||
//to know which graph. But, if that changes here is a stub
|
||||
@@ -195,8 +196,8 @@ void GraphingWindow::gotCenterTimeID(int32_t ID, double timestamp)
|
||||
void GraphingWindow::titleDoubleClick(QMouseEvent* event, QCPPlotTitle* title)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(title)
|
||||
// Set the plot title by double clicking on it
|
||||
bool ok;
|
||||
|
||||
/*
|
||||
QString newTitle = QInputDialog::getText(this, "SavvyCAN Graphing", "New plot title:", QLineEdit::Normal, title->text(), &ok);
|
||||
@@ -354,6 +355,8 @@ bool GraphingWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
// standard event processing
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GraphingWindow::resetView()
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "qcustomplot.h"
|
||||
#include "can_structs.h"
|
||||
#include "dbchandler.h"
|
||||
#include "dbc/dbchandler.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
@@ -151,7 +151,7 @@ void ISOTP_HANDLER::processFrame(const CANFrame &frame)
|
||||
int frameType;
|
||||
int frameLen;
|
||||
int ln;
|
||||
int offset;
|
||||
//int offset;
|
||||
ISOTP_MESSAGE msg;
|
||||
ISOTP_MESSAGE *pMsg;
|
||||
|
||||
@@ -230,7 +230,7 @@ void ISOTP_HANDLER::processFrame(const CANFrame &frame)
|
||||
}
|
||||
if (!pMsg) return;
|
||||
ln = pMsg->len - pMsg->data.count();
|
||||
offset = pMsg->data.count();
|
||||
//offset = pMsg->data.count();
|
||||
if (useExtendedAddressing)
|
||||
{
|
||||
if (ln > 6) ln = 6;
|
||||
@@ -145,7 +145,6 @@ void NewGraphDialog::loadSignals(int idx)
|
||||
void NewGraphDialog::bitfieldClicked(int x,int y)
|
||||
{
|
||||
int bit = (y * 8 + (7-x));
|
||||
int res;
|
||||
|
||||
qDebug() << "Clicked bit: " << bit;
|
||||
startBit = bit;
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include "graphingwindow.h"
|
||||
#include "dbchandler.h"
|
||||
#include "dbc/dbchandler.h"
|
||||
|
||||
namespace Ui {
|
||||
class NewGraphDialog;
|
||||
@@ -171,7 +171,7 @@ void RangeStateWindow::refreshFilterList()
|
||||
void RangeStateWindow::recalcButton()
|
||||
{
|
||||
QHash<int, bool>::iterator iter;
|
||||
int id;
|
||||
uint32_t id;
|
||||
|
||||
ui->listCandidates->clear();
|
||||
foundSignals.clear();
|
||||
@@ -376,7 +376,7 @@ void RangeStateWindow::createGraph(QVector<int> values)
|
||||
else ymin *= 0.8;
|
||||
|
||||
ymax = maxval;
|
||||
if (ymax < 0) ymax * 0.8;
|
||||
if (ymax < 0) ymax *= 0.8;
|
||||
else ymax *= 1.2;
|
||||
|
||||
if (fabs(ymin) < 0.01) ymin -= (ymax / 60.0);
|
||||
@@ -401,7 +401,7 @@ void RangeStateWindow::clickedSignalList(int idx)
|
||||
{
|
||||
if (idx == -1) return; //just in case...
|
||||
|
||||
int id, startBit, bitLength;
|
||||
uint32_t id, startBit, bitLength;
|
||||
bool isSigned = false, isBigEndian = false;
|
||||
int64_t valu;
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include "snifferitem.h"
|
||||
|
||||
|
||||
SnifferItem::SnifferItem(const CANFrame& pFrame):
|
||||
mNotch(0),
|
||||
mID(pFrame.ID)
|
||||
{
|
||||
mMarker = {0,0};
|
||||
mLastMarker = {0,0};
|
||||
/* that's dirty */
|
||||
update(pFrame);
|
||||
update(pFrame);
|
||||
}
|
||||
|
||||
|
||||
SnifferItem::~SnifferItem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
quint64 SnifferItem::getId() const
|
||||
{
|
||||
return mID;
|
||||
}
|
||||
|
||||
float SnifferItem::getDelta() const
|
||||
{
|
||||
return ((float)(mCurrentTime-mLastTime))/1000000;
|
||||
}
|
||||
|
||||
int SnifferItem::getData(uchar i) const
|
||||
{
|
||||
return (i>=mCurrent.len) ? -1 : ((uchar*) &mCurrent.data)[i];
|
||||
}
|
||||
|
||||
dc SnifferItem::dataChange(uchar i) const
|
||||
{
|
||||
if( i<mCurrent.len &&
|
||||
((uchar*) &mLastMarker.data)[i] &&
|
||||
!((uchar*) &mNotch)[i] )
|
||||
{
|
||||
return ((uchar*) &mCurrent.data)[i] >= ((uchar*) &mLast.data)[i] ? dc::INC : dc::DEC;
|
||||
}
|
||||
|
||||
return dc::NO;
|
||||
}
|
||||
|
||||
int SnifferItem::elapsed() const
|
||||
{
|
||||
return mTime.elapsed();
|
||||
}
|
||||
|
||||
void SnifferItem::update(const CANFrame& pFrame)
|
||||
{
|
||||
/* copy current to last */
|
||||
mLast = mCurrent;
|
||||
mLastTime = mCurrentTime;
|
||||
|
||||
/* copy new value */
|
||||
memcpy(&mCurrent.data, pFrame.data, 8);
|
||||
mCurrent.len = pFrame.len;
|
||||
mCurrentTime = pFrame.timestamp;
|
||||
|
||||
/* update marker */
|
||||
mMarker.data |= mLast.data ^ mCurrent.data;
|
||||
mMarker.len |= mLast.len ^ mCurrent.len;
|
||||
|
||||
/* restart timeout */
|
||||
mTime.restart();
|
||||
}
|
||||
|
||||
void SnifferItem::updateMarker()
|
||||
{
|
||||
mLastMarker = mMarker;
|
||||
mMarker = {0, 0};
|
||||
}
|
||||
|
||||
void SnifferItem::notch(bool pNotch)
|
||||
{
|
||||
if(pNotch)
|
||||
mNotch |= mLastMarker.data;
|
||||
else
|
||||
mNotch = 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef SNIFFERITEM_H
|
||||
#define SNIFFERITEM_H
|
||||
|
||||
#include <QVariant>
|
||||
#include <QTime>
|
||||
#include "can_structs.h"
|
||||
|
||||
struct fstCan
|
||||
{
|
||||
quint64 data;
|
||||
int len;
|
||||
};
|
||||
|
||||
enum dc
|
||||
{
|
||||
NO,
|
||||
INC,
|
||||
DEC
|
||||
};
|
||||
|
||||
|
||||
class SnifferItem
|
||||
{
|
||||
public:
|
||||
explicit SnifferItem(const CANFrame& pFrame);
|
||||
virtual ~SnifferItem();
|
||||
|
||||
quint64 getId() const;
|
||||
float getDelta() const;
|
||||
int getData(uchar i) const;
|
||||
dc dataChange(uchar) const;
|
||||
int elapsed() const;
|
||||
void update(const CANFrame& pFrame);
|
||||
void updateMarker();
|
||||
void notch(bool);
|
||||
private:
|
||||
quint64 mID;
|
||||
struct fstCan mLast;
|
||||
struct fstCan mCurrent;
|
||||
struct fstCan mLastMarker;
|
||||
struct fstCan mMarker;
|
||||
quint64 mNotch;
|
||||
quint64 mLastTime;
|
||||
quint64 mCurrentTime;
|
||||
|
||||
QTime mTime;
|
||||
};
|
||||
|
||||
#endif // SNIFFERITEM_H
|
||||
@@ -0,0 +1,267 @@
|
||||
#include <QDebug>
|
||||
#include "sniffermodel.h"
|
||||
#include "snifferwindow.h"
|
||||
|
||||
|
||||
SnifferModel::SnifferModel(QObject *parent)
|
||||
: QAbstractItemModel(parent),
|
||||
mFilter(false)
|
||||
{
|
||||
}
|
||||
|
||||
SnifferModel::~SnifferModel()
|
||||
{
|
||||
qDeleteAll(mMap);
|
||||
mMap.clear();
|
||||
mFilters.clear();
|
||||
}
|
||||
|
||||
|
||||
int SnifferModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : tc::LAST+1;
|
||||
}
|
||||
|
||||
|
||||
int SnifferModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
const QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
|
||||
return parent.isValid() ? 0 : map.size();
|
||||
}
|
||||
|
||||
|
||||
QVariant SnifferModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
SnifferItem *item = static_cast<SnifferItem*>(index.internalPointer());
|
||||
if(!item) QVariant();
|
||||
|
||||
int col = index.column();
|
||||
|
||||
switch(role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
switch(col)
|
||||
{
|
||||
case tc::DELTA:
|
||||
return QString::number(item->getDelta(), 'f');
|
||||
case tc::ID:
|
||||
return QString("%1").arg(item->getId(), 5, 16, QLatin1Char(' ')).toUpper();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(tc::DATA_0<=col && col <=tc::DATA_7)
|
||||
{
|
||||
int data = item->getData(col-tc::DATA_0);
|
||||
if(data>=0)
|
||||
return QString("%1").arg(data, 2, 16, QLatin1Char('0')).toUpper();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Qt::BackgroundRole:
|
||||
{
|
||||
if(tc::ID==col)
|
||||
{
|
||||
if(item->elapsed()>4000)
|
||||
return QBrush(Qt::red);
|
||||
}
|
||||
else if(tc::DATA_0<=col && col<=tc::DATA_7)
|
||||
{
|
||||
dc change = item->dataChange(col-tc::DATA_0);
|
||||
switch(change)
|
||||
{
|
||||
case dc::INC:
|
||||
return QBrush(Qt::green);
|
||||
case dc::DEC:
|
||||
return QBrush(Qt::red);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
Qt::ItemFlags SnifferModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
return QAbstractItemModel::flags(index);
|
||||
}
|
||||
|
||||
|
||||
QVariant SnifferModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
{
|
||||
switch(section)
|
||||
{
|
||||
case tc::DELTA:
|
||||
return QString("Delta");
|
||||
case tc::ID:
|
||||
return QString("ID");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(tc::DATA_0<=section && section <=tc::DATA_7)
|
||||
return QString::number(section-tc::DATA_0);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
QModelIndex SnifferModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
const QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
|
||||
|
||||
if(column>tc::LAST || row>=map.size())
|
||||
return QModelIndex();
|
||||
|
||||
/* ugly but I can't find best without creating a list to keep indexes */
|
||||
QMap<quint32, SnifferItem*>::const_iterator iter;
|
||||
int i;
|
||||
for(iter = map.begin(), i=0 ; i<row ; ++i, ++iter);
|
||||
|
||||
return createIndex(row, column, iter.value());
|
||||
}
|
||||
|
||||
|
||||
QModelIndex SnifferModel::parent(const QModelIndex &) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
|
||||
void SnifferModel::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
qDeleteAll(mMap);
|
||||
mMap.clear();
|
||||
mFilters.clear();
|
||||
mFilter = false;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
void SnifferModel::refresh()
|
||||
{
|
||||
QMap<quint32, SnifferItem*>::iterator i;
|
||||
QVector<quint32> toRemove;
|
||||
SnifferItem* item;
|
||||
|
||||
/* update markers */
|
||||
|
||||
|
||||
for (i = mMap.begin(); i != mMap.end(); ++i)
|
||||
{
|
||||
i.value()->updateMarker();
|
||||
if(i.value()->elapsed()>5000)
|
||||
toRemove.append(i.key());
|
||||
}
|
||||
|
||||
if(toRemove.size())
|
||||
{
|
||||
beginResetModel();
|
||||
foreach(quint32 id, toRemove)
|
||||
{
|
||||
/* remove element */
|
||||
item = mMap.take(id);
|
||||
mFilters.remove(id);
|
||||
delete item;
|
||||
/* send notification */
|
||||
emit idChange(id, false);
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
else
|
||||
/* refresh data */
|
||||
dataChanged(createIndex(0, 0),
|
||||
createIndex(rowCount()-1, columnCount()-1), QVector<int>(Qt::DisplayRole));
|
||||
}
|
||||
|
||||
|
||||
void SnifferModel::filter(fltType pType, int pId)
|
||||
{
|
||||
beginResetModel();
|
||||
switch(pType)
|
||||
{
|
||||
case fltType::NONE:
|
||||
/* erase everything */
|
||||
mFilter = true;
|
||||
mFilters.clear();
|
||||
break;
|
||||
case fltType::ADD:
|
||||
/* add filter to list */
|
||||
mFilter = true;
|
||||
mFilters[pId] = mMap[pId];
|
||||
break;
|
||||
case fltType::REMOVE:
|
||||
/* remove filter */
|
||||
if(!mFilter)
|
||||
mFilters = mMap;
|
||||
mFilter = true;
|
||||
mFilters.remove(pId);
|
||||
break;
|
||||
case fltType::ALL:
|
||||
/* stop filtering */
|
||||
mFilter = false;
|
||||
mFilters.clear();
|
||||
break;
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
/***********************************************/
|
||||
/********** slots ****************/
|
||||
/***********************************************/
|
||||
|
||||
void SnifferModel::update(CANConnection*, QVector<CANFrame>& pFrames)
|
||||
{
|
||||
foreach(const CANFrame& frame, pFrames)
|
||||
{
|
||||
if(!mMap.contains(frame.ID))
|
||||
{
|
||||
int index = std::distance(mMap.begin(), mMap.lowerBound(frame.ID));
|
||||
/* add the frame */
|
||||
beginInsertRows(QModelIndex(), index, index);
|
||||
mMap[frame.ID] = new SnifferItem(frame);
|
||||
endInsertRows();
|
||||
|
||||
emit idChange(frame.ID, true);
|
||||
}
|
||||
else
|
||||
//updateData
|
||||
mMap[frame.ID]->update(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void SnifferModel::notch()
|
||||
{
|
||||
QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
|
||||
|
||||
foreach(SnifferItem* item, map)
|
||||
item->notch(true);
|
||||
}
|
||||
|
||||
void SnifferModel::unNotch()
|
||||
{
|
||||
QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
|
||||
|
||||
foreach(SnifferItem* item, map)
|
||||
item->notch(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef SNIFFERMODEL_H
|
||||
#define SNIFFERMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QTimer>
|
||||
|
||||
#include "can_structs.h"
|
||||
#include "connections/canconnection.h"
|
||||
#include "snifferitem.h"
|
||||
|
||||
|
||||
enum fltType
|
||||
{
|
||||
ALL,
|
||||
ADD,
|
||||
REMOVE,
|
||||
NONE
|
||||
};
|
||||
|
||||
class SnifferModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SnifferModel(QObject *parent = 0);
|
||||
virtual ~SnifferModel();
|
||||
|
||||
/* from QAbstractItemModel */
|
||||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
void refresh();
|
||||
void clear();
|
||||
void filter(fltType pType, int pId=0);
|
||||
|
||||
public slots:
|
||||
void update(CANConnection*, QVector<CANFrame>&);
|
||||
void notch();
|
||||
void unNotch();
|
||||
|
||||
signals:
|
||||
void idChange(int, bool);
|
||||
|
||||
private:
|
||||
QMap<quint32, SnifferItem*> mMap;
|
||||
QMap<quint32, SnifferItem*> mFilters;
|
||||
bool mFilter;
|
||||
};
|
||||
|
||||
#endif // SNIFFERMODEL_H
|
||||
@@ -0,0 +1,132 @@
|
||||
#include <QDebug>
|
||||
#include <QListWidgetItem>
|
||||
#include "snifferwindow.h"
|
||||
#include "ui_snifferwindow.h"
|
||||
#include "connections/canconmanager.h"
|
||||
|
||||
SnifferWindow::SnifferWindow(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::snifferWindow),
|
||||
mModel(this),
|
||||
mTimer(this),
|
||||
mFilter(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->treeView->setModel(&mModel);
|
||||
|
||||
/* set column width */
|
||||
ui->treeView->setColumnWidth(tc::ID, 50);
|
||||
ui->treeView->setColumnWidth(tc::LAST, 1);
|
||||
for(int i=tc::DATA_0 ; i<=tc::DATA_7 ; i++)
|
||||
ui->treeView->setColumnWidth(i, 30);
|
||||
ui->treeView->header()->setDefaultAlignment(Qt::AlignCenter);
|
||||
|
||||
/* activate sorting */
|
||||
ui->listWidget->setSortingEnabled(true);
|
||||
|
||||
/* connect timer */
|
||||
connect(&mTimer, &QTimer::timeout, this, &SnifferWindow::update);
|
||||
mTimer.setInterval(200);
|
||||
|
||||
/* connect buttons */
|
||||
connect(ui->btNotch, &QPushButton::clicked, &mModel, &SnifferModel::notch);
|
||||
connect(ui->btUnNotch, &QPushButton::clicked, &mModel, &SnifferModel::unNotch);
|
||||
connect(ui->btAll, &QPushButton::clicked, this, &SnifferWindow::fltAll);
|
||||
connect(ui->btNone, &QPushButton::clicked, this, &SnifferWindow::fltNone);
|
||||
connect(&mModel, &SnifferModel::idChange, this, &SnifferWindow::idChange);
|
||||
connect(ui->listWidget, &QListWidget::itemChanged, this, &SnifferWindow::itemChanged);
|
||||
|
||||
}
|
||||
|
||||
SnifferWindow::~SnifferWindow()
|
||||
{
|
||||
closeEvent(NULL);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void SnifferWindow::showEvent(QShowEvent* event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
connect(CANConManager::getInstance(), &CANConManager::framesReceived, &mModel, &SnifferModel::update);
|
||||
mTimer.start();
|
||||
|
||||
qDebug() << "show";
|
||||
}
|
||||
|
||||
|
||||
void SnifferWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
/* stop timer */
|
||||
mTimer.stop();
|
||||
/* disconnect reception of frames */
|
||||
disconnect(CANConManager::getInstance(), 0, this, 0);
|
||||
/* clear model */
|
||||
mModel.clear();
|
||||
/* clean list */
|
||||
qDeleteAll(mMap);
|
||||
mMap.clear();
|
||||
/* reset filtering */
|
||||
mFilter = false;
|
||||
}
|
||||
|
||||
|
||||
void SnifferWindow::update()
|
||||
{
|
||||
mModel.refresh();
|
||||
}
|
||||
|
||||
|
||||
void SnifferWindow::fltAll()
|
||||
{
|
||||
filter(false);
|
||||
}
|
||||
|
||||
|
||||
void SnifferWindow::fltNone()
|
||||
{
|
||||
filter(true);
|
||||
}
|
||||
|
||||
void SnifferWindow::filter(bool pFilter)
|
||||
{
|
||||
mFilter = pFilter;
|
||||
mModel.filter(mFilter ? fltType::NONE : fltType::ALL);
|
||||
|
||||
foreach(QListWidgetItem* item, mMap)
|
||||
item->setCheckState(mFilter ? Qt::Unchecked : Qt::Checked);
|
||||
}
|
||||
|
||||
void SnifferWindow::idChange(int pId, bool pAdd)
|
||||
{
|
||||
QListWidgetItem* item;
|
||||
|
||||
if(pAdd)
|
||||
{
|
||||
QString text = QString("0x") + QString("%1").arg(pId, 3, 16, QLatin1Char('0')).toUpper();
|
||||
item = new QListWidgetItem(text);
|
||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(mFilter ? Qt::Unchecked : Qt::Checked);
|
||||
ui->listWidget->addItem(item);
|
||||
mMap[pId] = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = mMap.take(pId);
|
||||
ui->listWidget->removeItemWidget(item);
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SnifferWindow::itemChanged(QListWidgetItem * item)
|
||||
{
|
||||
bool checked = (Qt::Checked == item->checkState());
|
||||
|
||||
if( !mFilter && checked )
|
||||
return;
|
||||
|
||||
mModel.filter(checked ? fltType::ADD : fltType::REMOVE, mMap.key(item));
|
||||
mFilter = true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef SNIFFER_H
|
||||
#define SNIFFER_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QListWidgetItem>
|
||||
#include "sniffermodel.h"
|
||||
|
||||
namespace Ui {
|
||||
class snifferWindow;
|
||||
}
|
||||
|
||||
enum tc
|
||||
{
|
||||
DELTA = 0,
|
||||
ID,
|
||||
DATA_0,
|
||||
DATA_1,
|
||||
DATA_2,
|
||||
DATA_3,
|
||||
DATA_4,
|
||||
DATA_5,
|
||||
DATA_6,
|
||||
DATA_7,
|
||||
LAST
|
||||
};
|
||||
|
||||
|
||||
class SnifferWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SnifferWindow(QWidget *parent = 0);
|
||||
~SnifferWindow();
|
||||
|
||||
void showEvent(QShowEvent*);
|
||||
void closeEvent(QCloseEvent*);
|
||||
|
||||
public slots:
|
||||
void update();
|
||||
void idChange(int, bool);
|
||||
void fltAll();
|
||||
void fltNone();
|
||||
void itemChanged(QListWidgetItem*);
|
||||
|
||||
private:
|
||||
void filter(bool pFilter);
|
||||
|
||||
Ui::snifferWindow* ui;
|
||||
SnifferModel mModel;
|
||||
QTimer mTimer;
|
||||
QMap<int, QListWidgetItem*> mMap;
|
||||
bool mFilter;
|
||||
};
|
||||
|
||||
#endif // SNIFFER_H
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "udsscanwindow.h"
|
||||
#include "ui_udsscanwindow.h"
|
||||
#include "mainwindow.h"
|
||||
#include "connections/canconmanager.h"
|
||||
|
||||
UDSScanWindow::UDSScanWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@@ -20,10 +21,9 @@ UDSScanWindow::UDSScanWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
connect(ui->btnScan, &QPushButton::clicked, this, &UDSScanWindow::scanUDS);
|
||||
connect(waitTimer, &QTimer::timeout, this, &UDSScanWindow::timeOut);
|
||||
|
||||
ui->cbBuses->addItem("0");
|
||||
ui->cbBuses->addItem("1");
|
||||
ui->cbBuses->addItem("Both");
|
||||
|
||||
int numBuses = CANConManager::getInstance()->getNumBuses();
|
||||
for (int n = 0; n < numBuses; n++) ui->cbBuses->addItem(QString::number(n));
|
||||
ui->cbBuses->addItem(tr("All"));
|
||||
}
|
||||
|
||||
UDSScanWindow::~UDSScanWindow()
|
||||
@@ -53,8 +53,6 @@ void UDSScanWindow::scanUDS()
|
||||
endID = Utility::ParseStringToNum(ui->txtEndID->text());
|
||||
|
||||
int buses = ui->cbBuses->currentIndex();
|
||||
buses++;
|
||||
if (buses < 1) buses = 1;
|
||||
|
||||
//start out by sending tester present to every address to see if anyone replies
|
||||
for (id = startID; id <= endID; id++)
|
||||
@@ -68,18 +66,22 @@ void UDSScanWindow::scanUDS()
|
||||
frame.data[3] = 0;frame.data[4] = 0;frame.data[5] = 0;
|
||||
frame.data[6] = 0;frame.data[7] = 0;
|
||||
|
||||
if (buses & 1)
|
||||
if (buses < ui->cbBuses->count()- 1)
|
||||
{
|
||||
frame.bus = 0;
|
||||
frame.bus = buses;
|
||||
sendingFrames.append(frame);
|
||||
}
|
||||
if (buses & 2)
|
||||
else
|
||||
{
|
||||
frame.bus = 1;
|
||||
for (int c = 0; c < ui->cbBuses->count() - 1; c++)
|
||||
{
|
||||
frame.bus = c;
|
||||
sendingFrames.append(frame);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//then try asking for the various diagnostic session types
|
||||
for (typ = 1; typ < 5; typ++)
|
||||
{
|
||||
@@ -94,18 +96,21 @@ void UDSScanWindow::scanUDS()
|
||||
frame.data[3] = 0;frame.data[4] = 0;frame.data[5] = 0;
|
||||
frame.data[6] = 0;frame.data[7] = 0;
|
||||
|
||||
if (buses & 1)
|
||||
if (buses < ui->cbBuses->count()- 1)
|
||||
{
|
||||
frame.bus = 0;
|
||||
frame.bus = buses;
|
||||
sendingFrames.append(frame);
|
||||
}
|
||||
if (buses & 2)
|
||||
else
|
||||
{
|
||||
frame.bus = 1;
|
||||
for (int c = 0; c < ui->cbBuses->count() - 1; c++)
|
||||
{
|
||||
frame.bus = c;
|
||||
sendingFrames.append(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
waitTimer->start();
|
||||
currIdx = -1;
|
||||
@@ -129,11 +134,12 @@ void UDSScanWindow::updatedFrames(int numFrames)
|
||||
}
|
||||
|
||||
//Updates here are nearly once per millisecond if there is heavy traffic. That's more like it!
|
||||
//TODO: I really doubt this works anymore with the new connection system. This breaks the UDS scanner for now! ;(
|
||||
void UDSScanWindow::rapidFrames(int numFrames)
|
||||
{
|
||||
CANFrame thisFrame;
|
||||
QString result;
|
||||
int id;
|
||||
uint32_t id;
|
||||
int offset = ui->spinReplyOffset->value();
|
||||
CANFrame sentFrame;
|
||||
bool gotReply = false;
|
||||
@@ -151,7 +157,7 @@ void UDSScanWindow::rapidFrames(int numFrames)
|
||||
thisFrame = modelFrames->at(i);
|
||||
id = thisFrame.ID;
|
||||
|
||||
if ((id == (sentFrame.ID + offset)) || ui->cbAllowAdaptiveOffset->isChecked())
|
||||
if ((id == (uint32_t)(sentFrame.ID + offset)) || ui->cbAllowAdaptiveOffset->isChecked())
|
||||
{
|
||||
int temp = thisFrame.data[0] >> 4;
|
||||
if (temp == 0) //single frame reply (maybe)
|
||||
@@ -210,7 +216,7 @@ void UDSScanWindow::sendNextMsg()
|
||||
currIdx++;
|
||||
if (currIdx < sendingFrames.count())
|
||||
{
|
||||
emit sendCANFrame(&sendingFrames[currIdx], sendingFrames[currIdx].bus);
|
||||
CANConManager::getInstance()->sendFrame(sendingFrames[currIdx]);
|
||||
waitTimer->start();
|
||||
}
|
||||
else
|
||||
@@ -17,9 +17,6 @@ public:
|
||||
explicit UDSScanWindow(const QVector<CANFrame> *frames, QWidget *parent = 0);
|
||||
~UDSScanWindow();
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
|
||||
private slots:
|
||||
void updatedFrames(int numFrames);
|
||||
void rapidFrames(int numFrames);
|
||||
+36
-15
@@ -1,14 +1,12 @@
|
||||
#include "scriptcontainer.h"
|
||||
|
||||
#include <QJSValueIterator>
|
||||
#include <QDebug>
|
||||
|
||||
ScriptContainer::ScriptContainer()
|
||||
{
|
||||
fileName = QString();
|
||||
filePath = QString();
|
||||
scriptText = QString();
|
||||
#include "scriptcontainer.h"
|
||||
#include "connections/canconmanager.h"
|
||||
|
||||
ScriptContainer::ScriptContainer(QString& pConName):
|
||||
mConName(pConName)
|
||||
{
|
||||
connect(&timer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||
}
|
||||
|
||||
@@ -68,6 +66,22 @@ void ScriptContainer::setFilter(QJSValue id, QJSValue mask, QJSValue bus)
|
||||
CANFilter filter;
|
||||
filter.setFilter(idVal, maskVal, busVal);
|
||||
filters.append(filter);
|
||||
|
||||
qDebug() << "FIXME setFilter";
|
||||
CANConnection* conn_p = CANConManager::getInstance()->getByName(mConName);
|
||||
if(conn_p)
|
||||
{
|
||||
CANFlt canFlt;
|
||||
for(int i=0 ; i<conn_p->getNumBuses() ; i++)
|
||||
{
|
||||
foreach(const CANFilter& flt, filters)
|
||||
{
|
||||
if(flt.bus==i) {
|
||||
conn_p->addTargettedFrame(busVal, idVal, maskVal, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptContainer::setTickInterval(QJSValue interval)
|
||||
@@ -86,6 +100,13 @@ void ScriptContainer::clearFilters()
|
||||
{
|
||||
qDebug() << "Called clear filters";
|
||||
filters.clear();
|
||||
|
||||
qDebug() << "FIXME clearFilters";
|
||||
CANConnection* conn_p = CANConManager::getInstance()->getByName(mConName);
|
||||
if(conn_p)
|
||||
{
|
||||
conn_p->removeAllTargettedFrames(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptContainer::sendFrame(QJSValue bus, QJSValue id, QJSValue length, QJSValue data)
|
||||
@@ -93,25 +114,25 @@ void ScriptContainer::sendFrame(QJSValue bus, QJSValue id, QJSValue length, QJSV
|
||||
CANFrame frame;
|
||||
frame.extended = false;
|
||||
frame.ID = id.toInt();
|
||||
frame.len = length.toInt();
|
||||
if (frame.len < 0) frame.len = 0;
|
||||
frame.len = length.toUInt();
|
||||
if (frame.len > 8) frame.len = 8;
|
||||
|
||||
if (!data.isArray()) qDebug() << "data isn't an array";
|
||||
|
||||
for (int i = 0; i < frame.len; i++)
|
||||
for (unsigned int i = 0; i < frame.len; i++)
|
||||
{
|
||||
frame.data[i] = (uint8_t)data.property(i).toInt();
|
||||
}
|
||||
|
||||
frame.bus = bus.toInt();
|
||||
if (frame.bus < 0) frame.bus = 0;
|
||||
frame.bus = (uint32_t)bus.toInt();
|
||||
if (frame.bus > 1) frame.bus = 1;
|
||||
|
||||
if (frame.ID > 0x7FF) frame.extended = true;
|
||||
|
||||
//qDebug() << "Sending frame from script";
|
||||
emit sendCANFrame(&frame, frame.bus);
|
||||
qDebug() << "sending frame from script";
|
||||
CANConnection* conn_p = CANConManager::getInstance()->getByName(mConName);
|
||||
if(conn_p)
|
||||
conn_p->sendFrame(frame);
|
||||
}
|
||||
|
||||
void ScriptContainer::gotFrame(const CANFrame &frame)
|
||||
@@ -125,7 +146,7 @@ void ScriptContainer::gotFrame(const CANFrame &frame)
|
||||
QJSValueList args;
|
||||
args << frame.bus << frame.ID << frame.len;
|
||||
QJSValue dataBytes = scriptEngine.newArray(frame.len);
|
||||
for (int j = 0; j < frame.len; j++) dataBytes.setProperty(j, QJSValue(frame.data[j]));
|
||||
for (unsigned int j = 0; j < frame.len; j++) dataBytes.setProperty(j, QJSValue(frame.data[j]));
|
||||
args.append(dataBytes);
|
||||
gotFrameFunction.call(args);
|
||||
return; //as soon as one filter matches we jump out
|
||||
|
||||
+2
-4
@@ -13,12 +13,13 @@ class ScriptContainer : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScriptContainer();
|
||||
ScriptContainer(QString&);
|
||||
void gotFrame(const CANFrame &frame);
|
||||
|
||||
QString fileName;
|
||||
QString filePath;
|
||||
QString scriptText;
|
||||
QString mConName;
|
||||
|
||||
public slots:
|
||||
void compileScript();
|
||||
@@ -31,9 +32,6 @@ public slots:
|
||||
private slots:
|
||||
void tick();
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
|
||||
private:
|
||||
QJSEngine scriptEngine;
|
||||
QJSValue compiledScript;
|
||||
|
||||
+27
-21
@@ -3,9 +3,10 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QSettings>
|
||||
#include <Qsci/qscilexerjavascript.h>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "connections/canconmanager.h"
|
||||
|
||||
ScriptingWindow::ScriptingWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@@ -23,7 +24,8 @@ ScriptingWindow::ScriptingWindow(const QVector<CANFrame> *frames, QWidget *paren
|
||||
connect(ui->btnRemoveScript, &QAbstractButton::pressed, this, &ScriptingWindow::deleteCurrentScript);
|
||||
connect(ui->btnRevertScript, &QAbstractButton::pressed, this, &ScriptingWindow::revertScript);
|
||||
connect(ui->btnSaveScript, &QAbstractButton::pressed, this, &ScriptingWindow::saveScript);
|
||||
connect(MainWindow::getReference(), &MainWindow::framesUpdated, this, &ScriptingWindow::updatedFrames);
|
||||
|
||||
connect(CANConManager::getInstance(), &CANConManager::framesReceived, this, &ScriptingWindow::newFrames);
|
||||
|
||||
ui->txtScriptSource->setLexer(new QsciLexerJavaScript(ui->txtScriptSource));
|
||||
}
|
||||
@@ -33,27 +35,22 @@ ScriptingWindow::~ScriptingWindow()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ScriptingWindow::updatedFrames(int numFrames)
|
||||
|
||||
void ScriptingWindow::newFrames(const CANConnection* pConn, const QVector<CANFrame>& pFrames)
|
||||
{
|
||||
CANFrame thisFrame;
|
||||
//-1 means all frames deleted and -2 means a full refresh, neither of which we care about here.
|
||||
if (numFrames > 0)
|
||||
{
|
||||
if (numFrames > modelFrames->count()) return;
|
||||
qDebug() << "Got frames into script window: " << numFrames;
|
||||
//for every new frame pass it on to each script container. The container will determine if it needs to actually
|
||||
//notify the script and do that if applicable.
|
||||
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
|
||||
{
|
||||
thisFrame = modelFrames->at(i);
|
||||
/*FIXME: name of the probe and bus should be checked */
|
||||
Q_UNUSED(pConn);
|
||||
|
||||
for (int j = 0; j < scripts.length(); j++)
|
||||
{
|
||||
scripts[j]->gotFrame(thisFrame);
|
||||
}
|
||||
foreach(const CANFrame& frame, pFrames)
|
||||
{
|
||||
scripts[j]->gotFrame(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScriptingWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
@@ -90,7 +87,6 @@ void ScriptingWindow::loadNewScript()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog;
|
||||
bool result = false;
|
||||
ScriptContainer *container;
|
||||
|
||||
QStringList filters;
|
||||
@@ -115,13 +111,19 @@ void ScriptingWindow::loadNewScript()
|
||||
QStringList fileList = filename.split('/');
|
||||
QString justFileName = fileList[fileList.length() - 1];
|
||||
ui->listLoadedScripts->addItem(justFileName);
|
||||
container = new ScriptContainer();
|
||||
/* get the first connection in the list for now */
|
||||
qDebug() << "FIXME: connection is always the first in list";
|
||||
QString portName;
|
||||
QList<CANConnection*> list = CANConManager::getInstance()->getConnections();
|
||||
if(!list.isEmpty())
|
||||
portName = list.first()->getPort();
|
||||
|
||||
container = new ScriptContainer(portName);
|
||||
container->fileName = justFileName;
|
||||
container->filePath = filename;
|
||||
container->scriptText = contents;
|
||||
container->setErrorWidget(ui->listErrors);
|
||||
container->compileScript();
|
||||
connect(container, &ScriptContainer::sendCANFrame, this, &ScriptingWindow::sendCANFrame);
|
||||
scripts.append(container);
|
||||
currentScript = container;
|
||||
ui->txtScriptSource->setText(container->scriptText);
|
||||
@@ -135,13 +137,17 @@ void ScriptingWindow::createNewScript()
|
||||
{
|
||||
ScriptContainer *container;
|
||||
|
||||
container = new ScriptContainer();
|
||||
QString portName;
|
||||
QList<CANConnection*> list = CANConManager::getInstance()->getConnections();
|
||||
if(!list.isEmpty())
|
||||
portName = list.first()->getPort();
|
||||
|
||||
container = new ScriptContainer(portName);
|
||||
|
||||
container->fileName = "UNNAMED_" + QString::number((qrand() % 10000)) + ".js";
|
||||
container->filePath = QString();
|
||||
container->scriptText = QString();
|
||||
container->setErrorWidget(ui->listErrors);
|
||||
connect(container, &ScriptContainer::sendCANFrame, this, &ScriptingWindow::sendCANFrame);
|
||||
scripts.append(container);
|
||||
ui->listLoadedScripts->addItem(container->fileName);
|
||||
currentScript = container;
|
||||
|
||||
+2
-8
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "can_structs.h"
|
||||
#include "scriptcontainer.h"
|
||||
#include "connections/canconnection.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QJSEngine>
|
||||
@@ -28,12 +29,7 @@ private slots:
|
||||
void saveScript();
|
||||
void revertScript();
|
||||
void recompileScript();
|
||||
void updatedFrames(int);
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
void newFrames(const CANConnection*, const QVector<CANFrame>&);
|
||||
|
||||
private:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
@@ -44,8 +40,6 @@ private:
|
||||
QList<ScriptContainer *> scripts;
|
||||
ScriptContainer *currentScript;
|
||||
const QVector<CANFrame> *modelFrames;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // SCRIPTINGWINDOW_H
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
#ifndef SERIALWORKER_H
|
||||
#define SERIALWORKER_H
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QSerialPort>
|
||||
#include <QSerialPortInfo>
|
||||
#include <QTimer>
|
||||
#include "can_structs.h"
|
||||
#include "canframemodel.h"
|
||||
|
||||
namespace SERIALSTATE {
|
||||
|
||||
enum STATE //keep this enum synchronized with the Arduino firmware project
|
||||
{
|
||||
IDLE,
|
||||
GET_COMMAND,
|
||||
BUILD_CAN_FRAME,
|
||||
TIME_SYNC,
|
||||
GET_DIG_INPUTS,
|
||||
GET_ANALOG_INPUTS,
|
||||
SET_DIG_OUTPUTS,
|
||||
SETUP_CANBUS,
|
||||
GET_CANBUS_PARAMS,
|
||||
GET_DEVICE_INFO,
|
||||
SET_SINGLEWIRE_MODE
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using namespace SERIALSTATE;
|
||||
class SerialWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SerialWorker(CANFrameModel *model, QObject *parent = 0);
|
||||
~SerialWorker();
|
||||
void readSettings();
|
||||
void targetFrameID(int);
|
||||
|
||||
signals: //we emit signals
|
||||
void error(const QString &);
|
||||
void frameUpdateRapid(int); //sent *much* more rapidly than the above signal - one param for # of frames
|
||||
void connectionSuccess(int, int);
|
||||
void connectionFailure();
|
||||
void deviceInfo(int, int);
|
||||
void gotTargettedFrame(int);
|
||||
|
||||
private slots: //we receive things in slots
|
||||
void readSerialData();
|
||||
void connectionTimeout();
|
||||
void handleTick();
|
||||
void handleReconnect();
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
void setSerialPort(QSerialPortInfo*);
|
||||
void closeSerialPort();
|
||||
void sendFrame(const CANFrame *, int);
|
||||
void sendFrameBatch(const QList<CANFrame> *);
|
||||
void updateBaudRates(int, int);
|
||||
void stopFrameCapture();
|
||||
void startFrameCapture(); //only need to call this if previously stopped. Otherwise it's the default
|
||||
|
||||
private:
|
||||
QString portName;
|
||||
bool quit;
|
||||
bool connected;
|
||||
bool capturing;
|
||||
bool doValidation;
|
||||
bool gotValidated;
|
||||
bool isAutoRestart;
|
||||
bool continuousTimeSync;
|
||||
QSerialPort *serial;
|
||||
QSerialPortInfo *currentPort;
|
||||
CANFrameModel *canModel;
|
||||
QTimer *ticker;
|
||||
QMutex sendBulkMutex;
|
||||
int framesRapid;
|
||||
int targetID;
|
||||
STATE rx_state;
|
||||
int rx_step;
|
||||
CANFrame *buildFrame;
|
||||
int can0Baud, can1Baud;
|
||||
bool can0Enabled, can1Enabled;
|
||||
int deviceBuildNum;
|
||||
int deviceSingleWireMode;
|
||||
uint64_t txTimestampBasis;
|
||||
uint32_t buildTimeBasis;
|
||||
|
||||
void procRXChar(unsigned char);
|
||||
void sendCommValidation();
|
||||
};
|
||||
|
||||
#endif // SERIALTHREAD_H
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <QtTest>
|
||||
|
||||
#include "tst_lfqueue.h"
|
||||
#include "tst_cancon.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
int status = 0;
|
||||
auto ASSERT_TEST = [&status, argc, argv](QObject* obj) {
|
||||
status |= QTest::qExec(obj, argc, argv);
|
||||
delete obj;
|
||||
};
|
||||
|
||||
ASSERT_TEST(new TestLFQueue());
|
||||
ASSERT_TEST(new TestCanCon(CANCon::SOCKETCAN, "vcan0", 1));
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
QT += core gui serialbus widgets testlib serialbus
|
||||
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
INCLUDEPATH += ../ ../connections
|
||||
|
||||
SOURCES += \
|
||||
tst_lfqueue.cpp \
|
||||
main.cpp \
|
||||
tst_cancon.cpp \
|
||||
../connections/canconfactory.cpp \
|
||||
../connections/canconnection.cpp \
|
||||
../connections/gvretserial.cpp \
|
||||
../connections/socketcan.cpp \
|
||||
../canbus.cpp
|
||||
|
||||
|
||||
#HEADERS += \
|
||||
# ../utils/lfqueue.h
|
||||
|
||||
target.path= .
|
||||
INSTALLS += target
|
||||
|
||||
HEADERS += \
|
||||
tst_lfqueue.h \
|
||||
tst_cancon.h \
|
||||
../connections/canconconst.h \
|
||||
../connections/canconfactory.h \
|
||||
../connections/canconnection.h \
|
||||
../connections/gvretserial.h \
|
||||
../connections/socketcan.h \
|
||||
../canbus.h
|
||||
@@ -0,0 +1,366 @@
|
||||
#include <QtTest>
|
||||
#include <QVector>
|
||||
|
||||
#include "tst_cancon.h"
|
||||
#include "canconnection.h"
|
||||
#include "canconfactory.h"
|
||||
|
||||
|
||||
#define QVERIFYB(statement) \
|
||||
do {\
|
||||
if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__))\
|
||||
return false;\
|
||||
} while (0)
|
||||
|
||||
#define QCOMPAREB(actual, expected) \
|
||||
do {\
|
||||
if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__))\
|
||||
return false;\
|
||||
} while (0)
|
||||
|
||||
Q_DECLARE_METATYPE(QVector<CANFlt>);
|
||||
|
||||
|
||||
|
||||
TestCanCon::TestCanCon(CANCon::type pType, QString pPortName, int pNbBus):
|
||||
mType(pType),
|
||||
mPortName(pPortName),
|
||||
mNbBus(pNbBus){}
|
||||
|
||||
void TestCanCon::create()
|
||||
{
|
||||
CANConnection* conn_p;
|
||||
QVERIFY(pCreate(conn_p));
|
||||
/* try to get an element from the queue */
|
||||
QVERIFY(conn_p->getQueue().get());
|
||||
|
||||
if(conn_p)
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
void TestCanCon::connectToDevice()
|
||||
{
|
||||
CANConnection* conn_p;
|
||||
QVERIFY(pCreate(conn_p));
|
||||
|
||||
QSignalSpy spy(conn_p, SIGNAL(status(CANCon::status)));
|
||||
|
||||
/* start connection */
|
||||
conn_p->start();
|
||||
|
||||
/* wait for a signal */
|
||||
for(int i=0 ; (spy.count() != 1) && (i < 10) ; i++)
|
||||
QTest::qWait(500);
|
||||
|
||||
|
||||
QCOMPARE(spy.count(), 1); // make sure the signal was emitted exactly one time
|
||||
QList<QVariant> arguments = spy.takeFirst(); // take the first signal
|
||||
|
||||
QVERIFY(arguments.at(0).toInt() == CANCon::CONNECTED); // verify the first argument
|
||||
|
||||
/* stop connection */
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
void TestCanCon::recvFrames()
|
||||
{
|
||||
CANConnection* conn_p;
|
||||
QVERIFY(pCreate(conn_p));
|
||||
|
||||
/* start connection */
|
||||
conn_p->start();
|
||||
|
||||
/* configure */
|
||||
QVERIFY(pConfig(conn_p));
|
||||
|
||||
LFQueue<CANFrame>& queue = conn_p->getQueue();
|
||||
|
||||
/* wait for frames to arrive */
|
||||
QTest::qWait(1000);
|
||||
|
||||
int i;
|
||||
for(i=0 ; queue.peek() && i<1000 ; i++)
|
||||
{
|
||||
CANFrame* canf_p = queue.peek();
|
||||
QVERIFY(pValidateFrame(conn_p, canf_p));
|
||||
|
||||
queue.dequeue();
|
||||
}
|
||||
|
||||
QVERIFY(i>0);
|
||||
|
||||
/* stop connection */
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
|
||||
void TestCanCon::suspend()
|
||||
{
|
||||
CANConnection* conn_p;
|
||||
QVERIFY(pCreate(conn_p));
|
||||
|
||||
/* start connection */
|
||||
conn_p->start();
|
||||
|
||||
/* configure */
|
||||
QVERIFY(pConfig(conn_p));
|
||||
|
||||
LFQueue<CANFrame>& queue = conn_p->getQueue();
|
||||
|
||||
/* wait for frames to arrive */
|
||||
QTest::qWait(1000);
|
||||
|
||||
CANFrame* canf_p = queue.peek();
|
||||
QVERIFY(pValidateFrame(conn_p, canf_p));
|
||||
|
||||
conn_p->suspend(true);
|
||||
|
||||
/* the queue should be flushed */
|
||||
canf_p = queue.peek();
|
||||
QVERIFY(!canf_p);
|
||||
|
||||
/* restart capture */
|
||||
conn_p->suspend(false);
|
||||
|
||||
/* wait for frames to arrive */
|
||||
QTest::qWait(1000);
|
||||
|
||||
/* get a frame */
|
||||
canf_p = queue.peek();
|
||||
QVERIFY(pValidateFrame(conn_p, canf_p));
|
||||
|
||||
/* stop connection */
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
|
||||
void TestCanCon::filter_data()
|
||||
{
|
||||
CANConnection* conn_p;
|
||||
QVERIFY(pCreate(conn_p));
|
||||
|
||||
/* start connection */
|
||||
conn_p->start();
|
||||
|
||||
/* configure */
|
||||
QVERIFY(pConfig(conn_p));
|
||||
|
||||
LFQueue<CANFrame>& queue = conn_p->getQueue();
|
||||
|
||||
/* wait for frames to arrive */
|
||||
QTest::qWait(1000);
|
||||
|
||||
/* find 3 different ids */
|
||||
QVector<quint32> ids;
|
||||
|
||||
while( queue.peek() && ids.count()!=3 )
|
||||
{
|
||||
CANFrame* canf_p = queue.peek();
|
||||
QVERIFY(pValidateFrame(conn_p, canf_p));
|
||||
|
||||
if(!ids.contains(canf_p->ID))
|
||||
ids.append(canf_p->ID);
|
||||
|
||||
queue.dequeue();
|
||||
}
|
||||
|
||||
QCOMPARE(ids.count(), 3);
|
||||
|
||||
/* stop connection */
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
|
||||
/* prepare test vector */
|
||||
|
||||
QTest::addColumn<QVector<CANFlt>>("filters");
|
||||
QTest::addColumn<bool>("filterOut");
|
||||
QTest::addColumn<bool>("signalReceived");
|
||||
QTest::addColumn<QVector<quint32>>("filtered");
|
||||
|
||||
QVector<CANFlt> filters;
|
||||
QVector<quint32> filteredIds;
|
||||
|
||||
/* one filter no signal*/
|
||||
filters.clear();
|
||||
filteredIds.clear();
|
||||
filters.append({ids[0], 0xFFFF, false});
|
||||
filteredIds.append(ids[0]);
|
||||
QTest::newRow("1filternosignal") << filters << false << false << filteredIds;
|
||||
|
||||
/* one filter & signal*/
|
||||
filters.clear();
|
||||
filteredIds.clear();
|
||||
filters.append({ids[0], 0xFFFF, true});
|
||||
filteredIds.append(ids[0]);
|
||||
QTest::newRow("1filtersignal") << filters << false << true << filteredIds;
|
||||
|
||||
/* 3 filters */
|
||||
filters.clear();
|
||||
filteredIds.clear();
|
||||
foreach(quint32 id, ids) {
|
||||
filters.append({id, 0xFFFF, false});
|
||||
filteredIds.append(id);
|
||||
}
|
||||
QTest::newRow("3filters") << filters << false << false << filteredIds;
|
||||
}
|
||||
|
||||
|
||||
void TestCanCon::filter()
|
||||
{
|
||||
QFETCH(QVector<CANFlt>, filters);
|
||||
QFETCH(bool, filterOut);
|
||||
QFETCH(bool, signalReceived);
|
||||
QFETCH(QVector<quint32>, filtered);
|
||||
|
||||
CANConnection* conn_p;
|
||||
QVERIFY(pCreate(conn_p));
|
||||
|
||||
/* start connection */
|
||||
conn_p->start();
|
||||
|
||||
/* set filters */
|
||||
for(int i=0 ; i<conn_p->getNumBuses() ; i++)
|
||||
QVERIFY(conn_p->setFilters(i, filters, filterOut));
|
||||
|
||||
/* spy signal */
|
||||
QSignalSpy spy(conn_p, SIGNAL(notify()));
|
||||
|
||||
/* configure */
|
||||
QVERIFY(pConfig(conn_p));
|
||||
|
||||
LFQueue<CANFrame>& queue = conn_p->getQueue();
|
||||
|
||||
/* wait for frames to arrive */
|
||||
QTest::qWait(1000);
|
||||
|
||||
if(signalReceived)
|
||||
QVERIFY(spy.count()>0);
|
||||
|
||||
int i;
|
||||
for(i=0 ; queue.peek() && i<1000 ; i++)
|
||||
{
|
||||
CANFrame* canf_p = queue.peek();
|
||||
QVERIFY(pValidateFrame(conn_p, canf_p));
|
||||
|
||||
if(filterOut)
|
||||
QVERIFY(filtered.contains(canf_p->ID));
|
||||
|
||||
queue.dequeue();
|
||||
}
|
||||
|
||||
QVERIFY(i>0);
|
||||
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
|
||||
void TestCanCon::write()
|
||||
{
|
||||
CANConnection* conn_p;
|
||||
QVERIFY(pCreate(conn_p));
|
||||
|
||||
/* start connection */
|
||||
conn_p->start();
|
||||
|
||||
/* configure */
|
||||
QVERIFY(pConfig(conn_p));
|
||||
|
||||
QList<CANFrame> frames;
|
||||
/* build frames */
|
||||
CANFrame frame;
|
||||
frame.bus = 0;
|
||||
frame.ID = 0x1DE;
|
||||
frame.data[0] = 0xDE;
|
||||
frame.data[1] = 0xAD;
|
||||
frame.data[2] = 0xC0;
|
||||
frame.data[3] = 0xDE;
|
||||
frame.len = 4;
|
||||
|
||||
frames.append(frame);
|
||||
|
||||
frame.data[2] = 0xBE;
|
||||
frame.data[3] = 0xEF;
|
||||
frames.append(frame);
|
||||
|
||||
frame.data[2] = 0xDE;
|
||||
frame.data[3] = 0xAD;
|
||||
|
||||
|
||||
/* bad frame length */
|
||||
unsigned int oldVal = frame.len;
|
||||
frame.len = 9;
|
||||
QCOMPARE(conn_p->sendFrame(frame), false);
|
||||
frame.len = oldVal;
|
||||
|
||||
/* bad bus id */
|
||||
oldVal = frame.bus;
|
||||
frame.bus = 48;
|
||||
QCOMPARE(conn_p->sendFrame(frame), false);
|
||||
frame.bus = oldVal;
|
||||
|
||||
qDebug() << "Sending DE AD DE AD";
|
||||
/* send */
|
||||
QVERIFY(conn_p->sendFrame(frame));
|
||||
|
||||
/* leave some time for the frame to be sent */
|
||||
QTest::qWait(1000);
|
||||
|
||||
qDebug() << "Sending DE AD C0 DE";
|
||||
qDebug() << "Sending DE AD BE EF";
|
||||
/* send */
|
||||
QVERIFY(conn_p->sendFrames(frames));
|
||||
|
||||
/* leave some time for the frame to be sent */
|
||||
QTest::qWait(1000);
|
||||
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************/
|
||||
|
||||
bool TestCanCon::pCreate(CANConnection*& pConn_p)
|
||||
{
|
||||
pConn_p = CanConFactory::create(mType, mPortName);
|
||||
QVERIFYB(pConn_p);
|
||||
|
||||
QCOMPAREB(pConn_p->getPort(), mPortName);
|
||||
QCOMPAREB(pConn_p->getNumBuses(), mNbBus);
|
||||
QCOMPAREB(pConn_p->getType(), mType);
|
||||
QCOMPAREB(pConn_p->getStatus(), CANCon::NOT_CONNECTED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestCanCon::pConfig(CANConnection* pConn_p)
|
||||
{
|
||||
/*configure buses */
|
||||
CANBus bus;
|
||||
CANBus retBus;
|
||||
for(int i=0 ; i<pConn_p->getNumBuses() ; i++)
|
||||
{
|
||||
/* TODO: fix configuration */
|
||||
bus.active = true;
|
||||
pConn_p->setBusSettings(i, bus);
|
||||
QVERIFYB(pConn_p->getBusSettings(i, retBus));
|
||||
QCOMPAREB(bus, retBus);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestCanCon::pValidateFrame(CANConnection* pConn_p, CANFrame* pCan_p)
|
||||
{
|
||||
QVERIFYB( pCan_p );
|
||||
QVERIFYB( (0<=pCan_p->bus) && (pCan_p->bus <= pConn_p->getNumBuses()) );
|
||||
QVERIFYB( pCan_p->isReceived);
|
||||
QVERIFYB( pCan_p->len<=8 );
|
||||
QVERIFYB( (0<=pCan_p->ID) && (pCan_p->ID<2048) );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef TESTCANCON_H
|
||||
#define TESTCANCON_H
|
||||
|
||||
#include <QObject>
|
||||
#include "canconconst.h"
|
||||
#include "canconnection.h"
|
||||
|
||||
class TestCanCon: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestCanCon(CANCon::type, QString pPortName, int pNbBus);
|
||||
private:
|
||||
CANCon::type mType;
|
||||
QString mPortName;
|
||||
int mNbBus;
|
||||
|
||||
private slots:
|
||||
void create();
|
||||
void connectToDevice();
|
||||
void recvFrames();
|
||||
void suspend();
|
||||
void filter();
|
||||
void filter_data();
|
||||
void write();
|
||||
|
||||
private:
|
||||
bool pCreate(CANConnection*& pConn_p);
|
||||
bool pConfig(CANConnection* pConn_p);
|
||||
bool pValidateFrame(CANConnection* pConn_p, CANFrame* pCan_p);
|
||||
};
|
||||
|
||||
#endif // TESTCANCON_H
|
||||
@@ -0,0 +1,85 @@
|
||||
#include <QtTest>
|
||||
|
||||
#include <QtConcurrent/qtconcurrentrun.h>
|
||||
|
||||
#include "utils/lfqueue.h"
|
||||
#include "tst_lfqueue.h"
|
||||
|
||||
|
||||
|
||||
void TestLFQueue::setSize_data()
|
||||
{
|
||||
QTest::addColumn<int>("size");
|
||||
QTest::addColumn<bool>("result");
|
||||
|
||||
QTest::newRow("-1") << -1 << false;
|
||||
QTest::newRow("0") << 0 << true;
|
||||
QTest::newRow("10") << 10 << true;
|
||||
QTest::newRow("2000") << 20000 << true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TestLFQueue::setSize()
|
||||
{
|
||||
QFETCH(int, size);
|
||||
QFETCH(bool, result);
|
||||
|
||||
LFQueue<void*> queue;
|
||||
QCOMPARE(queue.setSize(size), result);
|
||||
}
|
||||
|
||||
|
||||
void readerThread(LFQueue<int>* pQueue_p, int pSize, bool pSleep) {
|
||||
int* val_p;
|
||||
|
||||
for(int i=0; i<pSize ; i++) {
|
||||
while(! (val_p = pQueue_p->peek()) );
|
||||
QVERIFY(val_p);
|
||||
|
||||
QCOMPARE(*val_p, i);
|
||||
pQueue_p->dequeue();
|
||||
|
||||
if(pSleep)
|
||||
QThread::msleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TestLFQueue::exchange_data()
|
||||
{
|
||||
QTest::addColumn<int>("size");
|
||||
QTest::addColumn<bool>("writerSleep");
|
||||
QTest::addColumn<bool>("readerSleep");
|
||||
|
||||
QTest::newRow("nosleep") << 1000 << false << false;
|
||||
QTest::newRow("readersleep") << 1000 << false << true;
|
||||
QTest::newRow("writersleep") << 1000 << true << false;
|
||||
}
|
||||
|
||||
|
||||
void TestLFQueue::exchange()
|
||||
{
|
||||
LFQueue<int> queue;
|
||||
QFETCH(int, size);
|
||||
QFETCH(bool, writerSleep);
|
||||
QFETCH(bool, readerSleep);
|
||||
|
||||
int* val_p;
|
||||
QCOMPARE(queue.setSize(2), true);
|
||||
|
||||
QFuture<void> thread = QtConcurrent::run(readerThread, &queue, size, readerSleep);
|
||||
|
||||
for(int i=0; i<size ; i++) {
|
||||
while(! (val_p = queue.get()) );
|
||||
QVERIFY(val_p);
|
||||
|
||||
*val_p = i;
|
||||
queue.queue();
|
||||
|
||||
if(writerSleep)
|
||||
QThread::msleep(1);
|
||||
}
|
||||
|
||||
thread.waitForFinished();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef TST_LFQUEUE_H
|
||||
#define TST_LFQUEUE_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class TestLFQueue: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
||||
private slots:
|
||||
void setSize_data();
|
||||
void setSize();
|
||||
void exchange_data();
|
||||
void exchange();
|
||||
};
|
||||
|
||||
#endif // TST_LFQUEUE_H
|
||||
@@ -0,0 +1,223 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BisectWindow</class>
|
||||
<widget class="QDialog" name="BisectWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>692</width>
|
||||
<height>319</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Bisector Window</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Splitting Strategy:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbIDRange">
|
||||
<property name="text">
|
||||
<string>ID Range</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbIDLower"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>TO</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbIDUpper"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,10,3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbFrameNumber">
|
||||
<property name="text">
|
||||
<string>Frame Number</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="slideFrameNumber">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editFrameNumber"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,10,3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbPercentage">
|
||||
<property name="text">
|
||||
<string>Percentage</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="slidePercentage">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editPercentage"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Save Which Side:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbLowerSection">
|
||||
<property name="text">
|
||||
<string>Lower Section</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbUpperSection">
|
||||
<property name="text">
|
||||
<string>Upper Section</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Number of Frames in Main List:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelMainListNum">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Saved Frames after split:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelSplitNum">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCalculate">
|
||||
<property name="text">
|
||||
<string>Calculate Split</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSaveFrames">
|
||||
<property name="text">
|
||||
<string>Save split frames to a new file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnReplaceFrames">
|
||||
<property name="text">
|
||||
<string>Replace main list with split frames</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,268 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ConnectionWindow</class>
|
||||
<widget class="QWidget" name="ConnectionWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>956</width>
|
||||
<height>527</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Connection Settings</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="2,1">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Connections:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableConnections">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnNewConn">
|
||||
<property name="text">
|
||||
<string>New Connection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRemoveBus">
|
||||
<property name="text">
|
||||
<string>Remove Selected Connection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnActivateAll">
|
||||
<property name="text">
|
||||
<string>Activate All Connections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDeactivateAll">
|
||||
<property name="text">
|
||||
<string>Deactivate All Connections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gbType">
|
||||
<property name="title">
|
||||
<string>Connection Type</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbGVRET">
|
||||
<property name="text">
|
||||
<string>GVRET Serial</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbKvaser">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Kvaser</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbSocketCAN">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SocketCAN</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lPort">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stPort">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="cbPage">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbPort">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>341</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="etPage">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lePort">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ckSingleWire">
|
||||
<property name="text">
|
||||
<string>Single Wire Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ckListenOnly">
|
||||
<property name="text">
|
||||
<string>Listen Only Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ckEnabled">
|
||||
<property name="text">
|
||||
<string>Enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>CAN Speed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbSpeed"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnOK">
|
||||
<property name="text">
|
||||
<string>Create New Connection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRevert">
|
||||
<property name="text">
|
||||
<string>Revert</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
<string>Firmware Updater</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user