Got it working so you can flash and read chips on the SIMM individually.

This commit is contained in:
Doug Brown 2013-07-04 18:34:27 -07:00
parent 8f60d21c0c
commit 6110068d04
5 changed files with 1128 additions and 46 deletions

View File

@ -35,7 +35,11 @@ static Programmer *p;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
ui(new Ui::MainWindow),
writeFile(NULL),
readFile(NULL),
writeBuffer(NULL),
readBuffer(NULL)
{
initializing = true;
// Make default QSettings use these settings
@ -46,6 +50,7 @@ MainWindow::MainWindow(QWidget *parent) :
p = new Programmer();
ui->setupUi(this);
hideFlashIndividualControls();
ui->pages->setCurrentWidget(ui->notConnectedPage);
ui->actionUpdate_firmware->setEnabled(false);
@ -122,9 +127,6 @@ MainWindow::MainWindow(QWidget *parent) :
ui->statusLabel->setText("");
ui->cancelButton->setEnabled(false);
readFile = NULL;
writeFile = 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)));
@ -144,6 +146,37 @@ MainWindow::MainWindow(QWidget *parent) :
connect(p, SIGNAL(programmerBoardDisconnectedDuringOperation()), SLOT(programmerBoardDisconnectedDuringOperation()));
p->startCheckingPorts();
// Set up the multi chip flasher UI -- connect signals
connect(ui->chosenFlashIC1File, SIGNAL(textEdited(QString)), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->chosenFlashIC2File, SIGNAL(textEdited(QString)), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->chosenFlashIC3File, SIGNAL(textEdited(QString)), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->chosenFlashIC4File, SIGNAL(textEdited(QString)), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->chosenReadIC1File, SIGNAL(textEdited(QString)), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->chosenReadIC2File, SIGNAL(textEdited(QString)), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->chosenReadIC3File, SIGNAL(textEdited(QString)), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->chosenReadIC4File, SIGNAL(textEdited(QString)), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->flashIC1CheckBox, SIGNAL(clicked()), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->flashIC2CheckBox, SIGNAL(clicked()), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->flashIC3CheckBox, SIGNAL(clicked()), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->flashIC4CheckBox, SIGNAL(clicked()), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->readIC1CheckBox, SIGNAL(clicked()), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->readIC2CheckBox, SIGNAL(clicked()), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->readIC3CheckBox, SIGNAL(clicked()), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->readIC4CheckBox, SIGNAL(clicked()), SLOT(updateFlashIndividualControlsEnabled()));
connect(ui->selectFlashIC1Button, SIGNAL(clicked()), SLOT(selectIndividualWriteFileClicked()));
connect(ui->selectFlashIC2Button, SIGNAL(clicked()), SLOT(selectIndividualWriteFileClicked()));
connect(ui->selectFlashIC3Button, SIGNAL(clicked()), SLOT(selectIndividualWriteFileClicked()));
connect(ui->selectFlashIC4Button, SIGNAL(clicked()), SLOT(selectIndividualWriteFileClicked()));
connect(ui->selectReadIC1Button, SIGNAL(clicked()), SLOT(selectIndividualReadFileClicked()));
connect(ui->selectReadIC2Button, SIGNAL(clicked()), SLOT(selectIndividualReadFileClicked()));
connect(ui->selectReadIC3Button, SIGNAL(clicked()), SLOT(selectIndividualReadFileClicked()));
connect(ui->selectReadIC4Button, SIGNAL(clicked()), SLOT(selectIndividualReadFileClicked()));
initializing = false;
}
@ -177,6 +210,18 @@ void MainWindow::on_selectReadFileButton_clicked()
void MainWindow::on_readFromSIMMButton_clicked()
{
// Ensure we don't think we're in buffer writing/reading mode...we're reading to
// an actual file.
if (writeBuffer)
{
delete writeBuffer;
writeBuffer = NULL;
}
if (readBuffer)
{
delete readBuffer;
readBuffer = NULL;
}
if (readFile)
{
readFile->close();
@ -204,6 +249,18 @@ void MainWindow::on_readFromSIMMButton_clicked()
void MainWindow::on_writeToSIMMButton_clicked()
{
// Ensure we don't think we're in buffer writing/reading mode...we're writing
// an actual file.
if (writeBuffer)
{
delete writeBuffer;
writeBuffer = NULL;
}
if (readBuffer)
{
delete readBuffer;
readBuffer = NULL;
}
if (writeFile)
{
writeFile->close();
@ -273,7 +330,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
switch (newStatus)
{
case WriteErasing:
ui->statusLabel->setText("Erasing SIMM (this may take a few seconds)...");
if (writeBuffer)
{
ui->statusLabel->setText("Erasing chip(s) to be flashed (this may take a few seconds)...");
}
else
{
ui->statusLabel->setText("Erasing SIMM (this may take a few seconds)...");
}
break;
case WriteCompleteNoVerify:
if (writeFile)
@ -284,7 +348,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
}
QMessageBox::information(this, "Write complete", "The write operation finished.");
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteCompleteVerifyOK:
if (writeFile)
@ -295,9 +366,15 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
}
QMessageBox::information(this, "Write complete", "The write operation finished, and the contents were verified successfully.");
ui->pages->setCurrentWidget(ui->controlPage);
break;
returnToControlPage();
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteVerifying:
resetAndShowStatusPage();
break;
@ -311,8 +388,15 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
delete writeFile;
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Verify error", "An error occurred reading the SIMM contents for verification.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteVerifyCancelled:
if (writeFile)
@ -322,8 +406,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Verify cancelled", "The verify operation was cancelled.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteVerifyTimedOut:
if (writeFile)
@ -333,8 +423,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Verify timed out", "The verify operation timed out.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteVerificationFailure:
if (writeFile)
@ -347,6 +443,12 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
// The verify failure code is somewhat complicated so it's best to put
// it elsewhere.
handleVerifyFailureReply();
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteError:
if (writeFile)
@ -356,8 +458,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Write error", "An error occurred writing to the SIMM.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteNeedsFirmwareUpdateBiggerSIMM:
if (writeFile)
@ -367,8 +475,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
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.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteNeedsFirmwareUpdateVerifyWhileWrite:
if (writeFile)
@ -378,8 +492,48 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
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.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteNeedsFirmwareUpdateErasePortion:
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
returnToControlPage();
QMessageBox::warning(this, "Firmware update needed", "The programmer board needs a firmware update to support the \"erase only a portion of the SIMM\" capability. Please update the firmware and try again.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteNeedsFirmwareUpdateIndividualChips:
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
returnToControlPage();
QMessageBox::warning(this, "Firmware update needed", "The programmer board needs a firmware update to support the \"program individual chips\" capability. Please update the firmware and try again.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteCancelled:
if (writeFile)
@ -389,8 +543,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Write cancelled", "The write operation was cancelled.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteEraseComplete:
ui->statusLabel->setText("Writing SIMM...");
@ -403,8 +563,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Write error", "An error occurred erasing the SIMM.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteTimedOut:
if (writeFile)
@ -414,8 +580,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Write timed out", "The write operation timed out.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteFileTooBig:
if (writeFile)
@ -425,8 +597,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "File too big", "The file you chose to write to the SIMM is too big according to the chip size you have selected.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
case WriteEraseBlockWrongSize:
if (writeFile)
@ -436,8 +614,14 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Bad erase size", "The programmer cannot handle the erase size you chose.");
if (writeBuffer)
{
writeBuffer->close();
delete writeBuffer;
writeBuffer = NULL;
}
break;
}
}
@ -523,9 +707,18 @@ void MainWindow::programmerReadStatusChanged(ReadStatus newStatus)
delete readFile;
readFile = NULL;
}
if (readBuffer)
{
finishMultiRead();
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::information(this, "Read complete", "The read operation finished.");
if (readBuffer)
{
delete readBuffer;
readBuffer = NULL;
}
break;
case ReadError:
if (readFile)
@ -535,8 +728,13 @@ void MainWindow::programmerReadStatusChanged(ReadStatus newStatus)
readFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Read error", "An error occurred reading from the SIMM.");
if (readBuffer)
{
delete readBuffer;
readBuffer = NULL;
}
break;
case ReadCancelled:
if (readFile)
@ -546,8 +744,13 @@ void MainWindow::programmerReadStatusChanged(ReadStatus newStatus)
readFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Read cancelled", "The read operation was cancelled.");
if (readBuffer)
{
delete readBuffer;
readBuffer = NULL;
}
break;
case ReadTimedOut:
if (readFile)
@ -557,8 +760,13 @@ void MainWindow::programmerReadStatusChanged(ReadStatus newStatus)
readFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
QMessageBox::warning(this, "Read timed out", "The read operation timed out.");
if (readBuffer)
{
delete readBuffer;
readBuffer = NULL;
}
break;
}
}
@ -668,7 +876,7 @@ void MainWindow::on_identifyButton_clicked()
void MainWindow::programmerBoardConnected()
{
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
ui->actionUpdate_firmware->setEnabled(true);
}
@ -794,6 +1002,467 @@ void MainWindow::handleVerifyFailureReply()
}
}
ui->pages->setCurrentWidget(ui->controlPage);
returnToControlPage();
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);
}
void MainWindow::on_flashIndividualEnterButton_clicked()
{
showFlashIndividualControls();
updateFlashIndividualControlsEnabled();
ui->pages->setCurrentWidget(ui->flashChipsPage);
}
void MainWindow::on_returnNormalButton_clicked()
{
hideFlashIndividualControls(); // to allow the window to be shrunk when not active
ui->pages->setCurrentWidget(ui->controlPage);
}
void MainWindow::hideFlashIndividualControls()
{
ui->chosenFlashIC1File->hide();
ui->chosenFlashIC2File->hide();
ui->chosenFlashIC3File->hide();
ui->chosenFlashIC4File->hide();
ui->chosenReadIC1File->hide();
ui->chosenReadIC2File->hide();
ui->chosenReadIC3File->hide();
ui->chosenReadIC4File->hide();
ui->flashIC1CheckBox->hide();
ui->flashIC2CheckBox->hide();
ui->flashIC3CheckBox->hide();
ui->flashIC4CheckBox->hide();
ui->readIC1CheckBox->hide();
ui->readIC2CheckBox->hide();
ui->readIC3CheckBox->hide();
ui->readIC4CheckBox->hide();
ui->selectFlashIC1Button->hide();
ui->selectFlashIC2Button->hide();
ui->selectFlashIC3Button->hide();
ui->selectFlashIC4Button->hide();
ui->selectReadIC1Button->hide();
ui->selectReadIC2Button->hide();
ui->selectReadIC3Button->hide();
ui->selectReadIC4Button->hide();
ui->multiFlashChipsButton->hide();
ui->multiReadChipsButton->hide();
ui->returnNormalButton->hide();
}
void MainWindow::showFlashIndividualControls()
{
ui->chosenFlashIC1File->show();
ui->chosenFlashIC2File->show();
ui->chosenFlashIC3File->show();
ui->chosenFlashIC4File->show();
ui->chosenReadIC1File->show();
ui->chosenReadIC2File->show();
ui->chosenReadIC3File->show();
ui->chosenReadIC4File->show();
ui->flashIC1CheckBox->show();
ui->flashIC2CheckBox->show();
ui->flashIC3CheckBox->show();
ui->flashIC4CheckBox->show();
ui->readIC1CheckBox->show();
ui->readIC2CheckBox->show();
ui->readIC3CheckBox->show();
ui->readIC4CheckBox->show();
ui->selectFlashIC1Button->show();
ui->selectFlashIC2Button->show();
ui->selectFlashIC3Button->show();
ui->selectFlashIC4Button->show();
ui->selectReadIC1Button->show();
ui->selectReadIC2Button->show();
ui->selectReadIC3Button->show();
ui->selectReadIC4Button->show();
ui->multiFlashChipsButton->show();
ui->multiReadChipsButton->show();
ui->returnNormalButton->show();
}
void MainWindow::updateFlashIndividualControlsEnabled()
{
int numWriteFilesChecked = 0;
int numReadFilesChecked = 0;
bool hasBadWriteFileName = false;
bool hasBadReadFileName = false;
QCheckBox * const flashBoxes[] = {ui->flashIC1CheckBox,
ui->flashIC2CheckBox,
ui->flashIC3CheckBox,
ui->flashIC4CheckBox};
QCheckBox * const readBoxes[] = {ui->readIC1CheckBox,
ui->readIC2CheckBox,
ui->readIC3CheckBox,
ui->readIC4CheckBox};
QPushButton * const flashSelectButtons[] = {ui->selectFlashIC1Button,
ui->selectFlashIC2Button,
ui->selectFlashIC3Button,
ui->selectFlashIC4Button};
QPushButton * const readSelectButtons[] = {ui->selectReadIC1Button,
ui->selectReadIC2Button,
ui->selectReadIC3Button,
ui->selectReadIC4Button};
QLineEdit * const flashChosenFileEdits[] = {ui->chosenFlashIC1File,
ui->chosenFlashIC2File,
ui->chosenFlashIC3File,
ui->chosenFlashIC4File};
QLineEdit * const readChosenFileEdits[] = {ui->chosenReadIC1File,
ui->chosenReadIC2File,
ui->chosenReadIC3File,
ui->chosenReadIC4File};
for (size_t x = 0; x < sizeof(flashBoxes)/sizeof(flashBoxes[0]); x++)
{
bool isChecked = flashBoxes[x]->isChecked();
flashChosenFileEdits[x]->setEnabled(isChecked);
flashSelectButtons[x]->setEnabled(isChecked);
if (isChecked)
{
numWriteFilesChecked++;
QFileInfo fi(flashChosenFileEdits[x]->text());
if (flashChosenFileEdits[x]->text().isEmpty() || !fi.exists() || !fi.isFile())
{
hasBadWriteFileName = true;
}
}
isChecked = readBoxes[x]->isChecked();
readChosenFileEdits[x]->setEnabled(isChecked);
readSelectButtons[x]->setEnabled(isChecked);
if (isChecked)
{
numReadFilesChecked++;
QFileInfo fi(readChosenFileEdits[x]->text());
if (readChosenFileEdits[x]->text().isEmpty() || !fi.dir().exists())
{
hasBadReadFileName = true;
}
}
}
// All of the individual controls should be handled; now do the two main
// buttons.
if ((numWriteFilesChecked == 0) || hasBadWriteFileName)
{
ui->multiFlashChipsButton->setEnabled(false);
}
else
{
ui->multiFlashChipsButton->setEnabled(true);
}
if ((numReadFilesChecked == 0) || hasBadReadFileName)
{
ui->multiReadChipsButton->setEnabled(false);
}
else
{
ui->multiReadChipsButton->setEnabled(true);
}
}
void MainWindow::selectIndividualWriteFileClicked()
{
QString filename = QFileDialog::getOpenFileName(this, "Select a file to write to the chip:");
if (!filename.isNull())
{
if (sender() == static_cast<QObject *>(ui->selectFlashIC1Button))
{
ui->chosenFlashIC1File->setText(filename);
}
else if (sender() == static_cast<QObject *>(ui->selectFlashIC2Button))
{
ui->chosenFlashIC2File->setText(filename);
}
else if (sender() == static_cast<QObject *>(ui->selectFlashIC3Button))
{
ui->chosenFlashIC3File->setText(filename);
}
else if (sender() == static_cast<QObject *>(ui->selectFlashIC4Button))
{
ui->chosenFlashIC4File->setText(filename);
}
updateFlashIndividualControlsEnabled();
}
}
void MainWindow::selectIndividualReadFileClicked()
{
QString filename = QFileDialog::getSaveFileName(this, "Save binary file as:");
if (!filename.isNull())
{
if (sender() == static_cast<QObject *>(ui->selectReadIC1Button))
{
ui->chosenReadIC1File->setText(filename);
}
else if (sender() == static_cast<QObject *>(ui->selectReadIC2Button))
{
ui->chosenReadIC2File->setText(filename);
}
else if (sender() == static_cast<QObject *>(ui->selectReadIC3Button))
{
ui->chosenReadIC3File->setText(filename);
}
else if (sender() == static_cast<QObject *>(ui->selectReadIC4Button))
{
ui->chosenReadIC4File->setText(filename);
}
updateFlashIndividualControlsEnabled();
}
}
void MainWindow::on_multiFlashChipsButton_clicked()
{
QCheckBox * const flashBoxes[] = {ui->flashIC1CheckBox,
ui->flashIC2CheckBox,
ui->flashIC3CheckBox,
ui->flashIC4CheckBox};
QLineEdit * const flashChosenFileEdits[] = {ui->chosenFlashIC1File,
ui->chosenFlashIC2File,
ui->chosenFlashIC3File,
ui->chosenFlashIC4File};
// Read up to four files and create a combined image that we flash using
// the standard procedure...
if (writeBuffer)
{
delete writeBuffer;
}
writeBuffer = new QBuffer();
qint64 maxSize = 0;
bool hadError = false;
uint8_t chipsMask = 0;
// Read each file and ensure it exists. Oh, and create the mask of which
// chips we're flashing.
QFile *files[sizeof(flashBoxes)/sizeof(flashBoxes[0])] = {NULL, NULL, NULL, NULL};
for (size_t x = 0; x < sizeof(files)/sizeof(files[0]); x++)
{
if (flashBoxes[x]->isChecked())
{
files[x] = new QFile(flashChosenFileEdits[x]->text());
if (!files[x]->exists())
{
hadError = true;
}
if (files[x]->size() > maxSize)
{
maxSize = files[x]->size();
}
files[x]->open(QFile::ReadOnly);
// Create our chip mask. chip mask is backward from IC numbering
// (bit 0 = IC4, bit 1 = IC3, ...)
chipsMask |= (1 << (3-x));
}
}
// If there was an error or one of the files picked was too big,
// error out.
if (hadError || (maxSize > (p->SIMMCapacity() / 4)))
{
for (size_t x = 0; x < sizeof(files)/sizeof(files[0]); x++)
{
if (files[x]) delete files[x];
}
programmerWriteStatusChanged(WriteError);
return;
}
// Combine the (up to four) files into a single
// interleaved file to send to the SIMM
writeBuffer->open(QFile::ReadWrite);
for (int x = 0; x < maxSize; x++)
{
// Go in reverse order through the files so the data is saved to
// the SIMM in the correct order
for (int y = (int)(sizeof(files)/sizeof(files[0])) - 1; y >= 0; y--)
{
char c = 0xFF;
if (files[y] && !files[y]->atEnd())
{
files[y]->getChar(&c);
}
writeBuffer->putChar(c);
}
}
// Discard the temporary files
for (size_t x = 0; x < sizeof(files)/sizeof(files[0]); x++)
{
if (files[x])
{
files[x]->close();
delete files[x];
}
}
// Now go back to the beginning of the file...
// and write it!
resetAndShowStatusPage();
writeBuffer->seek(0);
p->writeToSIMM(writeBuffer, chipsMask);
}
void MainWindow::on_multiReadChipsButton_clicked()
{
QCheckBox * const readBoxes[] = {ui->readIC1CheckBox,
ui->readIC2CheckBox,
ui->readIC3CheckBox,
ui->readIC4CheckBox};
QLineEdit * const readChosenFileEdits[] = {ui->chosenReadIC1File,
ui->chosenReadIC2File,
ui->chosenReadIC3File,
ui->chosenReadIC4File};
// Prepare to read the files; when the read is complete we will save
// the files as necessary
if (readBuffer)
{
delete readBuffer;
}
readBuffer = new QBuffer();
// Try to open each file to make sure it's writable first. Then close it.
bool hadError = false;
for (size_t x = 0; x < sizeof(readBoxes)/sizeof(readBoxes[0]); x++)
{
if (readBoxes[x]->isChecked())
{
QFile tmp(readChosenFileEdits[x]->text());
if (!tmp.open(QFile::ReadWrite))
{
hadError = true;
}
else
{
tmp.close();
}
}
}
// If there was an error creating one of the files, bail out.
if (hadError)
{
programmerReadStatusChanged(ReadError);
return;
}
// Open up the buffer to read into
readBuffer->open(QFile::ReadWrite);
// Now start reading it!
resetAndShowStatusPage();
p->readSIMM(readBuffer);
}
void MainWindow::finishMultiRead()
{
QCheckBox * const readBoxes[] = {ui->readIC1CheckBox,
ui->readIC2CheckBox,
ui->readIC3CheckBox,
ui->readIC4CheckBox};
QLineEdit * const readChosenFileEdits[] = {ui->chosenReadIC1File,
ui->chosenReadIC2File,
ui->chosenReadIC3File,
ui->chosenReadIC4File};
bool hadError = false;
QFile *files[sizeof(readBoxes)/sizeof(readBoxes[0])] = {NULL, NULL, NULL, NULL};
for (size_t x = 0; x < sizeof(files)/sizeof(files[0]); x++)
{
if (readBoxes[x]->isChecked())
{
files[x] = new QFile(readChosenFileEdits[x]->text());
if (!files[x]->open(QFile::WriteOnly))
{
hadError = true;
}
}
}
if (hadError)
{
for (size_t x = 0; x < sizeof(files)/sizeof(files[0]); x++)
{
if (files[x]) delete files[x];
}
programmerReadStatusChanged(ReadError);
return;
}
// Take the final read file and de-interleave it into separate chip files
readBuffer->seek(0);
while (!readBuffer->atEnd())
{
// Go in reverse order through the files so the data is saved to the
// files in the correct order
for (int y = (int)(sizeof(files)/sizeof(files[0])) - 1; y >= 0; y--)
{
char c = 0xFF;
if (readBuffer->getChar(&c)) // grab a character...
{
// and as long as it was a success, stick it into the appropriate file
// (IF we have one), or discard it if we didn't care about the chip
// it went with.
if (files[y])
{
files[y]->putChar(c);
}
}
else // no success? we're probably near end of SIMM. just discard it and close the file
{
files[y]->close();
delete files[y];
files[y] = NULL;
}
}
}
// Close the individual files that are remaining
for (size_t x = 0; x < sizeof(files)/sizeof(files[0]); x++)
{
if (files[x])
{
files[x]->close();
delete files[x];
}
}
}
void MainWindow::returnToControlPage()
{
// Depending on what we were doing, return to the correct page
if (writeBuffer || readBuffer)
{
ui->pages->setCurrentWidget(ui->flashChipsPage);
}
else
{
ui->pages->setCurrentWidget(ui->controlPage);
}
}

View File

@ -85,6 +85,17 @@ private slots:
void on_howMuchToWriteBox_currentIndexChanged(int index);
void on_flashIndividualEnterButton_clicked();
void on_returnNormalButton_clicked();
void updateFlashIndividualControlsEnabled();
void selectIndividualWriteFileClicked();
void selectIndividualReadFileClicked();
void on_multiFlashChipsButton_clicked();
void on_multiReadChipsButton_clicked();
void finishMultiRead();
private:
Ui::MainWindow *ui;
bool initializing;
@ -93,9 +104,16 @@ private:
QFile *writeFile;
QFile *readFile;
QString electricalTestString;
QBuffer *writeBuffer;
QBuffer *readBuffer;
void resetAndShowStatusPage();
void handleVerifyFailureReply();
void hideFlashIndividualControls();
void showFlashIndividualControls();
void returnToControlPage();
};
#endif // MAINWINDOW_H

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>557</width>
<height>405</height>
<height>444</height>
</rect>
</property>
<property name="windowTitle">
@ -24,7 +24,7 @@
<item>
<widget class="QStackedWidget" name="pages">
<property name="currentIndex">
<number>0</number>
<number>3</number>
</property>
<widget class="QWidget" name="controlPage">
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -174,6 +174,13 @@
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="flashIndividualEnterButton">
<property name="text">
<string>Flash individual chips...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
@ -207,7 +214,7 @@
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -276,6 +283,289 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="flashChipsPage">
<layout class="QVBoxLayout" name="verticalLayout_14">
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Flash file(s) to chips</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<item>
<layout class="QFormLayout" name="formLayout_4">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="flashIC1CheckBox">
<property name="text">
<string>Flash IC1:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_22">
<item>
<widget class="QLineEdit" name="chosenFlashIC1File"/>
</item>
<item>
<widget class="QPushButton" name="selectFlashIC1Button">
<property name="text">
<string>Select file...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="flashIC2CheckBox">
<property name="text">
<string>Flash IC2:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_23">
<item>
<widget class="QLineEdit" name="chosenFlashIC2File"/>
</item>
<item>
<widget class="QPushButton" name="selectFlashIC2Button">
<property name="text">
<string>Select file...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_24">
<item>
<widget class="QLineEdit" name="chosenFlashIC3File"/>
</item>
<item>
<widget class="QPushButton" name="selectFlashIC3Button">
<property name="text">
<string>Select file...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_25">
<item>
<widget class="QLineEdit" name="chosenFlashIC4File"/>
</item>
<item>
<widget class="QPushButton" name="selectFlashIC4Button">
<property name="text">
<string>Select file...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="flashIC3CheckBox">
<property name="text">
<string>Flash IC3:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="flashIC4CheckBox">
<property name="text">
<string>Flash IC4:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_26">
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="multiFlashChipsButton">
<property name="text">
<string>Flash chip(s)</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Read files(s) from chips</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="readIC1CheckBox">
<property name="text">
<string>Read IC1:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_17">
<item>
<widget class="QLineEdit" name="chosenReadIC1File"/>
</item>
<item>
<widget class="QPushButton" name="selectReadIC1Button">
<property name="text">
<string>Select file...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="readIC2CheckBox">
<property name="text">
<string>Read IC2:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_18">
<item>
<widget class="QLineEdit" name="chosenReadIC2File"/>
</item>
<item>
<widget class="QPushButton" name="selectReadIC2Button">
<property name="text">
<string>Select file...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_19">
<item>
<widget class="QLineEdit" name="chosenReadIC3File"/>
</item>
<item>
<widget class="QPushButton" name="selectReadIC3Button">
<property name="text">
<string>Select file...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_20">
<item>
<widget class="QLineEdit" name="chosenReadIC4File"/>
</item>
<item>
<widget class="QPushButton" name="selectReadIC4Button">
<property name="text">
<string>Select file...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="readIC3CheckBox">
<property name="text">
<string>Read IC3:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="readIC4CheckBox">
<property name="text">
<string>Read IC4:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_21">
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="multiReadChipsButton">
<property name="text">
<string>Read chip(s)</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_29">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>This mode allows you to flash/read individual chips on a SIMM</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="returnNormalButton">
<property name="text">
<string>Return to normal mode</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -28,6 +28,8 @@ typedef enum ProgrammerCommandState
WriteSIMMWaitingSetSizeReply,
WriteSIMMWaitingSetVerifyModeReply,
WriteSIMMWaitingSetChipMaskReply,
WriteSIMMWaitingSetChipMaskValueReply,
WriteSIMMWaitingEraseReply,
WriteSIMMWaitingWriteReply,
WriteSIMMWaitingFinishReply,
@ -65,6 +67,8 @@ typedef enum ProgrammerCommandState
WritePortionWaitingSetSizeReply,
WritePortionWaitingSetVerifyModeReply,
WritePortionWaitingSetChipMaskReply,
WritePortionWaitingSetChipMaskValueReply,
WritePortionWaitingEraseReply,
WritePortionWaitingEraseConfirmation,
WritePortionWaitingEraseResult,
@ -96,7 +100,8 @@ typedef enum ProgrammerCommand
SetNoVerifyWhileWriting,
ErasePortion,
WriteChipsAt,
ReadChipsAt
ReadChipsAt,
SetChipsMask
} ProgrammerCommand;
typedef enum ProgrammerReply
@ -259,9 +264,10 @@ void Programmer::internalReadSIMM(QIODevice *device, uint32_t len, uint32_t offs
}
}
void Programmer::writeToSIMM(QIODevice *device)
void Programmer::writeToSIMM(QIODevice *device, uint8_t chipsMask)
{
writeDevice = device;
writeChipMask = chipsMask;
if (writeDevice->size() > SIMMCapacity())
{
curState = WaitingForNextCommand;
@ -288,9 +294,10 @@ void Programmer::writeToSIMM(QIODevice *device)
}
}
void Programmer::writeToSIMM(QIODevice *device, uint32_t startOffset, uint32_t length)
void Programmer::writeToSIMM(QIODevice *device, uint32_t startOffset, uint32_t length, uint8_t chipsMask)
{
writeDevice = device;
writeChipMask = chipsMask;
if ((writeDevice->size() > SIMMCapacity()) ||
(startOffset + length > SIMMCapacity()))
{
@ -451,20 +458,16 @@ void Programmer::handleChar(uint8_t c)
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);
// If we got an OK reply, we're good. Now try to set the chip mask.
if (curState == WriteSIMMWaitingSetVerifyModeReply)
{
sendByte(EraseChips);
curState = WriteSIMMWaitingEraseReply;
sendByte(SetChipsMask);
curState = WriteSIMMWaitingSetChipMaskReply;
}
else if (curState == WritePortionWaitingSetVerifyModeReply)
{
sendByte(ErasePortion);
curState = WritePortionWaitingEraseReply;
sendByte(SetChipsMask);
curState = WritePortionWaitingSetChipMaskReply;
}
break;
case CommandReplyInvalid:
@ -488,20 +491,104 @@ void Programmer::handleChar(uint8_t c)
// 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.
// So move onto the next thing to try.
if (curState == WriteSIMMWaitingSetVerifyModeReply)
{
sendByte(SetChipsMask);
curState = WriteSIMMWaitingSetChipMaskReply;
}
else if (curState == WritePortionWaitingSetVerifyModeReply)
{
sendByte(SetChipsMask);
curState = WritePortionWaitingSetChipMaskReply;
}
}
break;
}
break;
case WriteSIMMWaitingSetChipMaskReply:
case WritePortionWaitingSetChipMaskReply:
switch (c)
{
case CommandReplyOK:
// OK, now we can send the chip mask and move onto the next state
sendByte(writeChipMask);
if (curState == WriteSIMMWaitingSetChipMaskReply)
{
curState = WriteSIMMWaitingSetChipMaskValueReply;
}
else if (curState == WritePortionWaitingSetChipMaskReply)
{
curState = WritePortionWaitingSetChipMaskValueReply;
}
break;
case CommandReplyInvalid:
case CommandReplyError:
// Error reply. If we're trying to set a mask of 0x0F, no error, it
// just means the firmware's out of date and doesn't support setting
// custom chip masks. Ignore and move on.
if (writeChipMask == 0x0F)
{
// OK, erase the SIMM and get the ball rolling.
// 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);
if (curState == WriteSIMMWaitingSetVerifyModeReply)
if (curState == WriteSIMMWaitingSetChipMaskReply)
{
sendByte(EraseChips);
curState = WriteSIMMWaitingEraseReply;
}
else if (curState == WritePortionWaitingSetVerifyModeReply)
else if (curState == WritePortionWaitingSetChipMaskReply)
{
sendByte(ErasePortion);
curState = WritePortionWaitingEraseReply;
}
}
else
{
// Uh oh -- this is an old firmware that doesn't support custom
// chip masks. Let the caller know that the programmer board
// needs a firmware update.
qDebug() << "Programmer board needs firmware update.";
curState = WaitingForNextCommand;
closePort();
emit writeStatusChanged(WriteNeedsFirmwareUpdateIndividualChips);
}
break;
}
break;
case WriteSIMMWaitingSetChipMaskValueReply:
case WritePortionWaitingSetChipMaskValueReply:
switch (c)
{
case CommandReplyOK:
// OK, erase the SIMM and get the ball rolling.
// 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);
if (curState == WriteSIMMWaitingSetChipMaskValueReply)
{
sendByte(EraseChips);
curState = WriteSIMMWaitingEraseReply;
}
else if (curState == WritePortionWaitingSetChipMaskValueReply)
{
sendByte(ErasePortion);
curState = WritePortionWaitingEraseReply;
}
break;
case CommandReplyInvalid:
case CommandReplyError:
// Error after trying to set the value.
qDebug() << "Error reply setting chip mask.";
curState = WaitingForNextCommand;
closePort();
emit writeStatusChanged(WriteError);
break;
}
@ -1569,7 +1656,23 @@ void Programmer::doVerifyAfterWriteCompare()
}
}
emitStatus = WriteVerificationFailure;
// Now make sure we're not complaining about chips we didn't
// write to...this will zero out errors on chips we weren't
// flashing, but will leave errors intact for chips we did write.
// (the chip mask is backwards from the IC numbering...that's why
// I have to do this in a special way)
if ((writeChipMask & 0x01) == 0) _verifyBadChipMask &= ~0x08;
if ((writeChipMask & 0x02) == 0) _verifyBadChipMask &= ~0x04;
if ((writeChipMask & 0x04) == 0) _verifyBadChipMask &= ~0x02;
if ((writeChipMask & 0x08) == 0) _verifyBadChipMask &= ~0x01;
if (_verifyBadChipMask != 0)
{
emitStatus = WriteVerificationFailure;
}
else
{
emitStatus = WriteCompleteVerifyOK;
}
}
else
{

View File

@ -63,7 +63,8 @@ typedef enum WriteStatus
WriteVerifyTimedOut,
WriteCompleteVerifyOK,
WriteEraseBlockWrongSize,
WriteNeedsFirmwareUpdateErasePortion
WriteNeedsFirmwareUpdateErasePortion,
WriteNeedsFirmwareUpdateIndividualChips
} WriteStatus;
typedef enum ElectricalTestStatus
@ -119,8 +120,8 @@ public:
explicit Programmer(QObject *parent = 0);
virtual ~Programmer();
void readSIMM(QIODevice *device, uint32_t len = 0);
void writeToSIMM(QIODevice *device);
void writeToSIMM(QIODevice *device, uint32_t startOffset, uint32_t length);
void writeToSIMM(QIODevice *device, uint8_t chipsMask = 0x0F);
void writeToSIMM(QIODevice *device, uint32_t startOffset, uint32_t length, uint8_t chipsMask = 0x0F);
void runElectricalTest();
QString electricalTestPinName(uint8_t index);
void identifySIMMChips();
@ -200,6 +201,7 @@ private:
uint32_t writeOffset;
uint32_t writeLength;
uint8_t writeChipMask;
void openPort();
void closePort();