mirror of
https://github.com/rzzzwilson/pymlac.git
synced 2025-06-10 09:32:41 +00:00
854 lines
29 KiB
Python
Executable File
854 lines
29 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
"""
|
|
The Python Imlac emulator (pymlac).
|
|
|
|
Console-only version
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import wx
|
|
|
|
from Globals import *
|
|
import Imlac
|
|
|
|
import Memory
|
|
import Ptr
|
|
import Ptp
|
|
import MainCPU
|
|
import Trace
|
|
|
|
|
|
# map ROM name to type
|
|
RomTypeMap = {'ptr': ROM_PTR,
|
|
'tty': ROM_TTY,
|
|
'none': ROM_NONE}
|
|
|
|
count = 1
|
|
|
|
def abort(msg):
|
|
"""Handle a terminal problem."""
|
|
|
|
print(msg)
|
|
sys.exit(1)
|
|
|
|
def check_int(value, msg):
|
|
"""Check that a value is a valid 16 bit positive value.
|
|
|
|
We allow decimal and octal number representations.
|
|
"""
|
|
|
|
try:
|
|
if str(value)[0] == '0':
|
|
data = int(value, 8)
|
|
else:
|
|
data = int(value)
|
|
except:
|
|
abort(msg)
|
|
if data < 0 or data > 0177777:
|
|
abort(msg)
|
|
|
|
return data
|
|
|
|
def get_next(options, index, msg):
|
|
"""If possible, get next arg in list."""
|
|
|
|
if index < len(options):
|
|
next_arg = options[index]
|
|
else:
|
|
abort(msg)
|
|
|
|
return next_arg
|
|
|
|
def handle_options():
|
|
"""Routine to analyse command line options.
|
|
|
|
Returns a list of operation objects which are tuples:
|
|
(OPERATION, ARGS)
|
|
"""
|
|
|
|
options = sys.argv[1:]
|
|
|
|
index = 0
|
|
result = []
|
|
boot_rom = 'ptr'
|
|
|
|
while index < len(options):
|
|
arg = options[index]
|
|
index += 1
|
|
|
|
if arg[0] == '-':
|
|
if arg == '-b':
|
|
next_arg = get_next(options, index,
|
|
"-b option must be 'ptr' or 'tty' or 'none'")
|
|
index += 1
|
|
next_arg = next_arg.lower()
|
|
#next_arg = RomTypeMap.get(next_arg, False)
|
|
|
|
if next_arg:
|
|
op = ('boot', next_arg)
|
|
boot_rom = next_arg
|
|
else:
|
|
abort("-b option must be 'ptr', 'tty' or 'none'")
|
|
elif arg == '-c':
|
|
op = ('clear', boot_rom)
|
|
elif arg == '-d':
|
|
next_arg = get_next(options, index,
|
|
"-d option must be data switch value, positive & max 16 bits")
|
|
index += 1
|
|
data = check_int(next_arg,
|
|
"-d option must be data switch value, positive & max 16 bits")
|
|
op = ('data', data)
|
|
elif arg == '-h':
|
|
usage()
|
|
elif arg == '-ptp':
|
|
next_arg = get_next(options, index,
|
|
"-ptp option must be papertape punch file")
|
|
index += 1
|
|
if not os.path.isfile(next_arg):
|
|
abort("File %s isn't a papertape file" % next_arg)
|
|
op = ('load_ptp', next_arg)
|
|
elif arg == '-ptr':
|
|
next_arg = get_next(options, index,
|
|
"-ptr option must be papertape reader file")
|
|
index += 1
|
|
if not os.path.isfile(next_arg):
|
|
abort("File %s isn't a papertape file" % next_arg)
|
|
op = ('load_ptr', next_arg)
|
|
elif arg == '-r':
|
|
next_arg = get_next(options, index,
|
|
"-r option must be 'PC' or run address, positive & max 16 bits")
|
|
index += 1
|
|
next_arg = next_arg.lower()
|
|
if next_arg == 'pc':
|
|
op = ('run', None)
|
|
else:
|
|
address = check_int(next_arg,
|
|
"-r option must be 'PC' or run address, positive & max 16 bits")
|
|
op = ('run', address)
|
|
elif arg == '-s':
|
|
next_arg = get_next(options, index,
|
|
"-s option must be set file")
|
|
index += 1
|
|
if not os.path.isfile(next_arg):
|
|
abort("File %s isn't a 'set' file" % next_arg)
|
|
op = ('set', next_arg)
|
|
elif arg == '-t':
|
|
next_arg = get_next(options, index,
|
|
"-t option must be trace range")
|
|
index += 1
|
|
addr = next_arg.split(',')
|
|
if len(addr) == 1:
|
|
trace1 = addr[0]
|
|
if trace1.lower() == 'off':
|
|
trace1 = None
|
|
else:
|
|
trace1 = check_int(trace1,
|
|
"-t option must be trace range")
|
|
trace2 = None
|
|
elif len(addr) == 2:
|
|
trace1 = check_int(addr[0], "-t option must be trace range")
|
|
trace2 = check_int(addr[1], "-t option must be trace range")
|
|
else:
|
|
abort("-t option must be trace range")
|
|
op = ('trace', (trace1, trace2))
|
|
elif arg == '-ttyin':
|
|
next_arg = get_next(options, index,
|
|
"-ttyin option must be teletype input file")
|
|
index += 1
|
|
if not os.path.isfile(next_arg):
|
|
abort("File %s isn't a teletype file" % next_arg)
|
|
op = ('load_ttyin', next_arg)
|
|
elif arg == '-ttyout':
|
|
next_arg = get_next(options, index,
|
|
"-ttyout option must be teletype output file")
|
|
index += 1
|
|
if not os.path.isfile(next_arg):
|
|
abort("File %s isn't a teletype file" % next_arg)
|
|
op = ('load_ttyout', next_arg)
|
|
elif arg == '-v':
|
|
next_arg = get_next(options, index,
|
|
"-v option must be view file")
|
|
index += 1
|
|
if not os.path.isfile(next_arg):
|
|
abort("File %s isn't a 'view' file" % next_arg)
|
|
op = ('view', next_arg)
|
|
elif arg == '-w':
|
|
next_arg = get_next(options, index,
|
|
"-W option must be ON|OFF")
|
|
index += 1
|
|
next_arg = next_arg.lower()
|
|
if next_arg in ['on', 'off']:
|
|
op = ('write', next_arg)
|
|
else:
|
|
abort("-w option must be 'ON' or 'OFF'")
|
|
else:
|
|
usage()
|
|
else:
|
|
usage()
|
|
|
|
result.append(op)
|
|
return result
|
|
|
|
def usage():
|
|
"""Help for befuddled user."""
|
|
|
|
print('Usage:\n')
|
|
print('pymlac [-b (ptr|tty|none)] [-c] [-t [<a>[,<b>]]] [-r <address>] [<imlacfile>]\n')
|
|
print('where -b (ptr|tty|none) sets the bootstrap ROM code, if no device disable ROM')
|
|
print(' -c clear core, except bootstrap ROM')
|
|
print(' -d <value> set data switches')
|
|
print(' -h prints this help')
|
|
print(' -ptp <file> mount <file> on the papertape punch')
|
|
print(' -ptr <file> mount <file> on the papertape reader')
|
|
print(' -r (<address>|PC) execute from the <address>, no address runs from current PC')
|
|
print(' -s <setfile> sets memory values from file')
|
|
print(' -t (<addr1>[,<addr2>]|off) controls trace:')
|
|
print(' -t 100 trace from address 0100')
|
|
print(' -t 100,200 traces between addresses 100 and 200')
|
|
print(' -t off trace OFF')
|
|
print(' -ttyin <file> mount <file> on the teletype reader')
|
|
print(' -ttyout <file> mount <file> on the teletype writer')
|
|
print(' -v <viewfile> prints memory locations from file')
|
|
print(' -w (on|off) turn ROM writability ON or OFF')
|
|
sys.exit()
|
|
|
|
|
|
def main():
|
|
"""Start of the Imlac emulator."""
|
|
|
|
# get operations list
|
|
ops = handle_options()
|
|
|
|
# Initialize the emulator.
|
|
boot_rom = 'ptr' # default ROM loader
|
|
Imlac.init(0, TRACE_FILENAME, None, None, boot_rom, CORE_FILENAME)
|
|
|
|
# now perform operations
|
|
for (operation, args) in ops:
|
|
if operation == 'boot':
|
|
Memory.set_ROM(args)
|
|
Trace.comment('Bootstrap ROM set to %s' % args.upper())
|
|
elif operation == 'clear':
|
|
Memory.clear_core()
|
|
Trace.comment('Core cleared')
|
|
elif operation == 'load_ptp':
|
|
Ptp.mount(args)
|
|
Trace.comment("File '%s' mounted on PTP" % args)
|
|
elif operation == 'load_ptr':
|
|
Ptr.mount(args)
|
|
Trace.comment("File '%s' mounted on PTR" % args)
|
|
elif operation == 'data':
|
|
MainCPU.DS = args
|
|
Trace.comment('Dataswitch value set to %06o' % args)
|
|
elif operation == 'run':
|
|
MainCPU.PC = args
|
|
Trace.comment('Running from address %06o' % args)
|
|
if Imlac.tracestart:
|
|
Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs')
|
|
Trace.comment('------ ------------- ------ -------------- '
|
|
'-----------------------')
|
|
Imlac.run()
|
|
Trace.comment('Imlac halted')
|
|
elif operation == 'set':
|
|
Trace.comment("Setting memory from file '%s'" % args)
|
|
elif operation == 'trace':
|
|
if args == 'off':
|
|
Imlac.tracestart = None
|
|
Imlac.traceend = None
|
|
else:
|
|
(start, end) = args
|
|
Imlac.tracestart = start
|
|
Imlac.traceend = end
|
|
tstart = Imlac.tracestart
|
|
if tstart is not None:
|
|
tstart = '%06o' % tstart
|
|
tend = Imlac.traceend
|
|
if tend is not None:
|
|
tend = '%06o' % tend
|
|
Trace.comment('Trace set to (%s, %s)' % (tstart, tend))
|
|
elif operation == 'ttyin':
|
|
TtyIn.mount(args)
|
|
Trace.comment("File '%s' mounted on TTYIN" % args)
|
|
elif operation == 'ttyout':
|
|
TtyOut.mount(args)
|
|
Trace.comment("File '%s' mounted on TTYOUT" % args)
|
|
elif operation == 'view':
|
|
Trace.comment("Viewing memory from file '%s'" % args)
|
|
elif operation == 'write':
|
|
if args == 'on':
|
|
Memory.using_rom = True
|
|
elif args == 'off':
|
|
Memory.using_rom = False
|
|
else:
|
|
abort("Invalid view arg: %s" % args)
|
|
Trace.comment('ROM write protect set %s' % args.upper())
|
|
else:
|
|
abort('Invalid internal operation: %s' % operation)
|
|
|
|
Imlac.close(CORE_FILENAME)
|
|
|
|
class Led_1(object):
|
|
def __init__(self, parent, label, x, y, off, on):
|
|
wx.StaticText(parent, -1, label, pos=(x, y))
|
|
y += 15
|
|
wx.StaticBitmap(parent, -1, off, pos=(x-1, y))
|
|
self.led = wx.StaticBitmap(parent, -1, on, pos=(x-1, y))
|
|
self.set_value(0)
|
|
|
|
def set_value(self, value):
|
|
if value:
|
|
self.led.Enable()
|
|
else:
|
|
self.led.Disable()
|
|
|
|
|
|
class Led_16(object):
|
|
def __init__(self, parent, label, x, y, off, on):
|
|
led_width = off.GetWidth()
|
|
led_height = off.GetHeight()
|
|
wx.StaticText(parent, -1, label, pos=(x, y))
|
|
y += 15
|
|
self.leds = []
|
|
mark_count = 2
|
|
ticks = [(x-17+led_width,y+led_height/2+5)]
|
|
dc = wx.PaintDC(parent)
|
|
for i in range(16):
|
|
wx.StaticBitmap(parent, -1, off, pos=(x-1+i*17, y))
|
|
led = wx.StaticBitmap(parent, -1, on, pos=(x-1+i*17, y))
|
|
self.leds.append(led)
|
|
mark_count += 1
|
|
if mark_count >= 3:
|
|
mark_count = 0
|
|
ticks.append((x+i*17 + led_width, y+led_height/2+5))
|
|
|
|
self.set_value(0)
|
|
self.ticks = ticks
|
|
|
|
def set_value(self, value):
|
|
mask = 0x8000
|
|
for l in self.leds:
|
|
if value & mask:
|
|
l.Enable()
|
|
else:
|
|
l.Disable()
|
|
mask = mask >> 1
|
|
|
|
|
|
class MyFrame(wx.Frame):
|
|
"""a frame with two panels"""
|
|
|
|
WIDTH_SCREEN = 1024
|
|
HEIGHT_SCREEN = 1024
|
|
WIDTH_CONSOLE = 330 # 400 # 256
|
|
HEIGHT_CONSOLE = HEIGHT_SCREEN
|
|
|
|
SCREEN_COLOUR = (0, 0, 0)
|
|
CONSOLE_COLOUR = (255, 223, 169)
|
|
PHOSPHOR_COLOUR = '#F0F000' # yellow
|
|
#PHOSPHOR_COLOUR = '#40FF40' # green
|
|
|
|
V_MARGIN = 20
|
|
CTL_MARGIN = 15
|
|
LED_MARGIN = 5
|
|
|
|
IMAGE_LED_OFF = 'images/led_off.png'
|
|
IMAGE_LED_ON = 'images/led_on.png'
|
|
|
|
INC = 0.01
|
|
|
|
def __init__(self, parent=None, id=-1, title=None):
|
|
wx.Frame.__init__(self, parent, id, title)
|
|
|
|
self.make_gui()
|
|
self.run()
|
|
|
|
def make_gui(self):
|
|
self.screen = wx.Panel(self,
|
|
size=(self.WIDTH_SCREEN, self.HEIGHT_SCREEN),
|
|
pos=(0,0))
|
|
self.screen.SetBackgroundColour(self.SCREEN_COLOUR)
|
|
self.screen.Bind(wx.EVT_PAINT, self.on_paint)
|
|
self.console = wx.Panel(self, style=wx.SIMPLE_BORDER,
|
|
size=(self.WIDTH_CONSOLE, self.HEIGHT_SCREEN),
|
|
pos=(self.WIDTH_SCREEN,0))
|
|
self.console.SetBackgroundColour(self.CONSOLE_COLOUR)
|
|
self.console.Bind(wx.EVT_PAINT, self.on_paint)
|
|
|
|
python_png = wx.Image('images/PythonPowered.png',
|
|
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
|
python_height = python_png.GetHeight()
|
|
python_width = python_png.GetWidth()
|
|
|
|
wxpython_png = wx.Image('images/wxPython2.png',
|
|
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
|
wxpython_height = wxpython_png.GetHeight()
|
|
wxpython_width = wxpython_png.GetWidth()
|
|
|
|
h_margin = (self.WIDTH_CONSOLE - wxpython_width - python_width) / 3
|
|
|
|
png_height = max(python_height, wxpython_height) + self.V_MARGIN
|
|
|
|
v_margin = (png_height - python_height)/2
|
|
python_ypos = self.HEIGHT_CONSOLE - png_height + v_margin
|
|
v_margin = (png_height - wxpython_height)/2
|
|
wxpython_ypos = self.HEIGHT_CONSOLE - png_height + v_margin
|
|
|
|
wx.StaticBitmap(self.console, -1, python_png,
|
|
pos=(h_margin, python_ypos))
|
|
wx.StaticBitmap(self.console, -1, wxpython_png,
|
|
pos=(python_width + 2*h_margin, wxpython_ypos))
|
|
|
|
self.png_height = png_height
|
|
|
|
led_off = wx.Image('images/led_off.png',
|
|
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
|
led_on = wx.Image('images/led_on.png',
|
|
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
|
|
|
y_pos = 8
|
|
self.led_l = Led_1(self.console, 'l', self.CTL_MARGIN, y_pos,
|
|
led_off, led_on)
|
|
self.led_ac = Led_16(self.console, 'ac', 3*self.CTL_MARGIN, y_pos,
|
|
led_off, led_on)
|
|
y_pos += 35
|
|
self.led_pc = Led_16(self.console, 'pc', 3*self.CTL_MARGIN, y_pos,
|
|
led_off, led_on)
|
|
|
|
|
|
y_pos = 305
|
|
wx.StaticText(self.console, -1, 'ptr', pos=(self.CTL_MARGIN, y_pos))
|
|
y_pos += 15
|
|
self.txt_ptrFile = wx.TextCtrl(self.console, -1,
|
|
pos=(self.CTL_MARGIN, y_pos),
|
|
size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25))
|
|
y_pos += 30
|
|
|
|
wx.StaticText(self.console, -1, 'ptp', pos=(self.CTL_MARGIN, y_pos))
|
|
y_pos += 15
|
|
self.txt_ptpFile = wx.TextCtrl(self.console, -1,
|
|
pos=(self.CTL_MARGIN, y_pos),
|
|
size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25))
|
|
y_pos += 15
|
|
|
|
dc = wx.PaintDC(self.console)
|
|
dc.SetPen(wx.Pen('black', 1))
|
|
dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height,
|
|
self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height)
|
|
|
|
for (x, y) in self.led_ac.ticks:
|
|
dc.DrawLine(x, y, x, y+5)
|
|
first = self.led_ac.ticks[0]
|
|
last = self.led_ac.ticks[-1]
|
|
(x1, y1) = first
|
|
(x2, y2) = last
|
|
dc.DrawLine(x1, y2+5, x2, y2+5)
|
|
|
|
for (x, y) in self.led_pc.ticks:
|
|
dc.DrawLine(x, y, x, y+5)
|
|
first = self.led_pc.ticks[0]
|
|
last = self.led_pc.ticks[-1]
|
|
(x1, y1) = first
|
|
(x2, y2) = last
|
|
dc.DrawLine(x1, y2+5, x2, y2+5)
|
|
|
|
self.y_offset = 0
|
|
self.y_sign = +1
|
|
|
|
self.Fit()
|
|
|
|
def run(self):
|
|
# get operations list
|
|
ops = handle_options()
|
|
|
|
# Initialize the emulator.
|
|
boot_rom = 'ptr' # default ROM loader
|
|
Imlac.init(0, TRACE_FILENAME, None, None, boot_rom, CORE_FILENAME)
|
|
|
|
# now perform operations
|
|
for (operation, args) in ops:
|
|
if operation == 'boot':
|
|
Memory.set_ROM(args)
|
|
Trace.comment('Bootstrap ROM set to %s' % args.upper())
|
|
self.on_paint()
|
|
elif operation == 'clear':
|
|
Memory.clear_core()
|
|
Trace.comment('Core cleared')
|
|
self.on_paint()
|
|
elif operation == 'load_ptp':
|
|
Ptp.mount(args)
|
|
Trace.comment("File '%s' mounted on PTP" % args)
|
|
self.on_paint()
|
|
elif operation == 'load_ptr':
|
|
Ptr.mount(args)
|
|
Trace.comment("File '%s' mounted on PTR" % args)
|
|
self.on_paint()
|
|
elif operation == 'data':
|
|
MainCPU.DS = args
|
|
Trace.comment('Dataswitch value set to %06o' % args)
|
|
self.on_paint()
|
|
elif operation == 'run':
|
|
MainCPU.PC = args
|
|
Trace.comment('Running from address %06o' % args)
|
|
if Imlac.tracestart:
|
|
Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs')
|
|
Trace.comment('------ ------------- ------ -------------- '
|
|
'-----------------------')
|
|
self.on_paint()
|
|
Imlac.run()
|
|
self.on_paint()
|
|
Trace.comment('Imlac halted')
|
|
self.on_paint()
|
|
elif operation == 'set':
|
|
Trace.comment("Setting memory from file '%s'" % args)
|
|
self.on_paint()
|
|
elif operation == 'trace':
|
|
if args == 'off':
|
|
Imlac.tracestart = None
|
|
Imlac.traceend = None
|
|
else:
|
|
(start, end) = args
|
|
Imlac.tracestart = start
|
|
Imlac.traceend = end
|
|
tstart = Imlac.tracestart
|
|
if tstart is not None:
|
|
tstart = '%06o' % tstart
|
|
tend = Imlac.traceend
|
|
if tend is not None:
|
|
tend = '%06o' % tend
|
|
Trace.comment('Trace set to (%s, %s)' % (tstart, tend))
|
|
self.on_paint()
|
|
elif operation == 'ttyin':
|
|
TtyIn.mount(args)
|
|
Trace.comment("File '%s' mounted on TTYIN" % args)
|
|
self.on_paint()
|
|
elif operation == 'ttyout':
|
|
TtyOut.mount(args)
|
|
Trace.comment("File '%s' mounted on TTYOUT" % args)
|
|
self.on_paint()
|
|
elif operation == 'view':
|
|
Trace.comment("Viewing memory from file '%s'" % args)
|
|
self.on_paint()
|
|
elif operation == 'write':
|
|
if args == 'on':
|
|
Memory.using_rom = True
|
|
elif args == 'off':
|
|
Memory.using_rom = False
|
|
else:
|
|
abort("Invalid view arg: %s" % args)
|
|
Trace.comment('ROM write protect set %s' % args.upper())
|
|
self.on_paint()
|
|
else:
|
|
abort('Invalid internal operation: %s' % operation)
|
|
|
|
Imlac.close(CORE_FILENAME)
|
|
|
|
|
|
def on_paint(self, event=None):
|
|
global count
|
|
|
|
# establish the painting surface
|
|
dc = wx.PaintDC(self.screen)
|
|
dc.SetBackground(wx.Brush(self.SCREEN_COLOUR, 1))
|
|
dc.SetPen(wx.Pen(self.PHOSPHOR_COLOUR, 1))
|
|
dc.Clear()
|
|
if self.y_sign > 0:
|
|
self.y_offset = self.y_offset + self.INC
|
|
if self.y_offset > self.HEIGHT_SCREEN-1:
|
|
self.y_sign = -1
|
|
self.y_offset = self.HEIGHT_SCREEN-1
|
|
else:
|
|
self.y_offset = self.y_offset - self.INC
|
|
if self.y_offset < 0:
|
|
self.y_sign = +1
|
|
self.y_offset = 0
|
|
dc.DrawLine(0, int(self.y_offset), self.WIDTH_SCREEN-1, int(self.HEIGHT_SCREEN-self.y_offset-1))
|
|
dc.DrawLine(0, int(self.HEIGHT_SCREEN-self.y_offset-1), self.WIDTH_SCREEN-1, int(self.y_offset))
|
|
|
|
dc = wx.PaintDC(self.console)
|
|
#dc.SetPen(wx.Pen('black', wx.DOT))
|
|
dc.SetPen(wx.Pen('black', 1))
|
|
dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height,
|
|
self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height)
|
|
|
|
for (x, y) in self.led_ac.ticks:
|
|
dc.DrawLine(x, y, x, y+5)
|
|
first = self.led_ac.ticks[0]
|
|
last = self.led_ac.ticks[-1]
|
|
(x1, y1) = first
|
|
(x2, y2) = last
|
|
dc.DrawLine(x1, y2+5, x2, y2+5)
|
|
|
|
for (x, y) in self.led_pc.ticks:
|
|
dc.DrawLine(x, y, x, y+5)
|
|
first = self.led_pc.ticks[0]
|
|
last = self.led_pc.ticks[-1]
|
|
(x1, y1) = first
|
|
(x2, y2) = last
|
|
dc.DrawLine(x1, y2+5, x2, y2+5)
|
|
|
|
count += 1
|
|
self.led_ac.set_value(count)
|
|
|
|
|
|
pass
|
|
|
|
|
|
# test it ...
|
|
app = wx.PySimpleApp()
|
|
frame1 = MyFrame(title='pymlac 0.1')
|
|
frame1.Center()
|
|
frame1.Show()
|
|
app.MainLoop()
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
#import profile
|
|
#profile.run('main()', 'profile.out')
|
|
|
|
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
count = 1
|
|
|
|
class Led_1(object):
|
|
def __init__(self, parent, label, x, y, off, on):
|
|
wx.StaticText(parent, -1, label, pos=(x, y))
|
|
y += 15
|
|
wx.StaticBitmap(parent, -1, off, pos=(x-1, y))
|
|
self.led = wx.StaticBitmap(parent, -1, on, pos=(x-1, y))
|
|
self.set_value(0)
|
|
|
|
def set_value(self, value):
|
|
if value:
|
|
self.led.Enable()
|
|
else:
|
|
self.led.Disable()
|
|
|
|
|
|
class Led_16(object):
|
|
def __init__(self, parent, label, x, y, off, on):
|
|
led_width = off.GetWidth()
|
|
led_height = off.GetHeight()
|
|
wx.StaticText(parent, -1, label, pos=(x, y))
|
|
y += 15
|
|
self.leds = []
|
|
mark_count = 2
|
|
ticks = [(x-17+led_width,y+led_height/2+5)]
|
|
dc = wx.PaintDC(parent)
|
|
for i in range(16):
|
|
wx.StaticBitmap(parent, -1, off, pos=(x-1+i*17, y))
|
|
led = wx.StaticBitmap(parent, -1, on, pos=(x-1+i*17, y))
|
|
self.leds.append(led)
|
|
mark_count += 1
|
|
if mark_count >= 3:
|
|
mark_count = 0
|
|
ticks.append((x+i*17 + led_width, y+led_height/2+5))
|
|
|
|
self.set_value(0)
|
|
self.ticks = ticks
|
|
|
|
def set_value(self, value):
|
|
mask = 0x8000
|
|
for l in self.leds:
|
|
if value & mask:
|
|
l.Enable()
|
|
else:
|
|
l.Disable()
|
|
mask = mask >> 1
|
|
|
|
|
|
class MyFrame(wx.Frame):
|
|
"""a frame with two panels"""
|
|
|
|
WIDTH_SCREEN = 1024
|
|
HEIGHT_SCREEN = 1024
|
|
WIDTH_CONSOLE = 330 # 400 # 256
|
|
HEIGHT_CONSOLE = HEIGHT_SCREEN
|
|
|
|
SCREEN_COLOUR = (0, 0, 0)
|
|
CONSOLE_COLOUR = (255, 223, 169)
|
|
PHOSPHOR_COLOUR = '#F0F000' # yellow
|
|
#PHOSPHOR_COLOUR = '#40FF40' # green
|
|
|
|
V_MARGIN = 20
|
|
CTL_MARGIN = 15
|
|
LED_MARGIN = 5
|
|
|
|
IMAGE_LED_OFF = 'images/led_off.png'
|
|
IMAGE_LED_ON = 'images/led_on.png'
|
|
|
|
def __init__(self, parent=None, id=-1, title=None):
|
|
wx.Frame.__init__(self, parent, id, title)
|
|
|
|
self.make_gui()
|
|
# self.run()
|
|
|
|
def make_gui(self):
|
|
self.screen = wx.Panel(self,
|
|
size=(self.WIDTH_SCREEN, self.HEIGHT_SCREEN),
|
|
pos=(0,0))
|
|
self.screen.SetBackgroundColour(self.SCREEN_COLOUR)
|
|
self.screen.Bind(wx.EVT_PAINT, self.on_paint)
|
|
self.console = wx.Panel(self, style=wx.SIMPLE_BORDER,
|
|
size=(self.WIDTH_CONSOLE, self.HEIGHT_SCREEN),
|
|
pos=(self.WIDTH_SCREEN,0))
|
|
self.console.SetBackgroundColour(self.CONSOLE_COLOUR)
|
|
self.console.Bind(wx.EVT_PAINT, self.on_paint)
|
|
|
|
python_png = wx.Image('images/PythonPowered.png',
|
|
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
|
python_height = python_png.GetHeight()
|
|
python_width = python_png.GetWidth()
|
|
|
|
wxpython_png = wx.Image('images/wxPython2.png',
|
|
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
|
wxpython_height = wxpython_png.GetHeight()
|
|
wxpython_width = wxpython_png.GetWidth()
|
|
|
|
h_margin = (self.WIDTH_CONSOLE - wxpython_width - python_width) / 3
|
|
|
|
png_height = max(python_height, wxpython_height) + self.V_MARGIN
|
|
|
|
v_margin = (png_height - python_height)/2
|
|
python_ypos = self.HEIGHT_CONSOLE - png_height + v_margin
|
|
v_margin = (png_height - wxpython_height)/2
|
|
wxpython_ypos = self.HEIGHT_CONSOLE - png_height + v_margin
|
|
|
|
wx.StaticBitmap(self.console, -1, python_png,
|
|
pos=(h_margin, python_ypos))
|
|
wx.StaticBitmap(self.console, -1, wxpython_png,
|
|
pos=(python_width + 2*h_margin, wxpython_ypos))
|
|
|
|
self.png_height = png_height
|
|
|
|
led_off = wx.Image('images/led_off.png',
|
|
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
|
led_on = wx.Image('images/led_on.png',
|
|
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
|
|
|
y_pos = 8
|
|
self.led_l = Led_1(self.console, 'l', self.CTL_MARGIN, y_pos,
|
|
led_off, led_on)
|
|
self.led_ac = Led_16(self.console, 'ac', 3*self.CTL_MARGIN, y_pos,
|
|
led_off, led_on)
|
|
y_pos += 35
|
|
self.led_pc = Led_16(self.console, 'pc', 3*self.CTL_MARGIN, y_pos,
|
|
led_off, led_on)
|
|
|
|
y_pos = 305
|
|
wx.StaticText(self.console, -1, 'ptr', pos=(self.CTL_MARGIN, y_pos))
|
|
y_pos += 15
|
|
self.txt_ptrFile = wx.TextCtrl(self.console, -1,
|
|
pos=(self.CTL_MARGIN, y_pos),
|
|
size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25))
|
|
y_pos += 30
|
|
|
|
wx.StaticText(self.console, -1, 'ptp', pos=(self.CTL_MARGIN, y_pos))
|
|
y_pos += 15
|
|
self.txt_ptpFile = wx.TextCtrl(self.console, -1,
|
|
pos=(self.CTL_MARGIN, y_pos),
|
|
size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25))
|
|
y_pos += 15
|
|
|
|
dc = wx.PaintDC(self.console)
|
|
dc.SetPen(wx.Pen('black', 1))
|
|
dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height,
|
|
self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height)
|
|
|
|
for (x, y) in self.led_ac.ticks:
|
|
dc.DrawLine(x, y, x, y+5)
|
|
first = self.led_ac.ticks[0]
|
|
last = self.led_ac.ticks[-1]
|
|
(x1, y1) = first
|
|
(x2, y2) = last
|
|
dc.DrawLine(x1, y2+5, x2, y2+5)
|
|
|
|
for (x, y) in self.led_pc.ticks:
|
|
dc.DrawLine(x, y, x, y+5)
|
|
first = self.led_pc.ticks[0]
|
|
last = self.led_pc.ticks[-1]
|
|
(x1, y1) = first
|
|
(x2, y2) = last
|
|
dc.DrawLine(x1, y2+5, x2, y2+5)
|
|
|
|
self.y_offset = 0
|
|
self.y_sign = +1
|
|
|
|
self.Fit()
|
|
|
|
def on_paint(self, event):
|
|
global count
|
|
|
|
# establish the painting surface
|
|
dc = wx.PaintDC(self.screen)
|
|
dc.SetBackground(wx.Brush(self.SCREEN_COLOUR, 1))
|
|
dc.SetPen(wx.Pen(self.PHOSPHOR_COLOUR, 1))
|
|
dc.Clear()
|
|
if self.y_sign > 0:
|
|
self.y_offset = self.y_offset + self.INC
|
|
if self.y_offset > self.HEIGHT_SCREEN-1:
|
|
self.y_sign = -1
|
|
self.y_offset = self.HEIGHT_SCREEN-1
|
|
else:
|
|
self.y_offset = self.y_offset - self.INC
|
|
if self.y_offset < 0:
|
|
self.y_sign = +1
|
|
self.y_offset = 0
|
|
dc.DrawLine(0, int(self.y_offset), self.WIDTH_SCREEN-1, int(self.HEIGHT_SCREEN-self.y_offset-1))
|
|
dc.DrawLine(0, int(self.HEIGHT_SCREEN-self.y_offset-1), self.WIDTH_SCREEN-1, int(self.y_offset))
|
|
|
|
dc = wx.PaintDC(self.console)
|
|
#dc.SetPen(wx.Pen('black', wx.DOT))
|
|
dc.SetPen(wx.Pen('black', 1))
|
|
dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height,
|
|
self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height)
|
|
|
|
for (x, y) in self.led_ac.ticks:
|
|
dc.DrawLine(x, y, x, y+5)
|
|
first = self.led_ac.ticks[0]
|
|
last = self.led_ac.ticks[-1]
|
|
(x1, y1) = first
|
|
(x2, y2) = last
|
|
dc.DrawLine(x1, y2+5, x2, y2+5)
|
|
|
|
for (x, y) in self.led_pc.ticks:
|
|
dc.DrawLine(x, y, x, y+5)
|
|
first = self.led_pc.ticks[0]
|
|
last = self.led_pc.ticks[-1]
|
|
(x1, y1) = first
|
|
(x2, y2) = last
|
|
dc.DrawLine(x1, y2+5, x2, y2+5)
|
|
|
|
count += 1
|
|
self.led_ac.set_value(count)
|
|
|
|
|
|
# test it ...
|
|
app = wx.PySimpleApp()
|
|
frame1 = MyFrame(title='pymlac 0.1')
|
|
frame1.Center()
|
|
frame1.Show()
|
|
app.MainLoop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# test it ...
|
|
app = wx.PySimpleApp()
|
|
frame1 = MyFrame(title='pymlac 0.1')
|
|
frame1.Center()
|
|
frame1.Show()
|
|
app.MainLoop()
|