#!/usr/bin/env python # # AVR-8 emulator GUI # # Copyright (C) 2007 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. AVR8EMU_VERSION = "001" import tempfile import sys import os import pyavr8emu as emu from PyQt4.QtCore import * from PyQt4.QtGui import * #FIXME inst = emu.Instance(0) class EmulatorStatus(QTextBrowser): def __init__(self, parent=None): QTextBrowser.__init__(self, parent) self.setFontFamily("Courier") self.setFontPointSize(10) self.setLineWrapMode(QTextEdit.NoWrap) self.timer = QTimer() self.timer.setInterval(300) self.timer.setSingleShot(False) self.connect(self.timer, SIGNAL("timeout()"), self.pollMsgs) self.timer.start() def pollMsgs(self): while True: msg = inst.pollStatusMsg() if not msg: return self.append(msg[:-1]) class CodeEditor(QTextEdit): def __init__(self, parent): QTextEdit.__init__(self, parent) self.setFontFamily("Courier") self.setFontPointSize(12) self.setLineWrapMode(QTextEdit.NoWrap) def statusBar(self): return self.parent().statusBar() def loadFile(self, filename): fd = QFile(filename) if not fd.open(QIODevice.ReadOnly): self.statusBar().showMessage("Could not open file %s" % filename) return data = fd.readAll() fd.close() if not data: self.statusBar().showMessage("Could not read file %s" % filename) return self.setText(str(data)) class CentralWidget(QWidget): def __init__(self, mainwnd): QWidget.__init__(self, mainwnd) self.mainwnd = mainwnd l = QVBoxLayout(self) sp = QSplitter(self) sp.setOrientation(Qt.Vertical) self.editor = CodeEditor(self) sp.addWidget(self.editor) self.emuStatus = EmulatorStatus(self) sp.addWidget(self.emuStatus) l.addWidget(sp) def statusBar(self): return self.parent().statusBar() def loadFile(self): fn = QFileDialog.getOpenFileName(self, "Open assembly file") if not fn: return inst.loadFlash(file(fn).read()) #FIXME self.editor.loadFile(fn) def __assemble(self, assembly): #FIXME not portable asmfile = tempfile.NamedTemporaryFile() asmfile.write(assembly) asmfile.flush() os.system("avra %s" % asmfile.name) hexfile = asmfile.name + ".hex" binfile = asmfile.name + ".bin" os.system("avr-objcopy -I ihex -O binary %s %s" % (hexfile, binfile)) fd = file(binfile) bindata = fd.read() fd.close() os.system("rm %s.*" % asmfile.name) print "Got %d bytes binary" % len(bindata) return bindata def reset(self): inst.reset() class StatusBar(QStatusBar): def showMessage(self, msg): QStatusBar.showMessage(self, msg, 10000) class MainWindow(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setWindowTitle("Fast! Atmel AVR 8-bit emulator") self.setCentralWidget(CentralWidget(self)) self.setStatusBar(StatusBar(self)) mb = QMenuBar(self) filemen = QMenu("&File", mb) filemen.addAction("&Load...", self.centralWidget().loadFile) filemen.addAction("&Reset", self.centralWidget().reset) filemen.addSeparator() filemen.addAction("&Exit", self.close) mb.addMenu(filemen) mb.addSeparator() helpmen = QMenu("&Help", mb) helpmen.addAction("&About", self.about) mb.addMenu(helpmen) self.setMenuBar(mb) def about(self): QMessageBox.information(self, "About", "Fast! Atmel AVR 8-bit emulator\n" "Version %s\n" "Copyright (c) 2007 Michael Buesch" % AVR8EMU_VERSION) def main(): app = QApplication(sys.argv) mainwnd = MainWindow() mainwnd.show() sys.exit(app.exec_()) if __name__ == "__main__": main()