Skip to content

Commit 43c0e2c

Browse files
authored
Version 1.5.0 (#13)
* Adding bank viewer * Changing type
1 parent 072a628 commit 43c0e2c

File tree

10 files changed

+271
-24
lines changed

10 files changed

+271
-24
lines changed

gui/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ add_compile_definitions(GIT_HASH="${GIT_HASH}")
2424
find_package(Qt6 REQUIRED COMPONENTS Widgets SerialPort Network)
2525

2626
add_executable(pico-sst39sf0x0-programmer
27+
src/bankviewer.cpp
2728
src/cartridgereadthread.cpp
2829
src/dialogslotselection.cpp
2930
src/filedownloader.cpp

gui/assets/icon/clipboard.png

784 Bytes
Loading

gui/pico-sst39sf0x0-programmer.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CONFIG += c++17
99
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
1010

1111
SOURCES += \
12+
src/bankviewer.cpp \
1213
src/cartridgereadthread.cpp \
1314
src/dialogslotselection.cpp \
1415
src/filedownloader.cpp \
@@ -24,6 +25,7 @@ SOURCES += \
2425
src/settingswidget.cpp
2526

2627
HEADERS += \
28+
src/bankviewer.h \
2729
src/colors.h \
2830
src/config.h \
2931
src/cartridgereadthread.h \

gui/resources.qrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
<file>assets/roms/WordProcessor 1.bin</file>
4141
<file>assets/roms/WordProcessor 2.bin</file>
4242
<file>assets/roms/Zemon 1.4.bin</file>
43-
<file>assets/fonts/Consolas.ttf</file>
43+
<file>assets/fonts/Consolas.ttf</file>
44+
<file>assets/icon/clipboard.png</file>
4445
</qresource>
4546
</RCC>

gui/src/bankviewer.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include "bankviewer.h"
2+
3+
BankViewer::BankViewer(unsigned int nrbanks, const QByteArray& _data, QWidget *parent)
4+
: QDialog{parent} {
5+
6+
// set data
7+
this->data = _data;
8+
9+
// set icon
10+
this->setWindowIcon(QIcon(":/assets/icon/eeprom_icon.ico"));
11+
this->setWindowTitle("Overview banks on EEPROM");
12+
13+
this->build_widget(nrbanks);
14+
}
15+
16+
void BankViewer::build_widget(unsigned int nrbanks) {
17+
// build layout
18+
QVBoxLayout* layout = new QVBoxLayout();
19+
this->setLayout(layout);
20+
QString chipname;
21+
switch(nrbanks) {
22+
case 8:
23+
chipname = "SST39SF010";
24+
break;
25+
case 16:
26+
chipname = "SST39SF020";
27+
break;
28+
case 32:
29+
chipname = "SST39SF040";
30+
break;
31+
default:
32+
chipname = "Unknown";
33+
break;
34+
}
35+
36+
layout->addWidget(new QLabel(tr("Overview banks on %1 EEPROM").arg(chipname)));
37+
38+
QWidget *container = new QWidget(this);
39+
layout->addWidget(container);
40+
41+
QHBoxLayout* hlayout = new QHBoxLayout();
42+
container->setLayout(hlayout);
43+
44+
for(unsigned int i=0; i<nrbanks / 8; i++) {
45+
QGroupBox* groupbox = new QGroupBox(tr("ROM slots %1 - %2").arg(i*8).arg((i+1)*8-1));
46+
hlayout->addWidget(groupbox);
47+
QGridLayout* grid = new QGridLayout();
48+
groupbox->setLayout(grid);
49+
50+
for(unsigned int j=0; j<8; j++) {
51+
QLabel *bank = new QLabel(tr("Bank %1").arg(i*8+j), this);
52+
grid->addWidget(bank, j, 0);
53+
grid->addWidget(this->create_data_label(i*8+j), j, 1);
54+
QPushButton *button_copy = new QPushButton();
55+
button_copy->setIcon(QIcon(":/assets/icon/clipboard.png"));
56+
button_copy->setProperty("slot_id", QVariant(i*8+j));
57+
button_copy->setToolTip("Copy MD5 checksum to clipboard");
58+
grid->addWidget(button_copy, j, 2);
59+
connect(button_copy, SIGNAL(released()), this, SLOT(slot_copy_checksum()));
60+
}
61+
}
62+
63+
// button to close Window and exit screen
64+
QPushButton *button_ok = new QPushButton("OK", this);
65+
layout->addWidget(button_ok);
66+
connect(button_ok, SIGNAL(released()), this, SLOT(accept()));
67+
}
68+
69+
QLabel* BankViewer::create_data_label(unsigned int bank_id) {
70+
QByteArray subdata = this->data.mid(bank_id * BANKSIZE, BANKSIZE);
71+
QByteArray hash = QCryptographicHash::hash(subdata, QCryptographicHash::Md5);
72+
QString checksum = QString(hash.toHex());
73+
QString title = "Unknown";
74+
QString stylesheet;
75+
76+
auto itr = this->checksum_table.find(checksum);
77+
if(itr != this->checksum_table.end()) {
78+
title = itr.value();
79+
}
80+
81+
QString text;
82+
if(subdata.count((unsigned char)0xFF) == BANKSIZE) {
83+
stylesheet = "color: #098056;";
84+
text = tr("Free<br>(empty 16kb x 0xFF)");
85+
} else if(subdata.count((unsigned char)0x00) == BANKSIZE) {
86+
stylesheet = "color: #098056;";
87+
text = tr("Free<br>(empty 16kb x 0x00)");
88+
} else {
89+
stylesheet = "color: #b0216d;";
90+
text = tr("<b>%1</b><br><span style='color: black;'>%2<span>").arg(title).arg(checksum);
91+
}
92+
93+
QLabel *res = new QLabel(text);
94+
//res->setTextFormat(Qt::TextFormat::RichText);
95+
res->setStyleSheet(stylesheet);
96+
return res;
97+
}
98+
99+
void BankViewer::slot_copy_checksum() {
100+
QPushButton* button = qobject_cast<QPushButton*>(sender());
101+
unsigned int slot_id = button->property("slot_id").toUInt();
102+
QByteArray subdata = this->data.mid(slot_id * BANKSIZE, BANKSIZE);
103+
QByteArray hash = QCryptographicHash::hash(subdata, QCryptographicHash::Md5);
104+
QString checksum = QString(hash.toHex());
105+
QGuiApplication::clipboard()->setText(checksum);
106+
}

gui/src/bankviewer.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#ifndef BANKVIEWER_H
2+
#define BANKVIEWER_H
3+
4+
#include <QDialog>
5+
#include <QVBoxLayout>
6+
#include <QLabel>
7+
#include <QGroupBox>
8+
#include <QGridLayout>
9+
#include <QPushButton>
10+
#include <QDebug>
11+
#include <QByteArray>
12+
#include <QCryptographicHash>
13+
#include <QPushButton>
14+
#include <QClipboard>
15+
#include <QGuiApplication>
16+
#include <QHash>
17+
18+
#include "romsizes.h" // contains sizes
19+
20+
class BankViewer : public QDialog
21+
{
22+
Q_OBJECT
23+
24+
private:
25+
QByteArray data;
26+
27+
const QHash<QString,QString> checksum_table = {
28+
{"2191811aa64f8e7f273ce0f462374728", "Basic NL 1.1"},
29+
{"526132548429f7c1bc275b07f5eb609d", "Assembler 5.6"},
30+
{"1bf96263f5456e04f9c47d4b2e98e9b2", "Assembler 5.9"},
31+
{"9aa06a27142c9a6af5b93c6a2c98016c", "Familiegeheugen 2"},
32+
{"449951c31f6439f6215e593ce22fb73a", "Familiegeheugen 3"},
33+
{"26b0c8cfeba85c52723d4cca55198f5a", "Familiegeheugen 4"},
34+
{"29cbab5494e9ca3389d7e596e678f228", "Flexbase"},
35+
{"758757a6a1bdc459b89c6023b4be6f30", "Forth 3.0"},
36+
{"99420a88ab7cf03642c51b61b65e87b9", "Maintenance 1"},
37+
{"ac38f883bebf919c76596c12493dabfa", "Maintenance 2.2"},
38+
{"e04ec6879e9c946a1dd8b997c6d78d31", "Tekst 1"},
39+
{"f8840ebb9d0fe7872c501ff378dba059", "Text2000 2"},
40+
{"7145d89a3f9047e90484187a9d247a0b", "Text2000 3"},
41+
{"ac61d66e577b5874d6c4281069ba25f6", "WordProcessor 1"},
42+
{"c13a29d0409b975abd91547b23301267", "WordProcessor 2"},
43+
{"ea226775d5d5832c8e9e704fbda56eb2", "Zemon 1.4"},
44+
{"2c0cb28a502beff4d2b402161d1a37d5", "JWS Basic"},
45+
46+
{"87efa58eef7aac30d4fdbfecf3f3442c", "Bootstrap BASICNL for DATA cartridge v0.5.1"},
47+
{"6cf63d15c3991190b2ec7fac4c6e7df5", "Bootstrap BASICNL for SD-CARD cartridge v0.3.0"},
48+
{"784c7ce4f6479be115dad9d9357a5108", "Cassette to EEPROM Utility v0.5.1"},
49+
{"55dbbb16230d9bbd078409447719ba79", "Flasher for DATA cartridge v0.5.1"},
50+
{"3949a2126191e4782f005287681fbb7b", "Flasher for SD-CARD cartridge v0.3.0"},
51+
{"5ad780d5e50bcf810540994c73a65dc0", "RAM (expansion board) Test v0.4.0"},
52+
};
53+
54+
public:
55+
explicit BankViewer(unsigned int nrbanks,
56+
const QByteArray& _data,
57+
QWidget *parent = nullptr);
58+
59+
private:
60+
void build_widget(unsigned int nrbanks);
61+
62+
QLabel* create_data_label(unsigned int bank_id);
63+
64+
private slots:
65+
void slot_copy_checksum();
66+
67+
signals:
68+
};
69+
70+
#endif // BANKVIEWER_H

gui/src/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#define _CONFIG_H
2323

2424
#define PROGRAM_NAME "PICO SST39sf0x0 Programmer"
25-
#define PROGRAM_VERSION "1.4.0"
25+
#define PROGRAM_VERSION "1.5.0"
2626
#define UNUSED(x) (void)(x)
2727

2828
#endif // _CONFIG_H

gui/src/dialogslotselection.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
DialogSlotSelection::DialogSlotSelection(unsigned int _nr_banks) :
2424
nr_banks(_nr_banks)
2525
{
26+
// set icon
27+
this->setWindowIcon(QIcon(":/assets/icon/eeprom_icon.ico"));
28+
2629
// build layout
2730
QVBoxLayout* layout = new QVBoxLayout();
2831
this->setLayout(layout);

gui/src/mainwindow.cpp

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -298,27 +298,31 @@ void MainWindow::build_operations_menu(QVBoxLayout* target_layout) {
298298
this->button_read_cartridge = new QPushButton("Read P2000T Cartridge");
299299
this->button_flash_rom = new QPushButton("Write ROM");
300300
this->button_flash_bank = new QPushButton("Write ROM to bank");
301+
this->button_scan_slots = new QPushButton("Scan slots");
301302

302303
layout->addWidget(this->button_identify_chip);
303304
layout->addWidget(this->button_read_rom);
304305
layout->addWidget(this->button_read_cartridge);
305306
layout->addWidget(this->button_flash_rom);
306307
layout->addWidget(this->button_flash_bank);
307308
layout->addWidget(this->button_erase_chip);
309+
layout->addWidget(this->button_scan_slots);
308310

309311
this->button_identify_chip->setEnabled(false);
310312
this->button_erase_chip->setEnabled(false);
311313
this->button_read_cartridge->setEnabled(false);
312314
this->button_read_rom->setEnabled(false);
313315
this->button_flash_rom->setEnabled(false);
314316
this->button_flash_bank->setEnabled(false);
317+
this->button_scan_slots->setEnabled(false);
315318

316319
connect(this->button_read_rom, SIGNAL(released()), this, SLOT(read_rom()));
317320
connect(this->button_read_cartridge, SIGNAL(released()), this, SLOT(read_cartridge()));
318321
connect(this->button_flash_rom, SIGNAL(released()), this, SLOT(flash_rom()));
319322
connect(this->button_identify_chip, SIGNAL(released()), this, SLOT(read_chip_id()));
320323
connect(this->button_flash_bank, SIGNAL(released()), this, SLOT(flash_bank()));
321324
connect(this->button_erase_chip, SIGNAL(released()), this, SLOT(erase_chip()));
325+
connect(this->button_scan_slots, SIGNAL(released()), this, SLOT(scan_chip()));
322326

323327
target_layout->addWidget(container);
324328
this->progress_bar_load = new QProgressBar();
@@ -682,6 +686,36 @@ void MainWindow::slot_update_settings() {
682686
this->hex_widget->viewport()->repaint();
683687
}
684688

689+
/**
690+
* @brief Convenience function on completing a chip scan
691+
*/
692+
void MainWindow::parse_chip_read_results() {
693+
this->progress_bar_load->setValue(this->progress_bar_load->maximum());
694+
695+
QByteArray data;
696+
if(this->readerthread) {
697+
data = this->readerthread->get_data();
698+
this->readerthread.reset(); // delete object
699+
} else if(this->cartridgereaderthread) {
700+
data = this->cartridgereaderthread->get_data();
701+
this->readerthread.reset(); // delete object
702+
} else {
703+
qDebug() << "This function should not have been called.";
704+
}
705+
706+
qDebug() << "Read " << data.size() << " bytes from chip.";
707+
this->hex_widget->set_data(data);
708+
709+
QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5);
710+
this->label_data_descriptor->setText(QString("<b>%1</b> | Size: %2 kb | MD5: %3")
711+
.arg("ROM data")
712+
.arg(data.size() / 1024)
713+
.arg(QString(hash.toHex()))
714+
);
715+
716+
statusBar()->showMessage(QString("Done reading chip in %1 seconds.").arg(this->timer1.elapsed() / 1000.f));
717+
}
718+
685719
/**
686720
* @brief Close the application
687721
*/
@@ -804,6 +838,7 @@ void MainWindow::read_chip_id() {
804838
this->button_flash_rom->setEnabled(true);
805839
this->button_flash_bank->setEnabled(true);
806840
this->button_erase_chip->setEnabled(true);
841+
this->button_scan_slots->setEnabled(true);
807842
} catch (const std::exception& e) {
808843
QMessageBox msg_box;
809844
msg_box.setIcon(QMessageBox::Warning);
@@ -892,30 +927,18 @@ void MainWindow::read_block_done(unsigned int block_id, unsigned int nr_blocks)
892927
* @brief Signal that a read operation is finished
893928
*/
894929
void MainWindow::read_result_ready() {
895-
this->progress_bar_load->setValue(this->progress_bar_load->maximum());
896-
897-
QByteArray data;
898-
if(this->readerthread) {
899-
data = this->readerthread->get_data();
900-
this->readerthread.reset(); // delete object
901-
} else if(this->cartridgereaderthread) {
902-
data = this->cartridgereaderthread->get_data();
903-
this->readerthread.reset(); // delete object
904-
} else {
905-
qDebug() << "This function should not have been called.";
906-
}
907-
908-
qDebug() << "Read " << data.size() << " bytes from chip.";
909-
this->hex_widget->set_data(data);
930+
this->parse_chip_read_results();
931+
}
910932

911-
QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5);
912-
this->label_data_descriptor->setText(QString("<b>%1</b> | Size: %2 kb | MD5: %3")
913-
.arg("ROM data")
914-
.arg(data.size() / 1024)
915-
.arg(QString(hash.toHex()).toUpper())
916-
);
933+
/*
934+
* @brief Signal that a scan chip operation is finished
935+
*/
936+
void MainWindow::scan_chip_result_ready() {
937+
this->parse_chip_read_results();
917938

918-
statusBar()->showMessage(QString("Done reading chip in %1 seconds.").arg(this->timer1.elapsed() / 1000.f));
939+
// at this point, the chip has been scanned and we can process the results
940+
BankViewer bankviewer(this->num_blocks / BLOCKSPERBANK, this->hex_widget->get_data(), this);
941+
bankviewer.exec();
919942
}
920943

921944
/****************************************************************************
@@ -1035,6 +1058,30 @@ void MainWindow::erase_chip() {
10351058
QMessageBox::information(this, "Chip erased.", "Done erasing the chip. All bytes are set of 0xFF.");
10361059
}
10371060

1061+
/**
1062+
* @brief MainWindow::Scan the ROMs on the chip
1063+
*/
1064+
void MainWindow::scan_chip() {
1065+
// ask where to store file
1066+
statusBar()->showMessage("Reading from chip, please wait...");
1067+
this->label_data_descriptor->clear();
1068+
1069+
// dispatch thread
1070+
this->timer1.start();
1071+
1072+
// disable all buttons so that the user cannot interrupt this task
1073+
//this->disable_all_buttons();
1074+
1075+
// dispatch thread
1076+
//this->operation = "Reading"; // message for statusbar
1077+
this->readerthread = std::make_unique<ReadThread>(this->serial_interface);
1078+
this->readerthread->set_serial_port(this->combobox_serial_ports->currentText().toStdString());
1079+
connect(this->readerthread.get(), SIGNAL(read_result_ready()), this, SLOT(scan_chip_result_ready()));
1080+
connect(this->readerthread.get(), SIGNAL(read_block_start(uint,uint)), this, SLOT(read_block_start(uint,uint)));
1081+
connect(this->readerthread.get(), SIGNAL(read_block_done(uint,uint)), this, SLOT(read_block_done(uint,uint)));
1082+
this->readerthread->start();
1083+
}
1084+
10381085
/**
10391086
* @brief Slot to indicate that a sector is about to be written
10401087
*/

0 commit comments

Comments
 (0)