You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

498 lines
14 KiB

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QFileDialog>
#include <QtConcurrent/QtConcurrent>
#include <QMessageBox>
#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<QString>());
ui->tb_binOffset->setText(_settings->value(BIN_OFFSET).value<QString>());
ui->cb_binBarNum->setCurrentIndex(_settings->value(BIN_BAR_INDEX).value<int>());
ui->rbtn_reg->setChecked(_settings->value(REG_ACCESS_SEL).value<bool>());
ui->rbtn_offset->setChecked(!_settings->value(REG_ACCESS_SEL).value<bool>());
ui->tb_fpgaBit->setText(_settings->value(FPGA_FILE_PATH).value<QString>());
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<void> watcher;
connect(&watcher, &QFutureWatcher<void>::finished, this, &MainWindow::threadFinished);
auto future = QtConcurrent::run(this, &MainWindow::binaryFileUploader, bar, offset, path);
watcher.setFuture(future);
_dial->exec();
disconnect(&watcher, &QFutureWatcher<void>::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<void> watcher;
connect(&watcher, &QFutureWatcher<void>::finished, this, &MainWindow::threadFinished);
auto future = QtConcurrent::run(this, &MainWindow::binaryFileVerifier, bar, offset, path);
watcher.setFuture(future);
_dial->exec();
disconnect(&watcher, &QFutureWatcher<void>::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<void> watcher;
connect(&watcher, &QFutureWatcher<void>::finished, this, &MainWindow::threadFinished);
auto future = QtConcurrent::run(this, &MainWindow::fpgaProgrammer, bar, offset, path);
watcher.setFuture(future);
_dial->exec();
disconnect(&watcher, &QFutureWatcher<void>::finished, this, &MainWindow::threadFinished);
}
/*************************************************************************************************/
void MainWindow::newMessage(QString message)
{
QMessageBox msgBox;
msgBox.setText(message);
msgBox.exec();
}
void MainWindow::threadFinished()
{
_dial->close();
}