#!/usr/bin/env python """ # TOP2049 Open Source programming suite # # Qt-based graphical user interface # # Copyright (c) 2010 Michael Buesch # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ from libtoprammer.toprammer_main import * from libtoprammer.util import * from PyQt4.QtCore import * from PyQt4.QtGui import * import sys import time import cgi def htmlEscape(plaintext): return cgi.escape(plaintext) def getIconPath(name): return pkg_resources.resource_filename("libtoprammer", "icons/" + name + ".png") def getIcon(name): return QIcon(getIconPath(name)) def bin2hex(bindata): if not bindata: return "" hexdata = [] for c in bindata: hexdata.append("%02X" % ord(c)) return "".join(hexdata) def bin2ascii(bindata): if not bindata: return "" asciidata = [] for c in bindata: if ord(c) >= 32 and ord(c) <= 126: asciidata.append(c) else: asciidata.append(".") return "".join(asciidata) class GuiUserInterface(AbstractUserInterface): # Global progress PROGRESSMETER_USER_GLOBAL = AbstractUserInterface.PROGRESSMETER_USER + 0 def __init__(self, hwThread): self.hwThread = hwThread def progressMeterInit(self, meterId, message, nrSteps): self.hwThread.appendMessage("progrInit", (meterId, message, nrSteps)) def progressMeterFinish(self, meterId): self.hwThread.appendMessage("progrFinish", meterId) def progressMeter(self, meterId, step): self.hwThread.appendMessage("progress", (meterId, step)) def __consoleMessage(self, message, newline=True): if newline: message += "\n" self.hwThread.appendMessage("console", message) def warningMessage(self, message, newline=True): self.__consoleMessage(message, newline) def infoMessage(self, message, newline=True): self.__consoleMessage(message, newline) def debugMessage(self, message, newline=True): self.__consoleMessage(message, newline) class HwThread(QThread): TASK_SHUTDOWN = 0 TASK_INITCHIP = 1 TASK_ERASE = 2 TASK_WRITEPROG = 3 TASK_WRITEEEPROM = 4 TASK_WRITEFUSE = 5 TASK_WRITELOCK = 6 TASK_READALL = 7 def __init__(self, mainWindow): QThread.__init__(self, mainWindow) self.mainWindow = mainWindow self.killRequest = False self.messageQueue = [] self.top = None self.task = None self.taskParameter = None self.pollTimer = QTimer(self) self.pollTimer.setSingleShot(False) self.connect(self.pollTimer, SIGNAL("timeout()"), self.__poll) self.waitCondition = QWaitCondition() self.mutex = QMutex() self.setTopParameters() self.start() def killThread(self): if self.isRunning(): self.mutex.lock() self.task = self.TASK_SHUTDOWN self.killRequest = True self.waitCondition.wakeAll() self.mutex.unlock() self.wait() def setTopParameters(self, busDev=None, verbose=2, forceLevel=0, usebroken=False, forceBitfileUpload=True): assert(self.top is None and self.task is None) self.param_busDev = busDev self.param_verbose = verbose self.param_forceLevel = forceLevel self.param_usebroken = usebroken self.param_forceBitfileUpload = forceBitfileUpload def triggerTask(self, task, taskParameter=None): self.mutex.lock() self.task = task self.taskParameter = taskParameter self.pollTimer.start(200) self.waitCondition.wakeAll() self.mutex.unlock() def run(self): self.mutex.lock() while True: if not self.killRequest and self.task is None: self.waitCondition.wait(self.mutex) self.mutex.unlock() self.__taskWorker() self.mutex.lock() if self.killRequest and self.task is None: break self.mutex.unlock() def appendMessage(self, message, data): if self.pollTimer.isActive(): self.mutex.lock() self.messageQueue.append( (message, data) ) self.mutex.unlock() def __taskWorker(self): try: result = self.__runTask(self.task) failed = False except (TOPException, Exception), e: result = e failed = True self.appendMessage("finished", (self.task, failed, result)) self.task = None self.taskParameter = None def __runTask(self, task): retval = None if task == self.TASK_SHUTDOWN: print "TOP hardware shutdown..." if self.top: self.top.shutdownChip() self.top = None return retval if not self.top: # Initialize Hardware access self.top = TOP(busDev = self.param_busDev, verbose = self.param_verbose, forceLevel = self.param_forceLevel, usebroken = self.param_usebroken, forceBitfileUpload = self.param_forceBitfileUpload, userInterface = GuiUserInterface(self)) if task == self.TASK_INITCHIP: self.top.initializeChip(self.taskParameter) chip = self.top.getChip() asciiArtLayout = None layoutGen = chip.getLayoutGenerator() if layoutGen: asciiArtLayout = layoutGen.zifLayoutAsciiArt() retval = (Chip.getSupportFlags(chip), asciiArtLayout) elif task == self.TASK_ERASE: self.top.eraseChip() elif task == self.TASK_WRITEPROG: self.top.writeProgmem(self.taskParameter) elif task == self.TASK_WRITEEEPROM: self.top.writeEEPROM(self.taskParameter) elif task == self.TASK_WRITEFUSE: self.top.writeFuse(self.taskParameter) elif task == self.TASK_WRITELOCK: self.top.writeLockbits(self.taskParameter) elif task == self.TASK_READALL: self.__globalProgressInit(6) self.top.checkChip() sigImage = None progmemImage = None eepromImage = None fuseImage = None lockbitsImage = None supportFlags = Chip.getSupportFlags(self.top.getChip()) if supportFlags & Chip.SUPPORT_SIGREAD: sigImage = self.top.readSignature() self.__globalProgress(1) if supportFlags & Chip.SUPPORT_PROGMEMREAD: progmemImage = self.top.readProgmem() self.__globalProgress(2) if supportFlags & Chip.SUPPORT_EEPROMREAD: eepromImage = self.top.readEEPROM() self.__globalProgress(3) if supportFlags & Chip.SUPPORT_FUSEREAD: fuseImage = self.top.readFuse() self.__globalProgress(4) if supportFlags & Chip.SUPPORT_LOCKREAD: lockbitsImage = self.top.readLockbits() self.__globalProgress(5) retval = (sigImage, progmemImage, eepromImage, fuseImage, lockbitsImage) else: raise TOPException("INTERNAL ERROR: HwThread: unknown task") return retval def __globalProgressInit(self, nrSteps): self.appendMessage("progrInit", (GuiUserInterface.PROGRESSMETER_USER_GLOBAL, None, nrSteps)) def __globalProgress(self, step): self.appendMessage("progress", (GuiUserInterface.PROGRESSMETER_USER_GLOBAL, step)) def __poll(self): self.mutex.lock() for (message, data) in self.messageQueue: if message == "finished": self.pollTimer.stop() self.mainWindow.hardwareTaskFinished( task=data[0], failed=data[1], returnValue=data[2]) elif message == "console": self.mainWindow.console.showMessage(data) elif message == "progrInit": (meterId, message, nrSteps) = data self.mainWindow.console.progressMeterInit(meterId, nrSteps) elif message == "progrFinish": meterId = data self.mainWindow.console.progressMeter(meterId, -1) elif message == "progress": (meterId, step) = data self.mainWindow.console.progressMeter(meterId, step) else: assert(0) self.messageQueue = [] self.mutex.unlock() class Console(QDockWidget): STAT_OK = 0 STAT_ERROR = 1 STAT_PROGRESS = 2 def __init__(self, mainWindow): QDockWidget.__init__(self, mainWindow) self.setFeatures(self.DockWidgetMovable | self.DockWidgetFloatable) self.setWidget(QWidget(self)) self.widget().show() self.widget().setLayout(QGridLayout(self.widget())) self.consoleMsgs = [] self.consoleText = QTextEdit(self) self.consoleText.setReadOnly(True) self.widget().layout().addWidget(self.consoleText, 0, 0, 1, 2) self.statusLabel = QLabel(self) self.widget().layout().addWidget(self.statusLabel, 1, 0, 2, 1) self.chipaccessProgress = QProgressBar(self) self.widget().layout().addWidget(self.chipaccessProgress, 1, 1) self.globalProgress = QProgressBar(self) self.widget().layout().addWidget(self.globalProgress, 2, 1) self.setStatus(self.STAT_OK) def setStatus(self, status): if status == self.STAT_OK: path = getIconPath("ok") elif status == self.STAT_ERROR: path = getIconPath("error") elif status == self.STAT_PROGRESS: path = getIconPath("progress") else: assert(0) self.statusLabel.setPixmap(QPixmap(path)) def __commitText(self): limit = 100 if len(self.consoleMsgs) > limit: self.consoleMsgs.pop(0) assert(len(self.consoleMsgs) == limit) html = "" + "".join(self.consoleMsgs) + "" self.consoleText.setHtml(html) # Scroll to end scroll = self.consoleText.verticalScrollBar() scroll.setTracking(True) scroll.setSliderPosition(scroll.maximum()) scroll.setValue(scroll.maximum()) def showMessage(self, message, bold=False): message = str(message) if not message: return newline = False if message.endswith("\n"): newline = True message = message[:-1] message = htmlEscape(message) if bold: message = "" + message + "" if newline: message += "
" lastmsg = None if self.consoleMsgs: lastmsg = self.consoleMsgs[-1] if lastmsg and not lastmsg.endswith("
"): self.consoleMsgs[-1] = self.consoleMsgs[-1] + message else: self.consoleMsgs.append(message) self.__commitText() def __meterIdToProgressBar(self, meterId): if meterId == GuiUserInterface.PROGRESSMETER_CHIPACCESS: progress = self.chipaccessProgress elif meterId == GuiUserInterface.PROGRESSMETER_USER_GLOBAL: progress = self.globalProgress else: assert(0) return progress def progressMeterInit(self, meterId, nrSteps): progress = self.__meterIdToProgressBar(meterId) progress.setMinimum(0) progress.setMaximum(max(0, nrSteps - 1)) progress.setValue(progress.maximum()) progress.setValue(0) def progressMeter(self, meterId, step): progress = self.__meterIdToProgressBar(meterId) if step == -1: progress.setMaximum(1) progress.reset() return if progress.maximum() == 0: progress.setMaximum(1) progress.setValue(1) else: progress.setValue(step) class BufferWidget(QWidget): def __init__(self, mainWindow, name): QWidget.__init__(self, mainWindow) self.mainWindow = mainWindow self.name = name self.hide() self.setLayout(QGridLayout(self)) self.setAvailable(False) self.setReadOnly() def getName(self): return self.name def setAvailable(self, available): self.available = available def isAvailable(self): return self.available def setReadOnly(self, readOnly=True): self.readOnly = readOnly def isReadOnly(self): return self.readOnly def getRawData(self): return None def setRawData(self, data): return False def clear(self): pass class InfoBufferWidget(BufferWidget): def __init__(self, mainWindow, name): BufferWidget.__init__(self, mainWindow, name) self.zifLayout = QLabel(self) font = self.zifLayout.font() font.setFixedPitch(True) font.setFamily("monospace") self.zifLayout.setFont(font) self.layout().addWidget(self.zifLayout, 0, 0, 3, 1) l = QLabel("Chip name:", self) self.layout().addWidget(l, 0, 1) self.chipName = QLabel(self) font = self.chipName.font() font.setBold(True) self.chipName.setFont(font) self.layout().addWidget(self.chipName, 0, 2) l = QLabel("Chip signature bytes:", self) self.layout().addWidget(l, 1, 1) self.chipSig = QLabel(self) font = self.chipSig.font() font.setBold(True) self.chipSig.setFont(font) self.layout().addWidget(self.chipSig, 1, 2) self.layout().setColumnStretch(3, 99) self.layout().setRowStretch(2, 99) self.clear() def clear(self): self.setChipName("") self.setChipSignature("") def setChipName(self, name): self.chipName.setText(name) def setChipSignature(self, bindata): self.chipSig.setText(bin2hex(bindata)) def setChipLayout(self, asciiArtLayout): if asciiArtLayout: self.zifLayout.setText(asciiArtLayout) self.zifLayout.setFrameShape(QFrame.StyledPanel) else: self.zifLayout.clear() self.zifLayout.setFrameShape(QFrame.NoFrame) class ImageBufferWidget(BufferWidget): def __init__(self, mainWindow, name): BufferWidget.__init__(self, mainWindow, name) self.browser = QPlainTextEdit(self) self.browser.setReadOnly(True) fmt = self.browser.currentCharFormat() fmt.setFontFamily("monospace") fmt.setFontFixedPitch(True) self.browser.setCurrentCharFormat(fmt) self.layout().addWidget(self.browser, 0, 0) self.image = None def loadImage(self, image): self.image = image if not self.image: self.browser.setPlainText("" % self.getName()) return text = [] asc = [] for i in range(0, len(image)): if i % 16 == 0: if i != 0: text.append(" |%s|\n" % "".join(asc)) asc = [] text.append("[%08X]: " % i) if i % 2 == 0: text.append(" ") text.append(bin2hex(image[i])) asc.append(bin2ascii(image[i])) if asc: if len(image) % 16: nrLeft = 16 - (len(image) % 16) text.append(" " * nrLeft) text.append(" " * (nrLeft / 2)) text.append(" |%s|" % "".join(asc)) self.browser.setPlainText("".join(text)) def getRawData(self): return self.image def setRawData(self, data): if self.isReadOnly(): return False self.loadImage(data) return True def clear(self): self.loadImage(None) class BitBufferWidget(BufferWidget): def __init__(self, mainWindow, name, bitDescriptionsAttr): BufferWidget.__init__(self, mainWindow, name) self.bitDescriptionsAttr = bitDescriptionsAttr self.bitsAreaScroll = QScrollArea(self) self.layout().addWidget(self.bitsAreaScroll, 0, 0) self.bitsAreaScroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.bitsAreaScroll.setWidgetResizable(False) self.bitsArea = None self.image = None self.checkboxes = [] def __getBitDescription(self, bitNr): if not self.mainWindow.currentChipDescription: return "" bitDescList = getattr(self.mainWindow.currentChipDescription, self.bitDescriptionsAttr, None) if not bitDescList: return "" bitDesc = filter(lambda x: x.bitNr == bitNr, bitDescList) if not bitDesc: return "" return bitDesc[0].description def loadImage(self, image): self.image = image for checkbox in self.checkboxes: checkbox.deleteLater() self.checkboxes = [] if self.bitsArea: self.bitsArea.deleteLater() self.bitsArea = None if not self.image: return self.bitsArea = QWidget(self) self.bitsArea.setLayout(QGridLayout(self.bitsArea)) self.bitsArea.layout().addWidget(QLabel("Currently set %s:" % self.getName(), self.bitsArea), 0, 0) self.hexView = QLabel(self.bitsArea) font = self.hexView.font() font.setBold(True) self.hexView.setFont(font) self.bitsArea.layout().addWidget(self.hexView, 0, 1) for i in range(0, len(image) * 8): desc = self.__getBitDescription(i) if desc: desc = " (%s)" % desc checkbox = QCheckBox("bit %d%s" % (i, desc), self.bitsArea) if ord(image[i // 8]) & (1 << (i % 8)): checkbox.setCheckState(Qt.Checked) self.bitsArea.layout().addWidget(checkbox, 1 + i, 0, 1, 2) self.connect(checkbox, SIGNAL("stateChanged(int)"), self.__bitStateChanged) self.checkboxes.append(checkbox) self.__updateHexView() def __updateHexView(self): self.hexView.setText(bin2hex(self.image)) self.bitsAreaScroll.setWidget(self.bitsArea) def __bitStateChanged(self, unused): self.image = "" tmp = 0 i = 0 for checkbox in self.checkboxes: if checkbox.checkState() == Qt.Checked: tmp |= (1 << i) i += 1 if i == 8: self.image += chr(tmp) i = 0 tmp = 0 assert(i == 0) self.__updateHexView() def getRawData(self): return self.image def setRawData(self, data): if self.isReadOnly(): return False if len(data) > 32: # Don't want huge files return False self.loadImage(data) return True def clear(self): self.loadImage(None) class BufferTabWidget(QTabWidget): def __init__(self, mainWindow): QTabWidget.__init__(self, mainWindow) self.mainWindow = mainWindow self.infoBuffer = InfoBufferWidget(mainWindow, "chip info") self.progmemBuffer = ImageBufferWidget(mainWindow, "program memory") self.eepromBuffer = ImageBufferWidget(mainWindow, "(E)EPROM memory") self.fuseBuffer = BitBufferWidget(mainWindow, "fuse bits", "fuseDesc") self.lockBuffer = BitBufferWidget(mainWindow, "lock bits", "lockbitDesc") self.setTabPosition(self.South) self.__addBufferTab(self.infoBuffer) self.removeAll() def __addBufferTab(self, bufferWidget, readOnly=True): self.addTab(bufferWidget, bufferWidget.getName()) bufferWidget.setReadOnly(readOnly) bufferWidget.setAvailable(True) def __removeBufferTab(self, bufferWidget): self.removeTab(self.indexOf(bufferWidget)) bufferWidget.clear() bufferWidget.setAvailable(False) def __removeAll(self): self.__removeBufferTab(self.progmemBuffer) self.__removeBufferTab(self.eepromBuffer) self.__removeBufferTab(self.fuseBuffer) self.__removeBufferTab(self.lockBuffer) def removeAll(self): self.__removeAll() def setupBuffers(self, chipSupportFlags): prevSelect = self.getCurrentBuffer() self.__removeAll() if chipSupportFlags & (Chip.SUPPORT_PROGMEMREAD | Chip.SUPPORT_PROGMEMWRITE): self.__addBufferTab(self.progmemBuffer, not bool(chipSupportFlags & Chip.SUPPORT_PROGMEMWRITE)) if chipSupportFlags & (Chip.SUPPORT_EEPROMREAD | Chip.SUPPORT_EEPROMWRITE): self.__addBufferTab(self.eepromBuffer, not bool(chipSupportFlags & Chip.SUPPORT_EEPROMWRITE)) if chipSupportFlags & (Chip.SUPPORT_FUSEREAD | Chip.SUPPORT_FUSEWRITE): self.__addBufferTab(self.fuseBuffer, not bool(chipSupportFlags & Chip.SUPPORT_FUSEWRITE)) if chipSupportFlags & (Chip.SUPPORT_LOCKREAD | Chip.SUPPORT_LOCKWRITE): self.__addBufferTab(self.lockBuffer, not bool(chipSupportFlags & Chip.SUPPORT_LOCKWRITE)) if prevSelect and prevSelect.isAvailable(): self.setCurrentIndex(self.indexOf(prevSelect)) def loadBuffers(self, progmemImage, eepromImage, fuseImage, lockbitsImage): if progmemImage is not None: self.progmemBuffer.loadImage(progmemImage) if eepromImage is not None: self.eepromBuffer.loadImage(eepromImage) if fuseImage is not None: self.fuseBuffer.loadImage(fuseImage) if lockbitsImage is not None: self.lockBuffer.loadImage(lockbitsImage) def verifyBuffers(self, progmemImage, eepromImage, fuseImage, lockbitsImage): fail = False for (image, bufferWidget) in ((progmemImage, self.progmemBuffer), (eepromImage, self.eepromBuffer), (fuseImage, self.fuseBuffer), (lockbitsImage, self.lockBuffer)): if image is None: continue if bufferWidget.getRawData() != image: self.mainWindow.console.showMessage( "Chip verify of %s FAILED!\n" % bufferWidget.getName(), bold=True) fail = True if fail: self.mainWindow.console.setStatus(Console.STAT_ERROR) else: self.mainWindow.console.showMessage("Chip verify succeed\n", bold=True) self.mainWindow.console.setStatus(Console.STAT_OK) def getCurrentBuffer(self): return self.currentWidget() class ChipSelectDialog(QDialog): def __init__(self, parent): QDialog.__init__(self, parent) self.setLayout(QGridLayout(self)) self.chipList = QListWidget(self) for chipDescription in registeredChips: if chipDescription.broken: continue if chipDescription.internal: continue item = QListWidgetItem(chipDescription.description, self.chipList) item.setData(Qt.UserRole, chipDescription) self.chipList.sortItems() self.layout().addWidget(self.chipList, 0, 0, 1, 2) self.okButton = QPushButton("&Ok", self) self.layout().addWidget(self.okButton, 1, 0) self.cancelButton = QPushButton("&Cancel", self) self.layout().addWidget(self.cancelButton, 1, 1) self.selectionChanged() self.connect(self.okButton, SIGNAL("released()"), self.accept) self.connect(self.cancelButton, SIGNAL("released()"), self.reject) self.connect(self.chipList, SIGNAL("itemSelectionChanged()"), self.selectionChanged) self.connect(self.chipList, SIGNAL("itemDoubleClicked(QListWidgetItem)"), self.accept) def selectionChanged(self): item = self.chipList.currentItem() self.okButton.setEnabled(bool(item)) def getSelectedChip(self): item = self.chipList.currentItem() if not item: return None chipDescription = item.data(Qt.UserRole).toPyObject() return chipDescription class StatusBar(QStatusBar): def __init__(self, mainWindow): QStatusBar.__init__(self, mainWindow) class TopToolBar(QToolBar): def __init__(self, mainWindow): QToolBar.__init__(self, mainWindow) self.addAction(getIcon("open"), "Load buffer", mainWindow.loadBuffer) self.addAction(getIcon("save"), "Save buffer", mainWindow.saveBuffer) self.addAction(getIcon("chip"), "Select chip", mainWindow.selectChip) self.addSeparator() self.addAction(getIcon("up"), "Read chip", mainWindow.readChip) self.addSeparator() self.addAction(getIcon("erase"), "Erase", mainWindow.eraseChip) self.addAction(getIcon("memory"), "Write progmem", mainWindow.writeChipProgmem) self.addAction(getIcon("memory"), "Write EPROM", mainWindow.writeChipEeprom) self.addAction(getIcon("memory"), "Write fuses", mainWindow.writeChipFuses) self.addAction(getIcon("lock"), "Write lockbits", mainWindow.writeChipLockbits) self.addAction(getIcon("verify"), "Verify", mainWindow.verifyChip) self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) class LeftToolBar(QToolBar): def __init__(self, mainWindow): QToolBar.__init__(self, mainWindow) class MainWindow(QMainWindow): OP_NONE = 0 OP_VERIFY = 1 def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setWindowTitle("TOPrammer - Open Source programming suite") self.chipSupportFlags = 0 # Chip.SUPPORT_... for the loaded chip self.currentChipDescription = None self.setStatusBar(StatusBar(self)) self.topToolBar = TopToolBar(self) self.addToolBar(Qt.TopToolBarArea, self.topToolBar) self.leftToolBar = LeftToolBar(self) self.addToolBar(Qt.LeftToolBarArea, self.leftToolBar) self.setMenuBar(QMenuBar(self)) menu = QMenu("&File", self) menu.addAction("&Load buffer...", self.loadBuffer) menu.addAction("&Save buffer...", self.saveBuffer) menu.addSeparator() menu.addAction("&Exit", self.close) self.menuBar().addMenu(menu) menu = QMenu("&Run", self) menu.addAction("&Select chip", self.selectChip) menu.addSeparator() menu.addAction("&Read chip", self.readChip) menu.addAction("&Erase", self.eraseChip) menu.addAction("Write &program memory", self.writeChipProgmem) menu.addAction("Write (E)EP&ROM", self.writeChipEeprom) menu.addAction("Write &fuses", self.writeChipFuses) menu.addAction("Write &lock bits", self.writeChipLockbits) menu.addAction("&Verify chip", self.verifyChip) self.menuBar().addMenu(menu) menu = QMenu("&Help", self) menu.addAction("&About", self.showAbout) self.menuBar().addMenu(menu) self.bufferTab = BufferTabWidget(self) self.setCentralWidget(self.bufferTab) self.console = Console(self) self.addDockWidget(Qt.BottomDockWidgetArea, self.console) self.hwThread = HwThread(self) self.taskRunning = False self.operation = self.OP_NONE def closeEvent(self, e): if self.taskRunning: QMessageBox.critical(self, "Task running", "A hardware access task is running. Wait for it " "to finish before closing the application.") e.ignore() return self.hwThread.killThread() e.accept() def showAbout(self): QMessageBox.information(self, "About TOPrammer", "Copyright (c) Michael Buesch ") def loadBuffer(self): bufWidget = self.bufferTab.getCurrentBuffer() if not bufWidget: return if bufWidget.isReadOnly(): QMessageBox.critical(self, "Buffer is read only", "Cannot load data into the %s buffer.\n" "The buffer is read-only." %\ bufWidget.getName()) return selectedFilter = QString() fn = QFileDialog.getOpenFileName(self, "%s - binary file" % bufWidget.getName(), QString(), "Intel hex file (*.hex *.ihex);;" "Binary file (*)", selectedFilter) if not fn: return extensions = str(selectedFilter).split("(")[1].\ split(")")[0].replace("*", "").strip().split() try: data = file(fn, "rb").read() except (IOError), e: QMessageBox.critical(self, "Failed to read file", "Failed to read %s:\n%s" %\ (str(fn), str(e.strerror))) return try: if ".hex" in extensions or ".ihex" in extensions: data = IO_ihex().toBinary(data) elif not extensions: data = IO_binary().toBinary(data) else: assert(0) except (TOPException), e: QMessageBox.critical(self, "Failed to convert data", "Failed to convert the input file data to binary\n%s" % str(e)) return if not bufWidget.setRawData(data): QMessageBox.critical(self, "Failed to load data", "Failed to load the file into the buffer") def saveBuffer(self): bufWidget = self.bufferTab.getCurrentBuffer() if not bufWidget: return data = bufWidget.getRawData() if not data: return selectedFilter = QString() fn = QFileDialog.getSaveFileName(self, "%s - binary file" % bufWidget.getName(), QString(), "Intel hex file (*.hex);;" "Binary file (*)", selectedFilter) if not fn: return extensions = str(selectedFilter).split("(")[1].\ split(")")[0].replace("*", "").strip().split() if not extensions: extensions = [ "" ] if not fn.endsWith(extensions[0]): fn += extensions[0] if ".hex" in extensions or ".ihex" in extensions: data = IO_ihex().fromBinary(data) elif not extensions[0]: data = IO_binary().fromBinary(data) else: assert(0) try: file(fn, "wb").write(data) except (IOError), e: QMessageBox.critical(self, "Failed to write file", "Failed to write %s:\n%s" %\ (str(fn), str(e.strerror))) return def selectChip(self): dlg = ChipSelectDialog(self) if dlg.exec_() != QDialog.Accepted: return chipDescription = dlg.getSelectedChip() if not chipDescription: return self.currentChipDescription = chipDescription self.runHardwareTask(HwThread.TASK_INITCHIP, chipDescription.chipID) def readChip(self): self.runHardwareTask(HwThread.TASK_READALL) def eraseChip(self): self.runHardwareTask(HwThread.TASK_ERASE) def writeChipProgmem(self): bufferWidget = self.bufferTab.progmemBuffer data = bufferWidget.getRawData() if not bufferWidget.isAvailable() or not data: QMessageBox.critical(self, "No program memory", "No program memory available") return self.runHardwareTask(HwThread.TASK_WRITEPROG, data) def writeChipEeprom(self): bufferWidget = self.bufferTab.eepromBuffer data = bufferWidget.getRawData() if not bufferWidget.isAvailable() or not data: QMessageBox.critical(self, "No (E)EPROM memory", "No (E)EPROM memory available") return self.runHardwareTask(HwThread.TASK_WRITEEEPROM, data) def writeChipFuses(self): bufferWidget = self.bufferTab.fuseBuffer data = bufferWidget.getRawData() if not bufferWidget.isAvailable() or not data: QMessageBox.critical(self, "No fuse bits", "No fuse bits available") return self.runHardwareTask(HwThread.TASK_WRITEFUSE, data) def writeChipLockbits(self): bufferWidget = self.bufferTab.lockBuffer data = bufferWidget.getRawData() if not bufferWidget.isAvailable() or not data: QMessageBox.critical(self, "No lock bits", "No lock bits available") return self.runHardwareTask(HwThread.TASK_WRITELOCK, data) def verifyChip(self): self.runHardwareTask(HwThread.TASK_READALL) self.operation = self.OP_VERIFY def guiUpdateEnable(self): self.menuBar().setEnabled(not self.taskRunning) self.topToolBar.setEnabled(not self.taskRunning) self.leftToolBar.setEnabled(not self.taskRunning) self.bufferTab.setEnabled(not self.taskRunning) def runHardwareTask(self, task, taskParameter=None): assert(not self.taskRunning) self.console.progressMeterInit(GuiUserInterface.PROGRESSMETER_CHIPACCESS, 0) self.console.progressMeterInit(GuiUserInterface.PROGRESSMETER_USER_GLOBAL, 0) self.console.setStatus(Console.STAT_PROGRESS) self.taskRunning = True self.guiUpdateEnable() self.hwThread.triggerTask(task, taskParameter) def hardwareTaskFinished(self, task, failed, returnValue): self.taskRunning = False if failed: self.console.showMessage("[HW op %d failed] %s\n" %\ (task, str(returnValue))) self.console.progressMeterInit(GuiUserInterface.PROGRESSMETER_CHIPACCESS, 100) self.console.progressMeterInit(GuiUserInterface.PROGRESSMETER_USER_GLOBAL, 100) self.console.setStatus(Console.STAT_ERROR) self.guiUpdateEnable() return # Task succeed self.console.progressMeter(GuiUserInterface.PROGRESSMETER_CHIPACCESS, -1) self.console.progressMeter(GuiUserInterface.PROGRESSMETER_USER_GLOBAL, -1) self.guiUpdateEnable() self.console.setStatus(Console.STAT_OK) if task == HwThread.TASK_SHUTDOWN: pass # Nothing to do elif task == HwThread.TASK_INITCHIP: (self.chipSupportFlags, asciiArtLayout) = returnValue self.bufferTab.setupBuffers(self.chipSupportFlags) self.bufferTab.infoBuffer.clear() self.bufferTab.infoBuffer.setChipName(self.currentChipDescription.description) self.bufferTab.infoBuffer.setChipLayout(asciiArtLayout) elif task == HwThread.TASK_ERASE: pass # Nothing to do elif task == HwThread.TASK_WRITEPROG: pass # Nothing to do elif task == HwThread.TASK_WRITEEEPROM: pass # Nothing to do elif task == HwThread.TASK_WRITEFUSE: pass # Nothing to do elif task == HwThread.TASK_WRITELOCK: pass # Nothing to do elif task == HwThread.TASK_READALL: (sigImage, progmemImage, eepromImage, fuseImage, lockbitsImage) = returnValue if self.operation == self.OP_VERIFY: self.bufferTab.verifyBuffers(progmemImage, eepromImage, fuseImage, lockbitsImage) else: self.bufferTab.setupBuffers(self.chipSupportFlags) self.bufferTab.loadBuffers(progmemImage, eepromImage, fuseImage, lockbitsImage) self.bufferTab.infoBuffer.setChipSignature(sigImage) self.operation = self.OP_NONE else: assert(0) def main(): app = QApplication(sys.argv) mainwnd = MainWindow() mainwnd.show() mainwnd.resize(int(mainwnd.width() * 1.0), int(mainwnd.height() * 1.4)) return app.exec_() if __name__ == "__main__": sys.exit(main())