#include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #define MESSAGE_BOX(M) \ emit showMessage(M) MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); _settings = new QSettings("Hasis", "HwTester"); _usd = new UltraSoundDevice(); _dial = new WaitDialog(); _dial->setModal(true); this->setFixedSize(this->width(),this->height()); ui->prg_binUpload->setVisible(false); ui->prg_fpgaProgram->setVisible(false); ui->tb_binFile->setReadOnly(true); ui->tb_fpgaBit->setReadOnly(true); ui->tb_binFile->setText(_settings->value(BIN_FILE_PATH).value()); ui->tb_binOffset->setText(_settings->value(BIN_OFFSET).value()); ui->cb_binBarNum->setCurrentIndex(_settings->value(BIN_BAR_INDEX).value()); ui->rbtn_reg->setChecked(_settings->value(REG_ACCESS_SEL).value()); ui->rbtn_offset->setChecked(!_settings->value(REG_ACCESS_SEL).value()); ui->tb_fpgaBit->setText(_settings->value(FPGA_FILE_PATH).value()); connect(this, &MainWindow::updateBlockProgressValue, this, &MainWindow::newBlockProgressValue); connect(this, &MainWindow::updateFpgaProgressValue, this, &MainWindow::newFpgaProgressValue); connect(this, &MainWindow::updateBlockProgressVisibility, this, &MainWindow::newBlockProgressVisibility); connect(this, &MainWindow::updateFpgaProgressVisibility, this, &MainWindow::newFpgaProgressVisibility); connect(this, &MainWindow::showMessage, this, &MainWindow::newMessage); } /*************************************************************************************************/ MainWindow::~MainWindow() { delete ui; delete _settings; delete _usd; delete _dial; } /*************************************************************************************************/ void MainWindow::on_btn_browse_clicked() { QFileDialog fileDialog; fileDialog.setNameFilters({"SRAM binary file (*.bin)"}); auto result = fileDialog.exec(); if(result) { auto selectedPath = fileDialog.selectedFiles()[0]; ui->tb_binFile->setText(selectedPath); _settings->setValue(BIN_FILE_PATH, selectedPath); } } /*************************************************************************************************/ void MainWindow::on_btn_binUpload_clicked() { auto bar = ui->cb_binBarNum->currentText().toUInt(); auto offset = ui->tb_binOffset->text().toUInt(Q_NULLPTR, 16); if(offset == 0 && ui->tb_binOffset->text() != "0") { MESSAGE_BOX("Invalid input format for offset"); return; } _settings->setValue(BIN_OFFSET, ui->tb_binOffset->text()); _settings->setValue(BIN_BAR_INDEX, ui->cb_binBarNum->currentIndex()); auto path = ui->tb_binFile->text(); QFutureWatcher watcher; connect(&watcher, &QFutureWatcher::finished, this, &MainWindow::threadFinished); auto future = QtConcurrent::run(this, &MainWindow::binaryFileUploader, bar, offset, path); watcher.setFuture(future); _dial->exec(); disconnect(&watcher, &QFutureWatcher::finished, this, &MainWindow::threadFinished); } /*************************************************************************************************/ void MainWindow::on_btn_binVerify_clicked() { auto bar = ui->cb_binBarNum->currentText().toUInt(); auto offset = ui->tb_binOffset->text().toUInt(Q_NULLPTR, 16); if(offset == 0 && ui->tb_binOffset->text() != "0") { MESSAGE_BOX("Invalid input format for offset"); return; } _settings->setValue(BIN_OFFSET, ui->tb_binOffset->text()); _settings->setValue(BIN_BAR_INDEX, ui->cb_binBarNum->currentIndex()); auto path = ui->tb_binFile->text(); QFutureWatcher watcher; connect(&watcher, &QFutureWatcher::finished, this, &MainWindow::threadFinished); auto future = QtConcurrent::run(this, &MainWindow::binaryFileVerifier, bar, offset, path); watcher.setFuture(future); _dial->exec(); disconnect(&watcher, &QFutureWatcher::finished, this, &MainWindow::threadFinished); } /*************************************************************************************************/ void MainWindow::binaryFileUploader(quint32 bar, quint32 offset, QString path) { QFile file(path); if (!file.open(QFile::ReadOnly)) { MESSAGE_BOX("Could not open binary file, aborting operation"); return; } emit updateBlockProgressVisibility(true); emit updateBlockProgressValue(0); const auto actualSize = file.size(); auto readSize = 0; while(readSize < actualSize) { QByteArray chunk = file.read(4); auto value = byteArrayTo32LittleEndian(chunk); try { _usd->writeWord(offset + readSize, bar, value); } catch (myexception e) { MESSAGE_BOX(e.what()); emit updateBlockProgressVisibility(false); file.close(); return; } readSize += 4; auto percentage = (readSize * 100 / actualSize); emit updateBlockProgressValue(percentage); } MESSAGE_BOX("Binary file upload finished with success"); emit updateBlockProgressVisibility(false); file.close(); } /*************************************************************************************************/ void MainWindow::binaryFileVerifier(quint32 bar, quint32 offset, QString path) { QFile file(path); if (!file.open(QFile::ReadOnly)) { MESSAGE_BOX("Could not open binary file, aborting operation"); return; } emit updateBlockProgressVisibility(true); emit updateBlockProgressValue(0); const auto actualSize = file.size(); auto readSize = 0; while(readSize < actualSize) { QByteArray chunk = file.read(4); auto value = byteArrayTo32LittleEndian(chunk); try { auto data = _usd->readWord(offset + readSize, bar); if(data != value) { auto message = QString("Error in data @ offset 0x%1, expected 0x%2 saw 0x%3") .arg(QString::number(offset + readSize)) .arg(QString::number(value, 16)) .arg(QString::number(data, 16)); MESSAGE_BOX(message); emit updateBlockProgressVisibility(false); file.close(); return; } } catch (myexception e) { MESSAGE_BOX(e.what()); emit updateBlockProgressVisibility(false); file.close(); return; } readSize += 4; auto percentage = (readSize * 100 / actualSize); emit updateBlockProgressValue(percentage); } MESSAGE_BOX("Binary verified with success"); emit updateBlockProgressVisibility(false); file.close(); } /*************************************************************************************************/ void MainWindow::fpgaProgrammer(quint32 bar, quint32 offset, QString path) { QFile file(path); if (!file.open(QFile::ReadOnly)) { MESSAGE_BOX("Could not open bit file, aborting operation"); return; } emit updateFpgaProgressValue(0); emit updateFpgaProgressVisibility(true); const auto actualSize = file.size(); auto readSize = 0; while(readSize < actualSize) { QByteArray chunk = file.read(4); auto value = byteArrayTo32BigEndian(chunk); try { _usd->writeWord(offset, bar, value); auto temp = _usd->readWord(offset + 4, bar); while ((temp & 0x01) == 0x01) { temp = _usd->readWord(offset + 4, bar); } if((temp & 0x08) == 0x08) { throw(myexception("init_fail flag raised")); } if((temp & 0x10) == 0x10) { throw(myexception("time_out flag raised")); } } catch (myexception e) { MESSAGE_BOX(e.what()); emit updateFpgaProgressVisibility(false); file.close(); return; } readSize += 4; auto percentage = (readSize * 100 / actualSize); emit updateFpgaProgressValue(percentage); } auto temp = _usd->readWord(offset + 4, bar); if((temp & 0x02) == 0x02) { MESSAGE_BOX("FPGA programming finished with success"); } else if((temp & 0x04) == 0x04) { MESSAGE_BOX("FPGA programming failed"); } emit updateFpgaProgressVisibility(false); file.close(); } /*************************************************************************************************/ quint32 MainWindow::byteArrayTo32LittleEndian(QByteArray data) { quint32 temp = 0; temp = (data[0] & 0x000000FF) | ((data[1] << 8) & 0x0000FF00) | ((data[2] << 16) & 0x00FF0000) | ((data[3] << 24) & 0xFF000000); return temp; } /*************************************************************************************************/ quint32 MainWindow::byteArrayTo32BigEndian(QByteArray data) { quint32 temp = 0; temp = (data[3] & 0x000000FF) | ((data[2] << 8) & 0x0000FF00) | ((data[1] << 16) & 0x00FF0000) | ((data[0] << 24) & 0xFF000000); return temp; } /*************************************************************************************************/ void MainWindow::on_rbtn_reg_toggled(bool checked) { if(checked) { _settings->setValue(REG_ACCESS_SEL, true); ui->l_regIndicator->setText("Register number: (Hex)"); } } /*************************************************************************************************/ void MainWindow::on_rbtn_offset_toggled(bool checked) { if(checked) { _settings->setValue(REG_ACCESS_SEL, false); ui->l_regIndicator->setText("Register offset: (Hex)"); } } /*************************************************************************************************/ void MainWindow::on_btn_readReg_clicked() { auto bar = ui->cb_regBarNum->currentText().toUInt(); auto offset = ui->tb_regIndicator->text().toUInt(Q_NULLPTR, 16); if(offset == 0 && ui->tb_regIndicator->text() != "0") { MESSAGE_BOX("Invalid input format for offset"); return; } quint64 value = 0; auto width = ui->cb_regWidth->currentIndex(); switch(width) { case 0: value = _usd->readByte(offset, bar); ui->lcd_regvalue->setDigitCount(2); break; case 1: if(ui->rbtn_reg->isChecked()) offset *= 2; value = _usd->readShort(offset, bar); ui->lcd_regvalue->setDigitCount(4); break; case 2: if(ui->rbtn_reg->isChecked()) offset *= 4; value = _usd->readWord(offset, bar); ui->lcd_regvalue->setDigitCount(8); break; case 3: if(ui->rbtn_reg->isChecked()) offset *= 8; value = _usd->readLong(offset, bar); ui->lcd_regvalue->setDigitCount(16); break; } ui->lcd_regvalue->display(QString::number(value, 16)); } /*************************************************************************************************/ void MainWindow::on_btn_writeReg_clicked() { auto bar = ui->cb_regBarNum->currentText().toUInt(); auto offset = ui->tb_regIndicator->text().toUInt(Q_NULLPTR, 16); if(offset == 0 && ui->tb_regIndicator->text() != "0") { MESSAGE_BOX("Invalid input format for offset"); return; } auto value = ui->tb_regValue->text().toULong(Q_NULLPTR, 16); if(value == 0 && ui->tb_regValue->text() != "0") { MESSAGE_BOX("Invalid input format for write value"); return; } auto width = ui->cb_regWidth->currentIndex(); switch(width) { case 0: _usd->writeByte(offset, bar, value); break; case 1: if(ui->rbtn_reg->isChecked()) offset *= 2; _usd->writeShort(offset, bar, value); break; case 2: if(ui->rbtn_reg->isChecked()) offset *= 4; _usd->writeWord(offset, bar, value); break; case 3: if(ui->rbtn_reg->isChecked()) offset *= 8; _usd->writeLong(offset, bar, value); break; } } /*************************************************************************************************/ void MainWindow::newBlockProgressValue(int percentage) { ui->prg_binUpload->setValue(percentage); } /*************************************************************************************************/ void MainWindow::newFpgaProgressValue(int percentage) { ui->prg_fpgaProgram->setValue(percentage); } /*************************************************************************************************/ void MainWindow::newBlockProgressVisibility(bool show) { ui->prg_binUpload->setVisible(show); } /*************************************************************************************************/ void MainWindow::newFpgaProgressVisibility(bool show) { ui->prg_fpgaProgram->setVisible(show); } /*************************************************************************************************/ void MainWindow::on_btn_fpgaBrowse_clicked() { QFileDialog fileDialog; fileDialog.setNameFilters({"FPGA program file (*.bit)"}); auto result = fileDialog.exec(); if(result) { auto selectedPath = fileDialog.selectedFiles()[0]; ui->tb_fpgaBit->setText(selectedPath); _settings->setValue(FPGA_FILE_PATH, selectedPath); } } /*************************************************************************************************/ void MainWindow::on_btn_fpgaProgram_clicked() { auto bar = 0; auto offset = 0x4; auto path = ui->tb_fpgaBit->text(); QFutureWatcher watcher; connect(&watcher, &QFutureWatcher::finished, this, &MainWindow::threadFinished); auto future = QtConcurrent::run(this, &MainWindow::fpgaProgrammer, bar, offset, path); watcher.setFuture(future); _dial->exec(); disconnect(&watcher, &QFutureWatcher::finished, this, &MainWindow::threadFinished); } /*************************************************************************************************/ void MainWindow::newMessage(QString message) { QMessageBox msgBox; msgBox.setText(message); msgBox.exec(); } void MainWindow::threadFinished() { _dial->close(); }