Much work on custom frame sender window. It is reasonably functional now and tested for timed sending
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
#ifndef CONFIG
|
||||
#define CONFIG
|
||||
|
||||
#define VERSION 132
|
||||
#define VERSION 133
|
||||
|
||||
//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 322
|
||||
#define CURRENT_GVRET_VER 323
|
||||
|
||||
#endif // CONFIG
|
||||
|
||||
|
||||
+351
-265
@@ -2,6 +2,17 @@
|
||||
#include "ui_framesenderwindow.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QDebug>
|
||||
#include "mainwindow.h"
|
||||
|
||||
/*
|
||||
* notes: need to ensure that you grab pointers when modifying data structures and dont
|
||||
* make copies. Also, check # of ms elapsed since last tick since they don't tend to come in at 1ms
|
||||
* intervals like we asked.
|
||||
* Also, rows default to enabled which is odd because the button state does not reflect that.
|
||||
*/
|
||||
|
||||
FrameSenderWindow::FrameSenderWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::FrameSenderWindow)
|
||||
@@ -16,19 +27,28 @@ FrameSenderWindow::FrameSenderWindow(const QVector<CANFrame> *frames, QWidget *p
|
||||
QStringList headers;
|
||||
headers << "En" << "Bus" << "ID" << "Len" << "Data" << "Trigger" << "Modifications" << "Count";
|
||||
ui->tableSender->setColumnCount(8);
|
||||
ui->tableSender->setColumnWidth(0, 40);
|
||||
ui->tableSender->setColumnWidth(1, 40);
|
||||
ui->tableSender->setColumnWidth(2, 40);
|
||||
ui->tableSender->setColumnWidth(3, 40);
|
||||
ui->tableSender->setColumnWidth(4, 200);
|
||||
ui->tableSender->setColumnWidth(5, 200);
|
||||
ui->tableSender->setColumnWidth(6, 200);
|
||||
ui->tableSender->setColumnWidth(0, 50);
|
||||
ui->tableSender->setColumnWidth(1, 50);
|
||||
ui->tableSender->setColumnWidth(2, 50);
|
||||
ui->tableSender->setColumnWidth(3, 50);
|
||||
ui->tableSender->setColumnWidth(4, 220);
|
||||
ui->tableSender->setColumnWidth(5, 220);
|
||||
ui->tableSender->setColumnWidth(6, 220);
|
||||
ui->tableSender->setColumnWidth(7, 80);
|
||||
ui->tableSender->setHorizontalHeaderLabels(headers);
|
||||
ui->tableSender->insertRow(0);
|
||||
createBlankRow();
|
||||
|
||||
connect(ui->tableSender, SIGNAL(cellChanged(int,int)), this, SLOT(onCellChanged(int,int)));
|
||||
connect(intervalTimer, SIGNAL(timeout()), this, SLOT(handleTick()));
|
||||
connect(ui->btnClearGrid, SIGNAL(clicked(bool)), this, SLOT(clearGrid()));
|
||||
connect(ui->btnDisableAll, SIGNAL(clicked(bool)), this, SLOT(disableAll()));
|
||||
connect(ui->btnEnableAll, SIGNAL(clicked(bool)), this, SLOT(enableAll()));
|
||||
connect(ui->btnLoadGrid, SIGNAL(clicked(bool)), this, SLOT(loadGrid()));
|
||||
connect(ui->btnSaveGrid, SIGNAL(clicked(bool)), this, SLOT(saveGrid()));
|
||||
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
|
||||
|
||||
intervalTimer->start();
|
||||
elapsedTimer.start();
|
||||
}
|
||||
|
||||
FrameSenderWindow::~FrameSenderWindow()
|
||||
@@ -39,12 +59,263 @@ FrameSenderWindow::~FrameSenderWindow()
|
||||
delete intervalTimer;
|
||||
}
|
||||
|
||||
void FrameSenderWindow::createBlankRow()
|
||||
{
|
||||
int row = ui->tableSender->rowCount();
|
||||
ui->tableSender->insertRow(row);
|
||||
|
||||
QTableWidgetItem *item = new QTableWidgetItem();
|
||||
item->setFlags(item->flags() |Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
inhibitChanged = true;
|
||||
ui->tableSender->setItem(row, 0, item);
|
||||
|
||||
for (int i = 1; i < 8; i++)
|
||||
{
|
||||
item = new QTableWidgetItem("");
|
||||
ui->tableSender->setItem(row, i, item);
|
||||
}
|
||||
|
||||
inhibitChanged = false;
|
||||
}
|
||||
|
||||
void FrameSenderWindow::buildFrameCache()
|
||||
{
|
||||
CANFrame thisFrame;
|
||||
frameCache.clear();
|
||||
for (int i = 0; i < modelFrames->count(); i++)
|
||||
{
|
||||
thisFrame = modelFrames->at(i);
|
||||
if (!frameCache.contains(thisFrame.ID))
|
||||
{
|
||||
frameCache.insert(thisFrame.ID, thisFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
frameCache[thisFrame.ID] = thisFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//remember, negative numbers are special -1 = all frames deleted, -2 = totally new set of frames.
|
||||
void FrameSenderWindow::updatedFrames(int numFrames)
|
||||
{
|
||||
CANFrame thisFrame;
|
||||
if (numFrames == -1) //all frames deleted.
|
||||
{
|
||||
}
|
||||
else if (numFrames == -2) //all new set of frames.
|
||||
{
|
||||
buildFrameCache();
|
||||
}
|
||||
else //just got some new frames. See if they are relevant.
|
||||
{
|
||||
qDebug() << "New frames in sender window";
|
||||
//run through the supposedly new frames in order
|
||||
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
|
||||
{
|
||||
if (!frameCache.contains(thisFrame.ID))
|
||||
{
|
||||
frameCache.insert(thisFrame.ID, thisFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
frameCache[thisFrame.ID] = thisFrame;
|
||||
}
|
||||
processIncomingFrame(&thisFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSenderWindow::processIncomingFrame(CANFrame *frame)
|
||||
{
|
||||
for (int sd = 0; sd < sendingData.count(); sd++)
|
||||
{
|
||||
if (sendingData[sd].triggers.count() == 0) continue;
|
||||
for (int trig = 0; trig < sendingData[sd].triggers.count(); trig++)
|
||||
{
|
||||
Trigger thisTrigger = sendingData[sd].triggers[trig];
|
||||
if (thisTrigger.ID > 0 && thisTrigger.ID == frame->ID)
|
||||
{
|
||||
if (thisTrigger.bus == frame->bus || thisTrigger.bus == -1)
|
||||
{
|
||||
if (thisTrigger.currCount < thisTrigger.maxCount)
|
||||
{
|
||||
if (thisTrigger.milliseconds == 0) //immediate reply
|
||||
{
|
||||
thisTrigger.currCount++;
|
||||
sendingData[sd].count++;
|
||||
doModifiers(sd);
|
||||
updateGridRow(sd);
|
||||
sendCANFrame(&sendingData[sd], sendingData[sd].bus);
|
||||
}
|
||||
else //delayed sending frame
|
||||
{
|
||||
thisTrigger.readyCount = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSenderWindow::enableAll()
|
||||
{
|
||||
for (int i = 0; i < ui->tableSender->rowCount() - 1; i++)
|
||||
{
|
||||
ui->tableSender->item(i, 0)->setCheckState(Qt::Checked);
|
||||
sendingData[i].enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSenderWindow::disableAll()
|
||||
{
|
||||
for (int i = 0; i < ui->tableSender->rowCount() - 1; i++)
|
||||
{
|
||||
ui->tableSender->item(i, 0)->setCheckState(Qt::Unchecked);
|
||||
sendingData[i].enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSenderWindow::clearGrid()
|
||||
{
|
||||
if (ui->tableSender->rowCount() == 1) return;
|
||||
for (int i = ui->tableSender->rowCount() - 2; i >= 0; i--)
|
||||
{
|
||||
sendingData[i].enabled = false;
|
||||
sendingData.removeAt(i);
|
||||
ui->tableSender->removeRow(i);
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSenderWindow::saveGrid()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog(this);
|
||||
|
||||
QStringList filters;
|
||||
filters.append(QString(tr("Frame Sender Definition (*.fsd)")));
|
||||
|
||||
dialog.setFileMode(QFileDialog::AnyFile);
|
||||
dialog.setNameFilters(filters);
|
||||
dialog.setViewMode(QFileDialog::Detail);
|
||||
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
|
||||
if (dialog.selectedNameFilter() == filters[0])
|
||||
{
|
||||
if (!filename.contains('.')) filename += ".fsd";
|
||||
saveSenderFile(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSenderWindow::loadGrid()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog(this);
|
||||
|
||||
QStringList filters;
|
||||
filters.append(QString(tr("Frame Sender Definition (*.fsd)")));
|
||||
|
||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||
dialog.setNameFilters(filters);
|
||||
dialog.setViewMode(QFileDialog::Detail);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
|
||||
if (dialog.selectedNameFilter() == filters[0])
|
||||
{
|
||||
loadSenderFile(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSenderWindow::saveSenderFile(QString filename)
|
||||
{
|
||||
QFile *outFile = new QFile(filename);
|
||||
QString outString;
|
||||
|
||||
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
{
|
||||
delete outFile;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int c = 0; c < sendingData.count(); c++)
|
||||
{
|
||||
outString.clear();
|
||||
if (ui->tableSender->item(c, 0)->checkState() == Qt::Checked)
|
||||
{
|
||||
outString = "T#";
|
||||
}
|
||||
else outString = "F#";
|
||||
for (int i = 1; i < 7; i++)
|
||||
{
|
||||
outString.append(ui->tableSender->item(c, i)->text());
|
||||
outString.append("#");
|
||||
}
|
||||
outString.append("\n");
|
||||
outFile->write(outString.toUtf8());
|
||||
}
|
||||
|
||||
outFile->close();
|
||||
delete outFile;
|
||||
|
||||
}
|
||||
|
||||
void FrameSenderWindow::loadSenderFile(QString filename)
|
||||
{
|
||||
QFile *inFile = new QFile(filename);
|
||||
QByteArray line;
|
||||
|
||||
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
delete inFile;
|
||||
return;
|
||||
}
|
||||
|
||||
ui->tableSender->clear();
|
||||
sendingData.clear();
|
||||
|
||||
while (!inFile->atEnd()) {
|
||||
line = inFile->readLine().simplified();
|
||||
if (line.length() > 2)
|
||||
{
|
||||
QList<QByteArray> tokens = line.split('#');
|
||||
int row = ui->tableSender->rowCount();
|
||||
ui->tableSender->insertRow(row);
|
||||
ui->tableSender->item(row, 0)->setFlags(Qt::ItemIsUserCheckable);
|
||||
if (tokens[0] == "T")
|
||||
{
|
||||
ui->tableSender->item(row, 0)->setCheckState(Qt::Checked);
|
||||
}
|
||||
else ui->tableSender->item(row, 0)->setCheckState(Qt::Unchecked);
|
||||
for (int i = 0; i < 7; i++) ui->tableSender->item(row, i)->setText(tokens[i]);
|
||||
for (int k = 0; k < 7; k++) processCellChange(row, k);
|
||||
|
||||
}
|
||||
}
|
||||
inFile->close();
|
||||
delete inFile;
|
||||
}
|
||||
|
||||
void FrameSenderWindow::onCellChanged(int row, int col)
|
||||
{
|
||||
if (inhibitChanged) return;
|
||||
qDebug() << "onCellChanged";
|
||||
if (row == ui->tableSender->rowCount() - 1)
|
||||
{
|
||||
ui->tableSender->insertRow(ui->tableSender->rowCount());
|
||||
createBlankRow();
|
||||
}
|
||||
|
||||
processCellChange(row, col);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,29 +325,33 @@ void FrameSenderWindow::onCellChanged(int row, int col)
|
||||
/// <param name="timerEventArgs"></param>
|
||||
void FrameSenderWindow::handleTick()
|
||||
{
|
||||
FrameSendData sendData;
|
||||
Trigger trigger;
|
||||
Modifier modifier;
|
||||
FrameSendData *sendData;
|
||||
Trigger *trigger;
|
||||
int elapsed = elapsedTimer.restart();
|
||||
if (elapsed == 0) elapsed = 1;
|
||||
//Modifier modifier;
|
||||
for (int i = 0; i < sendingData.count(); i++)
|
||||
{
|
||||
sendData = sendingData.at(i);
|
||||
if (!sendData.enabled) continue; //abort any processing on this if it is not enabled.
|
||||
if (sendData.triggers.count() == 0) return;
|
||||
for (int j = 0; j < sendData.triggers.count(); j++)
|
||||
sendData = &sendingData[i];
|
||||
if (!sendData->enabled) continue; //abort any processing on this if it is not enabled.
|
||||
if (sendData->triggers.count() == 0) return;
|
||||
for (int j = 0; j < sendData->triggers.count(); j++)
|
||||
{
|
||||
trigger = sendData.triggers.at(j);
|
||||
if (trigger.currCount >= trigger.maxCount) continue; //don't process if we've sent max frames we were supposed to
|
||||
if (!trigger.readyCount) continue; //don't tick if not ready to tick
|
||||
trigger = &sendData->triggers[j];
|
||||
if (trigger->currCount >= trigger->maxCount) continue; //don't process if we've sent max frames we were supposed to
|
||||
if (!trigger->readyCount) continue; //don't tick if not ready to tick
|
||||
//is it time to fire?
|
||||
if (++trigger.msCounter >= trigger.milliseconds)
|
||||
trigger->msCounter += elapsed; //gives proper tracking even if timer doesn't fire as fast as it should
|
||||
if (trigger->msCounter >= trigger->milliseconds)
|
||||
{
|
||||
trigger.msCounter = 0;
|
||||
sendData.count++;
|
||||
trigger.currCount++;
|
||||
trigger->msCounter = 0;
|
||||
sendData->count++;
|
||||
trigger->currCount++;
|
||||
doModifiers(i);
|
||||
//updateGridRow(i);
|
||||
//parent.SendCANFrame(sendingData[i], sendingData[i].bus);
|
||||
if (trigger.ID > 0) trigger.readyCount = false; //reset flag if this is a timed ID trigger
|
||||
updateGridRow(i);
|
||||
qDebug() << "About to try to send a frame";
|
||||
emit sendCANFrame(&sendingData[i], sendingData[i].bus);
|
||||
if (trigger->ID > 0) trigger->readyCount = false; //reset flag if this is a timed ID trigger
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,18 +366,20 @@ void FrameSenderWindow::doModifiers(int idx)
|
||||
int shadowReg = 0; //shadow register we use to accumulate results
|
||||
int first=0, second=0;
|
||||
|
||||
FrameSendData sendData = sendingData.at(idx);
|
||||
Modifier mod;
|
||||
FrameSendData *sendData = &sendingData[idx];
|
||||
Modifier *mod;
|
||||
ModifierOp op;
|
||||
|
||||
if (sendData.modifiers.count() == 0) return; //if no modifiers just leave right now
|
||||
if (sendData->modifiers.count() == 0) return; //if no modifiers just leave right now
|
||||
|
||||
for (int i = 0; i < sendData.modifiers.count(); i++)
|
||||
qDebug() << "Doin' dem mods son";
|
||||
|
||||
for (int i = 0; i < sendData->modifiers.count(); i++)
|
||||
{
|
||||
mod = sendData.modifiers.at(i);
|
||||
for (int j = 0; j < mod.operations.count(); j++)
|
||||
mod = &sendData->modifiers[i];
|
||||
for (int j = 0; j < mod->operations.count(); j++)
|
||||
{
|
||||
op = mod.operations.at(j);
|
||||
op = mod->operations.at(j);
|
||||
if (op.first.ID == -1)
|
||||
{
|
||||
first = shadowReg;
|
||||
@@ -135,7 +412,7 @@ void FrameSenderWindow::doModifiers(int idx)
|
||||
}
|
||||
}
|
||||
//Finally, drop the result into the proper data byte
|
||||
mod.destByte = (unsigned char) shadowReg;
|
||||
sendData->data[mod->destByte] = (unsigned char) shadowReg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,15 +446,10 @@ int FrameSenderWindow::fetchOperand(int idx, ModifierOperand op)
|
||||
/// <returns></returns>
|
||||
CANFrame* FrameSenderWindow::lookupFrame(int ID, int bus)
|
||||
{
|
||||
CANFrame frame;
|
||||
for (int a = 0; a < frameCache.count(); a++)
|
||||
{
|
||||
frame = frameCache.at(a);
|
||||
if ((ID == frame.ID) && ((bus == frame.bus) || bus == -1))
|
||||
{
|
||||
return &frame;
|
||||
}
|
||||
}
|
||||
if (!frameCache.contains(ID)) return NULL;
|
||||
|
||||
if (bus == -1 || frameCache[ID].bus == bus) return &frameCache[ID];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -188,6 +460,7 @@ CANFrame* FrameSenderWindow::lookupFrame(int ID, int bus)
|
||||
/// <param name="line"></param>
|
||||
void FrameSenderWindow::processModifierText(int line)
|
||||
{
|
||||
qDebug() << "processModifierText";
|
||||
QString modString;
|
||||
int numOps;
|
||||
|
||||
@@ -266,6 +539,7 @@ void FrameSenderWindow::processModifierText(int line)
|
||||
|
||||
void FrameSenderWindow::processTriggerText(int line)
|
||||
{
|
||||
qDebug() << "processTriggerText";
|
||||
QString trigger;
|
||||
|
||||
//Example line:
|
||||
@@ -340,6 +614,7 @@ void FrameSenderWindow::processTriggerText(int line)
|
||||
//Turn a set of tokens into an operand
|
||||
void FrameSenderWindow::parseOperandString(QStringList tokens, ModifierOperand &operand)
|
||||
{
|
||||
qDebug() << "parseOperandString";
|
||||
//example string -> bus:0:id:200:d3
|
||||
|
||||
operand.bus = -1;
|
||||
@@ -370,6 +645,7 @@ void FrameSenderWindow::parseOperandString(QStringList tokens, ModifierOperand &
|
||||
|
||||
ModifierOperationType FrameSenderWindow::parseOperation(QString op)
|
||||
{
|
||||
qDebug() << "parseOperation";
|
||||
if (op == "+") return ADDITION;
|
||||
if (op == "-") return SUBTRACTION;
|
||||
if (op == "*") return MULTIPLICATION;
|
||||
@@ -382,113 +658,43 @@ ModifierOperationType FrameSenderWindow::parseOperation(QString op)
|
||||
if (op == "XOR") return XOR;
|
||||
return ADDITION;
|
||||
}
|
||||
//The below is c# code from the old project. It won't run as-is and must be ported to C++/Qt
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Updaet the DataGridView with the newest info from sendingData
|
||||
/// Update the DataGridView with the newest info from sendingData
|
||||
/// </summary>
|
||||
/// <param name="idx"></param>
|
||||
private void updateGridRow(int idx)
|
||||
void FrameSenderWindow::updateGridRow(int idx)
|
||||
{
|
||||
FrameSendData temp = sendingData[idx];
|
||||
qDebug() << "updateGridRow";
|
||||
inhibitChanged = true;
|
||||
FrameSendData *temp = &sendingData[idx];
|
||||
int gridLine = idx;
|
||||
StringBuilder dataString = new StringBuilder();
|
||||
dataGridView1.Rows[gridLine].Cells[7].Value = temp.count.ToString();
|
||||
for (int i = 0; i < temp.len; i++)
|
||||
QString dataString;
|
||||
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++)
|
||||
{
|
||||
dataString.Append("0x");
|
||||
dataString.Append(temp.data[i].ToString("X2"));
|
||||
dataString.Append(" ");
|
||||
dataString.append(Utility::formatNumber(temp->data[i]));
|
||||
dataString.append(" ");
|
||||
}
|
||||
dataGridView1.Rows[gridLine].Cells[4].Value = dataString.ToString();
|
||||
ui->tableSender->item(gridLine, 4)->setText(dataString);
|
||||
inhibitChanged = false;
|
||||
}
|
||||
|
||||
public delegate void GotCANDelegate(CANFrame frame);
|
||||
/// <summary>
|
||||
/// Event callback for reception of canbus frames
|
||||
/// </summary>
|
||||
/// <param name="frame">The frame that came in</param>
|
||||
public void GotCANFrame(CANFrame frame)
|
||||
{
|
||||
if (this.InvokeRequired)
|
||||
{
|
||||
this.Invoke(new GotCANDelegate(GotCANFrame), frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
//search list of frames and add if no frame with this ID is found
|
||||
//or update if one was found.
|
||||
bool found = false;
|
||||
for (int a = 0; a < frames.Count; a++)
|
||||
{
|
||||
if ((frame.ID == frames[a].ID) && (frame.bus == frames[a].bus))
|
||||
{
|
||||
found = true;
|
||||
frames[a].len = frame.len;
|
||||
frames[a].data = frame.data;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
frames.Add(frame);
|
||||
}
|
||||
|
||||
//now that frame cache has been updated, try to see if this incoming frame
|
||||
//satisfies any triggers
|
||||
|
||||
for (int b = 0; b < sendingData.Count; b++)
|
||||
{
|
||||
if (sendingData[b].triggers == null) continue;
|
||||
for (int c = 0; c < sendingData[b].triggers.Length; c++)
|
||||
{
|
||||
Trigger thisTrigger = sendingData[b].triggers[c];
|
||||
if (thisTrigger.ID > 0)
|
||||
{
|
||||
if ((thisTrigger.bus == frame.bus) || (thisTrigger.bus == -1))
|
||||
{
|
||||
if (thisTrigger.ID == frame.ID)
|
||||
{
|
||||
//seems to match this trigger.
|
||||
if (thisTrigger.currCount < thisTrigger.maxCount)
|
||||
{
|
||||
if (thisTrigger.milliseconds == 0) //don't want to time the frame, send it right away
|
||||
{
|
||||
sendingData[b].triggers[c].currCount++;
|
||||
sendingData[b].count++;
|
||||
doModifiers(b);
|
||||
updateGridRow(b);
|
||||
parent.SendCANFrame(sendingData[b], sendingData[b].bus);
|
||||
}
|
||||
else //instead of immediate sending we start the timer
|
||||
{
|
||||
sendingData[b].triggers[c].readyCount = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dataGridView1_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
|
||||
{
|
||||
int rec = e.RowIndex;
|
||||
if (rec != -1) sendingData.RemoveAt(rec);
|
||||
}
|
||||
|
||||
private void processCellChange(int line, int col)
|
||||
void FrameSenderWindow::processCellChange(int line, int col)
|
||||
{
|
||||
qDebug() << "processCellChange";
|
||||
FrameSendData tempData;
|
||||
QStringList tokens;
|
||||
int tempVal;
|
||||
|
||||
//if this is a new line then create the base object for the line
|
||||
if ((line >= sendingData.Count) || (sendingData[line] == null))
|
||||
if (line >= sendingData.count())
|
||||
{
|
||||
tempData = new FrameSendData();
|
||||
sendingData.Add(tempData);
|
||||
FrameSendData tempData;
|
||||
tempData.enabled = false;
|
||||
sendingData.append(tempData);
|
||||
}
|
||||
|
||||
sendingData[line].count = 0;
|
||||
@@ -496,28 +702,31 @@ private void processCellChange(int line, int col)
|
||||
switch (col)
|
||||
{
|
||||
case 0: //Enable check box
|
||||
if (dataGridView1.Rows[line].Cells[0].Value != null)
|
||||
if (ui->tableSender->item(line, 0)->checkState() == Qt::Checked)
|
||||
{
|
||||
sendingData[line].enabled = (bool)dataGridView1.Rows[line].Cells[0].Value;
|
||||
sendingData[line].enabled = true;
|
||||
}
|
||||
else sendingData[line].enabled = false;
|
||||
qDebug() << "Setting enabled to " << sendingData[line].enabled;
|
||||
break;
|
||||
case 1: //Bus designation
|
||||
tempVal = Utility.ParseStringToNum((string)dataGridView1.Rows[line].Cells[1].Value);
|
||||
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 1)->text());
|
||||
if (tempVal < 0) tempVal = 0;
|
||||
if (tempVal > 1) tempVal = 1;
|
||||
sendingData[line].bus = tempVal;
|
||||
qDebug() << "Setting bus to " << tempVal;
|
||||
break;
|
||||
case 2: //ID field
|
||||
tempVal = Utility.ParseStringToNum((string)dataGridView1.Rows[line].Cells[2].Value);
|
||||
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 2)->text());
|
||||
if (tempVal < 1) tempVal = 1;
|
||||
if (tempVal > 0x7FFFFFFF) tempVal = 0x7FFFFFFF;
|
||||
sendingData[line].ID = tempVal;
|
||||
if (sendingData[line].ID <= 0x7FF) sendingData[line].extended = false;
|
||||
else sendingData[line].extended = true;
|
||||
qDebug() << "setting ID to " << tempVal;
|
||||
break;
|
||||
case 3: //length field
|
||||
tempVal = Utility.ParseStringToNum((string)dataGridView1.Rows[line].Cells[3].Value);
|
||||
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 3)->text());
|
||||
if (tempVal < 0) tempVal = 0;
|
||||
if (tempVal > 8) tempVal = 8;
|
||||
sendingData[line].len = tempVal;
|
||||
@@ -525,10 +734,10 @@ private void processCellChange(int line, int col)
|
||||
case 4: //Data bytes
|
||||
for (int i = 0; i < 8; i++) sendingData[line].data[i] = 0;
|
||||
|
||||
string[] tokens = ((string)dataGridView1.Rows[line].Cells[4].Value).Split(' ');
|
||||
for (int j = 0; j < tokens.Length; j++)
|
||||
tokens = ui->tableSender->item(line, 4)->text().split(" ");
|
||||
for (int j = 0; j < tokens.count(); j++)
|
||||
{
|
||||
sendingData[line].data[j] = (byte)Utility.ParseStringToNum(tokens[j]);
|
||||
sendingData[line].data[j] = (uint8_t)Utility::ParseStringToNum(tokens[j]);
|
||||
}
|
||||
break;
|
||||
case 5: //triggers
|
||||
@@ -540,126 +749,3 @@ private void processCellChange(int line, int col)
|
||||
}
|
||||
}
|
||||
|
||||
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
processCellChange(e.RowIndex, e.ColumnIndex);
|
||||
}
|
||||
|
||||
private void loadFromFileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult res;
|
||||
//First zap all existing data. Ask first. Might not need to actually ask here since you can abort the file open
|
||||
//and be OK that way too.
|
||||
if (sendingData.Count > 0)
|
||||
{
|
||||
res = MessageBox.Show("Proceding will erase the current\ncontents of the grid.", "Warning", MessageBoxButtons.YesNo);
|
||||
if (res == DialogResult.No) return;
|
||||
}
|
||||
res = openFileDialog1.ShowDialog();
|
||||
if (res == DialogResult.OK)
|
||||
{
|
||||
sendingData.Clear();
|
||||
dataGridView1.Rows.Clear();
|
||||
Stream inputFile = openFileDialog1.OpenFile();
|
||||
StreamReader inputReader = new StreamReader(inputFile);
|
||||
string line;
|
||||
int row;
|
||||
try
|
||||
{
|
||||
while (!inputReader.EndOfStream)
|
||||
{
|
||||
line = inputReader.ReadLine();
|
||||
string[] tokens = line.Split('#');
|
||||
row = dataGridView1.Rows.Add();
|
||||
if (tokens[0] == "T")
|
||||
{
|
||||
dataGridView1.Rows[row].Cells[0].Value = true;
|
||||
}
|
||||
else dataGridView1.Rows[row].Cells[0].Value = false;
|
||||
for (int j = 1; j < 7; j++)
|
||||
{
|
||||
dataGridView1.Rows[row].Cells[j].Value = tokens[j];
|
||||
}
|
||||
for (int k = 0; k < 7; k++) processCellChange(row, k);
|
||||
}
|
||||
}
|
||||
catch (Exception ee)
|
||||
{
|
||||
Debug.Print(ee.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveGridToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
StringBuilder buildStr = new StringBuilder();
|
||||
DialogResult res;
|
||||
res = saveFileDialog1.ShowDialog();
|
||||
if (res == DialogResult.OK)
|
||||
{
|
||||
Stream outputFile = saveFileDialog1.OpenFile();
|
||||
StreamWriter outputWriter = new StreamWriter(outputFile);
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < sendingData.Count; i++)
|
||||
{
|
||||
buildStr.Clear();
|
||||
if (dataGridView1.Rows[i].Cells[0].Value != null)
|
||||
{
|
||||
if ((bool)dataGridView1.Rows[i].Cells[0].Value == true)
|
||||
{
|
||||
buildStr.Append("T");
|
||||
}
|
||||
else buildStr.Append("F");
|
||||
}
|
||||
else buildStr.Append("F");
|
||||
buildStr.Append("#");
|
||||
for (int j = 1; j < 7; j++)
|
||||
{
|
||||
buildStr.Append(dataGridView1.Rows[i].Cells[j].Value);
|
||||
buildStr.Append("#");
|
||||
}
|
||||
outputWriter.WriteLine(buildStr.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception ee)
|
||||
{
|
||||
Debug.Print(ee.ToString());
|
||||
}
|
||||
outputWriter.Flush();
|
||||
outputWriter.Close();
|
||||
}
|
||||
}
|
||||
|
||||
//Note for the below three functions that they all handle the fact that a data view grid will always have an extra row that is blank
|
||||
//and available for a new record. Because of this the grid count is always one too high.
|
||||
private void button1_Click(object sender, EventArgs e) //enable all lines in the grid
|
||||
{
|
||||
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
|
||||
{
|
||||
dataGridView1.Rows[i].Cells[0].Value = true;
|
||||
sendingData[i].enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void button2_Click(object sender, EventArgs e) //disable all lines in the grid
|
||||
{
|
||||
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
|
||||
{
|
||||
dataGridView1.Rows[i].Cells[0].Value = false;
|
||||
sendingData[i].enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void button3_Click(object sender, EventArgs e) //delete all entries in the grid and data struct
|
||||
{
|
||||
if (dataGridView1.Rows.Count == 1) return;
|
||||
for (int i = dataGridView1.Rows.Count - 2; i >= 0; i--)
|
||||
{
|
||||
sendingData[i].enabled = false;
|
||||
sendingData.RemoveAt(i);
|
||||
dataGridView1.Rows.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
+21
-1
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTimer>
|
||||
#include <QElapsedTimer>
|
||||
#include <QTime>
|
||||
#include "can_structs.h"
|
||||
#include "can_trigger_structs.h"
|
||||
|
||||
@@ -21,14 +23,26 @@ public:
|
||||
private slots:
|
||||
void onCellChanged(int, int);
|
||||
void handleTick();
|
||||
void enableAll();
|
||||
void disableAll();
|
||||
void clearGrid();
|
||||
void saveGrid();
|
||||
void loadGrid();
|
||||
void updatedFrames(int);
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
|
||||
private:
|
||||
Ui::FrameSenderWindow *ui;
|
||||
QList<FrameSendData> sendingData;
|
||||
QList<CANFrame> frameCache;
|
||||
QHash<int, CANFrame> frameCache; //hash with frame ID as the key and the most recent frame as the value
|
||||
const QVector<CANFrame> *modelFrames;
|
||||
QTimer *intervalTimer;
|
||||
QElapsedTimer elapsedTimer;
|
||||
bool inhibitChanged = false;
|
||||
|
||||
void createBlankRow();
|
||||
void doModifiers(int);
|
||||
int fetchOperand(int, ModifierOperand);
|
||||
CANFrame* lookupFrame(int, int);
|
||||
@@ -36,6 +50,12 @@ private:
|
||||
void processTriggerText(int);
|
||||
void parseOperandString(QStringList tokens, ModifierOperand&);
|
||||
ModifierOperationType parseOperation(QString);
|
||||
void saveSenderFile(QString filename);
|
||||
void loadSenderFile(QString filename);
|
||||
void updateGridRow(int idx);
|
||||
void processCellChange(int line, int col);
|
||||
void buildFrameCache();
|
||||
void processIncomingFrame(CANFrame *frame);
|
||||
};
|
||||
|
||||
#endif // FRAMESENDERWINDOW_H
|
||||
|
||||
@@ -24,21 +24,21 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<widget class="QPushButton" name="btnEnableAll">
|
||||
<property name="text">
|
||||
<string>Enable All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_3">
|
||||
<widget class="QPushButton" name="btnDisableAll">
|
||||
<property name="text">
|
||||
<string>Disable All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_5">
|
||||
<widget class="QPushButton" name="btnClearGrid">
|
||||
<property name="text">
|
||||
<string>Clear Grid</string>
|
||||
</property>
|
||||
@@ -61,14 +61,14 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_4">
|
||||
<widget class="QPushButton" name="btnLoadGrid">
|
||||
<property name="text">
|
||||
<string>Load to Grid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<widget class="QPushButton" name="btnSaveGrid">
|
||||
<property name="text">
|
||||
<string>Save Grid</string>
|
||||
</property>
|
||||
|
||||
Reference in New Issue
Block a user