Refactored verification code so Programmer is in charge of it rather
than MainWindow. Also, I think I have verify while writing working but I can't test it yet because I haven't implemented in in the firmware. Bumped version number up as well.
This commit is contained in:
parent
23b28c2cc7
commit
b57f0a83e1
421
mainwindow.cpp
421
mainwindow.cpp
|
@ -30,6 +30,7 @@ static Programmer *p;
|
|||
|
||||
#define selectedCapacityKey "selectedCapacity"
|
||||
#define verifyAfterWriteKey "verifyAfterWrite"
|
||||
#define verifyWhileWritingKey "verifyWhileWriting"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
|
@ -64,8 +65,35 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
ui->simmCapacityBox->setCurrentIndex(selectedIndex);
|
||||
}
|
||||
|
||||
// Decide whether or not to verify after write
|
||||
ui->verifyAfterWriteBox->setChecked(settings.value(verifyAfterWriteKey, true).toBool());
|
||||
// Fill in the list of verification options
|
||||
ui->verifyBox->addItem("Don't verify", QVariant(NoVerification));
|
||||
ui->verifyBox->addItem("Verify while writing", QVariant(VerifyWhileWriting));
|
||||
ui->verifyBox->addItem("Verify after writing", QVariant(VerifyAfterWrite));
|
||||
|
||||
// Decide whether to verify while writing, after writing, or never.
|
||||
// This would probably be better suited as an enum rather than multiple bools,
|
||||
// but I started out with it as a single bool, so for backward compatibility,
|
||||
// I simply added another bool for the "verify while writing" capability.
|
||||
bool verifyAfterWrite = settings.value(verifyAfterWriteKey, false).toBool();
|
||||
bool verifyWhileWriting = settings.value(verifyWhileWritingKey, true).toBool();
|
||||
selectedIndex = 0;
|
||||
if (verifyWhileWriting)
|
||||
{
|
||||
selectedIndex = ui->verifyBox->findData(VerifyWhileWriting);
|
||||
}
|
||||
else if (verifyAfterWrite)
|
||||
{
|
||||
selectedIndex = ui->verifyBox->findData(VerifyAfterWrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedIndex = ui->verifyBox->findData(NoVerification);
|
||||
}
|
||||
|
||||
if (selectedIndex != -1)
|
||||
{
|
||||
ui->verifyBox->setCurrentIndex(selectedIndex);
|
||||
}
|
||||
|
||||
ui->chosenWriteFile->setText("");
|
||||
ui->chosenReadFile->setText("");
|
||||
|
@ -79,12 +107,12 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
|
||||
readFile = NULL;
|
||||
writeFile = NULL;
|
||||
verifyArray = NULL;
|
||||
verifyBuffer = NULL;
|
||||
|
||||
connect(p, SIGNAL(writeStatusChanged(WriteStatus)), SLOT(programmerWriteStatusChanged(WriteStatus)));
|
||||
connect(p, SIGNAL(writeTotalLengthChanged(uint32_t)), SLOT(programmerWriteTotalLengthChanged(uint32_t)));
|
||||
connect(p, SIGNAL(writeCompletionLengthChanged(uint32_t)), SLOT(programmerWriteCompletionLengthChanged(uint32_t)));
|
||||
connect(p, SIGNAL(writeVerifyTotalLengthChanged(uint32_t)), SLOT(programmerVerifyTotalLengthChanged(uint32_t)));
|
||||
connect(p, SIGNAL(writeVerifyCompletionLengthChanged(uint32_t)), SLOT(programmerVerifyCompletionLengthChanged(uint32_t)));
|
||||
connect(p, SIGNAL(electricalTestStatusChanged(ElectricalTestStatus)), SLOT(programmerElectricalTestStatusChanged(ElectricalTestStatus)));
|
||||
connect(p, SIGNAL(electricalTestFailLocation(uint8_t,uint8_t)), SLOT(programmerElectricalTestLocation(uint8_t,uint8_t)));
|
||||
connect(p, SIGNAL(readStatusChanged(ReadStatus)), SLOT(programmerReadStatusChanged(ReadStatus)));
|
||||
|
@ -132,8 +160,6 @@ void MainWindow::on_selectReadFileButton_clicked()
|
|||
|
||||
void MainWindow::on_readFromSIMMButton_clicked()
|
||||
{
|
||||
// We are not doing a verify after a write..
|
||||
readVerifying = false;
|
||||
if (readFile)
|
||||
{
|
||||
readFile->close();
|
||||
|
@ -223,7 +249,7 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
|
|||
case WriteErasing:
|
||||
ui->statusLabel->setText("Erasing SIMM (this may take a few seconds)...");
|
||||
break;
|
||||
case WriteComplete:
|
||||
case WriteCompleteNoVerify:
|
||||
if (writeFile)
|
||||
{
|
||||
writeFile->close();
|
||||
|
@ -231,53 +257,70 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
|
|||
writeFile = NULL;
|
||||
}
|
||||
|
||||
if (ui->verifyAfterWriteBox->isChecked())
|
||||
QMessageBox::information(this, "Write complete", "The write operation finished.");
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
break;
|
||||
case WriteCompleteVerifyOK:
|
||||
if (writeFile)
|
||||
{
|
||||
// Set up the read buffers
|
||||
readVerifying = true;
|
||||
if (verifyArray) delete verifyArray;
|
||||
verifyArray = new QByteArray((int)p->SIMMCapacity(), 0);
|
||||
if (verifyBuffer) delete verifyBuffer;
|
||||
verifyBuffer = new QBuffer(verifyArray);
|
||||
if (!verifyBuffer->open(QBuffer::ReadWrite))
|
||||
{
|
||||
delete verifyBuffer;
|
||||
delete verifyArray;
|
||||
verifyBuffer = NULL;
|
||||
verifyArray = NULL;
|
||||
programmerReadStatusChanged(ReadError);
|
||||
return;
|
||||
}
|
||||
|
||||
// Start reading from SIMM to temporary RAM buffer
|
||||
resetAndShowStatusPage();
|
||||
|
||||
// Only read back the size of the file if we can. This will save
|
||||
// some time and prevent us from needing to read the ENTIRE SIMM
|
||||
// if the file is only a quarter of the size of the SIMM.
|
||||
uint32_t readLen = 0;
|
||||
QFile temp(ui->chosenWriteFile->text());
|
||||
if (temp.exists())
|
||||
{
|
||||
qint64 tmpLen = temp.size();
|
||||
if (tmpLen > 0)
|
||||
{
|
||||
readLen = static_cast<uint32_t>(tmpLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
readLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
p->readSIMM(verifyBuffer, readLen);
|
||||
qDebug() << "Reading from SIMM for verification...";
|
||||
writeFile->close();
|
||||
delete writeFile;
|
||||
writeFile = NULL;
|
||||
}
|
||||
else
|
||||
|
||||
QMessageBox::information(this, "Write complete", "The write operation finished, and the contents were verified successfully.");
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
break;
|
||||
|
||||
case WriteVerifying:
|
||||
resetAndShowStatusPage();
|
||||
break;
|
||||
case WriteVerifyStarting:
|
||||
ui->statusLabel->setText("Verifying SIMM contents...");
|
||||
break;
|
||||
case WriteVerifyError:
|
||||
if (writeFile)
|
||||
{
|
||||
QMessageBox::information(this, "Write complete", "The write operation finished.");
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
writeFile->close();
|
||||
delete writeFile;
|
||||
writeFile = NULL;
|
||||
}
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Verify error", "An error occurred reading the SIMM contents for verification.");
|
||||
break;
|
||||
case WriteVerifyCancelled:
|
||||
if (writeFile)
|
||||
{
|
||||
writeFile->close();
|
||||
delete writeFile;
|
||||
writeFile = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Verify cancelled", "The verify operation was cancelled.");
|
||||
break;
|
||||
case WriteVerifyTimedOut:
|
||||
if (writeFile)
|
||||
{
|
||||
writeFile->close();
|
||||
delete writeFile;
|
||||
writeFile = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Verify timed out", "The verify operation timed out.");
|
||||
break;
|
||||
case WriteVerificationFailure:
|
||||
if (writeFile)
|
||||
{
|
||||
writeFile->close();
|
||||
delete writeFile;
|
||||
writeFile = NULL;
|
||||
}
|
||||
|
||||
// The verify failure code is somewhat complicated so it's best to put
|
||||
// it elsewhere.
|
||||
handleVerifyFailureReply();
|
||||
break;
|
||||
case WriteError:
|
||||
if (writeFile)
|
||||
|
@ -290,7 +333,7 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
|
|||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Write error", "An error occurred writing to the SIMM.");
|
||||
break;
|
||||
case WriteNeedsFirmwareUpdate:
|
||||
case WriteNeedsFirmwareUpdateBiggerSIMM:
|
||||
if (writeFile)
|
||||
{
|
||||
writeFile->close();
|
||||
|
@ -301,6 +344,17 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
|
|||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Firmware update needed", "The programmer board needs a firmware update to support a larger SIMM. Please update the firmware and try again.");
|
||||
break;
|
||||
case WriteNeedsFirmwareUpdateVerifyWhileWrite:
|
||||
if (writeFile)
|
||||
{
|
||||
writeFile->close();
|
||||
delete writeFile;
|
||||
writeFile = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Firmware update needed", "The programmer board needs a firmware update to support the \"verify while writing\" capability. Please update the firmware and try again.");
|
||||
break;
|
||||
case WriteCancelled:
|
||||
if (writeFile)
|
||||
{
|
||||
|
@ -361,7 +415,15 @@ void MainWindow::programmerWriteCompletionLengthChanged(uint32_t len)
|
|||
ui->progressBar->setValue((int)len);
|
||||
}
|
||||
|
||||
void MainWindow::programmerVerifyTotalLengthChanged(uint32_t totalLen)
|
||||
{
|
||||
ui->progressBar->setMaximum((int)totalLen);
|
||||
}
|
||||
|
||||
void MainWindow::programmerVerifyCompletionLengthChanged(uint32_t len)
|
||||
{
|
||||
ui->progressBar->setValue((int)len);
|
||||
}
|
||||
|
||||
void MainWindow::on_electricalTestButton_clicked()
|
||||
{
|
||||
|
@ -415,200 +477,51 @@ void MainWindow::programmerReadStatusChanged(ReadStatus newStatus)
|
|||
switch (newStatus)
|
||||
{
|
||||
case ReadStarting:
|
||||
if (readVerifying)
|
||||
{
|
||||
ui->statusLabel->setText("Verifying SIMM contents...");
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->statusLabel->setText("Reading SIMM contents...");
|
||||
}
|
||||
ui->statusLabel->setText("Reading SIMM contents...");
|
||||
break;
|
||||
case ReadComplete:
|
||||
if (readVerifying)
|
||||
if (readFile)
|
||||
{
|
||||
// Re-open the write file temporarily to compare it against the buffer.
|
||||
QFile temp(ui->chosenWriteFile->text());
|
||||
if (!temp.open(QFile::ReadOnly))
|
||||
{
|
||||
QMessageBox::warning(this, "Verify failed", "Unable to open file for verification.");
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray fileBytes = temp.readAll();
|
||||
|
||||
if (fileBytes.count() <= verifyArray->count())
|
||||
{
|
||||
const char *fileBytesPtr = fileBytes.constData();
|
||||
const char *readBytesPtr = verifyArray->constData();
|
||||
|
||||
if (memcmp(fileBytesPtr, readBytesPtr, fileBytes.count()) != 0)
|
||||
{
|
||||
// Now let's do some trickery and figure out which chip is acting up (or chips)
|
||||
uint8_t badICMask = 0;
|
||||
|
||||
// Keep a list of which chips are reading bad data back
|
||||
for (int x = 0; (x < fileBytes.count()) && (badICMask != 0xF); x++)
|
||||
{
|
||||
if (fileBytesPtr[x] != readBytesPtr[x])
|
||||
{
|
||||
// OK, we found a mismatched byte. Now look at
|
||||
// which byte (0-3) it is in each 4-byte group.
|
||||
// If it's byte 0, it's the MOST significant byte
|
||||
// because the 68k is big endian. IC4 contains the
|
||||
// MSB, so IC4 is the first chip, IC3 second, and
|
||||
// so on. That's why I subtract it from 3 --
|
||||
// 0 through 3 get mapped to 3 through 0.
|
||||
badICMask |= (1 << (3 - (x % 4)));
|
||||
}
|
||||
}
|
||||
|
||||
// Make a comma-separated list of IC names from this list
|
||||
QString icList;
|
||||
bool first = true;
|
||||
for (int x = 0; x < 4; x++)
|
||||
{
|
||||
if (badICMask & (1 << x))
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
// not IC0 through IC3; IC1 through IC4.
|
||||
// that's why I add one.
|
||||
icList.append(QString("IC%1").arg(x+1));
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
icList.append(QString(", IC%1").arg(x+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QMessageBox::warning(this, "Verify error", "The data read back from the SIMM did not match the data written to it. Bad data on chips: " + icList);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, "Write complete", "The write operation finished, and the contents were verified successfully.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, "Verify error", "The data read back from the SIMM did not match the data written to it--wrong amount of data read back.");
|
||||
}
|
||||
}
|
||||
|
||||
// Close stuff not needed anymore
|
||||
if (verifyBuffer)
|
||||
{
|
||||
verifyBuffer->close();
|
||||
delete verifyBuffer;
|
||||
verifyBuffer = NULL;
|
||||
}
|
||||
|
||||
if (verifyArray)
|
||||
{
|
||||
delete verifyArray;
|
||||
verifyArray = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
readFile->close();
|
||||
delete readFile;
|
||||
readFile = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readFile)
|
||||
{
|
||||
readFile->close();
|
||||
delete readFile;
|
||||
readFile = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::information(this, "Read complete", "The read operation finished.");
|
||||
}
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::information(this, "Read complete", "The read operation finished.");
|
||||
break;
|
||||
case ReadError:
|
||||
if (readVerifying)
|
||||
if (readFile)
|
||||
{
|
||||
if (verifyBuffer)
|
||||
{
|
||||
verifyBuffer->close();
|
||||
delete verifyBuffer;
|
||||
}
|
||||
verifyBuffer = NULL;
|
||||
if (verifyArray) delete verifyArray;
|
||||
verifyArray = NULL;
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Verify error", "An error occurred reading the SIMM contents for verification.");
|
||||
readFile->close();
|
||||
delete readFile;
|
||||
readFile = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readFile)
|
||||
{
|
||||
readFile->close();
|
||||
delete readFile;
|
||||
readFile = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Read error", "An error occurred reading from the SIMM.");
|
||||
}
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Read error", "An error occurred reading from the SIMM.");
|
||||
break;
|
||||
case ReadCancelled:
|
||||
if (readVerifying)
|
||||
if (readFile)
|
||||
{
|
||||
if (verifyBuffer)
|
||||
{
|
||||
verifyBuffer->close();
|
||||
delete verifyBuffer;
|
||||
}
|
||||
verifyBuffer = NULL;
|
||||
if (verifyArray) delete verifyArray;
|
||||
verifyArray = NULL;
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Verify cancelled", "The verify operation was cancelled.");
|
||||
readFile->close();
|
||||
delete readFile;
|
||||
readFile = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readFile)
|
||||
{
|
||||
readFile->close();
|
||||
delete readFile;
|
||||
readFile = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Read cancelled", "The read operation was cancelled.");
|
||||
}
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Read cancelled", "The read operation was cancelled.");
|
||||
break;
|
||||
case ReadTimedOut:
|
||||
if (readVerifying)
|
||||
if (readFile)
|
||||
{
|
||||
if (verifyBuffer)
|
||||
{
|
||||
verifyBuffer->close();
|
||||
delete verifyBuffer;
|
||||
}
|
||||
verifyBuffer = NULL;
|
||||
if (verifyArray) delete verifyArray;
|
||||
verifyArray = NULL;
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Verify timed out", "The verify operation timed out.");
|
||||
readFile->close();
|
||||
delete readFile;
|
||||
readFile = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readFile)
|
||||
{
|
||||
readFile->close();
|
||||
delete readFile;
|
||||
readFile = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Read timed out", "The read operation timed out.");
|
||||
}
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Read timed out", "The read operation timed out.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -758,7 +671,7 @@ void MainWindow::resetAndShowStatusPage()
|
|||
|
||||
void MainWindow::on_simmCapacityBox_currentIndexChanged(int index)
|
||||
{
|
||||
uint32_t newCapacity = (uint32_t)ui->simmCapacityBox->itemData(index).toUInt();
|
||||
uint32_t newCapacity = static_cast<uint32_t>(ui->simmCapacityBox->itemData(index).toUInt());
|
||||
p->setSIMMCapacity(newCapacity);
|
||||
QSettings settings;
|
||||
if (!initializing)
|
||||
|
@ -769,14 +682,66 @@ void MainWindow::on_simmCapacityBox_currentIndexChanged(int index)
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_verifyAfterWriteBox_toggled(bool checked)
|
||||
void MainWindow::on_verifyBox_currentIndexChanged(int index)
|
||||
{
|
||||
if (index < 0) return;
|
||||
|
||||
VerificationOption vo = static_cast<VerificationOption>(ui->verifyBox->itemData(index).toUInt());
|
||||
|
||||
// Save this as the new default.
|
||||
QSettings settings;
|
||||
settings.setValue(verifyAfterWriteKey, checked);
|
||||
|
||||
p->setVerifyMode(vo);
|
||||
|
||||
if (!initializing)
|
||||
{
|
||||
if (vo == NoVerification)
|
||||
{
|
||||
settings.setValue(verifyAfterWriteKey, false);
|
||||
settings.setValue(verifyWhileWritingKey, false);
|
||||
}
|
||||
else if (vo == VerifyAfterWrite)
|
||||
{
|
||||
settings.setValue(verifyAfterWriteKey, true);
|
||||
settings.setValue(verifyWhileWritingKey, false);
|
||||
}
|
||||
else if (vo == VerifyWhileWriting)
|
||||
{
|
||||
settings.setValue(verifyAfterWriteKey, false);
|
||||
settings.setValue(verifyWhileWritingKey, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAbout_SIMM_Programmer_triggered()
|
||||
{
|
||||
AboutBox::instance()->show();
|
||||
}
|
||||
|
||||
void MainWindow::handleVerifyFailureReply()
|
||||
{
|
||||
// Make a comma-separated list of IC names from this list
|
||||
uint8_t badICMask = p->verifyBadChipMask();
|
||||
QString icList;
|
||||
bool first = true;
|
||||
for (int x = 0; x < 4; x++)
|
||||
{
|
||||
if (badICMask & (1 << x))
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
// not IC0 through IC3; IC1 through IC4.
|
||||
// that's why I add one.
|
||||
icList.append(QString("IC%1").arg(x+1));
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
icList.append(QString(", IC%1").arg(x+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Verify error", "The data read back from the SIMM did not match the data written to it. Bad data on chips: " + icList);
|
||||
}
|
||||
|
|
11
mainwindow.h
11
mainwindow.h
|
@ -22,8 +22,6 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
#include <QByteArray>
|
||||
#include "programmer.h"
|
||||
|
||||
namespace Ui {
|
||||
|
@ -52,6 +50,9 @@ private slots:
|
|||
void programmerWriteTotalLengthChanged(uint32_t totalLen);
|
||||
void programmerWriteCompletionLengthChanged(uint32_t len);
|
||||
|
||||
void programmerVerifyTotalLengthChanged(uint32_t totalLen);
|
||||
void programmerVerifyCompletionLengthChanged(uint32_t len);
|
||||
|
||||
void programmerElectricalTestStatusChanged(ElectricalTestStatus newStatus);
|
||||
void programmerElectricalTestLocation(uint8_t loc1, uint8_t loc2);
|
||||
|
||||
|
@ -80,7 +81,7 @@ private slots:
|
|||
|
||||
void on_actionAbout_SIMM_Programmer_triggered();
|
||||
|
||||
void on_verifyAfterWriteBox_toggled(bool checked);
|
||||
void on_verifyBox_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
|
@ -89,12 +90,10 @@ private:
|
|||
bool readFileValid;
|
||||
QFile *writeFile;
|
||||
QFile *readFile;
|
||||
QBuffer *verifyBuffer;
|
||||
QByteArray *verifyArray;
|
||||
QString electricalTestString;
|
||||
bool readVerifying;
|
||||
|
||||
void resetAndShowStatusPage();
|
||||
void handleVerifyFailureReply();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
|
@ -82,14 +82,7 @@
|
|||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="verifyAfterWriteBox">
|
||||
<property name="text">
|
||||
<string>Verify contents after write</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="verifyBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
|
|
397
programmer.cpp
397
programmer.cpp
|
@ -27,6 +27,7 @@ typedef enum ProgrammerCommandState
|
|||
WaitingForNextCommand = 0,
|
||||
|
||||
WriteSIMMWaitingSetSizeReply,
|
||||
WriteSIMMWaitingSetVerifyModeReply,
|
||||
WriteSIMMWaitingEraseReply,
|
||||
WriteSIMMWaitingWriteReply,
|
||||
WriteSIMMWaitingFinishReply,
|
||||
|
@ -82,7 +83,9 @@ typedef enum ProgrammerCommand
|
|||
EnterProgrammer,
|
||||
BootloaderEraseAndWriteProgram,
|
||||
SetSIMMTypePLCC32_2MB,
|
||||
SetSIMMTypeLarger
|
||||
SetSIMMTypeLarger,
|
||||
SetVerifyWhileWriting,
|
||||
SetNoVerifyWhileWriting
|
||||
} ProgrammerCommand;
|
||||
|
||||
typedef enum ProgrammerReply
|
||||
|
@ -118,7 +121,8 @@ typedef enum ProgrammerWriteReply
|
|||
{
|
||||
ProgrammerWriteOK,
|
||||
ProgrammerWriteError,
|
||||
ProgrammerWriteConfirmCancel
|
||||
ProgrammerWriteConfirmCancel,
|
||||
ProgrammerWriteVerificationError = 0x80 /* high bit */
|
||||
} ProgrammerWriteReply;
|
||||
|
||||
typedef enum ProgrammerIdentifyReply
|
||||
|
@ -173,6 +177,11 @@ static QString programmerBoardPortName;
|
|||
Programmer::Programmer(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
_verifyMode = VerifyAfterWrite;
|
||||
_verifyBadChipMask = 0;
|
||||
verifyArray = new QByteArray();
|
||||
verifyBuffer = new QBuffer(verifyArray);
|
||||
verifyBuffer->open(QBuffer::ReadWrite);
|
||||
serialPort = new QextSerialPort(QextSerialPort::EventDriven);
|
||||
connect(serialPort, SIGNAL(readyRead()), SLOT(dataReady()));
|
||||
}
|
||||
|
@ -181,9 +190,19 @@ Programmer::~Programmer()
|
|||
{
|
||||
closePort();
|
||||
delete serialPort;
|
||||
verifyBuffer->close();
|
||||
delete verifyBuffer;
|
||||
delete verifyArray;
|
||||
}
|
||||
|
||||
void Programmer::readSIMM(QIODevice *device, uint32_t len)
|
||||
{
|
||||
// We're not verifying in this case
|
||||
isReadVerifying = false;
|
||||
internalReadSIMM(device, len);
|
||||
}
|
||||
|
||||
void Programmer::internalReadSIMM(QIODevice *device, uint32_t len)
|
||||
{
|
||||
readDevice = device;
|
||||
lenRead = 0;
|
||||
|
@ -268,17 +287,27 @@ void Programmer::handleChar(uint8_t c)
|
|||
case WaitingForNextCommand:
|
||||
// Not expecting anything. Ignore it.
|
||||
break;
|
||||
|
||||
// Expecting reply after we told the programmer the size of SIMM to expect
|
||||
case WriteSIMMWaitingSetSizeReply:
|
||||
switch (c)
|
||||
{
|
||||
case CommandReplyOK:
|
||||
// If we got an OK reply, we're ready to go, so start...
|
||||
// If we got an OK reply, we're good to go. Next, check for the
|
||||
// "verify while writing" capability if needed...
|
||||
|
||||
// Special case: Send out notification we are starting an erase command.
|
||||
// I don't have any hooks into the process between now and the erase reply.
|
||||
emit writeStatusChanged(WriteErasing);
|
||||
sendByte(EraseChips);
|
||||
curState = WriteSIMMWaitingEraseReply;
|
||||
uint8_t verifyCommand;
|
||||
if (verifyMode() == VerifyWhileWriting)
|
||||
{
|
||||
verifyCommand = SetVerifyWhileWriting;
|
||||
}
|
||||
else
|
||||
{
|
||||
verifyCommand = SetNoVerifyWhileWriting;
|
||||
}
|
||||
|
||||
curState = WriteSIMMWaitingSetVerifyModeReply;
|
||||
sendByte(verifyCommand);
|
||||
break;
|
||||
case CommandReplyInvalid:
|
||||
case CommandReplyError:
|
||||
|
@ -293,7 +322,7 @@ void Programmer::handleChar(uint8_t c)
|
|||
qDebug() << "Programmer board needs firmware update.";
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit writeStatusChanged(WriteNeedsFirmwareUpdate);
|
||||
emit writeStatusChanged(WriteNeedsFirmwareUpdateBiggerSIMM);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -301,6 +330,61 @@ void Programmer::handleChar(uint8_t c)
|
|||
// doesn't need updating -- it just didn't know how to handle
|
||||
// the "set size" command. But that's OK -- it only supports
|
||||
// the size we requested, so nothing's wrong.
|
||||
|
||||
// So...check for the "verify while writing" capability if needed.
|
||||
uint8_t verifyCommand;
|
||||
if (verifyMode() == VerifyWhileWriting)
|
||||
{
|
||||
verifyCommand = SetVerifyWhileWriting;
|
||||
}
|
||||
else
|
||||
{
|
||||
verifyCommand = SetNoVerifyWhileWriting;
|
||||
}
|
||||
|
||||
curState = WriteSIMMWaitingSetVerifyModeReply;
|
||||
sendByte(verifyCommand);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Expecting reply from programmer after we told it to verify during write
|
||||
// (or not to verify during write)
|
||||
case WriteSIMMWaitingSetVerifyModeReply:
|
||||
switch (c)
|
||||
{
|
||||
case CommandReplyOK:
|
||||
// If we got an OK reply, we're ready to go, so start...
|
||||
|
||||
// Special case: Send out notification we are starting an erase command.
|
||||
// I don't have any hooks into the process between now and the erase reply.
|
||||
emit writeStatusChanged(WriteErasing);
|
||||
sendByte(EraseChips);
|
||||
curState = WriteSIMMWaitingEraseReply;
|
||||
break;
|
||||
case CommandReplyInvalid:
|
||||
case CommandReplyError:
|
||||
// If we got an error reply, we MAY still be OK unless we were
|
||||
// asking to verify while writing, in which case the firmware
|
||||
// doesn't support verify during write so the user needs to know.
|
||||
if (verifyMode() == VerifyWhileWriting)
|
||||
{
|
||||
// Uh oh -- this is an old firmware that doesn't support verify
|
||||
// while write. Let the caller know that the programmer board
|
||||
// needs a firmware update.
|
||||
qDebug() << "Programmer board needs firmware update.";
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit writeStatusChanged(WriteNeedsFirmwareUpdateVerifyWhileWrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error reply, but we're not trying to verify while writing, so
|
||||
// the firmware doesn't need updating -- it just didn't know how to handle
|
||||
// the "set verify mode" command. But that's OK -- we don't need
|
||||
// that command if we're not verifying while writing.
|
||||
// Special case: Send out notification we are starting an erase command.
|
||||
// I don't have any hooks into the process between now and the erase reply.
|
||||
emit writeStatusChanged(WriteErasing);
|
||||
|
@ -311,6 +395,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
}
|
||||
|
||||
break;
|
||||
|
||||
// Expecting reply from programmer after we told it to erase the chip
|
||||
case WriteSIMMWaitingEraseReply:
|
||||
{
|
||||
switch (c)
|
||||
|
@ -332,33 +418,52 @@ void Programmer::handleChar(uint8_t c)
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Expecting reply from programmer after we sent a chunk of data to write
|
||||
// (or after we first told it we're going to start writing)
|
||||
case WriteSIMMWaitingWriteReply:
|
||||
switch (c)
|
||||
|
||||
// This is a special case in the protocol for efficiency.
|
||||
if (c & ProgrammerWriteVerificationError)
|
||||
{
|
||||
case CommandReplyOK:
|
||||
// We're in write SIMM mode. Now ask to start writing
|
||||
if (writeLenRemaining > 0)
|
||||
{
|
||||
sendByte(ComputerWriteMore);
|
||||
curState = WriteSIMMWaitingWriteMoreReply;
|
||||
qDebug() << "Write more..." << writeLenRemaining << "remaining.";
|
||||
}
|
||||
else
|
||||
{
|
||||
sendByte(ComputerWriteFinish);
|
||||
curState = WriteSIMMWaitingFinishReply;
|
||||
qDebug() << "Finished writing. Sending write finish command...";
|
||||
}
|
||||
break;
|
||||
case CommandReplyError:
|
||||
qDebug() << "Error entering write mode.";
|
||||
_verifyBadChipMask = c & ~ProgrammerWriteVerificationError;
|
||||
qDebug() << "Verification error during write.";
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit writeStatusChanged(WriteError);
|
||||
emit writeStatusChanged(WriteVerificationFailure);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case CommandReplyOK:
|
||||
// We're in write SIMM mode. Now ask to start writing
|
||||
if (writeLenRemaining > 0)
|
||||
{
|
||||
sendByte(ComputerWriteMore);
|
||||
curState = WriteSIMMWaitingWriteMoreReply;
|
||||
qDebug() << "Write more..." << writeLenRemaining << "remaining.";
|
||||
}
|
||||
else
|
||||
{
|
||||
sendByte(ComputerWriteFinish);
|
||||
curState = WriteSIMMWaitingFinishReply;
|
||||
qDebug() << "Finished writing. Sending write finish command...";
|
||||
}
|
||||
break;
|
||||
case CommandReplyError:
|
||||
qDebug() << "Error entering write mode.";
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit writeStatusChanged(WriteError);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Expecting reply from programmer after we requested to write another data chunk
|
||||
case WriteSIMMWaitingWriteMoreReply:
|
||||
{
|
||||
switch (c)
|
||||
|
@ -405,14 +510,41 @@ void Programmer::handleChar(uint8_t c)
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Expecting reply from programmer after we told it we're done writing
|
||||
case WriteSIMMWaitingFinishReply:
|
||||
switch (c)
|
||||
{
|
||||
case ProgrammerWriteOK:
|
||||
curState = WaitingForNextCommand;
|
||||
qDebug() << "Write success at end";
|
||||
closePort();
|
||||
emit writeStatusChanged(WriteComplete);
|
||||
if (verifyMode() == VerifyAfterWrite)
|
||||
{
|
||||
isReadVerifying = true;
|
||||
|
||||
// Ensure the verify buffer is empty
|
||||
verifyArray->clear();
|
||||
verifyBuffer->seek(0);
|
||||
|
||||
// Start reading from the SIMM now!
|
||||
emit writeStatusChanged(WriteVerifying);
|
||||
internalReadSIMM(verifyBuffer, writeDevice->size());
|
||||
}
|
||||
else
|
||||
{
|
||||
curState = WaitingForNextCommand;
|
||||
qDebug() << "Write success at end";
|
||||
closePort();
|
||||
|
||||
// Emit the correct signal based on how we finished
|
||||
if (verifyMode() == NoVerification)
|
||||
{
|
||||
emit writeStatusChanged(WriteCompleteNoVerify);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit writeStatusChanged(WriteCompleteVerifyOK);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case ProgrammerWriteError:
|
||||
default:
|
||||
|
@ -427,6 +559,7 @@ void Programmer::handleChar(uint8_t c)
|
|||
|
||||
// ELECTRICAL TEST STATE HANDLERS
|
||||
|
||||
// Expecting reply from programmer after we told it to run an electrical test
|
||||
case ElectricalTestWaitingStartReply:
|
||||
switch (c)
|
||||
{
|
||||
|
@ -443,6 +576,9 @@ void Programmer::handleChar(uint8_t c)
|
|||
emit electricalTestStatusChanged(ElectricalTestCouldntStart);
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting info from programmer about the electrical test in progress
|
||||
// (Either that it's done or that it found a failure)
|
||||
case ElectricalTestWaitingNextStatus:
|
||||
switch (c)
|
||||
{
|
||||
|
@ -464,22 +600,33 @@ void Programmer::handleChar(uint8_t c)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
// Expecting electrical test fail location #1
|
||||
case ElectricalTestWaitingFirstFail:
|
||||
electricalTestFirstErrorLoc = c;
|
||||
curState = ElectricalTestWaitingSecondFail;
|
||||
break;
|
||||
// Expecting electrical test fail location #2
|
||||
case ElectricalTestWaitingSecondFail:
|
||||
emit electricalTestFailLocation(electricalTestFirstErrorLoc, c);
|
||||
curState = ElectricalTestWaitingNextStatus;
|
||||
break;
|
||||
|
||||
// READ SIMM STATE HANDLERS
|
||||
|
||||
// Expecting reply after we told the programmer to start reading
|
||||
case ReadSIMMWaitingStartReply:
|
||||
switch (c)
|
||||
{
|
||||
case CommandReplyOK:
|
||||
|
||||
emit readStatusChanged(ReadStarting);
|
||||
if (!isReadVerifying)
|
||||
{
|
||||
emit readStatusChanged(ReadStarting);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit writeStatusChanged(WriteVerifyStarting);
|
||||
}
|
||||
curState = ReadSIMMWaitingLengthReply;
|
||||
|
||||
// Send the length requesting to be read
|
||||
|
@ -495,28 +642,59 @@ void Programmer::handleChar(uint8_t c)
|
|||
default:
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit readStatusChanged(ReadError);
|
||||
if (!isReadVerifying)
|
||||
{
|
||||
emit readStatusChanged(ReadError);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure the verify buffer is empty if we were verifying
|
||||
verifyArray->clear();
|
||||
verifyBuffer->seek(0);
|
||||
emit writeStatusChanged(WriteVerifyError);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting reply after we gave the programmer a length to read
|
||||
case ReadSIMMWaitingLengthReply:
|
||||
switch (c)
|
||||
{
|
||||
case ProgrammerReadOK:
|
||||
curState = ReadSIMMWaitingData;
|
||||
emit readTotalLengthChanged(lenRemaining);
|
||||
emit readCompletionLengthChanged(0);
|
||||
if (!isReadVerifying)
|
||||
{
|
||||
emit readTotalLengthChanged(lenRemaining);
|
||||
emit readCompletionLengthChanged(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit writeVerifyTotalLengthChanged(lenRemaining);
|
||||
emit writeVerifyCompletionLengthChanged(0);
|
||||
}
|
||||
readChunkLenRemaining = READ_CHUNK_SIZE;
|
||||
break;
|
||||
case ProgrammerReadError:
|
||||
default:
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit readStatusChanged(ReadError);
|
||||
if (!isReadVerifying)
|
||||
{
|
||||
emit readStatusChanged(ReadError);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure the verify buffer is empty if we were verifying
|
||||
verifyArray->clear();
|
||||
verifyBuffer->seek(0);
|
||||
emit writeStatusChanged(WriteVerifyError);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting a chunk of data back from the programmer
|
||||
case ReadSIMMWaitingData:
|
||||
// Only keep adding to the readback if we need to
|
||||
if (lenRead < trueLenToRead)
|
||||
|
@ -527,24 +705,51 @@ void Programmer::handleChar(uint8_t c)
|
|||
lenRead++;
|
||||
if (--readChunkLenRemaining == 0)
|
||||
{
|
||||
emit readCompletionLengthChanged(lenRead);
|
||||
if (!isReadVerifying)
|
||||
{
|
||||
emit readCompletionLengthChanged(lenRead);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit writeVerifyCompletionLengthChanged(lenRead);
|
||||
}
|
||||
qDebug() << "Received a chunk of data";
|
||||
sendByte(ComputerReadOK);
|
||||
curState = ReadSIMMWaitingStatusReply;
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting status reply from programmer after we confirmed reception of
|
||||
// previous chunk of data
|
||||
case ReadSIMMWaitingStatusReply:
|
||||
switch (c)
|
||||
{
|
||||
case ProgrammerReadFinished:
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit readStatusChanged(ReadComplete);
|
||||
if (!isReadVerifying)
|
||||
{
|
||||
emit readStatusChanged(ReadComplete);
|
||||
}
|
||||
else
|
||||
{
|
||||
doVerifyAfterWriteCompare();
|
||||
}
|
||||
break;
|
||||
case ProgrammerReadConfirmCancel:
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit readStatusChanged(ReadCancelled);
|
||||
if (!isReadVerifying)
|
||||
{
|
||||
emit readStatusChanged(ReadCancelled);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure the verify buffer is empty if we were verifying
|
||||
verifyArray->clear();
|
||||
verifyBuffer->seek(0);
|
||||
emit writeStatusChanged(WriteVerifyCancelled);
|
||||
}
|
||||
break;
|
||||
case ProgrammerReadMoreData:
|
||||
curState = ReadSIMMWaitingData;
|
||||
|
@ -555,6 +760,9 @@ void Programmer::handleChar(uint8_t c)
|
|||
break;
|
||||
|
||||
// BOOTLOADER STATE HANDLERS
|
||||
|
||||
// Expecting reply after we asked for bootloader state (original request is
|
||||
// to end up in programmer mode)
|
||||
case BootloaderStateAwaitingOKReply:
|
||||
if (c == CommandReplyOK)
|
||||
{
|
||||
|
@ -568,17 +776,14 @@ void Programmer::handleChar(uint8_t c)
|
|||
// TODO: Error out somehow
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting bootloader state after request was confirmed (original request
|
||||
// is to end up in programmer mode)
|
||||
case BootloaderStateAwaitingReply:
|
||||
switch (c)
|
||||
{
|
||||
case BootloaderStateInBootloader:
|
||||
// Oops! We're in the bootloader. Better change over to the programmer.
|
||||
// TODO: Send "enter programmer" command.
|
||||
// Close serial port.
|
||||
// Wait for serial port to reappear (or just wait a fixed time?)
|
||||
// Open serial port.
|
||||
// Ensure we're in the programmer?
|
||||
// Then do the command correctly
|
||||
qDebug() << "We're in the bootloader, so sending an \"enter programmer\" request.";
|
||||
emit startStatusChanged(ProgrammerInitializing);
|
||||
sendByte(EnterProgrammer);
|
||||
|
@ -600,6 +805,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
}
|
||||
break;
|
||||
|
||||
// Expecting reply after we asked for bootloader state (original request is
|
||||
// to end up in bootloader mode)
|
||||
case BootloaderStateAwaitingOKReplyToBootloader:
|
||||
if (c == CommandReplyOK)
|
||||
{
|
||||
|
@ -613,17 +820,14 @@ void Programmer::handleChar(uint8_t c)
|
|||
// TODO: Error out somehow
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting bootloader state after request was confirmed (original request
|
||||
// is to end up in bootloader mode)
|
||||
case BootloaderStateAwaitingReplyToBootloader:
|
||||
switch (c)
|
||||
{
|
||||
case BootloaderStateInProgrammer:
|
||||
// Oops! We're in the programmer. Better change over to the bootloader.
|
||||
// TODO: Send "enter bootloader" command.
|
||||
// Close serial port.
|
||||
// Wait for serial port to reappear (or just wait a fixed time?)
|
||||
// Open serial port.
|
||||
// Ensure we're in the bootloader?
|
||||
// Then do the command correctly
|
||||
qDebug() << "We're in the programmer, so sending an \"enter bootloader\" request.";
|
||||
emit startStatusChanged(ProgrammerInitializing);
|
||||
sendByte(EnterBootloader);
|
||||
|
@ -646,6 +850,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
break;
|
||||
|
||||
// IDENTIFICATION STATE HANDLERS
|
||||
|
||||
// // Expecting reply after we told the programmer what size of SIMM to use
|
||||
case IdentificationWaitingSetSizeReply:
|
||||
switch (c)
|
||||
{
|
||||
|
@ -681,6 +887,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting reply after we asked to identify chips
|
||||
case IdentificationAwaitingOKReply:
|
||||
if (c == CommandReplyOK)
|
||||
{
|
||||
|
@ -697,6 +905,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
curState = WaitingForNextCommand;
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting device/manufacturer info about the chips
|
||||
case IdentificationWaitingData:
|
||||
if (identificationCounter & 1) // device ID?
|
||||
{
|
||||
|
@ -713,6 +923,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
curState = IdentificationAwaitingDoneReply;
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting final done confirmation after receiving all device/manufacturer info
|
||||
case IdentificationAwaitingDoneReply:
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
|
@ -727,6 +939,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
break;
|
||||
|
||||
// WRITE BOOTLOADER PROGRAM STATE HANDLERS
|
||||
|
||||
// Expecting reply after we asked to flash the firmware
|
||||
case BootloaderEraseProgramAwaitingStartOKReply:
|
||||
if (c == CommandReplyOK)
|
||||
{
|
||||
|
@ -742,6 +956,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
emit firmwareFlashStatusChanged(FirmwareFlashError);
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting reply after we told bootloader we're done flashing firmware
|
||||
case BootloaderEraseProgramWaitingFinishReply:
|
||||
if (c == BootloaderWriteOK)
|
||||
{
|
||||
|
@ -758,6 +974,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
emit firmwareFlashStatusChanged(FirmwareFlashError);
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting reply after we asked to write more firmware data
|
||||
case BootloaderEraseProgramWaitingWriteMoreReply:
|
||||
if (c == BootloaderWriteOK)
|
||||
{
|
||||
|
@ -797,6 +1015,8 @@ void Programmer::handleChar(uint8_t c)
|
|||
emit firmwareFlashStatusChanged(FirmwareFlashError);
|
||||
}
|
||||
break;
|
||||
|
||||
// Expecting reply after we sent a chunk of firmware data
|
||||
case BootloaderEraseProgramWaitingWriteReply:
|
||||
if (c == CommandReplyOK)
|
||||
{
|
||||
|
@ -1086,7 +1306,78 @@ void Programmer::setSIMMCapacity(uint32_t bytes)
|
|||
_simmCapacity = bytes;
|
||||
}
|
||||
|
||||
uint32_t Programmer::SIMMCapacity()
|
||||
uint32_t Programmer::SIMMCapacity() const
|
||||
{
|
||||
return _simmCapacity;
|
||||
}
|
||||
|
||||
void Programmer::setVerifyMode(VerificationOption mode)
|
||||
{
|
||||
_verifyMode = mode;
|
||||
}
|
||||
|
||||
VerificationOption Programmer::verifyMode() const
|
||||
{
|
||||
return _verifyMode;
|
||||
}
|
||||
|
||||
void Programmer::doVerifyAfterWriteCompare()
|
||||
{
|
||||
// Do the comparison, emit the correct signal
|
||||
|
||||
// Read the entire file we just wrote into a QByteArray
|
||||
writeDevice->seek(0);
|
||||
QByteArray originalFileContents = writeDevice->readAll();
|
||||
|
||||
WriteStatus emitStatus;
|
||||
|
||||
// Now, compare the readback (but only for the length of originalFileContents
|
||||
// (because the readback might be longer since it has to be a multiple of
|
||||
// READ_CHUNK_SIZE)
|
||||
if (originalFileContents.size() <= verifyArray->size())
|
||||
{
|
||||
const char *fileBytesPtr = originalFileContents.constData();
|
||||
const char *readBytesPtr = verifyArray->constData();
|
||||
|
||||
if (memcmp(fileBytesPtr, readBytesPtr, originalFileContents.size()) != 0)
|
||||
{
|
||||
// Now let's do some trickery and figure out which chip is acting up (or chips)
|
||||
_verifyBadChipMask = 0;
|
||||
|
||||
// Keep a list of which chips are reading bad data back
|
||||
for (int x = 0; (x < originalFileContents.size()) && (_verifyBadChipMask != 0xF); x++)
|
||||
{
|
||||
if (fileBytesPtr[x] != readBytesPtr[x])
|
||||
{
|
||||
// OK, we found a mismatched byte. Now look at
|
||||
// which byte (0-3) it is in each 4-byte group.
|
||||
// If it's byte 0, it's the MOST significant byte
|
||||
// because the 68k is big endian. IC4 contains the
|
||||
// MSB, so IC4 is the first chip, IC3 second, and
|
||||
// so on. That's why I subtract it from 3 --
|
||||
// 0 through 3 get mapped to 3 through 0.
|
||||
_verifyBadChipMask |= (1 << (3 - (x % 4)));
|
||||
}
|
||||
}
|
||||
|
||||
emitStatus = WriteVerificationFailure;
|
||||
}
|
||||
else
|
||||
{
|
||||
emitStatus = WriteCompleteVerifyOK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wrong amount of data read back for some reason...shouldn't ever happen,
|
||||
// but I'll call it a verification failure.
|
||||
emitStatus = WriteVerificationFailure;
|
||||
}
|
||||
|
||||
// Reset verification buffer to emptiness
|
||||
verifyArray->clear();
|
||||
verifyBuffer->seek(0);
|
||||
|
||||
// Finally, emit the final status signal
|
||||
emit writeStatusChanged(emitStatus);
|
||||
}
|
||||
|
|
36
programmer.h
36
programmer.h
|
@ -26,6 +26,7 @@
|
|||
#include <qextserialport.h>
|
||||
#include <qextserialenumerator.h>
|
||||
#include <stdint.h>
|
||||
#include <QBuffer>
|
||||
|
||||
typedef enum StartStatus
|
||||
{
|
||||
|
@ -45,14 +46,22 @@ typedef enum ReadStatus
|
|||
typedef enum WriteStatus
|
||||
{
|
||||
WriteErasing,
|
||||
WriteComplete,
|
||||
WriteCompleteNoVerify,
|
||||
WriteError,
|
||||
WriteCancelled,
|
||||
WriteEraseComplete,
|
||||
WriteEraseFailed,
|
||||
WriteTimedOut,
|
||||
WriteFileTooBig,
|
||||
WriteNeedsFirmwareUpdate
|
||||
WriteNeedsFirmwareUpdateBiggerSIMM,
|
||||
WriteNeedsFirmwareUpdateVerifyWhileWrite,
|
||||
WriteVerifying,
|
||||
WriteVerificationFailure,
|
||||
WriteVerifyStarting,
|
||||
WriteVerifyError,
|
||||
WriteVerifyCancelled,
|
||||
WriteVerifyTimedOut,
|
||||
WriteCompleteVerifyOK
|
||||
} WriteStatus;
|
||||
|
||||
typedef enum ElectricalTestStatus
|
||||
|
@ -82,6 +91,14 @@ typedef enum FirmwareFlashStatus
|
|||
FirmwareFlashTimedOut
|
||||
} FirmwareFlashStatus;
|
||||
|
||||
// Various choices for verification
|
||||
typedef enum VerificationOption
|
||||
{
|
||||
NoVerification,
|
||||
VerifyWhileWriting,
|
||||
VerifyAfterWrite
|
||||
} VerificationOption;
|
||||
|
||||
// Electrical test indexes
|
||||
#define GROUND_FAIL_INDEX 0xFF
|
||||
|
||||
|
@ -108,7 +125,10 @@ public:
|
|||
void flashFirmware(QString filename);
|
||||
void startCheckingPorts();
|
||||
void setSIMMCapacity(uint32_t bytes);
|
||||
uint32_t SIMMCapacity();
|
||||
uint32_t SIMMCapacity() const;
|
||||
void setVerifyMode(VerificationOption mode);
|
||||
VerificationOption verifyMode() const;
|
||||
uint8_t verifyBadChipMask() const { return _verifyBadChipMask; }
|
||||
signals:
|
||||
void startStatusChanged(StartStatus status);
|
||||
|
||||
|
@ -119,6 +139,8 @@ signals:
|
|||
void writeStatusChanged(WriteStatus status);
|
||||
void writeTotalLengthChanged(uint32_t total);
|
||||
void writeCompletionLengthChanged(uint32_t len);
|
||||
void writeVerifyTotalLengthChanged(uint32_t total);
|
||||
void writeVerifyCompletionLengthChanged(uint32_t total);
|
||||
|
||||
void electricalTestStatusChanged(ElectricalTestStatus status);
|
||||
void electricalTestFailLocation(uint8_t loc1, uint8_t loc2);
|
||||
|
@ -164,11 +186,19 @@ private:
|
|||
uint32_t firmwareLenRemaining;
|
||||
uint32_t firmwareLenWritten;
|
||||
|
||||
VerificationOption _verifyMode;
|
||||
uint8_t _verifyBadChipMask;
|
||||
bool isReadVerifying;
|
||||
QBuffer *verifyBuffer;
|
||||
QByteArray *verifyArray;
|
||||
|
||||
void openPort();
|
||||
void closePort();
|
||||
|
||||
void internalReadSIMM(QIODevice *device, uint32_t len);
|
||||
void startProgrammerCommand(uint8_t commandByte, uint32_t newState);
|
||||
void startBootloaderCommand(uint8_t commandByte, uint32_t newState);
|
||||
void doVerifyAfterWriteCompare();
|
||||
|
||||
private slots:
|
||||
void dataReady();
|
||||
|
|
Loading…
Reference in New Issue