#include "mainwindow.h" #include "ui_mainwindow.h" #include "can_structs.h" #include #include #include #include "canframemodel.h" #include "utility.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); model = new CANFrameModel(); ui->canFramesView->setModel(model); QStringList headers; headers << "Timestamp" << "ID" << "Ext" << "Bus" << "Len" << "Data"; //model->setHorizontalHeaderLabels(headers); ui->canFramesView->setColumnWidth(0, 110); ui->canFramesView->setColumnWidth(1, 70); ui->canFramesView->setColumnWidth(2, 40); ui->canFramesView->setColumnWidth(3, 40); ui->canFramesView->setColumnWidth(4, 40); ui->canFramesView->setColumnWidth(5, 300); QList ports = QSerialPortInfo::availablePorts(); for (int i = 0; i < ports.count(); i++) { ui->cbSerialPorts->addItem(ports[i].portName()); } port = new QSerialPort(this); rx_state = IDLE; rx_step = 0; } MainWindow::~MainWindow() { delete ui; } void MainWindow::addFrameToDisplay(CANFrame &frame, bool autoRefresh = false) { model->addFrame(frame, autoRefresh); } void MainWindow::loadCRTDFile(QString filename) { } void MainWindow::loadNativeCSVFile(QString filename) { QFile *inFile = new QFile(filename); CANFrame thisFrame; QByteArray line; if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) return; line = inFile->readLine(); //read out the header first and discard it. while (!inFile->atEnd()) { line = inFile->readLine(); if (line.length() > 2) { QList tokens = line.split(','); if (tokens[0].length() > 10) { long long temp = tokens[0].toInt(); thisFrame.timestamp = temp; } else { QDateTime stamp = QDateTime::currentDateTime(); thisFrame.timestamp = (long)(((stamp.time().hour() * 3600) + (stamp.time().minute() * 60) + (stamp.time().second()) * 1000) + stamp.time().msec()); } thisFrame.ID = tokens[1].toInt(NULL, 16); if (tokens[2].contains("True")) thisFrame.extended = 1; else thisFrame.extended = 0; thisFrame.bus = tokens[3].toInt(); thisFrame.len = tokens[4].toInt(); for (int c = 0; c < 8; c++) thisFrame.data[c] = 0; for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = tokens[5 + d].toInt(NULL, 16); addFrameToDisplay(thisFrame); } } inFile->close(); model->sendRefresh(); } void MainWindow::loadGenericCSVFile(QString filename) { QFile *inFile = new QFile(filename); CANFrame thisFrame; QByteArray line; if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) return; line = inFile->readLine(); //read out the header first and discard it. while (!inFile->atEnd()) { line = inFile->readLine(); if (line.length() > 2) { QList tokens = line.split(','); QDateTime stamp = QDateTime::currentDateTime(); thisFrame.timestamp = (long)(((stamp.time().hour() * 3600) + (stamp.time().minute() * 60) + (stamp.time().second()) * 1000) + stamp.time().msec()); thisFrame.ID = tokens[0].toInt(NULL, 16); if (thisFrame.ID > 0x7FF) thisFrame.extended = true; else thisFrame.extended = false; thisFrame.bus = 0; QList 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); addFrameToDisplay(thisFrame); } } inFile->close(); model->sendRefresh(); } void MainWindow::loadLogFile(QString filename) { } void MainWindow::loadMicrochipFile(QString filename) { QFile *inFile = new QFile(filename); CANFrame thisFrame; QByteArray line; bool inComment = false; if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) return; line = inFile->readLine(); //read out the header first and discard it. while (!inFile->atEnd()) { line = inFile->readLine(); if (line.length() > 2) { if (line.startsWith("//")) { inComment = !inComment; } else { /* tokens: 0 = timestamp 1 = Transmission direction 2 = ID 3 = Data byte length 4-x = The data bytes */ if (!inComment) { QList tokens = line.split(';'); QDateTime stamp = QDateTime::currentDateTime(); thisFrame.timestamp = (long)(((stamp.time().hour() * 3600) + (stamp.time().minute() * 60) + (stamp.time().second()) * 1000) + stamp.time().msec()); //thisFrame.ID = Utility::ParseStringToNum(tokens[2]); if (thisFrame.ID <= 0x7FF) thisFrame.extended = false; else thisFrame.extended = true; thisFrame.bus = 0; thisFrame.len = tokens[3].toInt(); //for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = (unsigned char)Utility::ParseStringToNum(tokens[4 + d]); addFrameToDisplay(thisFrame); } } } } inFile->close(); model->sendRefresh(); } void MainWindow::handleLoadFile() { QString filename; QFileDialog dialog(this); QStringList filters; filters.append(QString(tr("CRTD Logs (*.txt)"))); filters.append(QString(tr("GVRET Logs (*.csv)"))); filters.append(QString(tr("Generic ID/Data CSV (*.csv)"))); filters.append(QString(tr("BusMaster Log (*.log)"))); filters.append(QString(tr("Microchip Log (*.log)"))); dialog.setFileMode(QFileDialog::ExistingFile); dialog.setNameFilters(filters); dialog.setViewMode(QFileDialog::Detail); if (dialog.exec()) { filename = dialog.selectedFiles()[0]; } if (dialog.selectedNameFilter() == filters[0]) loadCRTDFile(filename); if (dialog.selectedNameFilter() == filters[1]) loadNativeCSVFile(filename); if (dialog.selectedNameFilter() == filters[2]) loadGenericCSVFile(filename); if (dialog.selectedNameFilter() == filters[3]) loadLogFile(filename); if (dialog.selectedNameFilter() == filters[4]) loadMicrochipFile(filename); } void MainWindow::connButtonPress() { if (port->isOpen()) { port->close(); } else { port->setPortName(ui->cbSerialPorts->currentText()); port->open(QIODevice::ReadWrite); QByteArray output; output.append(0xE7); output.append(0xE7); port->write(output); ///isConnected = true; connect(port, SIGNAL(readyRead()), this, SLOT(readSerialData())); } } void MainWindow::readSerialData() { QByteArray data = port->readAll(); unsigned char c; ui->statusBar->showMessage(tr("Got data from serial. Len = %0").arg(data.length())); for (int i = 0; i < data.length(); i++) { c = data.at(i); procRXChar(c); } } void MainWindow::procRXChar(unsigned char c) { switch (rx_state) { case IDLE: if (c == 0xF1) rx_state = GET_COMMAND; break; case GET_COMMAND: switch (c) { case 0: //receiving a can frame rx_state = BUILD_CAN_FRAME; rx_step = 0; break; case 1: //we don't accept time sync commands from the firmware rx_state = IDLE; break; case 2: //process a return reply for digital input states. rx_state = GET_DIG_INPUTS; rx_step = 0; break; case 3: //process a return reply for analog inputs rx_state = GET_ANALOG_INPUTS; break; case 4: //we set digital outputs we don't accept replies so nothing here. rx_state = IDLE; break; case 5: //we set canbus specs we don't accept replies. rx_state = IDLE; break; } break; case BUILD_CAN_FRAME: switch (rx_step) { case 0: buildFrame.timestamp = c; break; case 1: buildFrame.timestamp |= (uint)(c << 8); break; case 2: buildFrame.timestamp |= (uint)c << 16; break; case 3: buildFrame.timestamp |= (uint)c << 24; break; case 4: buildFrame.ID = c; break; case 5: buildFrame.ID |= c << 8; break; case 6: buildFrame.ID |= c << 16; break; case 7: buildFrame.ID |= c << 24; if ((buildFrame.ID & 1 << 31) == 1 << 31) { buildFrame.ID &= 0x7FFFFFFF; buildFrame.extended = true; } else buildFrame.extended = false; break; case 8: buildFrame.len = c & 0xF; if (buildFrame.len > 8) buildFrame.len = 8; buildFrame.bus = (c & 0xF0) >> 4; break; default: if (rx_step < buildFrame.len + 9) { buildFrame.data[rx_step - 9] = c; } else { rx_state = IDLE; rx_step = 0; addFrameToDisplay(buildFrame, true); } break; } rx_step++; break; case GET_ANALOG_INPUTS: //get 9 bytes - 2 per analog input plus checksum switch (rx_step) { case 0: break; } rx_step++; break; case GET_DIG_INPUTS: //get two bytes. One for digital in status and one for checksum. switch (rx_step) { case 0: break; case 1: rx_state = IDLE; break; } rx_step++; break; } }