new UI is functional but may need some minor bugfixes

This commit is contained in:
2019-08-21 21:41:53 -04:00
parent 82928fe84b
commit a82ce2dd0d
10 changed files with 320 additions and 766 deletions

View File

@@ -95,25 +95,18 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
timer = new QTimer();
ui->setupUi(this);
setWindowTitle(APPLICATION + QString(" v") + VERSION);
//ui->menuBar->setVisible(false);
//ui->mainToolBar->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
setWindowTitle(QCoreApplication::applicationName() + QString(" v") + VERSION);
// by default hide the advanced controls
on_checkBoxAdvancedMode_stateChanged(0);
// (qtimer with 0 delay is a dumb way to make sure this is called after the window finishes updating geometry)
QTimer::singleShot(0, this, [this]() {
on_checkBoxAdvancedMode_stateChanged(0);
});
QSettings settings;
settings.beginGroup("MainWindow");
settings.endGroup();
settings.beginGroup("WriteOptions");
writeFlash = settings.value("writeFlash", true).toBool();
//writeConfig = settings.value("writeConfig", false).toBool();
writeConfig = false; //Force user to manually re-enable it every time they re-launch the application. Safer that way.
writeEeprom = settings.value("writeEeprom", false).toBool();
eraseDuringWrite = true;
settings.endGroup();
comm = new Comm();
@@ -124,13 +117,66 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
qRegisterMetaType<Comm::ErrorCode>("Comm::ErrorCode");
connect(ui->btnFlashFirmware, &QPushButton::clicked, this, [=](){
future = QtConcurrent::run([this](){
Comm::ErrorCode subResult;
//Update the progress bar so the user knows things are happening.
emit SetProgressBar(3);
//First erase the entire device.
emit IoWithDeviceStateChanged("(1/3) Erasing device...");
subResult = EraseDevice();
if (subResult != Comm::Success)
{
emit IoWithDeviceStateChanged("Erasing device failed!");
QMessageBox::critical(this, "Device Flashing Failed",
"An error ocurred while erasing the device. Please disconnect "
"and reconnect the device and try again.");
return subResult;
}
//then write the new firmware to the device
emit IoWithDeviceStateChanged("(2/3) Writing device...");
subResult = WriteDevice();
if (subResult != Comm::Success)
{
emit IoWithDeviceStateChanged("Writing device failed!");
QMessageBox::critical(this, "Device Flashing Failed",
"An error ocurred while writing the device. Please disconnect "
"and reconnect the device and try again.");
return subResult;
}
//finally verify the device's memory and write the signature word
emit IoWithDeviceStateChanged("(3/3) Verifying device...");
subResult = VerifyDevice();
emit SetProgressBar(100);
if (subResult != Comm::Success)
{
emit IoWithDeviceStateChanged("Verifying device failed!");
QMessageBox::critical(this, "Device Flashing Failed",
"An error ocurred while verifying the device. Please disconnect "
"and reconnect the device and try again.");
return subResult;
}
emit AppendString("Firmware was sucessfully flashed");
emit IoWithDeviceStateChanged("Ready.");
emit UserMustResetPrompt();
return Comm::Success;
});
ui->plainTextEdit->clear();
ui->plainTextEdit->appendPlainText("Starting Erase/Program/Verify Sequence.");
ui->plainTextEdit->appendPlainText("Do not unplug device or disconnect power until the operation is fully complete.");
ui->plainTextEdit->appendPlainText(" ");
});
connect(timer, SIGNAL(timeout()), this, SLOT(Connection()));
connect(this, SIGNAL(IoWithDeviceCompleted(QString,Comm::ErrorCode,double)), this, SLOT(IoWithDeviceComplete(QString,Comm::ErrorCode,double)));
connect(this, SIGNAL(IoWithDeviceStarted(QString)), this, SLOT(IoWithDeviceStart(QString)));
connect(this, SIGNAL(AppendString(QString)), this, SLOT(AppendStringToTextbox(QString)));
connect(this, SIGNAL(SetProgressBar(int)), this, SLOT(UpdateProgressBar(int)));
connect(comm, SIGNAL(SetProgressBar(int)), this, SLOT(UpdateProgressBar(int)));
connect(this, &MainWindow::IoWithDeviceStateChanged, this, &MainWindow::IoWithDeviceStateChange);
connect(this, &MainWindow::UserMustResetPrompt, this, &MainWindow::PromptUserToReset);
//Assume initally that the USB device that we are trying to find is using the default VID/PID.
DeviceVID = DEFAULT_VID;
@@ -189,9 +235,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
}
}
//Make initial check to see if the USB device is attached
comm->PollUSB(DeviceVID, DevicePID);
if(comm->isConnected())
@@ -204,16 +247,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
}
else
{
//ui->plainTextEdit->appendPlainText("Device not detected. Verify device is attached and in firmware update mode.");
ui->plainTextEdit->appendPlainText("Device not detected. Verify device is attached and in firmware update mode.");
hexOpen = false;
setBootloadEnabled(false);
emit SetProgressBar(0);
}
timer->start(1000); //Check for future USB connection status changes every 1000 milliseconds.
//Check if the user ran the .exe with extensions pointing staight to the hex file of interest to be programmed.
//If the device is connected, and the extra info was provided, jump straight to erase/program/verify operation
//and then exit the program. This is useful if you want to use the bootloader in a more production or automated
@@ -278,24 +319,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
}
}
MainWindow::~MainWindow()
{
QSettings settings;
settings.beginGroup("MainWindow");
settings.setValue("size", size());
settings.setValue("pos", pos());
settings.setValue("fileName", fileName);
settings.endGroup();
settings.beginGroup("WriteOptions");
settings.setValue("writeFlash", writeFlash);
settings.setValue("writeConfig", writeConfig);
settings.setValue("writeEeprom", writeEeprom);
settings.endGroup();
@@ -313,7 +341,6 @@ MainWindow::~MainWindow()
void MainWindow::Connection(void)
{
bool currStatus = comm->isConnected();
Comm::ErrorCode result;
comm->PollUSB(DeviceVID, DevicePID);
@@ -325,20 +352,6 @@ void MainWindow::Connection(void)
comm->open(DeviceVID, DevicePID);
ui->plainTextEdit->setPlainText("Device Attached.");
ui->plainTextEdit->appendPlainText("Connecting...");
if(writeConfig)
{
//ui->plainTextEdit->appendPlainText("Disabling Erase button to prevent accidental erasing of the configuration words without reprogramming them\n");
writeConfig = true;
result = comm->LockUnlockConfig(false);
if(result == Comm::Success)
{
ui->plainTextEdit->appendPlainText("Unlocked Configuration bits successfully\n");
}
}
else
{
writeConfig = false;
}
GetQuery();
}
else
@@ -346,6 +359,9 @@ void MainWindow::Connection(void)
qWarning("Closing device.");
comm->close();
ui->plainTextEdit->setPlainText("Device Detached.");
ui->lblDeviceConnected->setText("Not Connected");
ui->lblDeviceConnected->setStyleSheet("QLabel { background-color : red; }");
ui->lblDeviceStatusMsg->setText("Device not detected. Please connect the dancepad interface's USB cable to this computer.");
hexOpen = false;
setBootloadEnabled(false);
emit SetProgressBar(0);
@@ -355,14 +371,18 @@ void MainWindow::Connection(void)
void MainWindow::setBootloadEnabled(bool enable)
{
ui->action_Settings->setEnabled(enable);
ui->actionErase_Device->setEnabled(enable && !writeConfig);
ui->actionWrite_Device->setEnabled(enable && hexOpen);
//ui->actionExit->setEnabled(enable);
ui->action_Verify_Device->setEnabled(enable && hexOpen);
//ui->actionOpen->setEnabled(enable);
ui->actionBlank_Check->setEnabled(enable && !writeConfig);
ui->actionReset_Device->setEnabled(enable);
ui->groupFlashFirmware->setEnabled(enable && hexOpen);
ui->groupFirmwareFile->setEnabled(enable);
ui->btnResetDevice->setEnabled(enable);
ui->progressBar->reset();
if (!enable)
{
ui->lblFlashStatus->setText("Not ready.");
ui->lblDeviceBootloaderVer->setText("");
ui->lblDeviceAppFWVer->setText("");
}
}
void MainWindow::setBootloadBusy(bool busy)
@@ -378,15 +398,9 @@ void MainWindow::setBootloadBusy(bool busy)
timer->start(1000);
}
ui->action_Settings->setEnabled(!busy);
ui->actionErase_Device->setEnabled(!busy && !writeConfig);
ui->actionWrite_Device->setEnabled(!busy && hexOpen);
//ui->actionExit->setEnabled(!busy);
ui->action_Verify_Device->setEnabled(!busy && hexOpen);
ui->btnFwBrowse->setEnabled(!busy);
ui->action_Settings->setEnabled(!busy);
ui->actionBlank_Check->setEnabled(!busy && !writeConfig);
ui->actionReset_Device->setEnabled(!busy);
ui->btnFlashFirmware->setEnabled(!busy && hexOpen);
ui->groupFirmwareFile->setEnabled(!busy);
ui->btnResetDevice->setEnabled(!busy);
}
void MainWindow::IoWithDeviceStart(QString msg)
@@ -407,8 +421,6 @@ void MainWindow::UpdateProgressBar(int newValue)
ui->progressBar->setValue(newValue);
}
void MainWindow::IoWithDeviceComplete(QString msg, Comm::ErrorCode result, double time)
{
QTextStream ss(&msg);
@@ -440,24 +452,42 @@ void MainWindow::IoWithDeviceComplete(QString msg, Comm::ErrorCode result, doubl
}
ui->plainTextEdit->appendPlainText(msg);
if (result != Comm::Success)
{
ui->lblFlashStatus->setText(*ss.string());
QMessageBox::critical(this, "Error", *ss.string());
}
}
void MainWindow::on_action_Verify_Device_triggered()
void MainWindow::IoWithDeviceStateChange(QString msg)
{
future = QtConcurrent::run(this, &MainWindow::VerifyDevice);
ui->lblFlashStatus->setText(msg);
}
void MainWindow::PromptUserToReset()
{
QMessageBox::StandardButton resButton;
resButton = QMessageBox::information(this, "Firmware was sucessfully flashed",
"Reset device now?"
"(Note: Device must be reset or physically disconnected and "
"reconnected before it can be used.)",
QMessageBox::Yes | QMessageBox::No,
QMessageBox::Yes);
//reset device if user chose to
if (resButton == QMessageBox::Yes)
on_btnResetDevice_clicked();
}
//Routine that verifies the contents of the non-voltaile memory regions in the device, after an erase/programming cycle.
//This function requests the memory contents of the device, then compares it against the parsed .hex file data to make sure
//The locations that got programmed properly match.
void MainWindow::VerifyDevice()
Comm::ErrorCode MainWindow::VerifyDevice()
{
Comm::ErrorCode result;
DeviceData::MemoryRange deviceRange, hexRange;
QTime elapsed;
unsigned int i, j;
unsigned int arrayIndex;
bool failureDetected = false;
unsigned char flashData[MAX_ERASE_BLOCK_SIZE];
unsigned char hexEraseBlockData[MAX_ERASE_BLOCK_SIZE];
@@ -474,11 +504,8 @@ void MainWindow::VerifyDevice()
elapsed.start();
foreach(deviceRange, deviceData->ranges)
{
if(writeFlash && (deviceRange.type == PROGRAM_MEMORY))
if(deviceRange.type == PROGRAM_MEMORY)
{
//elapsed.start();
//emit IoWithDeviceStarted("Verifying Device's Program Memory...");
result = comm->GetData(deviceRange.start,
device->bytesPerPacket,
device->bytesPerAddressFLASH,
@@ -490,7 +517,6 @@ void MainWindow::VerifyDevice()
{
failureDetected = true;
qWarning("Error reading device.");
//emit IoWithDeviceCompleted("Verifying Device's Program Memory", result, ((double)elapsed.elapsed()) / 1000);
}
//Search through all of the programmable memory regions from the parsed .hex file data.
@@ -538,7 +564,7 @@ void MainWindow::VerifyDevice()
}
qWarning("Failed verify at address 0x%x", i);
emit IoWithDeviceCompleted("Verify", Comm::Fail, ((double)elapsed.elapsed()) / 1000);
return;
return Comm::Fail;
}
}//if(deviceRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressFLASH)+j] != hexRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressFLASH)+j])
}//for(j = 0; j < device->bytesPerAddressFLASH; j++)
@@ -549,9 +575,6 @@ void MainWindow::VerifyDevice()
}//if(writeFlash && (deviceRange.type == PROGRAM_MEMORY))
else if(writeEeprom && (deviceRange.type == EEPROM_MEMORY))
{
//elapsed.start();
//emit IoWithDeviceStarted("Verifying Device's EEPROM Memory...");
result = comm->GetData(deviceRange.start,
device->bytesPerPacket,
device->bytesPerAddressEEPROM,
@@ -590,7 +613,7 @@ void MainWindow::VerifyDevice()
qWarning("Device: 0x%x Hex: 0x%x", deviceRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressFLASH)+j], hexRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressFLASH)+j]);
qWarning("Failed verify at address 0x%x", i);
emit IoWithDeviceCompleted("Verify EEPROM Memory", Comm::Fail, ((double)elapsed.elapsed()) / 1000);
return;
return Comm::Fail;
}
}
}
@@ -598,87 +621,6 @@ void MainWindow::VerifyDevice()
}//foreach(hexRange, hexData->ranges)
//emit IoWithDeviceCompleted("Verifying", Comm::Success, ((double)elapsed.elapsed()) / 1000);
}//else if(writeEeprom && (deviceRange.type == EEPROM_MEMORY))
else if(writeConfig && (deviceRange.type == CONFIG_MEMORY))
{
//elapsed.start();
//emit IoWithDeviceStarted("Verifying Device's Config Words...");
result = comm->GetData(deviceRange.start,
device->bytesPerPacket,
device->bytesPerAddressConfig,
device->bytesPerWordConfig,
deviceRange.end,
deviceRange.pDataBuffer);
if(result != Comm::Success)
{
failureDetected = true;
qWarning("Error reading device.");
//emit IoWithDeviceCompleted("Verifying Device's Config Words", result, ((double)elapsed.elapsed()) / 1000);
}
//Search through all of the programmable memory regions from the parsed .hex file data.
//For each of the programmable memory regions found, if the region also overlaps a region
//that was included in the device programmed area (which just got read back with GetData()),
//then verify both the parsed hex contents and read back data match.
foreach(hexRange, hexData->ranges)
{
if(deviceRange.start == hexRange.start)
{
//For this entire programmable memory address range, check to see if the data read from the device exactly
//matches what was in the hex file.
for(i = deviceRange.start; i < deviceRange.end; i++)
{
//For each byte of each device address (1 on PIC18, 2 on PIC24, since flash memory is 16-bit WORD array)
for(j = 0; j < device->bytesPerAddressConfig; j++)
{
//Compute an index into the device and hex data arrays, based on the current i and j values.
arrayIndex = ((i - deviceRange.start) * device->bytesPerAddressConfig)+j;
//Check if the device response data matches the data we parsed from the original input .hex file.
if(deviceRange.pDataBuffer[arrayIndex] != hexRange.pDataBuffer[arrayIndex])
{
//A mismatch was detected. Perform additional checks to make sure it was a real/unexpected verify failure.
//Check if this is a PIC24 device and we are looking at the "phantom byte"
//(upper byte [j = 1] of odd address [i%2 == 1] 16-bit flash words). If the hex data doesn't match
//the device (which should be = 0x00 for these locations), this isn't a real verify
//failure, since value is a don't care anyway. This could occur if the hex file imported
//doesn't contain all locations, and we "filled" the region with pure 0xFFFFFFFF, instead of 0x00FFFFFF
//when parsing the hex file.
if((device->family == Device::PIC24) && ((i % 2) == 1) && (j == 1))
{
//Not a real verify failure, phantom byte is unimplemented and is a don't care.
}//Make further special checks for PIC18 non-J devices
else if((device->family == Device::PIC18) && (deviceRange.start == 0x300000) && ((i == 0x300004) || (i == 0x300007)))
{
//The "CONFIG3L" and "CONFIG4H" locations (0x300004 and 0x300007) on PIC18 non-J USB devices
//are unimplemented and should be masked out from the verify operation.
}
else
{
//If the data wasn't a match, and this wasn't a PIC24 phantom byte, then if we get
//here this means we found a true verify failure.
failureDetected = true;
if(device->family == Device::PIC24)
{
qWarning("Device: 0x%x Hex: 0x%x", *(uint16_t*)&deviceRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressConfig)+j], *(uint16_t*)&hexRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressConfig)+j]);
}
else
{
qWarning("Device: 0x%x Hex: 0x%x", deviceRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressConfig)+j], hexRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressConfig)+j]);
}
qWarning("Failed verify at address 0x%x", i);
emit IoWithDeviceCompleted("Verify Config Bit Memory", Comm::Fail, ((double)elapsed.elapsed()) / 1000);
return;
}
}
}
}//for(i = deviceRange.start; i < deviceRange.end; i++)
}//if(deviceRange.start == hexRange.start)
}//foreach(hexRange, hexData->ranges)
//emit IoWithDeviceCompleted("Verifying", Comm::Success, ((double)elapsed.elapsed()) / 1000);
}//else if(writeConfig && (deviceRange.type == CONFIG_MEMORY))
else
{
continue;
@@ -807,53 +749,41 @@ void MainWindow::VerifyDevice()
else
{
emit IoWithDeviceCompleted("Verify", Comm::Success, ((double)elapsed.elapsed()) / 1000);
emit AppendString("Erase/Program/Verify sequence completed successfully.");
emit AppendString("You may now unplug or reset the device.");
emit AppendString("Device verified successfully.");
//Set flags only used when the program was invoked from the console with extra parameters for auto-program and close behavior.
consoleEraseProgramVerifiedOkay = true;
consoleInvokedEraseProgramVerifyComplete = true;
}
emit SetProgressBar(100); //Set progress bar to 100%
return failureDetected ? Comm::Fail : Comm::Success;
}//void MainWindow::VerifyDevice()
//Gets called when the user clicks to program button in the GUI.
void MainWindow::on_actionWrite_Device_triggered()
{
future = QtConcurrent::run(this, &MainWindow::WriteDevice);
ui->plainTextEdit->clear();
ui->plainTextEdit->appendPlainText("Starting Erase/Program/Verify Sequence.");
ui->plainTextEdit->appendPlainText("Do not unplug device or disconnect power until the operation is fully complete.");
ui->plainTextEdit->appendPlainText(" ");
}
//This thread programs previously parsed .hex file data into the device's programmable memory regions.
void MainWindow::WriteDevice(void)
Comm::ErrorCode MainWindow::WriteDevice(void)
{
QTime elapsed;
Comm::ErrorCode result;
DeviceData::MemoryRange hexRange;
//Update the progress bar so the user knows things are happening.
emit SetProgressBar(3);
//First erase the entire device.
EraseDevice();
//Now begin re-programming each section based on the info we obtained when
//we parsed the user's .hex file.
// NOTE: The bootloader allows writing config bits. This functionality remains in
// the bootloader firmware but has been removed from this utility because the end user
// will never need to use it.
// NOTE 2: The original version of this utility provided a settings dialog to select which
// sections of flash memory should be written. This has been removed and this utility will
// instead always write only program flash. The ability to write EEPROM has been retained,
// however it is unused.
emit IoWithDeviceStarted("Writing Device...");
elapsed.start();
foreach(hexRange, hexData->ranges)
{
if(writeFlash && (hexRange.type == PROGRAM_MEMORY))
if(hexRange.type == PROGRAM_MEMORY)
{
//emit IoWithDeviceStarted("Writing Device Program Memory...");
//elapsed.start();
result = comm->Program(hexRange.start,
device->bytesPerPacket,
device->bytesPerAddressFLASH,
@@ -864,9 +794,6 @@ void MainWindow::WriteDevice(void)
}
else if(writeEeprom && (hexRange.type == EEPROM_MEMORY))
{
//emit IoWithDeviceStarted("Writing Device EEPROM Memory...");
//elapsed.start();
result = comm->Program(hexRange.start,
device->bytesPerPacket,
device->bytesPerAddressEEPROM,
@@ -875,125 +802,20 @@ void MainWindow::WriteDevice(void)
hexRange.end,
hexRange.pDataBuffer);
}
else if(writeConfig && (hexRange.type == CONFIG_MEMORY))
{
//emit IoWithDeviceStarted("Writing Device Config Words...");
//elapsed.start();
result = comm->Program(hexRange.start,
device->bytesPerPacket,
device->bytesPerAddressConfig,
device->bytesPerWordConfig,
device->family,
hexRange.end,
hexRange.pDataBuffer);
}
else
{
continue;
}
//emit IoWithDeviceCompleted("Writing", result, ((double)elapsed.elapsed()) / 1000);
if(result != Comm::Success)
{
qWarning("Programming failed");
return;
return result;
}
}
emit IoWithDeviceCompleted("Write", result, ((double)elapsed.elapsed()) / 1000);
VerifyDevice();
}
void MainWindow::on_actionBlank_Check_triggered()
{
future = QtConcurrent::run(this, &MainWindow::BlankCheckDevice);
}
void MainWindow::BlankCheckDevice(void)
{
QTime elapsed;
Comm::ErrorCode result;
DeviceData::MemoryRange deviceRange;
elapsed.start();
foreach(deviceRange, deviceData->ranges)
{
if(writeFlash && (deviceRange.type == PROGRAM_MEMORY))
{
emit IoWithDeviceStarted("Blank Checking Device's Program Memory...");
result = comm->GetData(deviceRange.start,
device->bytesPerPacket,
device->bytesPerAddressFLASH,
device->bytesPerWordFLASH,
deviceRange.end,
deviceRange.pDataBuffer);
if(result != Comm::Success)
{
qWarning("Blank Check failed");
emit IoWithDeviceCompleted("Blank Checking Program Memory", result, ((double)elapsed.elapsed()) / 1000);
return;
}
for(unsigned int i = 0; i < ((deviceRange.end - deviceRange.start) * device->bytesPerAddressFLASH); i++)
{
if((deviceRange.pDataBuffer[i] != 0xFF) && !((device->family == Device::PIC24) && ((i % 4) == 3)))
{
qWarning("Failed blank check at address 0x%x", deviceRange.start + i);
qWarning("The value was 0x%x", deviceRange.pDataBuffer[i]);
emit IoWithDeviceCompleted("Blank Check", Comm::Fail, ((double)elapsed.elapsed()) / 1000);
return;
}
}
emit IoWithDeviceCompleted("Blank Checking Program Memory", Comm::Success, ((double)elapsed.elapsed()) / 1000);
}
else if(writeEeprom && deviceRange.type == EEPROM_MEMORY)
{
emit IoWithDeviceStarted("Blank Checking Device's EEPROM Memory...");
result = comm->GetData(deviceRange.start,
device->bytesPerPacket,
device->bytesPerAddressEEPROM,
device->bytesPerWordEEPROM,
deviceRange.end,
deviceRange.pDataBuffer);
if(result != Comm::Success)
{
qWarning("Blank Check failed");
emit IoWithDeviceCompleted("Blank Checking EEPROM Memory", result, ((double)elapsed.elapsed()) / 1000);
return;
}
for(unsigned int i = 0; i < ((deviceRange.end - deviceRange.start) * device->bytesPerWordEEPROM); i++)
{
if(deviceRange.pDataBuffer[i] != 0xFF)
{
qWarning("Failed blank check at address 0x%x + 0x%x", deviceRange.start, i);
qWarning("The value was 0x%x", deviceRange.pDataBuffer[i]);
emit IoWithDeviceCompleted("Blank Check", Comm::Fail, ((double)elapsed.elapsed()) / 1000);
return;
}
}
emit IoWithDeviceCompleted("Blank Checking EEPROM Memory", Comm::Success, ((double)elapsed.elapsed()) / 1000);
}
else
{
continue;
}
}
}
void MainWindow::on_actionErase_Device_triggered()
{
future = QtConcurrent::run(this, &MainWindow::EraseDevice);
return Comm::Success;
}
void MainWindow::on_checkBoxAdvancedMode_stateChanged(int state)
@@ -1015,29 +837,26 @@ void MainWindow::on_checkBoxAdvancedMode_stateChanged(int state)
}
}
void MainWindow::EraseDevice(void)
Comm::ErrorCode MainWindow::EraseDevice(void)
{
QTime elapsed;
Comm::ErrorCode result;
Comm::BootInfo bootInfo;
emit IoWithDeviceStarted("Erasing Device... (no status update until complete, may take several seconds)");
elapsed.start();
//if(writeFlash || writeEeprom)
result = comm->Erase();
if(result != Comm::Success)
{
emit IoWithDeviceStarted("Erasing Device... (no status update until complete, may take several seconds)");
elapsed.start();
result = comm->Erase();
if(result != Comm::Success)
{
emit IoWithDeviceCompleted("Erase", result, ((double)elapsed.elapsed()) / 1000);
return;
}
result = comm->ReadBootloaderInfo(&bootInfo);
emit IoWithDeviceCompleted("Erase", result, ((double)elapsed.elapsed()) / 1000);
return result;
}
result = comm->ReadBootloaderInfo(&bootInfo);
emit IoWithDeviceCompleted("Erase", result, ((double)elapsed.elapsed()) / 1000);
return result;
}
//Executes when the user clicks the open hex file button on the main form.
@@ -1069,13 +888,12 @@ void MainWindow::LoadFile(QString newFileName)
HexImporter import;
HexImporter::ErrorCode result;
Comm::ErrorCode commResultCode;
int i;
hexData->ranges.clear();
//Print some debug info to the debug window.
qDebug(QString("Total Programmable Regions Reported by Device: " + QString::number(deviceData->ranges.count(), 10)).toLatin1());
qDebug("Total Programmable Regions Reported by Device: %d", deviceData->ranges.count());
//First duplicate the deviceData programmable region list and
//allocate some RAM buffers to hold the hex data that we are about to import.
@@ -1123,8 +941,7 @@ void MainWindow::LoadFile(QString newFileName)
hexData->ranges.append(HexBuffer);
//Print info regarding the programmable memory region to the debug window.
qDebug(QString("Device Programmable Region: [" + QString::number(HexBuffer.start, 16).toUpper() + " - " +
QString::number(HexBuffer.end, 16).toUpper() +")").toLatin1());
qDebug("Device Programmable Region: [0x%X - 0x%X]", HexBuffer.start, HexBuffer.end);
}
//Import the hex file data into the hexData->ranges[].pDataBuffer buffers.
@@ -1165,29 +982,9 @@ void MainWindow::LoadFile(QString newFileName)
return;
}
//Check if the user has imported a .hex file that doesn't contain config bits in it,
//even though the user is planning on re-programming the config bits section.
if(writeConfig && (import.hasConfigBits == false) && device->hasConfig())
{
//The user had config bit reprogramming selected, but the hex file opened didn't have config bit
//data in it. We should automatically prevent config bit programming, to avoid leaving the device
//in a broken state following the programming cycle.
commResultCode = comm->LockUnlockConfig(true); //Lock the config bits.
if(commResultCode != Comm::Success)
{
ui->plainTextEdit->appendPlainText("Unexpected internal error encountered. Recommend restarting the application to avoid ""bricking"" the device.\n");
}
QMessageBox::warning(this, "Warning!", "This HEX file does not contain config bit information.\n\nAutomatically disabling config bit reprogramming to avoid leaving the device in a state that could prevent further bootloading.", QMessageBox::AcceptRole, QMessageBox::AcceptRole);
writeConfig = false;
}
fileName = newFileName;
watchFileName = newFileName;
QSettings settings;
settings.beginGroup("MainWindow");
stream.setIntegerBase(10);
msg.clear();
@@ -1195,6 +992,7 @@ void MainWindow::LoadFile(QString newFileName)
QString name = fi.fileName();
stream << "Opened: " << name << "\n";
ui->plainTextEdit->appendPlainText(msg);
ui->lblFlashStatus->setText("Ready.");
hexOpen = true;
setBootloadEnabled(true);
QApplication::restoreOverrideCursor();
@@ -1211,42 +1009,6 @@ void MainWindow::openRecentFile(void)
}
}
void MainWindow::on_action_About_triggered()
{
QString msg;
QTextStream stream(&msg);
stream << "USB HID Bootloader v" << VERSION << "\n";
stream << "Copyright " << (char)Qt::Key_copyright << " 2011-2013, Microchip Technology Inc.\n\n";
stream << "Microchip licenses this software to you solely for use with\n";
stream << "Microchip products. The software is owned by Microchip and\n";
stream << "its licensors, and is protected under applicable copyright\n";
stream << "laws. All rights reserved.\n\n";
stream << "SOFTWARE IS PROVIDED \"AS IS.\" MICROCHIP EXPRESSLY\n";
stream << "DISCLAIMS ANY WARRANTY OF ANY KIND, WHETHER EXPRESS\n";
stream << "OR IMPLIED, INCLUDING BUT NOT LIMITED TO, THE IMPLIED\n";
stream << "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n";
stream << "PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT\n";
stream << "SHALL MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL,\n";
stream << "INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR\n";
stream << "LOST DATA, HARM TO YOUR EQUIPMENT, COST OF\n";
stream << "PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR\n";
stream << "SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT\n";
stream << "NOT LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS FOR\n";
stream << "INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.\n\n";
stream << "To the fullest extent allowed by law, Microchip and its\n";
stream << "licensors liability shall not exceed the amount of fees, if any,\n";
stream << "that you have paid directly to Microchip to use this software.\n\n";
stream << "MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON\n";
stream << "YOUR ACCEPTANCE OF THESE TERMS.";
QMessageBox::about(this, "About", msg);
}
void MainWindow::GetQuery()
{
QTime totalTime;
@@ -1279,7 +1041,9 @@ void MainWindow::GetQuery()
case Comm::Success:
wasBootloaderMode = true;
ss << "Device Ready";
//deviceLabel.setText("Connected");
ui->lblDeviceConnected->setText("Connected");
ui->lblDeviceConnected->setStyleSheet("QLabel { background-color : green; }");
ui->lblDeviceStatusMsg->setText("");
break;
default:
return;
@@ -1302,20 +1066,6 @@ void MainWindow::GetQuery()
device->bytesPerWordFLASH = 2;
device->bytesPerAddressFLASH = 1;
break;
case Device::PIC24:
device->bytesPerWordFLASH = 4;
device->bytesPerAddressFLASH = 2;
device->bytesPerWordConfig = 4;
device->bytesPerAddressConfig = 2;
break;
case Device::PIC32:
device->bytesPerWordFLASH = 4;
device->bytesPerAddressFLASH = 1;
break;
case Device::PIC16:
device->bytesPerWordFLASH = 2;
device->bytesPerAddressFLASH = 2;
break;
default:
device->bytesPerWordFLASH = 2;
device->bytesPerAddressFLASH = 1;
@@ -1341,7 +1091,7 @@ void MainWindow::GetQuery()
qDebug("Device bootloader firmware is v1.01 or newer and supports Extended Query.");
//Now fetch the extended query information packet from the USB firmware.
comm->ReadExtendedQueryInfo(&extendedBootInfo);
qDebug("Device bootloader firmware version is: " + extendedBootInfo.PIC18.bootloaderVersion);
qDebug("Device bootloader firmware version is: %d", extendedBootInfo.PIC18.bootloaderVersion);
}
else
{
@@ -1418,75 +1168,20 @@ void MainWindow::GetQuery()
deviceData->ranges.append(range);
}
ui->lblDeviceBootloaderVer->setText(QString::number(extendedBootInfo.PIC18.bootloaderVersion));
QString appVerMsg = (extendedBootInfo.PIC18.applicationVersion > 0) ?
QString::number(extendedBootInfo.PIC18.applicationVersion) :
"No FW on device";
ui->lblDeviceAppFWVer->setText(appVerMsg);
//Make sure user has allowed at least one region to be programmed
if(!(writeFlash || writeEeprom || writeConfig))
{
setBootloadEnabled(false);
ui->action_Settings->setEnabled(true);
}
else
setBootloadEnabled(true);
// if the user already loaded a hex file, attempt to load it again for the newly connected device
if (!ui->txtFirmwareFile->text().isEmpty())
LoadFile(ui->txtFirmwareFile->text());
setBootloadEnabled(true);
}
void MainWindow::on_action_Settings_triggered()
{
Comm::ErrorCode result;
Settings* dlg = new Settings(this);
dlg->enableEepromBox(device->hasEeprom());
dlg->setWriteFlash(writeFlash);
dlg->setWriteConfig(writeConfig);
dlg->setWriteEeprom(writeEeprom);
if(dlg->exec() == QDialog::Accepted)
{
writeFlash = dlg->writeFlash;
writeEeprom = dlg->writeEeprom;
if(!writeConfig && dlg->writeConfig)
{
ui->plainTextEdit->appendPlainText("Disabling Erase button to prevent accidental erasing of the configuration words without reprogramming them\n");
writeConfig = true;
hexOpen = false;
result = comm->LockUnlockConfig(false);
if(result == Comm::Success)
{
ui->plainTextEdit->appendPlainText("Unlocked Configuration bits successfully\n");
GetQuery();
}
}
else if(writeConfig && !dlg->writeConfig)
{
writeConfig = false;
hexOpen = false;
result = comm->LockUnlockConfig(true);
if(result == Comm::Success)
{
ui->plainTextEdit->appendPlainText("Locked Configuration bits successfully\n");
GetQuery();
}
}
if(!(writeFlash || writeEeprom || writeConfig))
{
setBootloadEnabled(false);
ui->action_Settings->setEnabled(true);
}
else
{
setBootloadEnabled(true);
}
}
delete dlg;
}
void MainWindow::on_actionReset_Device_triggered()
void MainWindow::on_btnResetDevice_clicked()
{
if(!comm->isConnected())
{