mirror of
https://github.com/steve-chamberlin/mac-rom-simm-programmer.software.git
synced 2024-12-22 08:30:44 +00:00
This is an incomplete implementation of the new "erase some of the SIMM"
feature. The erase capability is there, so next up comes the write. The next step is to add a mechanism to the protocol to start writing at a location other than 0 (although this is not needed for this particular feature, I'd like to have it in there first). Then, I have to update this software to use that new protocol and make sure verification still works. I'm about 50% done I'd say.
This commit is contained in:
parent
b57f0a83e1
commit
09686d2199
@ -31,6 +31,7 @@ static Programmer *p;
|
||||
#define selectedCapacityKey "selectedCapacity"
|
||||
#define verifyAfterWriteKey "verifyAfterWrite"
|
||||
#define verifyWhileWritingKey "verifyWhileWriting"
|
||||
#define selectedEraseSizeKey "selectedEraseSize"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
@ -95,6 +96,22 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->verifyBox->setCurrentIndex(selectedIndex);
|
||||
}
|
||||
|
||||
// Fill in list of "write first xxx bytes" options
|
||||
ui->howMuchToWriteBox->addItem("Erase/write entire SIMM", QVariant(0));
|
||||
ui->howMuchToWriteBox->addItem("Only erase/write first 256 KB", QVariant(256*1024));
|
||||
ui->howMuchToWriteBox->addItem("Only erase/write first 512 KB", QVariant(512*1024));
|
||||
ui->howMuchToWriteBox->addItem("Only erase/write first 1 MB", QVariant(1024*1024));
|
||||
ui->howMuchToWriteBox->addItem("Only erase/write first 1.5 MB", QVariant(3*512*1024));
|
||||
ui->howMuchToWriteBox->addItem("Only erase/write first 2 MB", QVariant(2*1024*1024));
|
||||
|
||||
// Select "erase entire SIMM" by default, or load last-used setting
|
||||
QVariant selectedEraseSize = settings.value(selectedEraseSizeKey, QVariant(0));
|
||||
selectedIndex = ui->howMuchToWriteBox->findData(selectedEraseSize);
|
||||
if (selectedIndex != -1)
|
||||
{
|
||||
ui->howMuchToWriteBox->setCurrentIndex(selectedIndex);
|
||||
}
|
||||
|
||||
ui->chosenWriteFile->setText("");
|
||||
ui->chosenReadFile->setText("");
|
||||
writeFileValid = false;
|
||||
@ -203,7 +220,16 @@ void MainWindow::on_writeToSIMMButton_clicked()
|
||||
return;
|
||||
}
|
||||
resetAndShowStatusPage();
|
||||
p->writeToSIMM(writeFile);
|
||||
|
||||
uint howMuchToErase = ui->howMuchToWriteBox->itemData(ui->howMuchToWriteBox->currentIndex()).toUInt();
|
||||
if (howMuchToErase == 0)
|
||||
{
|
||||
p->writeToSIMM(writeFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->writeToSIMM(writeFile, 0, howMuchToErase);
|
||||
}
|
||||
qDebug() << "Writing to SIMM...";
|
||||
}
|
||||
else
|
||||
@ -402,6 +428,17 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
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.");
|
||||
break;
|
||||
case WriteEraseBlockWrongSize:
|
||||
if (writeFile)
|
||||
{
|
||||
writeFile->close();
|
||||
delete writeFile;
|
||||
writeFile = NULL;
|
||||
}
|
||||
|
||||
ui->pages->setCurrentWidget(ui->controlPage);
|
||||
QMessageBox::warning(this, "Bad erase size", "The programmer cannot handle the erase size you chose.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -713,6 +750,21 @@ void MainWindow::on_verifyBox_currentIndexChanged(int index)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_howMuchToWriteBox_currentIndexChanged(int index)
|
||||
{
|
||||
if (index < 0) return;
|
||||
|
||||
uint32_t newEraseSize = static_cast<uint32_t>(ui->howMuchToWriteBox->itemData(index).toUInt());
|
||||
|
||||
QSettings settings;
|
||||
if (!initializing)
|
||||
{
|
||||
// If we're not initializing (it gets called while we're initializing),
|
||||
// go ahead and save this as the new default.
|
||||
settings.setValue(selectedEraseSizeKey, newEraseSize);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAbout_SIMM_Programmer_triggered()
|
||||
{
|
||||
AboutBox::instance()->show();
|
||||
|
@ -83,6 +83,8 @@ private slots:
|
||||
|
||||
void on_verifyBox_currentIndexChanged(int index);
|
||||
|
||||
void on_howMuchToWriteBox_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
bool initializing;
|
||||
|
@ -84,6 +84,9 @@
|
||||
<item>
|
||||
<widget class="QComboBox" name="verifyBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="howMuchToWriteBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
|
182
programmer.cpp
182
programmer.cpp
@ -60,7 +60,13 @@ typedef enum ProgrammerCommandState
|
||||
BootloaderEraseProgramAwaitingStartOKReply,
|
||||
BootloaderEraseProgramWaitingFinishReply,
|
||||
BootloaderEraseProgramWaitingWriteMoreReply,
|
||||
BootloaderEraseProgramWaitingWriteReply
|
||||
BootloaderEraseProgramWaitingWriteReply,
|
||||
|
||||
WritePortionWaitingSetSizeReply,
|
||||
WritePortionWaitingSetVerifyModeReply,
|
||||
WritePortionWaitingEraseReply,
|
||||
WritePortionWaitingEraseConfirmation,
|
||||
WritePortionWaitingEraseResult
|
||||
} ProgrammerCommandState;
|
||||
|
||||
typedef enum ProgrammerBoardFoundState
|
||||
@ -85,7 +91,8 @@ typedef enum ProgrammerCommand
|
||||
SetSIMMTypePLCC32_2MB,
|
||||
SetSIMMTypeLarger,
|
||||
SetVerifyWhileWriting,
|
||||
SetNoVerifyWhileWriting
|
||||
SetNoVerifyWhileWriting,
|
||||
ErasePortion
|
||||
} ProgrammerCommand;
|
||||
|
||||
typedef enum ProgrammerReply
|
||||
@ -156,6 +163,13 @@ typedef enum ComputerBootloaderEraseWriteRequest
|
||||
ComputerBootloaderCancel
|
||||
} ComputerBootloaderEraseWriteRequest;
|
||||
|
||||
typedef enum ProgrammerErasePortionOfChipReply
|
||||
{
|
||||
ProgrammerErasePortionOK = 0,
|
||||
ProgrammerErasePortionError,
|
||||
ProgrammerErasePortionFinished
|
||||
} ProgrammerErasePortionOfChipReply;
|
||||
|
||||
#define PROGRAMMER_USB_VENDOR_ID 0x16D0
|
||||
#define PROGRAMMER_USB_DEVICE_ID 0x06AA
|
||||
|
||||
@ -164,6 +178,8 @@ typedef enum ComputerBootloaderEraseWriteRequest
|
||||
#define READ_CHUNK_SIZE 1024
|
||||
#define FIRMWARE_CHUNK_SIZE 1024
|
||||
|
||||
#define BLOCK_ERASE_SIZE (256*1024UL)
|
||||
|
||||
static ProgrammerCommandState curState = WaitingForNextCommand;
|
||||
|
||||
// After identifying that we're in the main program, what will be the command
|
||||
@ -259,11 +275,57 @@ void Programmer::writeToSIMM(QIODevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
void Programmer::writeToSIMM(QIODevice *device, uint32_t startOffset, uint32_t length)
|
||||
{
|
||||
writeDevice = device;
|
||||
if ((writeDevice->size() > SIMMCapacity()) ||
|
||||
(startOffset + length > SIMMCapacity()))
|
||||
{
|
||||
curState = WaitingForNextCommand;
|
||||
emit writeStatusChanged(WriteFileTooBig);
|
||||
return;
|
||||
}
|
||||
else if ((startOffset % BLOCK_ERASE_SIZE) || (length % BLOCK_ERASE_SIZE))
|
||||
{
|
||||
curState = WaitingForNextCommand;
|
||||
emit writeStatusChanged(WriteEraseBlockWrongSize);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
lenWritten = 0;
|
||||
writeLenRemaining = length;
|
||||
device->seek(startOffset);
|
||||
writeOffset = startOffset;
|
||||
writeLength = length;
|
||||
|
||||
// Based on the SIMM size, tell the programmer board.
|
||||
uint8_t setSizeCommand;
|
||||
if (SIMMCapacity() > 2*1024*1024)
|
||||
{
|
||||
setSizeCommand = SetSIMMTypeLarger;
|
||||
}
|
||||
else
|
||||
{
|
||||
setSizeCommand = SetSIMMTypePLCC32_2MB;
|
||||
}
|
||||
startProgrammerCommand(setSizeCommand, WritePortionWaitingSetSizeReply);
|
||||
}
|
||||
}
|
||||
|
||||
void Programmer::sendByte(uint8_t b)
|
||||
{
|
||||
serialPort->write((const char *)&b, 1);
|
||||
}
|
||||
|
||||
void Programmer::sendWord(uint32_t w)
|
||||
{
|
||||
sendByte((w >> 0) & 0xFF);
|
||||
sendByte((w >> 8) & 0xFF);
|
||||
sendByte((w >> 16) & 0xFF);
|
||||
sendByte((w >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
uint8_t Programmer::readByte()
|
||||
{
|
||||
uint8_t returnVal;
|
||||
@ -290,6 +352,7 @@ void Programmer::handleChar(uint8_t c)
|
||||
|
||||
// Expecting reply after we told the programmer the size of SIMM to expect
|
||||
case WriteSIMMWaitingSetSizeReply:
|
||||
case WritePortionWaitingSetSizeReply:
|
||||
switch (c)
|
||||
{
|
||||
case CommandReplyOK:
|
||||
@ -306,7 +369,14 @@ void Programmer::handleChar(uint8_t c)
|
||||
verifyCommand = SetNoVerifyWhileWriting;
|
||||
}
|
||||
|
||||
curState = WriteSIMMWaitingSetVerifyModeReply;
|
||||
if (curState == WriteSIMMWaitingSetSizeReply)
|
||||
{
|
||||
curState = WriteSIMMWaitingSetVerifyModeReply;
|
||||
}
|
||||
else if (curState == WritePortionWaitingSetSizeReply)
|
||||
{
|
||||
curState = WritePortionWaitingSetVerifyModeReply;
|
||||
}
|
||||
sendByte(verifyCommand);
|
||||
break;
|
||||
case CommandReplyInvalid:
|
||||
@ -342,7 +412,14 @@ void Programmer::handleChar(uint8_t c)
|
||||
verifyCommand = SetNoVerifyWhileWriting;
|
||||
}
|
||||
|
||||
curState = WriteSIMMWaitingSetVerifyModeReply;
|
||||
if (curState == WriteSIMMWaitingSetSizeReply)
|
||||
{
|
||||
curState = WriteSIMMWaitingSetVerifyModeReply;
|
||||
}
|
||||
else if (curState == WritePortionWaitingSetSizeReply)
|
||||
{
|
||||
curState = WritePortionWaitingSetVerifyModeReply;
|
||||
}
|
||||
sendByte(verifyCommand);
|
||||
}
|
||||
break;
|
||||
@ -353,6 +430,7 @@ void Programmer::handleChar(uint8_t c)
|
||||
// Expecting reply from programmer after we told it to verify during write
|
||||
// (or not to verify during write)
|
||||
case WriteSIMMWaitingSetVerifyModeReply:
|
||||
case WritePortionWaitingSetVerifyModeReply:
|
||||
switch (c)
|
||||
{
|
||||
case CommandReplyOK:
|
||||
@ -361,8 +439,16 @@ void Programmer::handleChar(uint8_t c)
|
||||
// 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;
|
||||
if (curState == WriteSIMMWaitingSetVerifyModeReply)
|
||||
{
|
||||
sendByte(EraseChips);
|
||||
curState = WriteSIMMWaitingEraseReply;
|
||||
}
|
||||
else if (curState == WritePortionWaitingSetVerifyModeReply)
|
||||
{
|
||||
sendByte(ErasePortion);
|
||||
curState = WritePortionWaitingEraseReply;
|
||||
}
|
||||
break;
|
||||
case CommandReplyInvalid:
|
||||
case CommandReplyError:
|
||||
@ -388,8 +474,16 @@ void Programmer::handleChar(uint8_t c)
|
||||
// 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;
|
||||
if (curState == WriteSIMMWaitingSetVerifyModeReply)
|
||||
{
|
||||
sendByte(EraseChips);
|
||||
curState = WriteSIMMWaitingEraseReply;
|
||||
}
|
||||
else if (curState == WritePortionWaitingSetVerifyModeReply)
|
||||
{
|
||||
sendByte(ErasePortion);
|
||||
curState = WritePortionWaitingEraseReply;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -419,6 +513,73 @@ void Programmer::handleChar(uint8_t c)
|
||||
break;
|
||||
}
|
||||
|
||||
case WritePortionWaitingEraseReply:
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case CommandReplyOK:
|
||||
sendWord(writeOffset);
|
||||
sendWord(writeLength);
|
||||
qDebug("Sending %u, %u", writeOffset, writeLength);
|
||||
curState = WritePortionWaitingEraseConfirmation;
|
||||
qDebug() << "Sent erase positions, waiting for reply...";
|
||||
break;
|
||||
case CommandReplyError:
|
||||
// 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(WriteNeedsFirmwareUpdateErasePortion);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WritePortionWaitingEraseConfirmation:
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ProgrammerErasePortionOK:
|
||||
curState = WritePortionWaitingEraseResult;
|
||||
break;
|
||||
case ProgrammerErasePortionError:
|
||||
// Programmer didn't like the position/length we gave it
|
||||
qDebug() << "Programmer didn't like erase pos/length.";
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit writeStatusChanged(WriteEraseFailed);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WritePortionWaitingEraseResult:
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ProgrammerErasePortionFinished:
|
||||
// we're done erasing, now it's time to write the data
|
||||
// starting at where we wanted to flash to
|
||||
// TODO HERE IS WHERE I LEFT OFF
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit writeStatusChanged(WriteCompleteNoVerify);
|
||||
break;
|
||||
case ProgrammerErasePortionError:
|
||||
// Programmer failed to erase
|
||||
qDebug() << "Programmer had error erasing.";
|
||||
curState = WaitingForNextCommand;
|
||||
closePort();
|
||||
emit writeStatusChanged(WriteEraseFailed);
|
||||
break;
|
||||
}
|
||||
|
||||
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:
|
||||
@ -630,10 +791,7 @@ void Programmer::handleChar(uint8_t c)
|
||||
curState = ReadSIMMWaitingLengthReply;
|
||||
|
||||
// Send the length requesting to be read
|
||||
sendByte((lenRemaining >> 0) & 0xFF);
|
||||
sendByte((lenRemaining >> 8) & 0xFF);
|
||||
sendByte((lenRemaining >> 16) & 0xFF);
|
||||
sendByte((lenRemaining >> 24) & 0xFF);
|
||||
sendWord(lenRemaining);
|
||||
|
||||
// Now wait for the go-ahead from the programmer's side
|
||||
break;
|
||||
|
@ -61,7 +61,9 @@ typedef enum WriteStatus
|
||||
WriteVerifyError,
|
||||
WriteVerifyCancelled,
|
||||
WriteVerifyTimedOut,
|
||||
WriteCompleteVerifyOK
|
||||
WriteCompleteVerifyOK,
|
||||
WriteEraseBlockWrongSize,
|
||||
WriteNeedsFirmwareUpdateErasePortion
|
||||
} WriteStatus;
|
||||
|
||||
typedef enum ElectricalTestStatus
|
||||
@ -118,6 +120,7 @@ public:
|
||||
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 runElectricalTest();
|
||||
QString electricalTestPinName(uint8_t index);
|
||||
void identifySIMMChips();
|
||||
@ -165,6 +168,7 @@ private:
|
||||
|
||||
QextSerialPort *serialPort;
|
||||
void sendByte(uint8_t b);
|
||||
void sendWord(uint32_t w);
|
||||
uint8_t readByte();
|
||||
void handleChar(uint8_t c);
|
||||
uint32_t _simmCapacity;
|
||||
@ -192,6 +196,9 @@ private:
|
||||
QBuffer *verifyBuffer;
|
||||
QByteArray *verifyArray;
|
||||
|
||||
uint32_t writeOffset;
|
||||
uint32_t writeLength;
|
||||
|
||||
void openPort();
|
||||
void closePort();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user