-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathevbuframe.py
More file actions
327 lines (261 loc) · 11.6 KB
/
evbuframe.py
File metadata and controls
327 lines (261 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
'''
Top-level window (menus, statusbar, etc.) for EVBU GUI
'''
import sys
import os
import string
import queue
import time
from safestruct import *
import wx
from term import Term
import EVBUoptions
from PySim11 import PySim11
from kcmmemory import getkcmmemoryData
class EVBUFrame(wx.Frame):
def __init__(self, parent, id, title, q, simbreak):
# Queue for sending user input to cmdloop
self.queue = q
# Event flag for stopping simulation
self.simbreak = simbreak
# Set to 1 when PySim11 is simulating
self.isSimulating = 0
# Handle to EVBUCmd instance
self.evb = None
#####################################################
#
# Determine sizes
#
#####################################################
dc = wx.ScreenDC()
font = wx.Font(12 if sys.platform == "win32" else 14, wx.MODERN, wx.NORMAL, wx.NORMAL)
dc.SetFont(font)
ch = dc.GetCharHeight()
cw = dc.GetCharWidth()
# I hate sizing things. I hate it, I hate it, I hate it. It
# *never* works the way it's supposed to. GUI's suck.
# Size ourselves as follows. Try for an 80x25 display. We want
# to further account for a scrollbar and borders.
# Unfortunately, wxPython returns 0 for all of the below. Sigh.
m = wx.SystemSettings.GetMetric
w = m(wx.SYS_WINDOWMIN_X)*cw + \
m(wx.SYS_BORDER_X)*2 + \
m(wx.SYS_EDGE_X)*2 + \
m(wx.SYS_FRAMESIZE_X)*2 + \
m(wx.SYS_VSCROLL_X)
h = m(wx.SYS_WINDOWMIN_Y)*ch + ch + 4 +\
m(wx.SYS_BORDER_Y)*4 + \
m(wx.SYS_EDGE_Y)*4 + \
m(wx.SYS_FRAMESIZE_Y)*2 + \
m(wx.SYS_CAPTION_Y) + \
m(wx.SYS_MENU_Y)
print("Border: %d Edge: %d Framesize: %d" % (m(wx.SYS_BORDER_Y), m(wx.SYS_EDGE_Y), m(wx.SYS_FRAMESIZE_Y)))
print("Caption: %d Menu: %d" % (m(wx.SYS_CAPTION_Y), m(wx.SYS_MENU_Y)))
print("Frame: %d x %d" % (w,h))
# We'll just go with the slop approach
#w = 80*cw + 30
#h = 25*ch + ch + 72
# First, call the base class' __init__ method to create the frame
super().__init__(parent, id, title, wx.Point(-1, -1), wx.Size(w,h), wx.MAXIMIZE|wx.DEFAULT_FRAME_STYLE)
self.SetAutoLayout(True)
self.term = Term(self, -1, wx.Point(0,0), (m(wx.SYS_WINDOWMIN_X),m(wx.SYS_WINDOWMIN_Y)), font, q)
# The PySim11 thread calls our functions to post window update
# commands using this queue. We use a fake buttons with ID
# of 301. The event handler for this button pulls an object
# from the queue. Each object in the queue is a 2-tuple
# (func, parms) which is simply invoked as func(*parms)
# in the handler.
self.handlerqueue = queue.Queue()
self.handlerqueuebuttonid = wx.NewIdRef()
self.Bind(wx.EVT_BUTTON,self.Queue_handler,id=self.handlerqueuebuttonid) #wx.EVT_BUTTON(self, self.handlerqueuebuttonid, self.Queue_handler)
##############################################
#
# Create menu bar, event table, and accelerator
#
##############################################
self.menubar = wx.MenuBar()
self.menuIDs = {}
fileMenu = wx.Menu()
#self.menuIDs['Preferences'] = fileMenu.preferencesID = wx.NewIdRef()
#fileMenu.Append(fileMenu.preferencesID, "&Preferences...\tCtrl-P", "Edit global properties for this application")
#fileMenu.AppendSeparator()
self.menuIDs['Load'] = fileMenu.loadID = wx.NewIdRef()
fileMenu.Append(fileMenu.loadID, "&Load\tCtrl-L", "Load an S19 file")
self.menuIDs['Exit'] = fileMenu.exitID = wx.NewIdRef()
fileMenu.Append(fileMenu.exitID, "E&xit\tCtrl-Q", "Exit the program")
self.menubar.Append(fileMenu, "&File")
simMenu = wx.Menu()
self.menuIDs['Stop'] = simMenu.stopID = wx.NewIdRef()
simMenu.Append(simMenu.stopID, "&Stop\tCtrl-C", "Stop the simulation")
self.menubar.Append(simMenu, "&Simulation")
helpMenu = wx.Menu()
self.menuIDs['About'] = helpMenu.aboutID = wx.NewIdRef()
helpMenu.Append(helpMenu.aboutID, "&About...", "About this program")
self.menubar.Append(helpMenu, "&Help")
self.SetMenuBar(self.menubar)
self.menubar.Enable(simMenu.stopID, 0)
self.Bind(wx.EVT_CLOSE,self.OnCloseWindow) #wx.EVT_CLOSE(self, self.OnCloseWindow)
#self.Bind(wx.EVT_MENU,self.OnPreferences,id=fileMenu.preferencesID) #wx.EVT_MENU(self, fileMenu.preferencesID, self.OnPreferences)
self.Bind(wx.EVT_MENU,self.OnFileLoad,id=fileMenu.loadID) #wx.EVT_MENU(self, fileMenu.loadID, self.OnFileLoad)
self.Bind(wx.EVT_MENU,self.OnCloseWindow,id=fileMenu.exitID) #wx.EVT_MENU(self, fileMenu.exitID, self.OnCloseWindow)
self.Bind(wx.EVT_MENU,self.OnAbout,id=helpMenu.aboutID) #wx.EVT_MENU(self, helpMenu.aboutID, self.OnAbout)
self.Bind(wx.EVT_MENU,self.OnSimStop,id=simMenu.stopID) #wx.EVT_MENU(self, simMenu.stopID, self.OnSimStop)
accel = wx.AcceleratorTable([ \
(wx.ACCEL_CTRL, ord('q'), fileMenu.exitID), \
# (wx.ACCEL_CTRL, ord('p'), fileMenu.preferencesID), \
(wx.ACCEL_CTRL, ord('l'), fileMenu.loadID), \
(wx.ACCEL_CTRL, ord('c'), simMenu.stopID)])
self.SetAcceleratorTable(accel)
##############################################
#
# Create status bar
#
##############################################
self.statusBar = wx.StatusBar(self, -1, 0)
self.statusBar.SetFieldsCount(1)
self.statusBar.SetStatusWidths([-1])
self.statusBar.SetStatusText("Ready", 0)
self.SetStatusBar(self.statusBar)
#self.statusBarBackgroundColor = self.statusBar.GetBackgroundColour()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.term, 1, wx.EXPAND)
self.sizer.Fit(self)
self.SetSizer(self.sizer)
#c1 = wx.LayoutConstraints()
#c1.top.SameAs(self, wx.Top)
#c1.left.SameAs(self, wx.Left)
#c1.right.SameAs(self,wx.Right)
#c1.bottom.SameAs(self, wx.Bottom)
#c1.height.AsIs()
#self.term.SetConstraints(c1)
#c2 = wx.LayoutConstraints()
#c2.left.SameAs(self, wx.Left)
#c2.right.SameAs(self, wx.Right, 10)
#c2.bottom.SameAs(self, wx.Bottom, 10)
#c2.top.Below(self.term, 10)
#c2.height.AsIs()
#self.statusBar.SetConstraints(c2)
#self.Layout()
#self.Bind(wx.EVT_SIZE, self.OnSize) #wx.EVT_SIZE(self, self.OnSize)
#########################
#
# Icon
#
#########################
#self.SetIcon(wx.Icon(getkcmmemoryData(),type=wx.BITMAP_TYPE_XPM_DATA))
#def OnSize(self, event):
# self.Layout()
# event.Skip()
def Quit(self):
if self.isSimulating:
wx.MessageBox("Simulation is in progress. Terminate the simulation before quitting the program.", "Hold it, bub", wx.OK|wx.CENTRE)
return
self.queue.put(0)
self.Destroy()
def OnCloseWindow(self, event): self.Quit()
def OnPreferences(self, event): pass
def OnFileLoad(self, event):
line = wx.FileSelector('Select S19 file', os.getcwd(), '', '.s19', 'S19 files (*.s19)|*.s19|All files (*.*)|*.*', wx.FD_OPEN|wx.FD_FILE_MUST_EXIST, self)
if line: self.queue.put(f'load {line}')
def OnAbout(self, event):
aboutText = '''\
EVBU : A simulator for the Motorola 68HC11
EVBU Version %d.%d
PySim11 Version %d.%d
Andrew Sterian
Padnos College of Engineering & Computing
Grand Valley State University
<steriana@gvsu.edu>
<http://claymore.engineer.gvsu.edu/~steriana/Python>
Modified for Python3 by <tonyp@acm.org>
''' % (EVBUoptions.EVBUVersionMajor, EVBUoptions.EVBUVersionMinor,\
PySim11.PySim11VersionMajor, PySim11.PySim11VersionMinor)
wx.MessageBox(aboutText, "About EVBU", wx.OK|wx.CENTRE, self)
def FlushQueue(self):
# Flush the queue that sends user data to the EVBU
try:
while 1: junk = self.queue.get(0)
except queue.Empty: pass
def SetEVBU(self, evb):
self.evb = evb
evb.simstate.ucEvents.addHandler(evb.simstate.ucEvents.SimStart, self.OnSimStart)
evb.simstate.ucEvents.addHandler(evb.simstate.ucEvents.SimEnd, self.OnSimEnd)
evb.simstate.ucEvents.addHandler(evb.simstate.ucEvents.CharWait, self.OnCharWait)
evb.simstate.ucEvents.addHandler(evb.simstate.ucEvents.NoCharWait, self.OnNoCharWait)
# User-generated simulation stop
def OnSimStop(self, event):
if not self.isSimulating:
wx.MessageBox("Simulation not in progress", "Huh?", wx.OK|wx.CENTRE, self)
return
# Clear the flag, then wait for PySim11 to set it, indicating a
# successful break.
self.simbreak.clear()
while 1:
self.simbreak.wait(3.0)
if self.simbreak.isSet(): break
else:
ret = wx.MessageBox("The simulator has not stopped yet. Press OK to try again or Cancel to give up.", "Ooops", wx.OK|wx.CANCEL|wx.CENTRE|wx.ICON_ERROR)
if ret != wx.OK: return
##################################################################
##################################################################
##################################################################
# These functions are called as handlers in response to events
# from PySim11
def Queue_handler(self, event):
try: (func, args) = self.handlerqueue.get(0)
except queue.Empty: return
func(*args)
# Come back here for the next event in the queue
wx.PostEvent(self, wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.handlerqueuebuttonid))
def OnCharWait_handler(self):
self.statusBar.SetStatusText("Simulating...waiting for a character", 0)
self.statusBar.Refresh()
def OnNoCharWait_handler(self, event):
self.statusBar.SetStatusText("Simulating...", 0)
self.statusBar.Refresh()
def OnSimStart_handler(self):
self.isSimulating = 1
#self.menubar.Enable(self.menuIDs['Preferences'], 0)
self.menubar.Enable(self.menuIDs['Exit'], 0)
self.menubar.Enable(self.menuIDs['Stop'], 1)
self.term.SetCBreak(1)
self.statusBar.SetStatusText("Simulating...", 0)
def OnSimEnd_handler(self):
self.isSimulating = 0
#self.menubar.Enable(self.menuIDs['Preferences'], 1)
self.menubar.Enable(self.menuIDs['Exit'], 1)
self.menubar.Enable(self.menuIDs['Stop'], 0)
self.FlushQueue()
self.term.SetCBreak(0)
self.statusBar.SetStatusText("Ready", 0)
##################################################################
##################################################################
##################################################################
# The following functions are called from the PySim11 thread
# and must post to the queue for thread safety
def OnCharWait(self, event):
self.handlerqueue.put((self.OnCharWait_handler, ()))
wx.PostEvent(self, wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.handlerqueuebuttonid))
def OnNoCharWait(self, event):
self.handlerqueue.put((self.OnNoCharWait_handler, ()))
wx.PostEvent(self, wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.handlerqueuebuttonid))
def OnSimStart(self, event):
self.handlerqueue.put((self.OnSimStart_handler, ()))
wx.PostEvent(self, wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.handlerqueuebuttonid))
def OnSimEnd(self, event):
self.handlerqueue.put((self.OnSimEnd_handler, ()))
wx.PostEvent(self, wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.handlerqueuebuttonid))
if __name__ == "__main__":
class MyApp(wx.App):
# wx.Windows calls this method to initialize the application
def OnInit(self):
# Create an instance of our customized Frame class
import threading
frame = EVBUFrame(None, -1, "This is a test",queue.Queue(),threading.Event())
frame.Show(True)
# Tell wx.Windows that this is our main window
self.SetTopWindow(frame)
# Return a success flag
return True
app = MyApp(0) # Create an instance of the application class
app.MainLoop() # Tell it to start processing events